[Core] Create new plugin based class for credentials

* Moved credential class from rally.objects to rally.deployment.
* Added OpenStackCredential plugin.
* Simplified getting of osclients.
* Enabled client caching on OpenStackCredential plugin.

spec: deployment_type.rst

Change-Id: I9ac8c4989c681885534683bd4ee4bc34fcfabaac
This commit is contained in:
Anton Studenov 2017-03-21 12:49:11 +03:00
parent 91f22381a2
commit 7792aa71b7
46 changed files with 1111 additions and 645 deletions

View File

@ -50,12 +50,16 @@ then
cat >$1 <<EOF
{
"type": "ExistingCloud",
"auth_url": "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v$IDENTITY_API_VERSION",
"region_name": "$REGION_NAME",
"admin": {
"username": "admin",
"password": "$ADMIN_PASSWORD",
"tenant_name": "admin",
"creds": {
"openstack": {
"auth_url": "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v$IDENTITY_API_VERSION",
"region_name": "$REGION_NAME",
"admin": {
"username": "admin",
"password": "$ADMIN_PASSWORD",
"tenant_name": "admin",
}
}
}
}
EOF
@ -65,14 +69,18 @@ then
cat >$1 <<EOF
{
"type": "ExistingCloud",
"auth_url": "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v$IDENTITY_API_VERSION",
"region_name": "$REGION_NAME",
"admin": {
"username": "admin",
"password": "$ADMIN_PASSWORD",
"project_name": "admin",
"user_domain_name": "Default",
"project_domain_name": "Default"
"creds": {
"openstack": {
"auth_url": "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v$IDENTITY_API_VERSION",
"region_name": "$REGION_NAME",
"admin": {
"username": "admin",
"password": "$ADMIN_PASSWORD",
"project_name": "admin",
"user_domain_name": "Default",
"project_domain_name": "Default"
}
}
}
}
EOF

View File

@ -33,7 +33,6 @@ from rally.common import version as rally_version
from rally import consts
from rally.deployment import engine as deploy_engine
from rally import exceptions
from rally import osclients
from rally.task import engine
from rally.verification import context as vcontext
from rally.verification import manager as vmanager
@ -149,10 +148,9 @@ class _Deployment(object):
:param deployment: Deployment object
:returns: Service list
"""
# TODO(astudenov): put this work into Credential plugins
# TODO(astudenov): make this method platform independent
admin = deployment.get_credentials_for("openstack")["admin"]
clients = osclients.Clients(objects.Credential(**admin))
return clients.services()
return admin.list_services()
@staticmethod
def list(status=None, parent_uuid=None, name=None):
@ -168,13 +166,12 @@ class _Deployment(object):
:returns: Service list
"""
# TODO(astudenov): put this work into Credential plugins
services = cls.service_list(deployment)
users = deployment.get_credentials_for("openstack")["users"]
for endpoint_dict in users:
osclients.Clients(objects.Credential(**endpoint_dict)).keystone()
return services
# TODO(astudenov): make this method platform independent
creds = deployment.get_credentials_for("openstack")
creds["admin"].verify_connection()
for user in creds["users"]:
user.verify_connection()
return creds["admin"].list_services()
class _Task(object):

View File

@ -191,11 +191,13 @@ class DeploymentCommands(object):
metavar="<uuid>", required=False,
help="UUID or name of the deployment.")
@envutils.with_default_deployment()
@plugins.ensure_plugins_are_loaded
def show(self, api, deployment=None):
"""Show the credentials of the deployment.
:param deployment: UUID or name of the deployment
"""
# TODO(astudenov): make this method platform independent
headers = ["auth_url", "username", "password", "tenant_name",
"region_name", "endpoint_type"]
@ -208,7 +210,7 @@ class DeploymentCommands(object):
credentials = users + [admin] if admin else users
for ep in credentials:
data = ["***" if m == "password" else ep.get(m, "")
data = ["***" if m == "password" else getattr(ep, m, "")
for m in headers]
table_rows.append(utils.Struct(**dict(zip(headers, data))))
cliutils.print_list(table_rows, headers)
@ -217,11 +219,13 @@ class DeploymentCommands(object):
metavar="<uuid>", required=False,
help="UUID or name of the deployment.")
@envutils.with_default_deployment()
@plugins.ensure_plugins_are_loaded
def check(self, api, deployment=None):
"""Check keystone authentication and list all available services.
:param deployment: UUID or name of the deployment
"""
# TODO(astudenov): make this method platform independent
headers = ["services", "type", "status"]
table_rows = []
try:
@ -235,7 +239,7 @@ class DeploymentCommands(object):
services = api.deployment.check(deployment)
except keystone_exceptions.ConnectionRefused:
admin = deployment.get_credentials_for("openstack")["admin"]
print(_("Unable to connect %s.") % admin["auth_url"])
print(_("Unable to connect %s.") % admin.auth_url)
return(1)
except exceptions.InvalidArgumentsException:
@ -296,11 +300,13 @@ class DeploymentCommands(object):
@cliutils.args("--deployment", dest="deployment", type=str,
metavar="<uuid>", required=False,
help="UUID or name of a deployment.")
@plugins.ensure_plugins_are_loaded
def use(self, api, deployment):
"""Set active deployment.
:param deployment: UUID or name of the deployment
"""
# TODO(astudenov): make this method platform independent
try:
deployment = api.deployment.get(deployment)
print("Using deployment: %s" % deployment["uuid"])
@ -309,8 +315,9 @@ class DeploymentCommands(object):
deployment["uuid"])
creds = deployment.get_credentials_for("openstack")
credential = creds["admin"] or creds["users"][0]
self._update_openrc_deployment_file(
deployment["uuid"], creds["admin"] or creds["users"][0])
deployment["uuid"], credential.to_dict())
print("~/.rally/openrc was updated\n\nHINTS:\n"
"\n* To use standard OpenStack clients, set up your env by "
"running:\n\tsource ~/.rally/openrc\n"

View File

@ -13,43 +13,16 @@
# License for the specific language governing permissions and limitations
# under the License.
from rally import consts
from rally.plugins.openstack import credential
# TODO(astudenov): remove this class in future releases
class Credential(object):
def __init__(self, auth_url, username, password, tenant_name=None,
project_name=None,
permission=consts.EndpointPermission.USER,
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):
self.auth_url = auth_url
self.username = username
self.password = password
self.tenant_name = tenant_name or project_name
self.permission = permission
self.region_name = region_name
self.endpoint_type = endpoint_type
self.domain_name = domain_name
self.user_domain_name = user_domain_name
self.project_domain_name = project_domain_name
self.endpoint = endpoint
self.insecure = https_insecure
self.cacert = https_cacert
class Credential(credential.OpenStackCredential):
"""Deprecated version of OpenStackCredential class"""
def to_dict(self, include_permission=False):
dct = {"auth_url": self.auth_url, "username": self.username,
"password": self.password, "tenant_name": self.tenant_name,
"region_name": self.region_name,
"endpoint_type": self.endpoint_type,
"domain_name": self.domain_name,
"endpoint": self.endpoint,
"https_insecure": self.insecure,
"https_cacert": self.cacert,
"user_domain_name": self.user_domain_name,
"project_domain_name": self.project_domain_name}
if include_permission:
dct["permission"] = self.permission
dct = super(Credential, self).to_dict()
if not include_permission:
dct.pop("permission")
return dct

View File

@ -21,6 +21,7 @@ from rally.common.i18n import _, _LW
from rally.common import db
from rally.common import logging
from rally import consts
from rally.deployment import credential
from rally import exceptions
@ -34,7 +35,7 @@ CREDENTIALS_SCHEMA = {
"items": {
"type": "object",
"properties": {
"admin": {"type": "object"},
"admin": {"type": ["object", "null"]},
"users": {
"type": "array",
"items": {"type": "object"}
@ -97,12 +98,17 @@ class Deployment(object):
def get_credentials_for(self, namespace):
try:
return self.deployment["credentials"][namespace][0]
creds = self.deployment["credentials"][namespace][0]
except (KeyError, IndexError) as e:
LOG.exception(e)
raise exceptions.RallyException(_(
"No credentials found for %s") % namespace)
admin = creds["admin"]
credential_cls = credential.get(namespace)
return {"admin": credential_cls(**admin) if admin else None,
"users": [credential_cls(**user) for user in creds["users"]]}
def set_started(self):
self._update({"started_at": dt.datetime.now(),
"status": consts.DeployStatus.DEPLOY_STARTED})

View File

@ -0,0 +1,89 @@
# Copyright 2017: 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 abc
import jsonschema
import six
from rally.common.plugin import plugin
def configure(namespace):
def wrapper(cls):
cls = plugin.configure(name="credential", namespace=namespace)(cls)
return cls
return wrapper
def get(namespace):
return Credential.get(name="credential", namespace=namespace)
@plugin.base()
@six.add_metaclass(abc.ABCMeta)
class Credential(plugin.Plugin):
"""Base class for credentials."""
@abc.abstractmethod
def to_dict(self):
"""Converts creedential object to dict.
:returns: dict that can be used to recreate credential using
constructor: Credential(**credential.to_dict())
"""
@abc.abstractmethod
def verify_connection(self):
"""Verifies that credential can be used for connection."""
@abc.abstractmethod
def list_services(self):
"""Returns available services.
:returns: dict
"""
def configure_builder(namespace):
def wrapper(cls):
cls = plugin.configure(name="credential_builder",
namespace=namespace)(cls)
return cls
return wrapper
def get_builder(namespace):
return CredentialBuilder.get(name="credential_builder",
namespace=namespace)
@plugin.base()
@six.add_metaclass(abc.ABCMeta)
class CredentialBuilder(plugin.Plugin):
"""Base class for extensions of ExistingCloud deployment."""
CONFIG_SCHEMA = {"type": "null"}
def __init__(self, config):
self.config = config
@classmethod
def validate(cls, config):
jsonschema.validate(config, cls.CONFIG_SCHEMA)
@abc.abstractmethod
def build_credentials(self):
"""Builds credentials from provided configuration"""

View File

@ -19,7 +19,6 @@ import six
from rally.common.i18n import _
from rally.common import logging
from rally.common import objects
from rally import consts
from rally.deployment import engine
from rally.deployment.serverprovider import provider
@ -133,17 +132,13 @@ class DevstackEngine(engine.Engine):
stdin=local_conf)
devstack_server.ssh.run("~/devstack/stack.sh")
admin_credential = objects.Credential(
"http://%s:5000/v2.0/" % self.servers[0].host, "admin",
self.local_conf["ADMIN_PASSWORD"], "admin",
consts.EndpointPermission.ADMIN)
return {
"openstack": [
{
"admin": admin_credential.to_dict(include_permission=True),
"users": []
}
]}
admin_dict = dict(
auth_url="http://%s:5000/v2.0/" % self.servers[0].host,
username="admin",
password=self.local_conf["ADMIN_PASSWORD"],
tenant_name="admin",
permission=consts.EndpointPermission.ADMIN)
return {"openstack": [{"admin": admin_dict, "users": []}]}
def cleanup(self):
for resource in self.deployment.get_resources(type="credentials"):

View File

@ -13,16 +13,61 @@
# License for the specific language governing permissions and limitations
# under the License.
from rally.common import objects
import copy
from rally.common import logging
from rally import consts
from rally.deployment import credential
from rally.deployment import engine
LOG = logging.getLogger(__name__)
@engine.configure(name="ExistingCloud")
class ExistingCloud(engine.Engine):
"""Just use an existing OpenStack deployment without deploying anything.
"""Platform independent deployment engine.
To use ExistingCloud, you should put credential information to the config:
This deployment engine allows specifing list of credentials for one
or more platforms.
Example configuration:
.. code-block:: json
{
"type": "ExistingCloud",
"creds": {
"openstack": {
"auth_url": "http://localhost:5000/v3/",
"region_name": "RegionOne",
"endpoint_type": "public",
"admin": {
"username": "admin",
"password": "admin",
"user_domain_name": "admin",
"project_name": "admin",
"project_domain_name": "admin",
},
"https_insecure": False,
"https_cacert": "",
}
}
}
To specify extra options use can use special "extra" parameter:
.. code-block:: json
{
"type": "ExistingCloud",
...
"extra": {"some_var": "some_value"}
}
It also support deprecated version of configuration that supports
only OpenStack.
keystone v2:
.. code-block:: json
@ -40,7 +85,7 @@ class ExistingCloud(engine.Engine):
"https_cacert": "",
}
Or, using keystone v3 API endpoint:
keystone v3 API endpoint:
.. code-block:: json
@ -60,114 +105,132 @@ class ExistingCloud(engine.Engine):
"https_cacert": "",
}
To specify extra options use can use special "extra" parameter:
.. code-block:: json
{
"type": "ExistingCloud",
"auth_url": "http://localhost:5000/v2.0/",
"region_name": "RegionOne",
"endpoint_type": "public",
"admin": {
"username": "admin",
"password": "password",
"tenant_name": "demo"
},
"https_insecure": False,
"https_cacert": "",
"extra": {"some_var": "some_value"}
}
"""
CONFIG_SCHEMA = {
USER_SCHEMA = {
"type": "object",
"definitions": {
"user": {
"type": "object",
"oneOf": [
{
"description": "Keystone V2.0",
"properties": {
"username": {"type": "string"},
"password": {"type": "string"},
"tenant_name": {"type": "string"},
},
"required": ["username", "password", "tenant_name"],
"additionalProperties": False
},
{
"description": "Keystone V3.0",
"properties": {
"username": {"type": "string"},
"password": {"type": "string"},
"domain_name": {"type": "string"},
"user_domain_name": {"type": "string"},
"project_name": {"type": "string"},
"project_domain_name": {"type": "string"},
},
"required": ["username", "password", "project_name"],
"additionalProperties": False
}
],
"oneOf": [
{
"description": "Keystone V2.0",
"properties": {
"username": {"type": "string"},
"password": {"type": "string"},
"tenant_name": {"type": "string"},
},
"required": ["username", "password", "tenant_name"],
"additionalProperties": False
},
{
"description": "Keystone V3.0",
"properties": {
"username": {"type": "string"},
"password": {"type": "string"},
"domain_name": {"type": "string"},
"user_domain_name": {"type": "string"},
"project_name": {"type": "string"},
"project_domain_name": {"type": "string"},
},
"required": ["username", "password", "project_name"],
"additionalProperties": False
}
},
],
}
OLD_CONFIG_SCHEMA = {
"type": "object",
"description": "Deprecated schema (openstack only)",
"properties": {
"type": {"type": "string"},
"auth_url": {"type": "string"},
"region_name": {"type": "string"},
"endpoint": {"oneOf": [
# NOTE(andreykurilin): it looks like we do not use endpoint
# var at all
{"type": "string", "description": ""},
{"type": "null", "description": ""}]},
# NOTE(andreykurilin): it looks like we do not use endpoint
# var at all
"endpoint": {"type": ["string", "null"]},
"endpoint_type": {"enum": [consts.EndpointType.ADMIN,
consts.EndpointType.INTERNAL,
consts.EndpointType.PUBLIC,
None]},
"https_insecure": {"type": "boolean"},
"https_cacert": {"type": "string"},
"admin": {"$ref": "#/definitions/user"},
"users": {
"type": "array",
"items": {"$ref": "#/definitions/user"}
},
"admin": USER_SCHEMA,
"users": {"type": "array", "items": USER_SCHEMA},
"extra": {"type": "object", "additionalProperties": True}
},
"required": ["type", "auth_url", "admin"],
"additionalProperties": False
}
def _create_credential(self, common, user, permission):
return objects.Credential(
common["auth_url"], user["username"], user["password"],
tenant_name=user.get("project_name", user.get("tenant_name")),
permission=permission,
region_name=common.get("region_name"),
endpoint_type=common.get("endpoint_type"),
endpoint=common.get("endpoint"),
domain_name=user.get("domain_name"),
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")
)
NEW_CONFIG_SCHEMA = {
"type": "object",
"description": "New schema for multiplatform deployment",
"properties": {
"type": {"enum": ["ExistingCloud"]},
"creds": {
"type": "object",
"patternProperties": {
"^[a-z0-9_-]+$": {
"oneOf": [
{
"description": "Single credential",
"type": "object"
},
{
"description": "List of credentials",
"type": "array",
"items": {"type": "object"}
},
]
}
}
},
"extra": {"type": "object", "additionalProperties": True}
},
"required": ["type", "creds"],
"additionalProperties": False
}
CONFIG_SCHEMA = {"type": "object",
"oneOf": [OLD_CONFIG_SCHEMA, NEW_CONFIG_SCHEMA]}
def validate(self, config=None):
config = config or self.config
super(ExistingCloud, self).validate(config)
creds_config = self._get_creds(config)
for platform, config in creds_config.items():
builder_cls = credential.get_builder(platform)
for creds in config:
builder_cls.validate(creds)
def _get_creds(self, config):
if "creds" not in config:
# backward compatibility with old schema
config = copy.deepcopy(config)
del config["type"]
creds_config = {"openstack": [config]}
else:
creds_config = config["creds"]
# convert all credentials to list
for platform, config in creds_config.items():
if isinstance(config, dict):
creds_config[platform] = [config]
return creds_config
def deploy(self):
permissions = consts.EndpointPermission
users = [self._create_credential(self.config, user, permissions.USER)
for user in self.config.get("users", [])]
users = [user.to_dict(include_permission=True) for user in users]
admin = self._create_credential(self.config,
self.config.get("admin"),
permissions.ADMIN)
admin = admin.to_dict(include_permission=True)
return {"openstack": [{"admin": admin, "users": users}]}
if "creds" not in self.config:
LOG.warning("Old config schema is deprecated since Rally 0.10.0. "
"Please use new config schema for ExistingCloud")
creds_config = self._get_creds(self.config)
parsed_credentials = {}
for platform, config in creds_config.items():
builder_cls = credential.get_builder(platform)
credentials = []
for creds in config:
builder = builder_cls(creds)
credentials.append(builder.build_credentials())
parsed_credentials[platform] = credentials
return parsed_credentials
def cleanup(self):
pass

View File

@ -150,9 +150,7 @@ class LxcEngine(engine.Engine):
if network:
network += 1
admin = objects.Credential("", "", "", "").to_dict(
include_permission=True)
return {"openstack": [{"admin": admin, "users": []}]}
return {"openstack": [{"admin": None, "users": []}]}
def cleanup(self):
resources = self.deployment.get_resources()

View File

@ -21,10 +21,9 @@ import novaclient.exceptions
from rally.common.i18n import _
from rally.common import logging
from rally.common import objects
from rally.deployment.serverprovider import provider
from rally import exceptions
from rally import osclients
from rally.plugins.openstack import credential
from rally.task import utils
@ -144,11 +143,13 @@ class OpenStackProvider(provider.ProviderFactory):
def __init__(self, deployment, config):
super(OpenStackProvider, self).__init__(deployment, config)
user_credential = objects.Credential(
config["auth_url"], config["user"],
config["password"], config["tenant"],
user_credential = credential.OpenStackCredential(
auth_url=config["auth_url"],
username=config["user"],
password=config["password"],
tenant_name=config["tenant"],
region_name=config.get("region"))
clients = osclients.Clients(user_credential)
clients = user_credential.clients()
self.nova = clients.nova()
self.sg = None
try:

View File

@ -22,7 +22,6 @@ from six.moves.urllib import parse
from rally.cli import envutils
from rally.common.i18n import _
from rally.common import logging
from rally.common import objects
from rally.common.plugin import plugin
from rally import consts
from rally import exceptions
@ -687,10 +686,10 @@ class Watcher(OSClient):
class Clients(object):
"""This class simplify and unify work with OpenStack python clients."""
def __init__(self, credential, api_info=None):
def __init__(self, credential, api_info=None, cache=None):
self.credential = credential
self.api_info = api_info or {}
self.cache = {}
self.cache = cache or {}
def __getattr__(self, client_name):
"""Lazy load of clients."""
@ -700,20 +699,20 @@ class Clients(object):
@classmethod
def create_from_env(cls):
creds = envutils.get_creds_from_env_vars()
return cls(
objects.Credential(
creds["auth_url"],
creds["admin"]["username"],
creds["admin"]["password"],
creds["admin"]["tenant_name"],
endpoint_type=creds["endpoint_type"],
user_domain_name=creds["admin"].get("user_domain_name"),
project_domain_name=creds["admin"].get("project_domain_name"),
endpoint=creds["endpoint"],
region_name=creds["region_name"],
https_cacert=creds["https_cacert"],
https_insecure=creds["https_insecure"]
))
from rally.plugins.openstack import credential
oscred = credential.OpenStackCredential(
auth_url=creds["auth_url"],
username=creds["admin"]["username"],
password=creds["admin"]["password"],
tenant_name=creds["admin"]["tenant_name"],
endpoint_type=creds["endpoint_type"],
user_domain_name=creds["admin"].get("user_domain_name"),
project_domain_name=creds["admin"].get("project_domain_name"),
endpoint=creds["endpoint"],
region_name=creds["region_name"],
https_cacert=creds["https_cacert"],
https_insecure=creds["https_insecure"])
return cls(oscred)
def clear(self):
"""Remove all cached client handles."""

View File

@ -21,7 +21,6 @@ from rally.common import logging
from rally.common.plugin import discover
from rally.common.plugin import plugin
from rally.common import utils as rutils
from rally import osclients
from rally.plugins.openstack.cleanup import base
@ -29,7 +28,6 @@ LOG = logging.getLogger(__name__)
class SeekAndDestroy(object):
cache = {}
def __init__(self, manager_cls, admin, users, api_versions=None,
resource_classes=None, task_id=None):
@ -58,15 +56,8 @@ class SeekAndDestroy(object):
"""Simplifies initialization and caching OpenStack clients."""
if not user:
return None
if self.api_versions:
key = str((user["credential"], sorted(self.api_versions.items())))
else:
key = user["credential"]
if key not in self.cache:
self.cache[key] = osclients.Clients(
user["credential"], api_info=self.api_versions)
return self.cache[key]
# NOTE(astudenov): Credential now supports caching by default
return user["credential"].clients(api_info=self.api_versions)
def _delete_single_resource(self, resource):
"""Safe resource deletion with retries and timeouts.
@ -170,7 +161,6 @@ class SeekAndDestroy(object):
admin=admin_client,
user=self._get_cached_client(user),
tenant_uuid=user["tenant_id"])
_publish(self.admin, user, manager)
def _consumer(self, cache, args):
@ -268,14 +258,14 @@ def cleanup(names=None, admin_required=None, admin=None, users=None,
:param admin_required: If None -> return all plugins
If True -> return only admin plugins
If False -> return only non admin plugins
:param admin: rally.common.objects.Credential that corresponds to OpenStack
admin.
:param admin: rally.deployment.credential.Credential that corresponds to
OpenStack admin.
:param users: List of OpenStack users that was used during benchmarking.
Every user has next structure:
{
"id": <uuid1>,
"tenant_id": <uuid2>,
"credential": <rally.common.objects.Credential>
"credential": <rally.deployment.credential.Credential>
}
:param superclass: The plugin superclass to perform cleanup
for. E.g., this could be

View File

@ -15,8 +15,6 @@
from rally.common.i18n import _
from rally.common import logging
from rally.common import objects
from rally import osclients
from rally.task import context
@ -46,10 +44,8 @@ class ExistingUsers(context.Context):
self.context["tenants"] = {}
self.context["user_choice_method"] = "random"
for user in self.config:
user_credential = objects.Credential(**user)
user_clients = osclients.Clients(user_credential)
for user_credential in self.config:
user_clients = user_credential.clients()
user_id = user_clients.keystone.auth_ref.user_id
tenant_id = user_clients.keystone.auth_ref.project_id

View File

@ -21,11 +21,11 @@ from oslo_config import cfg
from rally.common import broker
from rally.common.i18n import _
from rally.common import logging
from rally.common import objects
from rally.common import utils as rutils
from rally import consts
from rally import exceptions
from rally import osclients
from rally.plugins.openstack import credential
from rally.plugins.openstack.services.identity import identity
from rally.plugins.openstack.wrappers import network
from rally.task import context
@ -207,10 +207,12 @@ class UserGenerator(context.Context):
project_id=tenant_id,
domain_name=user_dom,
default_role=default_role)
user_credential = objects.Credential(
self.credential.auth_url, user.name, password,
self.context["tenants"][tenant_id]["name"],
consts.EndpointPermission.USER,
user_credential = credential.OpenStackCredential(
auth_url=self.credential.auth_url,
username=user.name,
password=password,
tenant_name=self.context["tenants"][tenant_id]["name"],
permission=consts.EndpointPermission.USER,
project_domain_name=project_dom,
user_domain_name=user_dom,
endpoint_type=self.credential.endpoint_type,

View File

@ -0,0 +1,173 @@
# Copyright 2017: 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 import consts
from rally.deployment import credential
from rally import osclients
@credential.configure("openstack")
class OpenStackCredential(credential.Credential):
"""Credential for OpenStack."""
def __init__(self, auth_url, username, password, tenant_name=None,
project_name=None,
permission=consts.EndpointPermission.USER,
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):
self.auth_url = auth_url
self.username = username
self.password = password
self.tenant_name = tenant_name or project_name
self.permission = permission
self.region_name = region_name
self.endpoint_type = endpoint_type
self.domain_name = domain_name
self.user_domain_name = user_domain_name
self.project_domain_name = project_domain_name
self.endpoint = endpoint
self.https_insecure = https_insecure
self.https_cacert = https_cacert
self._clients_cache = {}
# backward compatibility
@property
def insecure(self):
return self.https_insecure
# backward compatibility
@property
def cacert(self):
return self.https_cacert
def to_dict(self):
return {"auth_url": self.auth_url,
"username": self.username,
"password": self.password,
"tenant_name": self.tenant_name,
"region_name": self.region_name,
"endpoint_type": self.endpoint_type,
"domain_name": self.domain_name,
"endpoint": self.endpoint,
"https_insecure": self.https_insecure,
"https_cacert": self.https_cacert,
"user_domain_name": self.user_domain_name,
"project_domain_name": self.project_domain_name,
"permission": self.permission}
def verify_connection(self):
if self.permission == consts.EndpointPermission.ADMIN:
self.clients().verified_keystone()
else:
self.clients().keystone()
def list_services(self):
return self.clients().services()
def clients(self, api_info=None):
return osclients.Clients(self, api_info=api_info,
cache=self._clients_cache)
@credential.configure_builder("openstack")
class OpenStackCredentialBuilder(credential.CredentialBuilder):
"""Builds credentials provided by ExistingCloud config."""
USER_SCHEMA = {
"type": "object",
"oneOf": [
{
"description": "Keystone V2.0",
"properties": {
"username": {"type": "string"},
"password": {"type": "string"},
"tenant_name": {"type": "string"},
},
"required": ["username", "password", "tenant_name"],
"additionalProperties": False
},
{
"description": "Keystone V3.0",
"properties": {
"username": {"type": "string"},
"password": {"type": "string"},
"domain_name": {"type": "string"},
"user_domain_name": {"type": "string"},
"project_name": {"type": "string"},
"project_domain_name": {"type": "string"},
},
"required": ["username", "password", "project_name"],
"additionalProperties": False
}
],
}
CONFIG_SCHEMA = {
"type": "object",
"properties": {
"admin": USER_SCHEMA,
"users": {"type": "array", "items": USER_SCHEMA},
"auth_url": {"type": "string"},
"region_name": {"type": "string"},
# NOTE(andreykurilin): it looks like we do not use endpoint
# var at all
"endpoint": {"type": ["string", "null"]},
"endpoint_type": {
"enum": [consts.EndpointType.ADMIN,
consts.EndpointType.INTERNAL,
consts.EndpointType.PUBLIC,
None]},
"https_insecure": {"type": "boolean"},
"https_cacert": {"type": "string"},
},
"required": ["auth_url", "admin"],
"additionalProperties": False
}
def _create_credential(self, common, user, permission):
cred = OpenStackCredential(
auth_url=common["auth_url"],
username=user["username"],
password=user["password"],
tenant_name=user.get("project_name", user.get("tenant_name")),
permission=permission,
region_name=common.get("region_name"),
endpoint_type=common.get("endpoint_type"),
endpoint=common.get("endpoint"),
domain_name=user.get("domain_name"),
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"))
return cred.to_dict()
def build_credentials(self):
permissions = consts.EndpointPermission
users = [self._create_credential(self.config, user, permissions.USER)
for user in self.config.get("users", [])]
admin = self._create_credential(self.config,
self.config.get("admin"),
permissions.ADMIN)
return {"admin": admin, "users": users}
# NOTE(astudenov): Let's consider moving rally.osclients here

View File

@ -108,9 +108,9 @@ class OpenStackScenario(scenario.Scenario):
@classmethod
def validate(cls, name, config, admin=None, users=None, deployment=None):
if admin:
admin = osclients.Clients(admin)
admin = admin.clients()
if users:
users = [osclients.Clients(user["credential"]) for user in users]
users = [user["credential"].clients() for user in users]
super(OpenStackScenario, cls).validate(
name=name, config=config, admin=admin, users=users,
deployment=deployment)

View File

@ -21,8 +21,6 @@ import six
from six.moves import configparser
from six.moves.urllib import parse
from rally.common import objects
from rally import osclients
from rally.verification import utils
@ -88,7 +86,7 @@ class TempestConfigfileManager(object):
def __init__(self, deployment):
self.credential = deployment.get_credentials_for("openstack")["admin"]
self.clients = osclients.Clients(objects.Credential(**self.credential))
self.clients = self.credential.clients()
self.available_services = self.clients.services().values()
self.conf = configparser.ConfigParser()
@ -100,14 +98,14 @@ class TempestConfigfileManager(object):
def _configure_auth(self, section_name="auth"):
self.conf.set(section_name, "admin_username",
self.credential["username"])
self.credential.username)
self.conf.set(section_name, "admin_password",
self.credential["password"])
self.credential.password)
self.conf.set(section_name, "admin_project_name",
self.credential["tenant_name"])
self.credential.tenant_name)
# Keystone v3 related parameter
self.conf.set(section_name, "admin_domain_name",
self.credential["user_domain_name"] or "Default")
self.credential.user_domain_name or "Default")
# Sahara has two service types: 'data_processing' and 'data-processing'.
# 'data_processing' is deprecated, but it can be used in previous OpenStack
@ -120,9 +118,9 @@ class TempestConfigfileManager(object):
def _configure_identity(self, section_name="identity"):
self.conf.set(section_name, "region",
self.credential["region_name"])
self.credential.region_name)
auth_url = self.credential["auth_url"]
auth_url = self.credential.auth_url
if "/v2" not in auth_url and "/v3" not in auth_url:
auth_version = "v2"
auth_url_v2 = parse.urljoin(auth_url, "/v2.0")
@ -136,9 +134,9 @@ class TempestConfigfileManager(object):
auth_url_v2.replace("/v2.0", "/v3"))
self.conf.set(section_name, "disable_ssl_certificate_validation",
str(self.credential["https_insecure"]))
str(self.credential.https_insecure))
self.conf.set(section_name, "ca_certificates_file",
self.credential["https_cacert"])
self.credential.https_cacert)
# The compute section is configured in context class for Tempest resources.
# Options which are configured there: 'image_ref', 'image_ref_alt',

View File

@ -21,9 +21,7 @@ from six.moves import configparser
from rally.common.i18n import _
from rally.common import logging
from rally.common import objects
from rally import exceptions
from rally import osclients
from rally.plugins.openstack.verification.tempest import config as conf
from rally.plugins.openstack.wrappers import glance
from rally.plugins.openstack.wrappers import network
@ -45,7 +43,7 @@ class TempestContext(context.VerifierContext):
super(TempestContext, self).__init__(ctx)
creds = self.verifier.deployment.get_credentials_for("openstack")
self.clients = osclients.Clients(objects.Credential(**creds["admin"]))
self.clients = creds["admin"].clients()
self.available_services = self.clients.services().values()
self.conf = configparser.ConfigParser()

View File

@ -326,13 +326,9 @@ class TaskEngine(object):
for platform, workloads in platforms.items():
creds = self.deployment.get_credentials_for(platform)
admin = objects.Credential(**creds["admin"])
# TODO(astudenov): move this check to validator of Credential
if platform == "openstack":
from rally import osclients
clients = osclients.Clients(admin)
clients.verified_keystone()
admin = creds["admin"]
if admin:
admin.verify_connection()
workloads_with_users = []
workloads_with_existing_users = []
@ -399,9 +395,6 @@ class TaskEngine(object):
creds = self.deployment.get_credentials_for(namespace)
existing_users = creds["users"]
# TODO(astudenov): use credential plugin in future refactoring
admin = objects.Credential(**creds["admin"])
scenario_context = copy.deepcopy(scenario_cls.get_default_context())
if existing_users and "users" not in ctx:
scenario_context.setdefault("existing_users", existing_users)
@ -411,7 +404,7 @@ class TaskEngine(object):
scenario_context.update(ctx)
context_obj = {
"task": self.task,
"admin": {"credential": admin},
"admin": {"credential": creds["admin"]},
"scenario_name": name,
"config": scenario_context
}

View File

@ -23,11 +23,9 @@ from novaclient import exceptions as nova_exc
import six
from rally.common.i18n import _
from rally.common import objects
from rally.common import yamlutils as yaml
from rally import consts
from rally import exceptions
from rally import osclients
from rally.plugins.openstack.context.nova import flavors as flavors_ctx
from rally.plugins.openstack import types as openstack_types
from rally.task import types
@ -461,8 +459,7 @@ def required_services(config, clients, deployment, *required_services):
if consts.Service.NOVA_NET in required_services:
creds = deployment.get_credentials_for("openstack")
nova = osclients.Clients(
objects.Credential(**creds["admin"])).nova()
nova = creds["admin"].clients().nova()
for service in nova.services.list():
if (service.binary == consts.Service.NOVA_NET and
service.status == "enabled"):
@ -507,8 +504,7 @@ def required_cinder_services(config, clients, deployment, service_name):
:param service_name: Cinder service name
"""
creds = deployment.get_credentials_for("openstack")
admin_client = osclients.Clients(
objects.Credential(**creds["admin"])).cinder()
admin_client = creds["admin"].clients().cinder()
for service in admin_client.services.list():
if (service.binary == six.text_type(service_name) and
@ -529,7 +525,7 @@ def required_clients(config, clients, deployment, *components, **kwargs):
"""
if kwargs.get("admin", False):
creds = deployment.get_credentials_for("openstack")
clients = osclients.Clients(objects.Credential(**creds["admin"]))
clients = creds["admin"].clients()
for client_component in components:
try:

View File

@ -24,10 +24,9 @@ import sys
import six
from rally.cli import cliutils
from rally.common import objects
from rally.common.plugin import discover
from rally import consts
from rally import osclients
from rally.plugins.openstack import credential
def skip_if_service(service):
@ -340,7 +339,7 @@ class CloudResources(object):
"""
def __init__(self, **kwargs):
self.clients = osclients.Clients(objects.Credential(**kwargs))
self.clients = credential.OpenStackCredential(**kwargs).clients()
def _deduplicate(self, lst):
"""Change list duplicates to make all items unique.
@ -426,8 +425,8 @@ def main():
out = subprocess.check_output(["rally", "deployment",
"config"])
config = json.loads(out if six.PY2 else out.decode("utf-8"))
config = config["creds"]["openstack"]
config.update(config.pop("admin"))
del config["type"]
if "users" in config:
del config["users"]

View File

@ -64,7 +64,7 @@ function setUp () {
DEPLOYMENT_CONFIG_FILE=~/.rally/with-existing-users-config
rally deployment config > $DEPLOYMENT_CONFIG_FILE
sed -i '1a "users": [\
sed -i '3a "users": [\
{\
"username": "rally-test-user-1",\
"password": "rally-test-password-1",\

View File

@ -23,8 +23,7 @@ import sys
import uuid
from rally.cli import envutils
from rally.common import objects
from rally import osclients
from rally.plugins.openstack import credential
from rally.ui import utils
LOG = logging.getLogger(__name__)
@ -172,9 +171,9 @@ def main():
config = json.loads(
subprocess.check_output(["rally", "deployment", "config"]))
config = config["creds"]["openstack"]
config.update(config.pop("admin"))
del config["type"]
clients = osclients.Clients(objects.Credential(**config))
clients = credential.OpenStackCredential(**config).clients()
if args.ctx_create_resources:
# If the 'ctx-create-resources' arg is provided, delete images and

View File

@ -25,7 +25,6 @@ import six
from rally import api
from rally.common import db
from rally.common import objects
from rally import plugins
from rally.plugins.openstack.context.keystone import users
from tests.functional import utils
@ -51,7 +50,7 @@ class TestTaskSamples(unittest.TestCase):
return False
@plugins.ensure_plugins_are_loaded
def test_task_samples_is_valid(self):
def test_task_samples_are_valid(self):
rally = utils.Rally(force_new_db=True)
# In TestTaskSamples, Rally API will be called directly (not via
# subprocess), so we need to change database options to temp database.
@ -60,8 +59,7 @@ class TestTaskSamples(unittest.TestCase):
# let's use pre-created users to make TestTaskSamples quicker
deployment = api.Deployment.get("MAIN")
creds = deployment.get_credentials_for("openstack")
admin_cred = objects.Credential(**creds["admin"])
admin_cred = deployment.get_credentials_for("openstack")["admin"]
ctx = {"admin": {"credential": admin_cred},
"task": {"uuid": self.__class__.__name__}}
@ -70,15 +68,16 @@ class TestTaskSamples(unittest.TestCase):
self.addCleanup(user_ctx.cleanup)
config = deployment["config"]
user = copy.copy(config["admin"])
os_creds = config["creds"]["openstack"]
user = copy.copy(os_creds["admin"])
user["username"] = ctx["users"][0]["credential"].username
user["password"] = ctx["users"][0]["credential"].password
if "project_name" in config["admin"]:
if "project_name" in os_creds["admin"]:
# it is Keystone
user["project_name"] = ctx["users"][0]["credential"].tenant_name
else:
user["tenant_name"] = ctx["users"][0]["credential"].tenant_name
config["users"] = [user]
config["creds"]["openstack"]["users"] = [user]
rally("deployment destroy MAIN", write_report=False)
deployment_cfg = os.path.join(rally.tmp_dir, "new_deployment.json")

View File

@ -20,7 +20,6 @@ import mock
from rally.cli.commands import deployment
from rally.cli import envutils
from rally.common import objects
from rally import consts
from rally import exceptions
from tests.unit import fakes
@ -231,14 +230,13 @@ class DeploymentCommandsTestCase(test.TestCase):
def test_show(self, mock_struct, mock_print_list):
deployment_id = "b1a6153e-a314-4cb3-b63b-cf08c1a416c3"
value = {
"admin": {
"auth_url": "url",
"username": "u",
"password": "p",
"tenant_name": "t",
"region_name": "r",
"endpoint_type": consts.EndpointType.INTERNAL
},
"admin": fakes.fake_credential(
auth_url="url",
username="u",
password="p",
tenant_name="t",
region_name="r",
endpoint_type=consts.EndpointType.INTERNAL),
"users": []
}
deployment = self.fake_api.deployment.get.return_value
@ -267,12 +265,12 @@ class DeploymentCommandsTestCase(test.TestCase):
deployment_id = "593b683c-4b16-4b2b-a56b-e162bd60f10b"
self.fake_api.deployment.get.return_value = fakes.FakeDeployment(
uuid=deployment_id,
admin={"auth_url": "fake_auth_url",
"username": "fake_username",
"password": "fake_password",
"tenant_name": "fake_tenant_name",
"endpoint": "fake_endpoint",
"region_name": None})
admin=fakes.fake_credential(**{"auth_url": "fake_auth_url",
"username": "fake_username",
"password": "fake_password",
"tenant_name": "fake_tenant_name",
"endpoint": "fake_endpoint",
"region_name": None}))
with mock.patch("rally.cli.commands.deployment.open", mock.mock_open(),
create=True) as mock_file:
@ -304,7 +302,7 @@ class DeploymentCommandsTestCase(test.TestCase):
self.fake_api.deployment.get.return_value = fakes.FakeDeployment(
uuid=deployment_id,
admin={
admin=fakes.fake_credential(**{
"auth_url": "http://localhost:5000/v3",
"username": "fake_username",
"password": "fake_password",
@ -312,7 +310,7 @@ class DeploymentCommandsTestCase(test.TestCase):
"endpoint": "fake_endpoint",
"region_name": None,
"user_domain_name": "fake_user_domain",
"project_domain_name": "fake_project_domain"})
"project_domain_name": "fake_project_domain"}))
with mock.patch("rally.cli.commands.deployment.open", mock.mock_open(),
create=True) as mock_file:
@ -342,9 +340,10 @@ class DeploymentCommandsTestCase(test.TestCase):
@mock.patch("rally.common.fileutils.update_globals_file")
def test_use_by_name(self, mock_update_globals_file,
mock__update_openrc_deployment_file):
fake_credential = fakes.fake_credential(foo="fake_credentials")
fake_deployment = fakes.FakeDeployment(
uuid="fake_uuid",
admin="fake_credentials")
admin=fake_credential)
self.fake_api.deployment.list.return_value = [fake_deployment]
self.fake_api.deployment.get.return_value = fake_deployment
status = self.deployment.use(self.fake_api, deployment="fake_name")
@ -353,7 +352,7 @@ class DeploymentCommandsTestCase(test.TestCase):
mock_update_globals_file.assert_called_once_with(
envutils.ENV_DEPLOYMENT, "fake_uuid")
mock__update_openrc_deployment_file.assert_called_once_with(
"fake_uuid", "fake_credentials")
"fake_uuid", {"foo": "fake_credentials"})
def test_deployment_not_found(self):
deployment_id = "e87e4dca-b515-4477-888d-5f6103f13b42"
@ -364,9 +363,9 @@ class DeploymentCommandsTestCase(test.TestCase):
@mock.patch("rally.cli.commands.deployment.cliutils.print_list")
def test_deployment_check(self, mock_print_list):
deployment_id = "e87e4dca-b515-4477-888d-5f6103f13b42"
sample_credential = objects.Credential("http://192.168.1.1:5000/v2.0/",
"admin",
"adminpass").to_dict()
sample_credential = fakes.fake_credential(
auth_url="http://192.168.1.1:5000/v2.0/",
username="admin", password="adminpass")
deployment = {"admin": sample_credential,
"users": [sample_credential]}
self.fake_api.deployment.get.return_value = deployment
@ -388,10 +387,9 @@ class DeploymentCommandsTestCase(test.TestCase):
def test_deployment_check_raise(self):
deployment_id = "e87e4dca-b515-4477-888d-5f6103f13b42"
sample_credential = objects.Credential("http://192.168.1.1:5000/v2.0/",
"admin",
"adminpass").to_dict()
sample_credential["not-exist-key"] = "error"
sample_credential = fakes.fake_credential(
auth_url="http://192.168.1.1:5000/v2.0/",
username="admin", password="adminpass")
deployment = self.fake_api.deployment.get.return_value
deployment.get_credentials_for.return_value = {
"admin": sample_credential, "users": []}

View File

@ -18,6 +18,8 @@ from rally import consts
from tests.unit import test
# TODO(astudenov): remove this class in future releases
class CredentialTestCase(test.TestCase):
def test_to_dict(self):

View File

@ -117,8 +117,10 @@ class DeploymentTestCase(test.TestCase):
{"config": {"opt": "val"}},
)
@mock.patch("rally.deployment.credential.get")
@mock.patch("rally.common.objects.deploy.db.deployment_update")
def test_update_credentials(self, mock_deployment_update):
def test_update_credentials(self, mock_deployment_update,
mock_credential_get):
mock_deployment_update.return_value = self.deployment
deploy = objects.Deployment(deployment=self.deployment)
credentials = {"foo": [{"admin": {"fake_admin": True},
@ -132,23 +134,38 @@ class DeploymentTestCase(test.TestCase):
"users": [{"fake_user": True}]}]}
})
def test_get_credentials_for(self):
@mock.patch("rally.deployment.credential.get")
def test_get_credentials_for(self, mock_credential_get):
credential_cls = mock_credential_get.return_value
credential_inst = credential_cls.return_value
credentials = {"foo": [{"admin": {"fake_admin": True},
"users": [{"fake_user": True}]}]}
self.deployment["credentials"] = credentials
deploy = objects.Deployment(deployment=self.deployment)
creds = deploy.get_credentials_for("foo")
self.assertEqual(credentials["foo"][0], creds)
def test_get_deprecated(self):
mock_credential_get.assert_called_once_with("foo")
credential_cls.assert_has_calls((
mock.call(fake_admin=True),
mock.call(fake_user=True),
))
self.assertEqual({"admin": credential_inst,
"users": [credential_inst]}, creds)
@mock.patch("rally.deployment.credential.get")
def test_get_deprecated(self, mock_credential_get):
credential_cls = mock_credential_get.return_value
credential_inst = credential_cls.return_value
credentials = {"openstack": [{"admin": {"fake_admin": True},
"users": [{"fake_user": True}]}]}
self.deployment["credentials"] = credentials
deploy = objects.Deployment(deployment=self.deployment)
self.assertEqual(credentials["openstack"][0]["admin"], deploy["admin"])
self.assertEqual(credentials["openstack"][0]["users"], deploy["users"])
self.assertEqual(credential_inst, deploy["admin"])
self.assertEqual([credential_inst], deploy["users"])
def test_update_empty_credentials(self):
deploy = objects.Deployment(deployment=self.deployment)

View File

@ -16,6 +16,7 @@
import jsonschema
import mock
from rally import consts
from rally.deployment.engines import devstack
from tests.unit import test
@ -77,14 +78,12 @@ class DevstackEngineTestCase(test.TestCase):
@mock.patch("rally.deployment.engines.devstack.get_updated_server")
@mock.patch("rally.deployment.engines.devstack.get_script")
@mock.patch("rally.deployment.serverprovider.provider.Server")
@mock.patch("rally.deployment.engines.devstack.objects.Credential")
def test_deploy(self, mock_credential, mock_server, mock_get_script,
def test_deploy(self, mock_server, mock_get_script,
mock_get_updated_server, mock_engine_get_provider):
mock_engine_get_provider.return_value = fake_provider = (
mock.Mock()
)
server = mock.Mock(host="host")
mock_credential.return_value.to_dict.return_value = "fake_credential"
mock_get_updated_server.return_value = ds_server = mock.Mock()
mock_get_script.return_value = "fake_script"
server.get_credentials.return_value = "fake_credentials"
@ -92,12 +91,16 @@ class DevstackEngineTestCase(test.TestCase):
with mock.patch.object(self.engine, "deployment") as mock_deployment:
credentials = self.engine.deploy()
self.assertEqual(
{"openstack": [{"admin": "fake_credential", "users": []}]},
{"openstack": [{
"admin": {
"auth_url": "http://host:5000/v2.0/",
"username": "admin",
"password": "secret",
"permission": consts.EndpointPermission.ADMIN,
"tenant_name": "admin",
},
"users": []}]},
credentials)
mock_credential.assert_called_once_with(
"http://host:5000/v2.0/", "admin", "secret", "admin", "admin")
mock_credential.return_value.to_dict.assert_called_once_with(
include_permission=True)
mock_deployment.add_resource.assert_called_once_with(
info="fake_credentials",
provider_name="DevstackEngine",

View File

@ -61,15 +61,35 @@ class TestExistingCloud(test.TestCase):
"user_domain_name": "Default",
}
}
},
"abstract": {
"config": {
"type": "ExistingCloud",
"creds": {
"openstack": {
"auth_url": "http://example.net:5000/v2.0/",
"region_name": "RegionOne",
"endpoint_type": consts.EndpointType.INTERNAL,
"https_insecure": False,
"https_cacert": "cacert",
"admin": {
"username": "admin",
"password": "myadminpass",
"tenant_name": "demo"
}
}
}
}
}
}
@ddt.data("v2.0", "v3")
@ddt.data("v2.0", "v3", "abstract")
def test_init_and_valid_config(self, keystone_version):
engine = existing.ExistingCloud(self.deployments[keystone_version])
engine.validate()
@ddt.data("v2.0", "v3")
@ddt.data("v2.0", "v3", "abstract")
def test_invalid_config(self, keystone_version):
deployment = self.deployments[keystone_version]
deployment["config"]["admin"] = 42
@ -77,7 +97,7 @@ class TestExistingCloud(test.TestCase):
self.assertRaises(jsonschema.ValidationError,
engine.validate)
@ddt.data("v2.0", "v3")
@ddt.data("v2.0", "v3", "abstract")
def test_additional_vars(self, keystone_version):
deployment = self.deployments[keystone_version]
deployment["extra"] = {}
@ -122,11 +142,36 @@ class TestExistingCloud(test.TestCase):
self.assertEqual(admin_credential, actual_credentials)
self.assertEqual([], credentials["users"])
@ddt.data("v2.0", "v3")
def test_deploy_abstract(self):
deployment = self.deployments["abstract"]
engine = existing.ExistingCloud(deployment)
credentials = engine.deploy()
self.assertEqual(1, len(credentials))
self.assertIn("openstack", credentials)
self.assertEqual(1, len(credentials["openstack"]))
credentials = credentials["openstack"][0]
self.assertEqual([], credentials["users"])
admin_credential = credentials["admin"]
self.assertEqual({
"auth_url": "http://example.net:5000/v2.0/",
"domain_name": None,
"endpoint": None,
"endpoint_type": "internal",
"https_cacert": "cacert",
"https_insecure": False,
"password": "myadminpass",
"permission": "admin",
"project_domain_name": None,
"region_name": "RegionOne",
"tenant_name": "demo",
"user_domain_name": None,
"username": "admin"}, admin_credential)
@ddt.data("v2.0", "v3", "abstract")
def test_cleanup(self, keystone_version):
existing.ExistingCloud(self.deployments[keystone_version]).cleanup()
@ddt.data("v2.0", "v3")
@ddt.data("v2.0", "v3", "abstract")
def test_is_in_factory(self, keystone_version):
name = self.deployments[keystone_version]["config"]["type"]
engine = deploy_engine.Engine.get_engine(

View File

@ -27,6 +27,7 @@ from tests.unit import fakes
from tests.unit import test
MOD_NAME = "rally.deployment.serverprovider.providers.openstack"
OS_CREDENTIAL_NAME = "rally.plugins.openstack.credential"
OSProvider = provider.OpenStackProvider
@ -82,11 +83,10 @@ class OpenStackProviderTestCase(test.TestCase):
self.clients.nova = mock.MagicMock(return_value=self.nova_client)
@mock.patch(
"rally.deployment.serverprovider.providers.openstack.osclients")
def test_openstack_provider_init(self, mock_osclients):
@mock.patch("rally.osclients.Clients")
def test_openstack_provider_init(self, mock_clients):
cfg = self._get_valid_config()
mock_osclients.Clients = mock.MagicMock(return_value=FakeOSClients())
mock_clients.return_value = FakeOSClients()
os_provider = OSProvider(mock.MagicMock(), cfg)
self.assertEqual("nova", os_provider.nova)
self.assertEqual("glance", os_provider.glance)
@ -98,60 +98,53 @@ class OpenStackProviderTestCase(test.TestCase):
provider = OSProvider(mock.MagicMock(), cfg)
self.assertIsNone(provider.glance)
@mock.patch(
"rally.deployment.serverprovider.providers.openstack.osclients")
@mock.patch("rally.osclients.Clients")
def test_openstack_provider_init_with_invalid_conf_no_user(self,
mock_osclients):
mock_clients):
cfg = self._get_valid_config()
cfg.pop("user")
self.assertRaises(jsonschema.ValidationError, OSProvider,
mock.MagicMock(), cfg)
@mock.patch(
"rally.deployment.serverprovider.providers.openstack.osclients")
@mock.patch("rally.osclients.Clients")
def test_openstack_provider_init_with_invalid_conf_no_url(self,
mock_osclients):
mock_clients):
cfg = self._get_valid_config()
del cfg["image"]["url"]
del cfg["image"]["checksum"]
self.assertRaises(jsonschema.ValidationError, OSProvider,
mock.MagicMock(), cfg)
@mock.patch(
"rally.deployment.serverprovider.providers.openstack.osclients")
@mock.patch("rally.osclients.Clients")
def test_openstack_provider_init_with_invalid_conf_extra_key(
self, mock_osclients):
self, mock_clients):
cfg = self._get_valid_config()
cfg["aaaaa"] = "bbbbb"
self.assertRaises(jsonschema.ValidationError, OSProvider,
mock.MagicMock(), cfg)
@mock.patch(
"rally.deployment.serverprovider.providers.openstack.osclients")
@mock.patch("rally.osclients.Clients")
def test_openstack_provider_init_with_invalid_conf_flavor_(self,
mock_osclients):
mock_clients):
cfg = self._get_valid_config()["user"] = 1111
self.assertRaises(jsonschema.ValidationError, OSProvider,
mock.MagicMock(), cfg)
@mock.patch(
"rally.deployment.serverprovider.providers.openstack.osclients")
@mock.patch("rally.osclients.Clients")
def test_openstack_provider_with_valid_config(self,
mock_osclients):
mock_clients):
cfg = self._get_valid_config()
OSProvider(mock.MagicMock(), cfg)
@mock.patch(
"rally.deployment.serverprovider.providers.openstack.osclients")
def test_openstack_provider_with_valid_config_uuid(self, mock_osclients):
@mock.patch("rally.osclients.Clients")
def test_openstack_provider_with_valid_config_uuid(self, mock_clients):
cfg = self._get_valid_config()
cfg["image"] = dict(uuid="289D7A51-1A0C-43C4-800D-706EA8A3CDF3")
OSProvider(mock.MagicMock(), cfg)
@mock.patch(
"rally.deployment.serverprovider.providers.openstack.osclients")
@mock.patch("rally.osclients.Clients")
def test_openstack_provider_with_valid_config_checksum(self,
mock_osclients):
mock_clients):
cfg = self._get_valid_config()
cfg["image"] = dict(checksum="checksum")
OSProvider(mock.MagicMock(), cfg)
@ -194,9 +187,9 @@ class OpenStackProviderTestCase(test.TestCase):
@mock.patch("time.sleep")
@mock.patch(MOD_NAME + ".provider.Server")
@mock.patch(MOD_NAME + ".osclients")
@mock.patch("rally.osclients.Clients")
@mock.patch(MOD_NAME + ".utils")
def test_create_servers(self, mock_utils, mock_osclients,
def test_create_servers(self, mock_utils, mock_clients,
mock_server, mock_sleep):
fake_keypair = mock.Mock()
fake_keypair.name = "fake_key_name"
@ -229,41 +222,40 @@ class OpenStackProviderTestCase(test.TestCase):
nics="fake_nics", key_name="fake_key_name", config_drive=False,
security_groups=[provider.sg.name])
@mock.patch(MOD_NAME + ".osclients")
def test_get_image_found_by_checksum(self, mock_osclients):
@mock.patch("rally.osclients.Clients")
def test_get_image_found_by_checksum(self, mock_clients):
self._init_mock_clients()
mock_osclients.Clients = mock.MagicMock(return_value=self.clients)
mock_clients.return_value = self.clients
prov = OSProvider(mock.MagicMock(), self._get_valid_config())
image_uuid = prov.get_image_uuid()
self.assertEqual(image_uuid, "fake-uuid")
@mock.patch(MOD_NAME + ".osclients")
def test_get_image_download(self, mock_osclients):
@mock.patch("rally.osclients.Clients")
def test_get_image_download(self, mock_clients):
self._init_mock_clients()
self.glance_client.images.list = mock.Mock(return_value=[])
mock_osclients.Clients = mock.MagicMock(return_value=self.clients)
mock_clients.return_value = self.clients
prov = OSProvider(mock.MagicMock(), self._get_valid_config())
image_uuid = prov.get_image_uuid()
self.assertEqual(image_uuid, "fake-uuid")
@mock.patch(MOD_NAME + ".osclients")
def test_get_image_no_glance_exception(
self, mock_osclients):
@mock.patch("rally.osclients.Clients")
def test_get_image_no_glance_exception(self, mock_clients):
prov = OSProvider(mock.MagicMock(), self._get_valid_config())
prov.glance = None
self.assertRaises(exceptions.InvalidConfigException,
prov.get_image_uuid)
@mock.patch(MOD_NAME + ".osclients")
def test_get_image_from_uuid_no_glance(self, mock_osclients):
@mock.patch("rally.osclients.Clients")
def test_get_image_from_uuid_no_glance(self, mock_clients):
conf = self._get_valid_config()
conf["image"]["uuid"] = "EC7A1DB7-C5BD-49A2-8066-613809CB22F5"
prov = OSProvider(mock.MagicMock(), conf)
prov.glance = True
self.assertEqual(conf["image"]["uuid"], prov.get_image_uuid())
@mock.patch(MOD_NAME + ".osclients")
def test_destroy_servers(self, mock_osclients):
@mock.patch("rally.osclients.Clients")
def test_destroy_servers(self, mock_clients):
prov = OSProvider(mock.MagicMock(), self._get_valid_config())
prov.resources.get_all.side_effect = [
[fakes.FakeResource(

View File

@ -0,0 +1,84 @@
# Copyright 2017: 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 jsonschema
from rally.deployment import credential
from tests.unit import test
@credential.configure("foo")
class FooCredential(credential.Credential):
def __init__(self, bar=None):
self.bar = bar
def to_dict(self):
return {"bar": self.bar}
def verify_connection(self):
pass
def list_services(self):
return {"foo": "foo-type"}
class CredentialTestCase(test.TestCase):
def setUp(self):
super(CredentialTestCase, self).setUp()
self.cred_cls = credential.get("foo")
def test_configure_and_get(self):
self.assertIs(FooCredential, self.cred_cls)
def test_foo_credential(self):
cred = self.cred_cls(bar=42)
cred.verify_connection()
self.assertEqual({"bar": 42}, cred.to_dict())
self.assertEqual({"foo": "foo-type"}, cred.list_services())
@credential.configure_builder("foo")
class FooCredentialBuilder(credential.CredentialBuilder):
CONFIG_SCHEMA = {
"type": "object",
"properties": {
"bar": {"type": "integer"}
},
"required": ["bar"],
"additionalProperties": False
}
def build_credentials(self):
return {"admin": {"bar": self.config["bar"]}, "users": []}
class CredentialBuilderTestCase(test.TestCase):
def setUp(self):
super(CredentialBuilderTestCase, self).setUp()
self.cred_builder_cls = credential.get_builder("foo")
def test_configure_and_get(self):
self.assertIs(FooCredentialBuilder, self.cred_builder_cls)
def test_validate(self):
self.cred_builder_cls.validate({"bar": 42})
def test_validate_error(self):
self.assertRaises(jsonschema.ValidationError,
self.cred_builder_cls.validate,
{"bar": "spam"})

View File

@ -151,7 +151,7 @@ class LxcEngineTestCase(test.TestCase):
self.assertEqual(1, len(credentials["openstack"]))
credential = credentials["openstack"][0]
self.assertIsInstance(credential["admin"], dict)
self.assertIsNone(credential["admin"])
self.assertEqual([], credential["users"])
lxc_host_calls = [
mock.call(fake_servers[0], {"network": "10.128.128.0/28",

View File

@ -115,11 +115,12 @@ class ConfigSchemasTestCase(test.TestCase):
self.fail(p, schema, ("Found unexpected key(s) for integer/number "
"type: %s." % ", ".join(unexpected_keys)))
def _check_simpliest_types(self, p, schema):
def _check_simpliest_types(self, p, schema, type_name):
unexpected_keys = set(schema.keys()) - {"type", "description"}
if unexpected_keys:
self.fail(p, schema, ("Found unexpected key(s) for boolean type: "
"%s." % ", ".join(unexpected_keys)))
self.fail(p, schema, ("Found unexpected key(s) for %s type: "
"%s." % (type_name,
", ".join(unexpected_keys))))
def _check_item(self, p, schema, definitions):
if "type" in schema or "anyOf" in schema or "oneOf" in schema:
@ -135,7 +136,9 @@ class ConfigSchemasTestCase(test.TestCase):
elif schema["type"] in ("number", "integer"):
self._check_number_type(p, schema)
elif schema["type"] in ("boolean", "null"):
self._check_simpliest_types(p, schema)
self._check_simpliest_types(p, schema, schema["type"])
elif isinstance(schema["type"], list):
self._check_simpliest_types(p, schema, "mixed")
else:
self.fail(p, schema,
"Wrong type is used: %s" % schema["type"])

View File

@ -28,7 +28,6 @@ import six
from swiftclient import exceptions as swift_exceptions
from rally import api
from rally.common import objects
from rally.common import utils as rally_utils
from rally import consts
from rally.task import context
@ -83,6 +82,14 @@ def setup_dict(data, required=None, defaults=None):
return defaults
def fake_credential(**config):
m = mock.Mock()
m.to_dict.return_value = config
for key, value in config.items():
setattr(m, key, value)
return m
class FakeResource(object):
def __init__(self, manager=None, name=None, status="ACTIVE", items=None,
@ -1594,11 +1601,11 @@ class FakeClients(object):
self._ec2 = None
self._senlin = None
self._watcher = None
self._credential = credential_ or objects.Credential(
"http://fake.example.org:5000/v2.0/",
"fake_username",
"fake_password",
"fake_tenant_name")
self._credential = credential_ or fake_credential(
auth_url="http://fake.example.org:5000/v2.0/",
username="fake_username",
password="fake_password",
tenant_name="fake_tenant_name")
def keystone(self, version=None):
if not self._keystone:
@ -1806,11 +1813,19 @@ class FakeUserContext(FakeContext):
admin = {
"id": "adminuuid",
"credential": objects.Credential("aurl", "aname", "apwd", "atenant")
"credential": fake_credential(
auth_url="aurl",
username="aname",
password="apwd",
tenant_name="atenant")
}
user = {
"id": "uuid",
"credential": objects.Credential("url", "name", "pwd", "tenant"),
"credential": fake_credential(
auth_url="url",
username="name",
password="pwd",
tenant_name="tenant"),
"tenant_id": "uuid"
}
tenants = {"uuid": {"name": "tenant"}}

View File

@ -31,86 +31,19 @@ class SeekAndDestroyTestCase(test.TestCase):
# clear out the client cache
manager.SeekAndDestroy.cache = {}
@mock.patch("%s.osclients.Clients" % BASE,
side_effect=[mock.MagicMock(), mock.MagicMock()])
def test__get_cached_client(self, mock_clients):
destroyer = manager.SeekAndDestroy(None, None, None)
self.assertIsNone(destroyer._get_cached_client(None))
users = [{"credential": "a"}, {"credential": "b"}]
self.assertEqual(destroyer._get_cached_client(users[0]),
destroyer._get_cached_client(users[0]))
# ensure that cache is used
self.assertItemsEqual(mock_clients.call_args_list,
[mock.call("a", api_info=None)])
mock_clients.reset_mock()
self.assertEqual(destroyer._get_cached_client(users[1]),
destroyer._get_cached_client(users[1]))
self.assertItemsEqual(mock_clients.call_args_list,
[mock.call("b", api_info=None)])
mock_clients.reset_mock()
self.assertNotEqual(destroyer._get_cached_client(users[0]),
destroyer._get_cached_client(users[1]))
self.assertFalse(mock_clients.called)
@mock.patch("%s.osclients.Clients" % BASE,
side_effect=[mock.MagicMock(), mock.MagicMock()])
def test__get_cached_client_shared_cache(self, mock_clients):
# ensure that cache is shared between SeekAndDestroy objects
destroyer1 = manager.SeekAndDestroy(None, None, None)
destroyer2 = manager.SeekAndDestroy(None, None, None)
user = {"credential": "a"}
self.assertEqual(destroyer1._get_cached_client(user),
destroyer2._get_cached_client(user))
self.assertItemsEqual(mock_clients.call_args_list,
[mock.call("a", api_info=None)])
@mock.patch("%s.osclients.Clients" % BASE,
side_effect=[mock.MagicMock(), mock.MagicMock()])
def test__get_cached_client_shared_cache_api_versions(self, mock_clients):
# ensure that cache is shared between SeekAndDestroy objects
# with matching api_versions dicts
def test__get_cached_client(self):
api_versions = {"cinder": {"version": "1", "service_type": "volume"}}
destroyer1 = manager.SeekAndDestroy(None, None, None,
api_versions=api_versions)
destroyer2 = manager.SeekAndDestroy(None, None, None,
api_versions=api_versions)
destroyer = manager.SeekAndDestroy(None, None, None,
api_versions=api_versions)
cred = mock.Mock()
user = {"credential": cred}
user = {"credential": "a"}
clients = destroyer._get_cached_client(user)
self.assertIs(cred.clients.return_value, clients)
cred.clients.assert_called_once_with(api_info=api_versions)
self.assertEqual(destroyer1._get_cached_client(user),
destroyer2._get_cached_client(user))
self.assertItemsEqual(mock_clients.call_args_list,
[mock.call("a", api_info=api_versions)])
@mock.patch("%s.osclients.Clients" % BASE,
side_effect=[mock.MagicMock(), mock.MagicMock()])
def test__get_cached_client_no_cache_api_versions(self, mock_clients):
# ensure that cache is not shared between SeekAndDestroy
# objects with different api_versions dicts
api_versions = [
{"cinder": {"version": "1", "service_type": "volume"}},
{"cinder": {"version": "2", "service_type": "volumev2"}}
]
destroyer1 = manager.SeekAndDestroy(None, None, None,
api_versions=api_versions[0])
destroyer2 = manager.SeekAndDestroy(None, None, None,
api_versions=api_versions[1])
user = {"credential": "a"}
self.assertNotEqual(destroyer1._get_cached_client(user),
destroyer2._get_cached_client(user))
self.assertItemsEqual(mock_clients.call_args_list,
[mock.call("a", api_info=api_versions[0]),
mock.call("a", api_info=api_versions[1])])
self.assertIsNone(destroyer._get_cached_client(None))
@mock.patch("%s.LOG" % BASE)
def test__delete_single_resource(self, mock_log):

View File

@ -22,9 +22,7 @@ CTX = "rally.plugins.openstack.context"
class ExistingUserTestCase(test.TestCase):
@mock.patch("%s.keystone.existing_users.osclients.Clients" % CTX)
@mock.patch("%s.keystone.existing_users.objects.Credential" % CTX)
def test_setup(self, mock_credential, mock_clients):
def test_setup(self):
user1 = mock.MagicMock(tenant_id="1", user_id="1",
tenant_name="proj", username="usr")
user2 = mock.MagicMock(tenant_id="1", user_id="2",
@ -48,8 +46,10 @@ class ExistingUserTestCase(test.TestCase):
self.PROJECT_ID_COUNT += 1
return user_list[self.PROJECT_ID_COUNT - 1].tenant_id
mock_clients.return_value.keystone.auth_ref = AuthRef()
mock_credential.side_effect = user_list
auth_ref = AuthRef()
user1.clients.return_value.keystone.auth_ref = auth_ref
user2.clients.return_value.keystone.auth_ref = auth_ref
user3.clients.return_value.keystone.auth_ref = auth_ref
context = {
"task": mock.MagicMock(),

View File

@ -15,10 +15,10 @@
import mock
from rally.common import objects
from rally import consts
from rally import exceptions
from rally.plugins.openstack.context.keystone import users
from rally.plugins.openstack import credential as oscredential
from tests.unit import test
CTX = "rally.plugins.openstack.context.keystone.users"
@ -274,16 +274,17 @@ class UserGeneratorTestCase(test.ScenarioTestCase):
def test_users_and_tenants_in_context(self, mock_identity):
identity_service = mock_identity.Identity.return_value
credential = objects.Credential("foo_url", "foo", "foo_pass",
https_insecure=True,
https_cacert="cacert")
credential = oscredential.OpenStackCredential(
"foo_url", "foo", "foo_pass",
https_insecure=True,
https_cacert="cacert")
tmp_context = dict(self.context)
tmp_context["config"]["users"] = {"tenants": 1,
"users_per_tenant": 2,
"resource_management_workers": 1}
tmp_context["admin"]["credential"] = credential
credential_dict = credential.to_dict(False)
credential_dict = credential.to_dict()
user_list = [mock.MagicMock(id="id_%d" % i)
for i in range(self.users_num)]
identity_service.create_user.side_effect = user_list
@ -302,7 +303,7 @@ class UserGeneratorTestCase(test.ScenarioTestCase):
self.assertEqual(set(["id", "credential", "tenant_id"]),
set(user.keys()))
user_credential_dict = user["credential"].to_dict(False)
user_credential_dict = user["credential"].to_dict()
excluded_keys = ["auth_url", "username", "password",
"tenant_name", "region_name",
@ -323,7 +324,7 @@ class UserGeneratorTestCase(test.ScenarioTestCase):
@mock.patch("%s.identity" % CTX)
def test_users_contains_correct_endpoint_type(self, mock_identity):
credential = objects.Credential(
credential = oscredential.OpenStackCredential(
"foo_url", "foo", "foo_pass",
endpoint_type=consts.EndpointType.INTERNAL)
config = {
@ -346,7 +347,8 @@ class UserGeneratorTestCase(test.ScenarioTestCase):
@mock.patch("%s.identity" % CTX)
def test_users_contains_default_endpoint_type(self, mock_identity):
credential = objects.Credential("foo_url", "foo", "foo_pass")
credential = oscredential.OpenStackCredential(
"foo_url", "foo", "foo_pass")
config = {
"config": {
"users": {

View File

@ -14,8 +14,8 @@
import mock
from rally.common import objects
from rally.plugins.openstack.context.sahara import sahara_output_data_sources
from rally.plugins.openstack import credential as oscredential
from rally.plugins.openstack.scenarios.sahara import utils as sahara_utils
from tests.unit import test
@ -26,8 +26,8 @@ class SaharaOutputDataSourcesTestCase(test.ScenarioTestCase):
def setUp(self):
super(SaharaOutputDataSourcesTestCase, self).setUp()
fake_dict = objects.Credential("http://fake.example.org:5000/v2.0/",
"user", "passwd")
fake_dict = oscredential.OpenStackCredential(
"http://fake.example.org:5000/v2.0/", "user", "passwd")
self.tenants_num = 2
self.users_per_tenant = 2
self.users = self.tenants_num * self.users_per_tenant

View File

@ -0,0 +1,149 @@
# Copyright 2017: 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 jsonschema
import mock
from rally import consts
from rally.deployment import credential
from tests.unit import test
class OpenStackCredentialTestCase(test.TestCase):
def setUp(self):
super(OpenStackCredentialTestCase, self).setUp()
cred_cls = credential.get("openstack")
self.credential = cred_cls(
"foo_url", "foo_user", "foo_password",
tenant_name="foo_tenant",
permission=consts.EndpointPermission.ADMIN)
def test_to_dict(self):
self.assertEqual({"auth_url": "foo_url",
"username": "foo_user",
"password": "foo_password",
"tenant_name": "foo_tenant",
"region_name": None,
"domain_name": None,
"endpoint": None,
"permission": consts.EndpointPermission.ADMIN,
"endpoint_type": None,
"https_insecure": False,
"https_cacert": None,
"project_domain_name": None,
"user_domain_name": None}, self.credential.to_dict())
@mock.patch("rally.osclients.Clients")
def test_verify_connection_admin(self, mock_clients):
self.credential.verify_connection()
mock_clients.assert_called_once_with(
self.credential, api_info=None, cache={})
mock_clients.return_value.verified_keystone.assert_called_once_with()
@mock.patch("rally.osclients.Clients")
def test_verify_connection_user(self, mock_clients):
self.credential.permission = consts.EndpointPermission.USER
self.credential.verify_connection()
mock_clients.assert_called_once_with(
self.credential, api_info=None, cache={})
mock_clients.return_value.keystone.assert_called_once_with()
@mock.patch("rally.osclients.Clients")
def test_list_services(self, mock_clients):
result = self.credential.list_services()
mock_clients.assert_called_once_with(
self.credential, api_info=None, cache={})
mock_clients.return_value.services.assert_called_once_with()
self.assertIs(mock_clients.return_value.services.return_value, result)
@mock.patch("rally.osclients.Clients")
def test_clients(self, mock_clients):
clients = self.credential.clients(api_info="fake_info")
mock_clients.assert_called_once_with(
self.credential, api_info="fake_info", cache={})
self.assertIs(mock_clients.return_value, clients)
class OpenStackCredentialBuilderTestCase(test.TestCase):
def setUp(self):
super(OpenStackCredentialBuilderTestCase, self).setUp()
self.config = {
"auth_url": "http://example.net:5000/v2.0/",
"region_name": "RegionOne",
"endpoint_type": consts.EndpointType.INTERNAL,
"https_insecure": False,
"https_cacert": "cacert",
"admin": {
"username": "admin",
"password": "myadminpass",
"tenant_name": "demo"
},
"users": [
{
"username": "user1",
"password": "userpass",
"tenant_name": "demo"
}
]
}
self.cred_builder_cls = credential.get_builder("openstack")
def test_validate(self):
self.cred_builder_cls.validate(self.config)
def test_validate_error(self):
self.assertRaises(jsonschema.ValidationError,
self.cred_builder_cls.validate,
{"foo": "bar"})
def test_build_credentials(self):
creds_builder = self.cred_builder_cls(self.config)
creds = creds_builder.build_credentials()
self.assertEqual({
"admin": {
"auth_url": "http://example.net:5000/v2.0/",
"username": "admin",
"password": "myadminpass",
"permission": consts.EndpointPermission.ADMIN,
"domain_name": None,
"endpoint": None,
"endpoint_type": consts.EndpointType.INTERNAL,
"https_cacert": "cacert",
"https_insecure": False,
"project_domain_name": None,
"region_name": "RegionOne",
"tenant_name": "demo",
"user_domain_name": None,
},
"users": [
{
"auth_url": "http://example.net:5000/v2.0/",
"username": "user1",
"password": "userpass",
"permission": consts.EndpointPermission.USER,
"domain_name": None,
"endpoint": None,
"endpoint_type": consts.EndpointType.INTERNAL,
"https_cacert": "cacert",
"https_insecure": False,
"project_domain_name": None,
"region_name": "RegionOne",
"tenant_name": "demo",
"user_domain_name": None,
}
]
}, creds)

View File

@ -18,6 +18,7 @@ import mock
from oslotest import mockpatch
from rally.plugins.openstack import scenario as base_scenario
from tests.unit import fakes
from tests.unit import test
@ -130,27 +131,21 @@ class OpenStackScenarioTestCase(test.TestCase):
@mock.patch("rally.task.scenario.Scenario.validate")
def test_validate(self, mock_scenario_validate):
cred1 = mock.Mock()
cred2 = mock.Mock()
cred3 = mock.Mock()
self.osclients.mock.side_effect = [cred1, cred2, cred3]
cred1 = fakes.fake_credential(foo="bar1")
cred2 = fakes.fake_credential(foo="bar2")
cred3 = fakes.fake_credential(foo="bar3")
base_scenario.OpenStackScenario.validate(
name="foo_name",
config="foo_config",
admin="foo_admin",
users=[{"credential": "foo_user1"},
{"credential": "foo_user2"}],
admin=cred1,
users=[{"credential": cred2},
{"credential": cred3}],
deployment=None)
mock_scenario_validate.assert_called_once_with(
name="foo_name",
config="foo_config",
admin=cred1,
users=[cred2, cred3],
admin=cred1.clients.return_value,
users=[cred2.clients.return_value, cred3.clients.return_value],
deployment=None)
self.osclients.mock.assert_has_calls([
mock.call("foo_admin"),
mock.call("foo_user1"),
mock.call("foo_user2"),
])

View File

@ -25,20 +25,17 @@ from tests.unit import test
CONF = cfg.CONF
CREDS = {
"admin": {
"username": "admin",
"tenant_name": "admin",
"password": "admin-12345",
"auth_url": "http://test:5000/v2.0/",
"permission": "admin",
"region_name": "test",
"https_insecure": False,
"https_cacert": "/path/to/cacert/file",
"user_domain_name": "admin",
"project_domain_name": "admin"
},
"uuid": "fake_deployment"
CRED = {
"username": "admin",
"tenant_name": "admin",
"password": "admin-12345",
"auth_url": "http://test:5000/v2.0/",
"permission": "admin",
"region_name": "test",
"https_insecure": False,
"https_cacert": "/path/to/cacert/file",
"user_domain_name": "admin",
"project_domain_name": "admin"
}
PATH = "rally.plugins.openstack.verification.tempest.config"
@ -49,10 +46,8 @@ class TempestConfigfileManagerTestCase(test.TestCase):
def setUp(self):
super(TempestConfigfileManagerTestCase, self).setUp()
mock.patch("rally.osclients.Clients").start()
deployment = fakes.FakeDeployment(**CREDS)
deployment = fakes.FakeDeployment(uuid="fake_deployment",
admin=fakes.fake_credential(**CRED))
self.tempest = config.TempestConfigfileManager(deployment)
def test__configure_auth(self):
@ -60,10 +55,10 @@ class TempestConfigfileManagerTestCase(test.TestCase):
self.tempest._configure_auth()
expected = (
("admin_username", CREDS["admin"]["username"]),
("admin_password", CREDS["admin"]["password"]),
("admin_project_name", CREDS["admin"]["tenant_name"]),
("admin_domain_name", CREDS["admin"]["user_domain_name"]))
("admin_username", CRED["username"]),
("admin_password", CRED["password"]),
("admin_project_name", CRED["tenant_name"]),
("admin_domain_name", CRED["user_domain_name"]))
result = self.tempest.conf.items("auth")
for item in expected:
self.assertIn(item, result)
@ -85,13 +80,13 @@ class TempestConfigfileManagerTestCase(test.TestCase):
self.tempest._configure_identity()
expected = (
("region", CREDS["admin"]["region_name"]),
("region", CRED["region_name"]),
("auth_version", "v2"),
("uri", CREDS["admin"]["auth_url"][:-1]),
("uri_v3", CREDS["admin"]["auth_url"].replace("/v2.0/", "/v3")),
("uri", CRED["auth_url"][:-1]),
("uri_v3", CRED["auth_url"].replace("/v2.0/", "/v3")),
("disable_ssl_certificate_validation",
str(CREDS["admin"]["https_insecure"])),
("ca_certificates_file", CREDS["admin"]["https_cacert"]))
str(CRED["https_insecure"])),
("ca_certificates_file", CRED["https_cacert"]))
result = self.tempest.conf.items("identity")
for item in expected:
self.assertIn(item, result)

View File

@ -30,20 +30,17 @@ from tests.unit import test
CONF = cfg.CONF
CREDS = {
"admin": {
"username": "admin",
"tenant_name": "admin",
"password": "admin-12345",
"auth_url": "http://test:5000/v2.0/",
"permission": "admin",
"region_name": "test",
"https_insecure": False,
"https_cacert": "/path/to/cacert/file",
"user_domain_name": "admin",
"project_domain_name": "admin"
},
"uuid": "fake_deployment"
CRED = {
"username": "admin",
"tenant_name": "admin",
"password": "admin-12345",
"auth_url": "http://test:5000/v2.0/",
"permission": "admin",
"region_name": "test",
"https_insecure": False,
"https_cacert": "/path/to/cacert/file",
"user_domain_name": "admin",
"project_domain_name": "admin"
}
PATH = "rally.plugins.openstack.verification.tempest.context"
@ -55,11 +52,12 @@ class TempestContextTestCase(test.TestCase):
def setUp(self):
super(TempestContextTestCase, self).setUp()
mock.patch("rally.osclients.Clients").start()
self.mock_isfile = mock.patch("os.path.isfile",
return_value=True).start()
self.deployment = fakes.FakeDeployment(**CREDS)
self.cred = fakes.fake_credential(**CRED)
self.deployment = fakes.FakeDeployment(
uuid="fake_deployment", admin=self.cred)
cfg = {"verifier": mock.Mock(deployment=self.deployment),
"verification": {"uuid": "uuid"}}
cfg["verifier"].manager.home_dir = "/p/a/t/h"
@ -244,6 +242,7 @@ class TempestContextTestCase(test.TestCase):
def test__discover_or_create_flavor(self):
client = self.context.clients.nova()
client.flavors.list.return_value = []
client.flavors.create.side_effect = [fakes.FakeFlavor(id="id1")]
flavor = self.context._discover_or_create_flavor(64)
@ -260,6 +259,7 @@ class TempestContextTestCase(test.TestCase):
client.create_network.side_effect = [{"network": fake_network}]
client.create_router.side_effect = [{"router": {"id": "rid1"}}]
client.create_subnet.side_effect = [{"subnet": {"id": "subid1"}}]
client.list_networks.return_value = {"networks": []}
network = self.context._create_network_resources()
self.assertEqual("nid1", network["id"])
@ -333,16 +333,14 @@ class TempestContextTestCase(test.TestCase):
@mock.patch("%s.TempestContext._configure_option" % PATH)
@mock.patch("%s.TempestContext._create_tempest_roles" % PATH)
@mock.patch("rally.verification.utils.create_dir")
@mock.patch("%s.osclients.Clients" % PATH)
def test_setup(self, mock_clients, mock_create_dir,
def test_setup(self, mock_create_dir,
mock__create_tempest_roles, mock__configure_option,
mock_open):
self.deployment = fakes.FakeDeployment(**CREDS)
verifier = mock.Mock(deployment=self.deployment)
verifier.manager.home_dir = "/p/a/t/h"
# case #1: no neutron and heat
mock_clients.return_value.services.return_value = {}
self.cred.clients.return_value.services.return_value = {}
ctx = context.TempestContext({"verifier": verifier})
ctx.conf = mock.Mock()
@ -377,10 +375,12 @@ class TempestContextTestCase(test.TestCase):
mock__configure_option.reset_mock()
# case #2: neutron and heat are presented
mock_clients.return_value.services.return_value = {
self.cred.clients.return_value.services.return_value = {
"network": "neutron", "orchestration": "heat"}
ctx = context.TempestContext({"verifier": verifier})
neutron = ctx.clients.neutron()
neutron.list_networks.return_value = {"networks": ["fake_net"]}
ctx.conf = mock.Mock()
ctx.setup()

View File

@ -16,7 +16,6 @@
"""Tests for the Test engine."""
import collections
import copy
import threading
import jsonschema
@ -286,10 +285,8 @@ class TaskEngineTestCase(test.TestCase):
eng._validate_config_semantic_helper, "a",
user_context, workloads, "fake_deployment")
@mock.patch("rally.osclients.Clients")
@mock.patch("rally.task.engine.scenario.Scenario.get")
@mock.patch("rally.task.engine.context.Context")
@mock.patch("rally.task.engine.objects.Credential")
@mock.patch("rally.task.engine.TaskConfig")
@mock.patch("rally.task.engine.TaskEngine"
"._validate_config_semantic_helper")
@ -298,11 +295,12 @@ class TaskEngineTestCase(test.TestCase):
def test__validate_config_semantic(
self, mock_deployment_get,
mock__validate_config_semantic_helper,
mock_task_config, mock_credential, mock_context,
mock_scenario_get, mock_clients):
mock_task_config, mock_context,
mock_scenario_get):
admin = fakes.fake_credential(foo="admin")
users = [fakes.fake_credential(bar="user1")]
deployment = fakes.FakeDeployment(
uuid="deployment_uuid", admin={"foo": "admin"},
users=[{"bar": "user1"}])
uuid="deployment_uuid", admin=admin, users=users)
scenario_cls = mock_scenario_get.return_value
scenario_cls.get_namespace.return_value = "default"
@ -324,12 +322,8 @@ class TaskEngineTestCase(test.TestCase):
eng._validate_config_semantic(mock_task_instance)
admin = mock_credential.return_value
user_context = mock_context.get.return_value.return_value
mock_clients.assert_called_once_with(admin)
mock_clients.return_value.verified_keystone.assert_called_once_with()
mock__validate_config_semantic_helper.assert_has_calls([
mock.call(admin, user_context, [wconf1], deployment),
mock.call(admin, user_context, [wconf2, wconf3], deployment),
@ -356,7 +350,6 @@ class TaskEngineTestCase(test.TestCase):
mock.call(consts.TaskStatus.FINISHED)
])
@mock.patch("rally.task.engine.objects.Credential")
@mock.patch("rally.task.engine.objects.task.Task.get_status")
@mock.patch("rally.task.engine.TaskConfig")
@mock.patch("rally.task.engine.LOG")
@ -368,7 +361,7 @@ class TaskEngineTestCase(test.TestCase):
def test_run_exception_is_logged(
self, mock_context_manager_setup, mock_context_manager_cleanup,
mock_scenario_runner, mock_scenario, mock_result_consumer,
mock_log, mock_task_config, mock_task_get_status, mock_credential):
mock_log, mock_task_config, mock_task_get_status):
scenario_cls = mock_scenario.get.return_value
scenario_cls.get_namespace.return_value = "openstack"
@ -394,7 +387,6 @@ class TaskEngineTestCase(test.TestCase):
self.assertEqual(2, mock_log.exception.call_count)
@mock.patch("rally.task.engine.objects.Credential")
@mock.patch("rally.task.engine.ResultConsumer")
@mock.patch("rally.task.engine.context.ContextManager.cleanup")
@mock.patch("rally.task.engine.context.ContextManager.setup")
@ -403,7 +395,7 @@ class TaskEngineTestCase(test.TestCase):
def test_run__task_soft_aborted(
self, mock_scenario_runner, mock_scenario,
mock_context_manager_setup, mock_context_manager_cleanup,
mock_result_consumer, mock_credential):
mock_result_consumer):
scenario_cls = mock_scenario.get.return_value
scenario_cls.get_namespace.return_value = "openstack"
task = mock.MagicMock()
@ -455,11 +447,9 @@ class TaskEngineTestCase(test.TestCase):
self.assertEqual(mock.call(consts.TaskStatus.ABORTED),
task.update_status.mock_calls[-1])
@mock.patch("rally.task.engine.objects.Credential")
@mock.patch("rally.task.engine.TaskConfig")
@mock.patch("rally.task.engine.scenario.Scenario.get")
def test__prepare_context(self, mock_scenario_get, mock_task_config,
mock_credential):
def test__prepare_context(self, mock_scenario_get, mock_task_config):
default_context = {"a": 1, "b": 2}
mock_scenario = mock_scenario_get.return_value
mock_scenario.get_default_context.return_value = default_context
@ -470,28 +460,24 @@ class TaskEngineTestCase(test.TestCase):
config = {
"a.task": [{"context": {"context_a": {"a": 1}}}],
}
admin = fakes.fake_credential(foo="admin")
deployment = fakes.FakeDeployment(
uuid="deployment_uuid", admin={"foo": "admin"})
uuid="deployment_uuid", admin=admin)
eng = engine.TaskEngine(config, task, deployment)
result = eng._prepare_context(context, name)
expected_context = copy.deepcopy(default_context)
expected_context.setdefault("users", {})
expected_context.update(context)
expected_result = {
"task": task,
"admin": {"credential": mock_credential.return_value},
"admin": {"credential": admin},
"scenario_name": name,
"config": expected_context
"config": {"a": 1, "b": 3, "c": 4, "users": {}}
}
self.assertEqual(result, expected_result)
mock_scenario_get.assert_called_once_with(name)
@mock.patch("rally.task.engine.objects.Credential")
@mock.patch("rally.task.engine.TaskConfig")
@mock.patch("rally.task.engine.scenario.Scenario.get")
def test__prepare_context_with_existing_users(self, mock_scenario_get,
mock_task_config,
mock_credential):
mock_task_config):
mock_scenario = mock_scenario_get.return_value
mock_scenario.get_default_context.return_value = {}
mock_scenario.get_namespace.return_value = "default"
@ -501,18 +487,17 @@ class TaskEngineTestCase(test.TestCase):
config = {
"a.task": [{"context": {"context_a": {"a": 1}}}],
}
deployment = fakes.FakeDeployment(
uuid="deployment_uuid", admin={"foo": "admin"},
users=[{"bar": "user1"}])
admin = fakes.fake_credential(foo="admin")
users = [fakes.fake_credential(bar="user1")]
deployment = fakes.FakeDeployment(uuid="deployment_uuid",
admin=admin, users=users)
eng = engine.TaskEngine(config, task, deployment)
result = eng._prepare_context(context, name)
expected_context = {"existing_users": [{"bar": "user1"}]}
expected_context.update(context)
expected_result = {
"task": task,
"admin": {"credential": mock_credential.return_value},
"admin": {"credential": admin},
"scenario_name": name,
"config": expected_context
"config": {"b": 3, "c": 4, "existing_users": users}
}
self.assertEqual(result, expected_result)
mock_scenario_get.assert_called_once_with(name)

View File

@ -24,7 +24,6 @@ import six
from rally.common.plugin import plugin
from rally import consts
from rally import exceptions
import rally.osclients
from rally.task import validation
from tests.unit import fakes
from tests.unit import test
@ -557,35 +556,32 @@ class ValidatorsTestCase(test.TestCase):
result = validator({"args": {"a": 1, "c": 3}}, None, None)
self.assertFalse(result.is_valid, result.msg)
@mock.patch("rally.common.objects.Credential")
def test_required_service(self, mock_credential):
def test_required_service(self):
validator = self._unwrap_validator(validation.required_services,
consts.Service.KEYSTONE,
consts.Service.NOVA,
consts.Service.NOVA_NET)
clients = mock.MagicMock()
admin = fakes.fake_credential(foo="bar")
clients = mock.Mock()
clients.services().values.return_value = [consts.Service.KEYSTONE,
consts.Service.NOVA,
consts.Service.NOVA_NET]
fake_service = mock.Mock(binary="nova-network", status="enabled")
admin_clients = admin.clients.return_value
nova_client = admin_clients.nova.return_value
nova_client.services.list.return_value = [fake_service]
deployment = fakes.FakeDeployment(admin=admin)
result = validator({}, clients, deployment)
with mock.patch("rally.osclients.Clients") as clients_cls:
nova_client = clients_cls.return_value.nova.return_value
nova_client.services.list.return_value = [fake_service]
deployment = fakes.FakeDeployment(admin={"info": "admin"})
result = validator({}, clients, deployment)
clients_cls.assert_called_once_with(mock_credential.return_value)
mock_credential.assert_called_once_with(info="admin")
self.assertTrue(result.is_valid, result.msg)
validator = self._unwrap_validator(validation.required_services,
consts.Service.KEYSTONE,
consts.Service.NOVA)
clients.services().values.return_value = [consts.Service.KEYSTONE]
with mock.patch("rally.osclients.Clients") as clients_cls:
result = validator({}, clients, None)
self.assertFalse(clients_cls.called)
result = validator({}, clients, None)
self.assertFalse(result.is_valid, result.msg)
def test_required_service_wrong_service(self):
@ -752,37 +748,33 @@ class ValidatorsTestCase(test.TestCase):
result = validator(context, clients, mock.MagicMock())
self.assertFalse(result.is_valid, result.msg)
@mock.patch(MODULE + "osclients")
def test_required_clients(self, mock_osclients):
def test_required_clients(self):
validator = self._unwrap_validator(validation.required_clients,
"keystone", "nova")
clients = mock.MagicMock()
clients = mock.Mock()
clients.keystone.return_value = "keystone"
clients.nova.return_value = "nova"
deployment = fakes.FakeDeployment()
result = validator({}, clients, deployment)
self.assertTrue(result.is_valid, result.msg)
self.assertFalse(mock_osclients.Clients.called)
clients.nova.side_effect = ImportError
result = validator({}, clients, deployment)
self.assertFalse(result.is_valid, result.msg)
@mock.patch(MODULE + "objects")
@mock.patch(MODULE + "osclients")
def test_required_clients_with_admin(self, mock_osclients, mock_objects):
def test_required_clients_with_admin(self):
validator = self._unwrap_validator(validation.required_clients,
"keystone", "nova", admin=True)
clients = mock.Mock()
admin = fakes.fake_credential(foo="bar")
clients = admin.clients.return_value
clients.keystone.return_value = "keystone"
clients.nova.return_value = "nova"
mock_osclients.Clients.return_value = clients
mock_objects.Credential.return_value = "foo_credential"
deployment = fakes.FakeDeployment(admin={"foo": "bar"})
deployment = fakes.FakeDeployment(admin=admin)
result = validator({}, clients, deployment)
self.assertTrue(result.is_valid, result.msg)
mock_objects.Credential.assert_called_once_with(foo="bar")
mock_osclients.Clients.assert_called_once_with("foo_credential")
clients.nova.side_effect = ImportError
result = validator({}, clients, deployment)
self.assertFalse(result.is_valid, result.msg)
@ -810,24 +802,17 @@ class ValidatorsTestCase(test.TestCase):
validation.required_cinder_services,
service_name=six.text_type("cinder-service"))
with mock.patch.object(rally.osclients.Cinder, "create_client") as c:
fake_service = mock.Mock(binary="cinder-service", state="up")
cinder_client = mock.Mock()
services = mock.Mock()
services.list.return_value = [fake_service]
cinder_client.services = services
c.return_value = cinder_client
fake_service = mock.Mock(binary="cinder-service", state="up")
admin = fakes.fake_credential(foo="bar")
cinder = admin.clients.return_value.cinder.return_value
cinder.services.list.return_value = [fake_service]
deployment = fakes.FakeDeployment(admin=admin)
result = validator({}, None, deployment)
self.assertTrue(result.is_valid, result.msg)
deployment = fakes.FakeDeployment(
admin={"auth_url": "fake_credential",
"username": "username",
"password": "password"})
result = validator({}, None, deployment)
self.assertTrue(result.is_valid, result.msg)
fake_service.state = "down"
result = validator({}, None, deployment)
self.assertFalse(result.is_valid, result.msg)
fake_service.state = "down"
result = validator({}, None, deployment)
self.assertFalse(result.is_valid, result.msg)
def test_restricted_parameters(self):
validator = self._unwrap_validator(

View File

@ -20,7 +20,6 @@ import os
import ddt
import jsonschema
from keystoneclient import exceptions as keystone_exceptions
import mock
from oslo_config import cfg
@ -349,8 +348,8 @@ class BaseDeploymentTestCase(test.TestCase):
class DeploymentAPITestCase(BaseDeploymentTestCase):
@mock.patch("rally.common.objects.deploy.db.deployment_update")
@mock.patch("rally.common.objects.deploy.db.deployment_create")
@mock.patch("rally.deployment.engine.Engine.validate")
def test_create(self, mock_engine_validate,
@mock.patch("rally.deployment.engines.existing.ExistingCloud.validate")
def test_create(self, mock_existing_cloud_validate,
mock_deployment_create, mock_deployment_update):
mock_deployment_create.return_value = self.deployment
mock_deployment_update.return_value = self.deployment
@ -360,7 +359,7 @@ class DeploymentAPITestCase(BaseDeploymentTestCase):
"name": "fake_deployment",
"config": self.deployment_config,
})
mock_engine_validate.assert_called_once_with()
mock_existing_cloud_validate.assert_called_once_with()
mock_deployment_update.assert_has_calls([
mock.call(self.deployment_uuid,
{"credentials": {"openstack": [self.credentials]}})
@ -368,10 +367,10 @@ class DeploymentAPITestCase(BaseDeploymentTestCase):
@mock.patch("rally.common.objects.deploy.db.deployment_update")
@mock.patch("rally.common.objects.deploy.db.deployment_create")
@mock.patch("rally.deployment.engine.Engine.validate",
@mock.patch("rally.deployment.engines.existing.ExistingCloud.validate",
side_effect=jsonschema.ValidationError("ValidationError"))
def test_create_validation_error(
self, mock_engine_validate, mock_deployment_create,
self, mock_existing_cloud_validate, mock_deployment_create,
mock_deployment_update):
mock_deployment_create.return_value = self.deployment
self.assertRaises(jsonschema.ValidationError,
@ -488,41 +487,25 @@ class DeploymentAPITestCase(BaseDeploymentTestCase):
for key in self.deployment:
self.assertEqual(ret[key], self.deployment[key])
@mock.patch("rally.osclients.Clients.services")
@mock.patch("rally.osclients.Keystone.create_client")
def test_deployment_check(self, mock_keystone_create_client,
mock_clients_services):
sample_credential = objects.Credential("http://192.168.1.1:5000/v2.0/",
"admin",
"adminpass").to_dict()
def test_deployment_check(self):
fake_credential1 = fakes.fake_credential()
fake_credential2 = fakes.fake_credential()
deployment = mock.Mock(spec=objects.Deployment)
deployment.get_credentials_for.return_value = {
"admin": sample_credential, "users": [sample_credential]}
api._Deployment.check(deployment)
mock_keystone_create_client.assert_called_with()
mock_clients_services.assert_called_once_with()
"admin": fake_credential1, "users": [fake_credential2]}
result = api._Deployment.check(deployment)
fake_credential1.verify_connection.assert_called_once_with()
fake_credential2.verify_connection.assert_called_once_with()
self.assertEqual(fake_credential1.list_services.return_value, result)
def test_deployment_check_raise(self):
sample_credential = objects.Credential("http://192.168.1.1:5000/v2.0/",
"admin",
"adminpass").to_dict()
sample_credential["not-exist-key"] = "error"
deployment = mock.Mock(spec=objects.Deployment)
self.assertRaises(TypeError, api._Deployment.check, deployment)
@mock.patch("rally.osclients.Clients.services")
def test_deployment_check_connect_failed(self, mock_clients_services):
sample_credential = objects.Credential("http://192.168.1.1:5000/v2.0/",
"admin",
"adminpass").to_dict()
def test_service_list(self):
fake_credential = fakes.fake_credential()
deployment = mock.Mock(spec=objects.Deployment)
deployment.get_credentials_for.return_value = {
"admin": sample_credential, "users": []}
refused = keystone_exceptions.ConnectionRefused()
mock_clients_services.side_effect = refused
self.assertRaises(
keystone_exceptions.ConnectionRefused,
api._Deployment.check, deployment)
"admin": fake_credential, "users": []}
result = api._Deployment.service_list(deployment)
self.assertEqual(fake_credential.list_services.return_value, result)
class APITestCase(test.TestCase):

View File

@ -18,10 +18,10 @@ from keystoneclient import exceptions as keystone_exceptions
import mock
from oslo_config import cfg
from rally.common import objects
from rally import consts
from rally import exceptions
from rally import osclients
from rally.plugins.openstack import credential as oscredential
from tests.unit import fakes
from tests.unit import test
@ -91,9 +91,10 @@ class OSClientTestCase(test.TestCase, OSClientTestCaseUtils):
@ddt.unpack
def test__get_endpoint(self, mock_keystone_service_catalog, endpoint_type,
service_type, region_name):
credential = objects.Credential("http://auth_url/v2.0", "user", "pass",
endpoint_type=endpoint_type,
region_name=region_name)
credential = oscredential.OpenStackCredential(
"http://auth_url/v2.0", "user", "pass",
endpoint_type=endpoint_type,
region_name=region_name)
mock_choose_service_type = mock.MagicMock()
osclient = osclients.OSClient(credential, {}, mock.MagicMock())
osclient.choose_service_type = mock_choose_service_type
@ -153,8 +154,8 @@ class TestCreateKeystoneClient(test.TestCase, OSClientTestCaseUtils):
def setUp(self):
super(TestCreateKeystoneClient, self).setUp()
self.credential = objects.Credential("http://auth_url/v2.0", "user",
"pass", "tenant")
self.credential = oscredential.OpenStackCredential(
"http://auth_url/v2.0", "user", "pass", "tenant")
def test_create_client(self):
# NOTE(bigjools): This is a very poor testing strategy as it
@ -201,8 +202,8 @@ class TestCreateKeystoneClient(test.TestCase, OSClientTestCaseUtils):
@ddt.data("http://auth_url/v2.0", "http://auth_url/v3",
"http://auth_url/", "auth_url")
def test_keystone_get_session(self, auth_url):
credential = objects.Credential(auth_url, "user",
"pass", "tenant")
credential = oscredential.OpenStackCredential(
auth_url, "user", "pass", "tenant")
self.set_up_keystone_mocks()
keystone = osclients.Keystone(credential, {}, {})
@ -255,8 +256,8 @@ class OSClientsTestCase(test.TestCase):
def setUp(self):
super(OSClientsTestCase, self).setUp()
self.credential = objects.Credential("http://auth_url/v2.0", "user",
"pass", "tenant")
self.credential = oscredential.OpenStackCredential(
"http://auth_url/v2.0", "user", "pass", "tenant")
self.clients = osclients.Clients(self.credential, {})
self.fake_keystone = fakes.FakeKeystoneClient()