Move rally.osclients to rally.plugins.openstack.osclients
- Fix few problems with oslo_config: -- Register only in one place opts (rally.api module) -- Do not import opts -> it actually does nothing -- Fix the bug with registration of DEFAULT group - Imports are not fixed in this patch to check that we are not braking anything Change-Id: I96283ef33963b46e85cf8f52df91e67659528143
This commit is contained in:
parent
dc98fa69c8
commit
4734665d15
|
@ -25,6 +25,7 @@ from rally.plugins.openstack.cfg import monasca
|
|||
from rally.plugins.openstack.cfg import murano
|
||||
from rally.plugins.openstack.cfg import neutron
|
||||
from rally.plugins.openstack.cfg import nova
|
||||
from rally.plugins.openstack.cfg import osclients
|
||||
from rally.plugins.openstack.cfg import profiler
|
||||
from rally.plugins.openstack.cfg import sahara
|
||||
from rally.plugins.openstack.cfg import senlin
|
||||
|
@ -44,10 +45,10 @@ def list_opts():
|
|||
opts = {}
|
||||
for l_opts in (cinder.OPTS, ec2.OPTS, heat.OPTS, ironic.OPTS, magnum.OPTS,
|
||||
manila.OPTS, mistral.OPTS, monasca.OPTS, murano.OPTS,
|
||||
nova.OPTS, profiler.OPTS, sahara.OPTS, vm.OPTS, glance.OPTS,
|
||||
watcher.OPTS, tempest.OPTS, keystone_roles.OPTS,
|
||||
keystone_users.OPTS, cleanup.OPTS, senlin.OPTS,
|
||||
neutron.OPTS):
|
||||
nova.OPTS, osclients.OPTS, profiler.OPTS, sahara.OPTS,
|
||||
vm.OPTS, glance.OPTS, watcher.OPTS, tempest.OPTS,
|
||||
keystone_roles.OPTS, keystone_users.OPTS, cleanup.OPTS,
|
||||
senlin.OPTS, neutron.OPTS):
|
||||
for category, opt in l_opts.items():
|
||||
opts.setdefault(category, [])
|
||||
opts[category].extend(opt)
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
# Copyright 2017: GoDaddy 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 oslo_config import cfg
|
||||
|
||||
|
||||
OPTS = {
|
||||
"DEFAULT": [
|
||||
cfg.FloatOpt(
|
||||
"openstack_client_http_timeout",
|
||||
default=180.0,
|
||||
help="HTTP timeout for any of OpenStack service in seconds")
|
||||
]
|
||||
}
|
|
@ -18,10 +18,6 @@ from oslo_config import cfg
|
|||
|
||||
from rally.task import utils
|
||||
|
||||
|
||||
from rally.common import opts
|
||||
opts.register()
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
cleanup_group = cfg.OptGroup(name="cleanup", title="Cleanup Options")
|
||||
|
|
|
@ -28,12 +28,6 @@ from rally.plugins.openstack.services.image import image
|
|||
from rally.task import utils as task_utils
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.import_opt("glance_image_delete_timeout",
|
||||
"rally.plugins.openstack.scenarios.glance.utils",
|
||||
"benchmark")
|
||||
CONF.import_opt("glance_image_delete_poll_interval",
|
||||
"rally.plugins.openstack.scenarios.glance.utils",
|
||||
"benchmark")
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -24,12 +24,6 @@ from rally.plugins.openstack.services.image import image
|
|||
from rally.task import context
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.import_opt("glance_image_delete_timeout",
|
||||
"rally.plugins.openstack.scenarios.glance.utils",
|
||||
"benchmark")
|
||||
CONF.import_opt("glance_image_delete_poll_interval",
|
||||
"rally.plugins.openstack.scenarios.glance.utils",
|
||||
"benchmark")
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -31,9 +31,6 @@ from rally.plugins.openstack.services.identity import identity
|
|||
from rally.plugins.openstack.wrappers import network
|
||||
from rally.task import context
|
||||
|
||||
from rally.common import opts
|
||||
opts.register()
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -0,0 +1,844 @@
|
|||
# Copyright 2013: Mirantis Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import abc
|
||||
import os
|
||||
|
||||
from oslo_config import cfg
|
||||
from six.moves.urllib import parse
|
||||
|
||||
from rally.cli import envutils
|
||||
from rally.common import logging
|
||||
from rally.common.plugin import plugin
|
||||
from rally import consts
|
||||
from rally import exceptions
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
def configure(name, default_version=None, default_service_type=None,
|
||||
supported_versions=None):
|
||||
"""OpenStack client class wrapper.
|
||||
|
||||
Each client class has to be wrapped by configure() wrapper. It
|
||||
sets essential configuration of client classes.
|
||||
|
||||
:param name: Name of the client
|
||||
:param default_version: Default version for client
|
||||
:param default_service_type: Default service type of endpoint(If this
|
||||
variable is not specified, validation will assume that your client
|
||||
doesn't allow to specify service type.
|
||||
:param supported_versions: List of supported versions(If this variable is
|
||||
not specified, `OSClients.validate_version` method will raise an
|
||||
exception that client doesn't support setting any versions. If this
|
||||
logic is wrong for your client, you should override `validate_version`
|
||||
in client object)
|
||||
"""
|
||||
def wrapper(cls):
|
||||
cls = plugin.configure(name=name, platform="openstack")(cls)
|
||||
cls._meta_set("default_version", default_version)
|
||||
cls._meta_set("default_service_type", default_service_type)
|
||||
cls._meta_set("supported_versions", supported_versions or [])
|
||||
return cls
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
@plugin.base()
|
||||
class OSClient(plugin.Plugin):
|
||||
"""Base class for openstack clients"""
|
||||
|
||||
def __init__(self, credential, api_info, cache_obj):
|
||||
self.credential = credential
|
||||
self.api_info = api_info
|
||||
self.cache = cache_obj
|
||||
|
||||
def choose_version(self, version=None):
|
||||
"""Return version string.
|
||||
|
||||
Choose version between transmitted(preferable value if present),
|
||||
version from api_info(configured from a context) and default.
|
||||
"""
|
||||
# NOTE(andreykurilin): The result of choose is converted to string,
|
||||
# since most of clients contain map for versioned modules, where a key
|
||||
# is a string value of version. Example of map and its usage:
|
||||
#
|
||||
# from oslo_utils import importutils
|
||||
# ...
|
||||
# version_map = {"1": "someclient.v1.client.Client",
|
||||
# "2": "someclient.v2.client.Client"}
|
||||
#
|
||||
# def Client(version, *args, **kwargs):
|
||||
# cls = importutils.import_class(version_map[version])
|
||||
# return cls(*args, **kwargs)
|
||||
#
|
||||
# That is why type of version so important and we should ensure that
|
||||
# version is a string object.
|
||||
# For those clients which doesn't accept string value(for example
|
||||
# zaqarclient), this method should be overridden.
|
||||
version = (version
|
||||
or self.api_info.get(self.get_name(), {}).get("version")
|
||||
or self._meta_get("default_version"))
|
||||
if version is not None:
|
||||
version = str(version)
|
||||
return version
|
||||
|
||||
@classmethod
|
||||
def get_supported_versions(cls):
|
||||
return cls._meta_get("supported_versions")
|
||||
|
||||
@classmethod
|
||||
def validate_version(cls, version):
|
||||
supported_versions = cls.get_supported_versions()
|
||||
if supported_versions:
|
||||
if str(version) not in supported_versions:
|
||||
raise exceptions.ValidationError(
|
||||
"'%(vers)s' is not supported. Should be one of "
|
||||
"'%(supported)s'"
|
||||
% {"vers": version, "supported": supported_versions})
|
||||
else:
|
||||
raise exceptions.RallyException("Setting version is not supported")
|
||||
try:
|
||||
float(version)
|
||||
except ValueError:
|
||||
raise exceptions.ValidationError(
|
||||
"'%s' is invalid. Should be numeric value." % version)
|
||||
|
||||
def choose_service_type(self, service_type=None):
|
||||
"""Return service_type string.
|
||||
|
||||
Choose service type between transmitted(preferable value if present),
|
||||
service type from api_info(configured from a context) and default.
|
||||
"""
|
||||
return (service_type
|
||||
or self.api_info.get(self.get_name(), {}).get("service_type")
|
||||
or self._meta_get("default_service_type"))
|
||||
|
||||
@classmethod
|
||||
def is_service_type_configurable(cls):
|
||||
"""Just checks that client supports setting service type."""
|
||||
if cls._meta_get("default_service_type") is None:
|
||||
raise exceptions.RallyException(
|
||||
"Setting service type is not supported.")
|
||||
|
||||
@property
|
||||
def keystone(self):
|
||||
return OSClient.get("keystone")(self.credential, self.api_info,
|
||||
self.cache)
|
||||
|
||||
def _get_session(self, auth_url=None, version=None):
|
||||
LOG.warning(
|
||||
"Method `rally.osclient.OSClient._get_session` is deprecated since"
|
||||
" Rally 0.6.0. Use "
|
||||
"`rally.osclient.OSClient.keystone.get_session` instead.")
|
||||
return self.keystone.get_session(version)
|
||||
|
||||
def _get_endpoint(self, service_type=None):
|
||||
kw = {"service_type": self.choose_service_type(service_type),
|
||||
"region_name": self.credential.region_name}
|
||||
if self.credential.endpoint_type:
|
||||
kw["interface"] = self.credential.endpoint_type
|
||||
api_url = self.keystone.service_catalog.url_for(**kw)
|
||||
return api_url
|
||||
|
||||
def _get_auth_info(self, user_key="username",
|
||||
password_key="password",
|
||||
auth_url_key="auth_url",
|
||||
project_name_key="project_id",
|
||||
domain_name_key="domain_name",
|
||||
user_domain_name_key="user_domain_name",
|
||||
project_domain_name_key="project_domain_name",
|
||||
cacert_key="cacert",
|
||||
endpoint_type="endpoint_type",
|
||||
):
|
||||
kw = {
|
||||
user_key: self.credential.username,
|
||||
password_key: self.credential.password,
|
||||
auth_url_key: self.credential.auth_url,
|
||||
cacert_key: self.credential.https_cacert,
|
||||
}
|
||||
if project_name_key:
|
||||
kw.update({project_name_key: self.credential.tenant_name})
|
||||
|
||||
if "v2.0" not in self.credential.auth_url:
|
||||
kw.update({
|
||||
domain_name_key: self.credential.domain_name})
|
||||
kw.update({
|
||||
user_domain_name_key:
|
||||
self.credential.user_domain_name or "Default"})
|
||||
kw.update({
|
||||
project_domain_name_key:
|
||||
self.credential.project_domain_name or "Default"})
|
||||
if self.credential.endpoint_type:
|
||||
kw[endpoint_type] = self.credential.endpoint_type
|
||||
return kw
|
||||
|
||||
@abc.abstractmethod
|
||||
def create_client(self, *args, **kwargs):
|
||||
"""Create new instance of client."""
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
"""Return initialized client instance."""
|
||||
key = "{0}{1}{2}".format(self.get_name(),
|
||||
str(args) if args else "",
|
||||
str(kwargs) if kwargs else "")
|
||||
if key not in self.cache:
|
||||
self.cache[key] = self.create_client(*args, **kwargs)
|
||||
return self.cache[key]
|
||||
|
||||
@classmethod
|
||||
def get(cls, name, **kwargs):
|
||||
# NOTE(boris-42): Remove this after we finish rename refactoring.
|
||||
kwargs.pop("platform", None)
|
||||
kwargs.pop("namespace", None)
|
||||
return super(OSClient, cls).get(name, platform="openstack", **kwargs)
|
||||
|
||||
|
||||
@configure("keystone", supported_versions=("2", "3"))
|
||||
class Keystone(OSClient):
|
||||
"""Wrapper for KeystoneClient which hides OpenStack auth details."""
|
||||
|
||||
@property
|
||||
def keystone(self):
|
||||
raise exceptions.RallyException(
|
||||
"Method 'keystone' is restricted for keystoneclient. :)")
|
||||
|
||||
@property
|
||||
def service_catalog(self):
|
||||
return self.auth_ref.service_catalog
|
||||
|
||||
@property
|
||||
def auth_ref(self):
|
||||
try:
|
||||
if "keystone_auth_ref" not in self.cache:
|
||||
sess, plugin = self.get_session()
|
||||
self.cache["keystone_auth_ref"] = plugin.get_access(sess)
|
||||
except Exception as e:
|
||||
if logging.is_debug():
|
||||
LOG.exception("Unable to authenticate for user"
|
||||
" %(username)s in project"
|
||||
" %(tenant_name)s" %
|
||||
{"username": self.credential.username,
|
||||
"tenant_name": self.credential.tenant_name})
|
||||
raise exceptions.AuthenticationFailed(
|
||||
username=self.credential.username,
|
||||
project=self.credential.tenant_name,
|
||||
url=self.credential.auth_url,
|
||||
etype=e.__class__.__name__,
|
||||
error=str(e))
|
||||
return self.cache["keystone_auth_ref"]
|
||||
|
||||
def get_session(self, version=None):
|
||||
key = "keystone_session_and_plugin_%s" % version
|
||||
if key not in self.cache:
|
||||
from keystoneauth1 import discover
|
||||
from keystoneauth1 import identity
|
||||
from keystoneauth1 import session
|
||||
|
||||
version = self.choose_version(version)
|
||||
auth_url = self.credential.auth_url
|
||||
if version is not None:
|
||||
auth_url = self._remove_url_version()
|
||||
|
||||
password_args = {
|
||||
"auth_url": auth_url,
|
||||
"username": self.credential.username,
|
||||
"password": self.credential.password,
|
||||
"tenant_name": self.credential.tenant_name
|
||||
}
|
||||
|
||||
if version is None:
|
||||
# NOTE(rvasilets): If version not specified than we discover
|
||||
# available version with the smallest number. To be able to
|
||||
# discover versions we need session
|
||||
temp_session = session.Session(
|
||||
verify=(self.credential.https_cacert or
|
||||
not self.credential.https_insecure),
|
||||
timeout=CONF.openstack_client_http_timeout)
|
||||
version = str(discover.Discover(
|
||||
temp_session,
|
||||
password_args["auth_url"]).version_data()[0]["version"][0])
|
||||
|
||||
if "v2.0" not in password_args["auth_url"] and (
|
||||
version != "2"):
|
||||
password_args.update({
|
||||
"user_domain_name": self.credential.user_domain_name,
|
||||
"domain_name": self.credential.domain_name,
|
||||
"project_domain_name": self.credential.project_domain_name
|
||||
})
|
||||
identity_plugin = identity.Password(**password_args)
|
||||
sess = session.Session(
|
||||
auth=identity_plugin,
|
||||
verify=(self.credential.https_cacert or
|
||||
not self.credential.https_insecure),
|
||||
timeout=CONF.openstack_client_http_timeout)
|
||||
self.cache[key] = (sess, identity_plugin)
|
||||
return self.cache[key]
|
||||
|
||||
def _remove_url_version(self):
|
||||
"""Remove any version from the auth_url.
|
||||
|
||||
The keystone Client code requires that auth_url be the root url
|
||||
if a version override is used.
|
||||
"""
|
||||
url = parse.urlparse(self.credential.auth_url)
|
||||
path = url.path.rstrip("/")
|
||||
if path.endswith("v2.0") or path.endswith("v3"):
|
||||
path = os.path.join(*os.path.split(path)[:-1])
|
||||
parts = (url.scheme, url.netloc, path, url.params, url.query,
|
||||
url.fragment)
|
||||
return parse.urlunparse(parts)
|
||||
return self.credential.auth_url
|
||||
|
||||
def create_client(self, version=None):
|
||||
"""Return a keystone client.
|
||||
|
||||
:param version: Keystone API version, can be one of:
|
||||
("2", "3")
|
||||
|
||||
If this object was constructed with a version in the api_info
|
||||
then that will be used unless the version parameter is passed.
|
||||
"""
|
||||
import keystoneclient
|
||||
from keystoneclient import client
|
||||
|
||||
# Use the version in the api_info if provided, otherwise fall
|
||||
# back to the passed version (which may be None, in which case
|
||||
# keystoneclient chooses).
|
||||
version = self.choose_version(version)
|
||||
|
||||
sess = self.get_session(version=version)[0]
|
||||
|
||||
kw = {"version": version, "session": sess,
|
||||
"timeout": CONF.openstack_client_http_timeout}
|
||||
if keystoneclient.__version__[0] == "1":
|
||||
# NOTE(andreykurilin): let's leave this hack for envs which uses
|
||||
# old(<2.0.0) keystoneclient version. Upstream fix:
|
||||
# https://github.com/openstack/python-keystoneclient/commit/d9031c252848d89270a543b67109a46f9c505c86
|
||||
from keystoneauth1 import plugin
|
||||
kw["auth_url"] = sess.get_endpoint(interface=plugin.AUTH_INTERFACE)
|
||||
if self.credential.endpoint_type:
|
||||
kw["interface"] = self.credential.endpoint_type
|
||||
|
||||
# NOTE(amyge):
|
||||
# In auth_ref(), plugin.get_access(sess) only returns a auth_ref object
|
||||
# and won't check the authentication access until it is actually being
|
||||
# called. To catch the authentication failure in auth_ref(), we will
|
||||
# have to call self.auth_ref.auth_token here to actually use auth_ref.
|
||||
self.auth_ref # noqa
|
||||
|
||||
return client.Client(**kw)
|
||||
|
||||
|
||||
@configure("nova", default_version="2", default_service_type="compute")
|
||||
class Nova(OSClient):
|
||||
"""Wrapper for NovaClient which returns a authenticated native client."""
|
||||
|
||||
@classmethod
|
||||
def validate_version(cls, version):
|
||||
from novaclient import api_versions
|
||||
from novaclient import exceptions as nova_exc
|
||||
|
||||
try:
|
||||
api_versions.get_api_version(version)
|
||||
except nova_exc.UnsupportedVersion:
|
||||
raise exceptions.RallyException(
|
||||
"Version string '%s' is unsupported." % version)
|
||||
|
||||
def create_client(self, version=None, service_type=None):
|
||||
"""Return nova client."""
|
||||
from novaclient import client as nova
|
||||
|
||||
client = nova.Client(
|
||||
session=self.keystone.get_session()[0],
|
||||
version=self.choose_version(version),
|
||||
endpoint_override=self._get_endpoint(service_type))
|
||||
return client
|
||||
|
||||
|
||||
@configure("neutron", default_version="2.0", default_service_type="network",
|
||||
supported_versions=["2.0"])
|
||||
class Neutron(OSClient):
|
||||
"""Wrapper for NeutronClient which returns an authenticated native client.
|
||||
|
||||
"""
|
||||
|
||||
def create_client(self, version=None, service_type=None):
|
||||
"""Return neutron client."""
|
||||
from neutronclient.neutron import client as neutron
|
||||
|
||||
kw_args = {}
|
||||
if self.credential.endpoint_type:
|
||||
kw_args["endpoint_type"] = self.credential.endpoint_type
|
||||
|
||||
client = neutron.Client(
|
||||
self.choose_version(version),
|
||||
session=self.keystone.get_session()[0],
|
||||
endpoint_override=self._get_endpoint(service_type),
|
||||
**kw_args)
|
||||
return client
|
||||
|
||||
|
||||
@configure("glance", default_version="2", default_service_type="image",
|
||||
supported_versions=["1", "2"])
|
||||
class Glance(OSClient):
|
||||
"""Wrapper for GlanceClient which returns an authenticated native client.
|
||||
|
||||
"""
|
||||
|
||||
def create_client(self, version=None, service_type=None):
|
||||
"""Return glance client."""
|
||||
import glanceclient as glance
|
||||
|
||||
session = self.keystone.get_session()[0]
|
||||
client = glance.Client(
|
||||
version=self.choose_version(version),
|
||||
endpoint_override=self._get_endpoint(service_type),
|
||||
session=session)
|
||||
return client
|
||||
|
||||
|
||||
@configure("heat", default_version="1", default_service_type="orchestration",
|
||||
supported_versions=["1"])
|
||||
class Heat(OSClient):
|
||||
"""Wrapper for HeatClient which returns an authenticated native client."""
|
||||
def create_client(self, version=None, service_type=None):
|
||||
"""Return heat client."""
|
||||
from heatclient import client as heat
|
||||
|
||||
# ToDo: Remove explicit endpoint_type or interface initialization
|
||||
# when heatclient no longer uses it.
|
||||
kw_args = {}
|
||||
if self.credential.endpoint_type:
|
||||
kw_args["endpoint_type"] = self.credential.endpoint_type
|
||||
kw_args["interface"] = self.credential.endpoint_type
|
||||
|
||||
client = heat.Client(
|
||||
self.choose_version(version),
|
||||
session=self.keystone.get_session()[0],
|
||||
# Remove endpoint once requirement is python-heatclient>=1.6
|
||||
endpoint=self._get_endpoint(service_type),
|
||||
endpoint_override=self._get_endpoint(service_type),
|
||||
**kw_args)
|
||||
return client
|
||||
|
||||
|
||||
@configure("cinder", default_version="2", default_service_type="volumev2",
|
||||
supported_versions=["1", "2"])
|
||||
class Cinder(OSClient):
|
||||
"""Wrapper for CinderClient which returns an authenticated native client.
|
||||
|
||||
"""
|
||||
def create_client(self, version=None, service_type=None):
|
||||
"""Return cinder client."""
|
||||
from cinderclient import client as cinder
|
||||
|
||||
client = cinder.Client(
|
||||
self.choose_version(version),
|
||||
session=self.keystone.get_session()[0],
|
||||
endpoint_override=self._get_endpoint(service_type))
|
||||
return client
|
||||
|
||||
|
||||
@configure("manila", default_version="1", default_service_type="share")
|
||||
class Manila(OSClient):
|
||||
"""Wrapper for ManilaClient which returns an authenticated native client.
|
||||
|
||||
"""
|
||||
@classmethod
|
||||
def validate_version(cls, version):
|
||||
from manilaclient import api_versions
|
||||
from manilaclient import exceptions as manila_exc
|
||||
|
||||
try:
|
||||
api_versions.get_api_version(version)
|
||||
except manila_exc.UnsupportedVersion:
|
||||
raise exceptions.RallyException(
|
||||
"Version string '%s' is unsupported." % version)
|
||||
|
||||
def create_client(self, version=None, service_type=None):
|
||||
"""Return manila client."""
|
||||
from manilaclient import client as manila
|
||||
manila_client = manila.Client(
|
||||
self.choose_version(version),
|
||||
session=self.keystone.get_session()[0],
|
||||
service_catalog_url=self._get_endpoint(service_type))
|
||||
return manila_client
|
||||
|
||||
|
||||
@configure("ceilometer", default_version="2", default_service_type="metering",
|
||||
supported_versions=["1", "2"])
|
||||
class Ceilometer(OSClient):
|
||||
"""Wrapper for CeilometerClient which returns authenticated native client.
|
||||
|
||||
"""
|
||||
def create_client(self, version=None, service_type=None):
|
||||
"""Return ceilometer client."""
|
||||
from ceilometerclient import client as ceilometer
|
||||
|
||||
client = ceilometer.get_client(
|
||||
self.choose_version(version),
|
||||
session=self.keystone.get_session()[0],
|
||||
endpoint_override=self._get_endpoint(service_type))
|
||||
return client
|
||||
|
||||
|
||||
@configure("gnocchi", default_service_type="metric", default_version="1",
|
||||
supported_versions=["1"])
|
||||
class Gnocchi(OSClient):
|
||||
"""Wrapper for GnocchiClient which returns an authenticated native client.
|
||||
|
||||
"""
|
||||
|
||||
def create_client(self, version=None, service_type=None):
|
||||
"""Return gnocchi client."""
|
||||
# NOTE(sumantmurke): gnocchiclient requires keystoneauth1 for
|
||||
# authenticating and creating a session.
|
||||
from gnocchiclient import client as gnocchi
|
||||
|
||||
service_type = self.choose_service_type(service_type)
|
||||
sess = self.keystone.get_session()[0]
|
||||
gclient = gnocchi.Client(version=self.choose_version(
|
||||
version), session=sess, service_type=service_type)
|
||||
return gclient
|
||||
|
||||
|
||||
@configure("ironic", default_version="1", default_service_type="baremetal",
|
||||
supported_versions=["1"])
|
||||
class Ironic(OSClient):
|
||||
"""Wrapper for IronicClient which returns an authenticated native client.
|
||||
|
||||
"""
|
||||
|
||||
def create_client(self, version=None, service_type=None):
|
||||
"""Return Ironic client."""
|
||||
from ironicclient import client as ironic
|
||||
|
||||
client = ironic.get_client(
|
||||
self.choose_version(version),
|
||||
session=self.keystone.get_session()[0],
|
||||
endpoint=self._get_endpoint(service_type))
|
||||
return client
|
||||
|
||||
|
||||
@configure("sahara", default_version="1.1", supported_versions=["1.0", "1.1"],
|
||||
default_service_type="data-processing")
|
||||
class Sahara(OSClient):
|
||||
"""Wrapper for SaharaClient which returns an authenticated native client.
|
||||
|
||||
"""
|
||||
|
||||
# NOTE(andreykurilin): saharaclient supports "1.0" version and doesn't
|
||||
# support "1". `choose_version` and `validate_version` methods are written
|
||||
# as a hack to covert 1 -> 1.0, which can simplify setting saharaclient
|
||||
# for end-users.
|
||||
def choose_version(self, version=None):
|
||||
return float(super(Sahara, self).choose_version(version))
|
||||
|
||||
@classmethod
|
||||
def validate_version(cls, version):
|
||||
super(Sahara, cls).validate_version(float(version))
|
||||
|
||||
def create_client(self, version=None, service_type=None):
|
||||
"""Return Sahara client."""
|
||||
from saharaclient import client as sahara
|
||||
|
||||
client = sahara.Client(
|
||||
self.choose_version(version),
|
||||
session=self.keystone.get_session()[0],
|
||||
sahara_url=self._get_endpoint(service_type))
|
||||
|
||||
return client
|
||||
|
||||
|
||||
@configure("zaqar", default_version="1.1", default_service_type="messaging",
|
||||
supported_versions=["1", "1.1"])
|
||||
class Zaqar(OSClient):
|
||||
"""Wrapper for ZaqarClient which returns an authenticated native client.
|
||||
|
||||
"""
|
||||
def choose_version(self, version=None):
|
||||
# zaqarclient accepts only int or float obj as version
|
||||
return float(super(Zaqar, self).choose_version(version))
|
||||
|
||||
def create_client(self, version=None, service_type=None):
|
||||
"""Return Zaqar client."""
|
||||
from zaqarclient.queues import client as zaqar
|
||||
client = zaqar.Client(url=self._get_endpoint(),
|
||||
version=self.choose_version(version),
|
||||
session=self.keystone.get_session()[0])
|
||||
return client
|
||||
|
||||
|
||||
@configure("murano", default_version="1",
|
||||
default_service_type="application-catalog",
|
||||
supported_versions=["1"])
|
||||
class Murano(OSClient):
|
||||
"""Wrapper for MuranoClient which returns an authenticated native client.
|
||||
|
||||
"""
|
||||
def create_client(self, version=None, service_type=None):
|
||||
"""Return Murano client."""
|
||||
from muranoclient import client as murano
|
||||
|
||||
client = murano.Client(self.choose_version(version),
|
||||
endpoint=self._get_endpoint(service_type),
|
||||
token=self.keystone.auth_ref.auth_token)
|
||||
|
||||
return client
|
||||
|
||||
|
||||
@configure("designate", default_version="1", default_service_type="dns",
|
||||
supported_versions=["1", "2"])
|
||||
class Designate(OSClient):
|
||||
"""Wrapper for DesignateClient which returns authenticated native client.
|
||||
|
||||
"""
|
||||
def create_client(self, version=None, service_type=None):
|
||||
"""Return designate client."""
|
||||
from designateclient import client
|
||||
|
||||
version = self.choose_version(version)
|
||||
|
||||
api_url = self._get_endpoint(service_type)
|
||||
api_url += "/v%s" % version
|
||||
|
||||
session = self.keystone.get_session()[0]
|
||||
if version == "2":
|
||||
return client.Client(version, session=session,
|
||||
endpoint_override=api_url)
|
||||
return client.Client(version, session=session,
|
||||
endpoint=api_url)
|
||||
|
||||
|
||||
@configure("trove", default_version="1.0", supported_versions=["1.0"],
|
||||
default_service_type="database")
|
||||
class Trove(OSClient):
|
||||
"""Wrapper for TroveClient which returns an authenticated native client.
|
||||
|
||||
"""
|
||||
def create_client(self, version=None, service_type=None):
|
||||
"""Returns trove client."""
|
||||
from troveclient import client as trove
|
||||
|
||||
client = trove.Client(self.choose_version(version),
|
||||
session=self.keystone.get_session()[0],
|
||||
endpoint=self._get_endpoint(service_type))
|
||||
return client
|
||||
|
||||
|
||||
@configure("mistral", default_service_type="workflowv2")
|
||||
class Mistral(OSClient):
|
||||
"""Wrapper for MistralClient which returns an authenticated native client.
|
||||
|
||||
"""
|
||||
def create_client(self, service_type=None):
|
||||
"""Return Mistral client."""
|
||||
from mistralclient.api import client as mistral
|
||||
|
||||
client = mistral.client(
|
||||
mistral_url=self._get_endpoint(service_type),
|
||||
service_type=self.choose_service_type(service_type),
|
||||
auth_token=self.keystone.auth_ref.auth_token)
|
||||
return client
|
||||
|
||||
|
||||
@configure("swift", default_service_type="object-store")
|
||||
class Swift(OSClient):
|
||||
"""Wrapper for SwiftClient which returns an authenticated native client.
|
||||
|
||||
"""
|
||||
def create_client(self, service_type=None):
|
||||
"""Return swift client."""
|
||||
from swiftclient import client as swift
|
||||
|
||||
auth_token = self.keystone.auth_ref.auth_token
|
||||
client = swift.Connection(retries=1,
|
||||
preauthurl=self._get_endpoint(service_type),
|
||||
preauthtoken=auth_token,
|
||||
insecure=self.credential.https_insecure,
|
||||
cacert=self.credential.https_cacert,
|
||||
user=self.credential.username,
|
||||
tenant_name=self.credential.tenant_name,
|
||||
)
|
||||
return client
|
||||
|
||||
|
||||
@configure("ec2")
|
||||
class EC2(OSClient):
|
||||
"""Wrapper for EC2Client which returns an authenticated native client.
|
||||
|
||||
"""
|
||||
def create_client(self):
|
||||
"""Return ec2 client."""
|
||||
LOG.warning("rally.osclient.EC2 is deprecated since Rally 0.10.0.")
|
||||
|
||||
import boto
|
||||
|
||||
kc = self.keystone()
|
||||
|
||||
if kc.version != "v2.0":
|
||||
raise exceptions.RallyException(
|
||||
"Rally EC2 scenario supports only Keystone version 2")
|
||||
ec2_credential = kc.ec2.create(user_id=kc.auth_user_id,
|
||||
tenant_id=kc.auth_tenant_id)
|
||||
client = boto.connect_ec2_endpoint(
|
||||
url=self._get_endpoint(),
|
||||
aws_access_key_id=ec2_credential.access,
|
||||
aws_secret_access_key=ec2_credential.secret,
|
||||
is_secure=self.credential.https_insecure)
|
||||
return client
|
||||
|
||||
|
||||
@configure("monasca", default_version="2_0",
|
||||
default_service_type="monitoring", supported_versions=["2_0"])
|
||||
class Monasca(OSClient):
|
||||
"""Wrapper for MonascaClient which returns an authenticated native client.
|
||||
|
||||
"""
|
||||
def create_client(self, version=None, service_type=None):
|
||||
"""Return monasca client."""
|
||||
from monascaclient import client as monasca
|
||||
|
||||
# Change this to use session once it's supported by monascaclient
|
||||
client = monasca.Client(
|
||||
self.choose_version(version),
|
||||
self._get_endpoint(service_type),
|
||||
token=self.keystone.auth_ref.auth_token,
|
||||
timeout=CONF.openstack_client_http_timeout,
|
||||
insecure=self.credential.https_insecure,
|
||||
**self._get_auth_info(project_name_key="tenant_name"))
|
||||
return client
|
||||
|
||||
|
||||
@configure("senlin", default_version="1", default_service_type="clustering",
|
||||
supported_versions=["1"])
|
||||
class Senlin(OSClient):
|
||||
"""Wrapper for SenlinClient which returns an authenticated native client.
|
||||
|
||||
"""
|
||||
def create_client(self, version=None, service_type=None):
|
||||
"""Return senlin client."""
|
||||
from senlinclient import client as senlin
|
||||
|
||||
return senlin.Client(
|
||||
self.choose_version(version),
|
||||
**self._get_auth_info(project_name_key="project_name",
|
||||
cacert_key="cert",
|
||||
endpoint_type="interface"))
|
||||
|
||||
|
||||
@configure("magnum", default_version="1", supported_versions=["1"],
|
||||
default_service_type="container-infra",)
|
||||
class Magnum(OSClient):
|
||||
"""Wrapper for MagnumClient which returns an authenticated native client.
|
||||
|
||||
"""
|
||||
def create_client(self, version=None, service_type=None):
|
||||
"""Return magnum client."""
|
||||
from magnumclient import client as magnum
|
||||
|
||||
api_url = self._get_endpoint(service_type)
|
||||
session = self.keystone.get_session()[0]
|
||||
|
||||
return magnum.Client(
|
||||
session=session,
|
||||
interface=self.credential.endpoint_type,
|
||||
magnum_url=api_url)
|
||||
|
||||
|
||||
@configure("watcher", default_version="1", default_service_type="infra-optim",
|
||||
supported_versions=["1"])
|
||||
class Watcher(OSClient):
|
||||
"""Wrapper for WatcherClient which returns an authenticated native client.
|
||||
|
||||
"""
|
||||
def create_client(self, version=None, service_type=None):
|
||||
"""Return watcher client."""
|
||||
from watcherclient import client as watcher_client
|
||||
watcher_api_url = self._get_endpoint(
|
||||
self.choose_service_type(service_type))
|
||||
client = watcher_client.Client(
|
||||
self.choose_version(version),
|
||||
endpoint=watcher_api_url,
|
||||
session=self.keystone.get_session()[0])
|
||||
return client
|
||||
|
||||
|
||||
class Clients(object):
|
||||
"""This class simplify and unify work with OpenStack python clients."""
|
||||
|
||||
def __init__(self, credential, api_info=None, cache=None):
|
||||
self.credential = credential
|
||||
self.api_info = api_info or {}
|
||||
self.cache = cache or {}
|
||||
|
||||
def __getattr__(self, client_name):
|
||||
"""Lazy load of clients."""
|
||||
return OSClient.get(client_name)(self.credential, self.api_info,
|
||||
self.cache)
|
||||
|
||||
@classmethod
|
||||
def create_from_env(cls):
|
||||
creds = envutils.get_creds_from_env_vars()
|
||||
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."""
|
||||
self.cache = {}
|
||||
|
||||
def verified_keystone(self):
|
||||
"""Ensure keystone endpoints are valid and then authenticate
|
||||
|
||||
:returns: Keystone Client
|
||||
"""
|
||||
# Ensure that user is admin
|
||||
if "admin" not in [role.lower() for role in
|
||||
self.keystone.auth_ref.role_names]:
|
||||
raise exceptions.InvalidAdminException(
|
||||
username=self.credential.username)
|
||||
return self.keystone()
|
||||
|
||||
def services(self):
|
||||
"""Return available services names and types.
|
||||
|
||||
:returns: dict, {"service_type": "service_name", ...}
|
||||
"""
|
||||
if "services_data" not in self.cache:
|
||||
services_data = {}
|
||||
available_services = self.keystone.service_catalog.get_endpoints()
|
||||
for stype in available_services.keys():
|
||||
if stype in consts.ServiceType:
|
||||
services_data[stype] = consts.ServiceType[stype]
|
||||
else:
|
||||
services_data[stype] = "__unknown__"
|
||||
self.cache["services_data"] = services_data
|
||||
|
||||
return self.cache["services_data"]
|
|
@ -0,0 +1,946 @@
|
|||
# Copyright 2013: Mirantis Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import ddt
|
||||
import mock
|
||||
from oslo_config import cfg
|
||||
|
||||
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
|
||||
|
||||
|
||||
@osclients.configure("dummy", supported_versions=("0.1", "1"),
|
||||
default_service_type="bar")
|
||||
class DummyClient(osclients.OSClient):
|
||||
def create_client(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
|
||||
class OSClientTestCaseUtils(object):
|
||||
|
||||
def set_up_keystone_mocks(self):
|
||||
self.ksc_module = mock.MagicMock(__version__="2.0.0")
|
||||
self.ksc_client = mock.MagicMock()
|
||||
self.ksa_identity_plugin = mock.MagicMock()
|
||||
self.ksa_password = mock.MagicMock(
|
||||
return_value=self.ksa_identity_plugin)
|
||||
self.ksa_identity = mock.MagicMock(Password=self.ksa_password)
|
||||
|
||||
self.ksa_auth = mock.MagicMock()
|
||||
self.ksa_session = mock.MagicMock()
|
||||
self.patcher = mock.patch.dict("sys.modules",
|
||||
{"keystoneclient": self.ksc_module,
|
||||
"keystoneauth1": self.ksa_auth})
|
||||
self.patcher.start()
|
||||
self.addCleanup(self.patcher.stop)
|
||||
self.ksc_module.client = self.ksc_client
|
||||
self.ksa_auth.identity = self.ksa_identity
|
||||
self.ksa_auth.session = self.ksa_session
|
||||
|
||||
def make_auth_args(self):
|
||||
auth_kwargs = {
|
||||
"auth_url": "http://auth_url/", "username": "user",
|
||||
"password": "password", "tenant_name": "tenant",
|
||||
"domain_name": "domain", "project_name": "project_name",
|
||||
"project_domain_name": "project_domain_name",
|
||||
"user_domain_name": "user_domain_name",
|
||||
}
|
||||
kwargs = {"https_insecure": False, "https_cacert": None}
|
||||
kwargs.update(auth_kwargs)
|
||||
return auth_kwargs, kwargs
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class OSClientTestCase(test.TestCase, OSClientTestCaseUtils):
|
||||
|
||||
@ddt.data((0.1, True), (1, True), ("0.1", True), ("1", True),
|
||||
(0.2, False), ("foo", False))
|
||||
@ddt.unpack
|
||||
def test_validate_version(self, version, valid):
|
||||
if valid:
|
||||
DummyClient.validate_version(version)
|
||||
else:
|
||||
self.assertRaises(exceptions.ValidationError,
|
||||
DummyClient.validate_version, version)
|
||||
|
||||
def test_choose_service_type(self):
|
||||
default_service_type = "default_service_type"
|
||||
|
||||
@osclients.configure("test_choose_service_type",
|
||||
default_service_type=default_service_type)
|
||||
class FakeClient(osclients.OSClient):
|
||||
create_client = mock.MagicMock()
|
||||
|
||||
fake_client = FakeClient(mock.MagicMock(), {}, {})
|
||||
self.assertEqual(default_service_type,
|
||||
fake_client.choose_service_type())
|
||||
self.assertEqual("foo",
|
||||
fake_client.choose_service_type("foo"))
|
||||
|
||||
@mock.patch("rally.osclients.Keystone.service_catalog")
|
||||
@ddt.data(
|
||||
{"endpoint_type": None, "service_type": None, "region_name": None},
|
||||
{"endpoint_type": "et", "service_type": "st", "region_name": "rn"}
|
||||
)
|
||||
@ddt.unpack
|
||||
def test__get_endpoint(self, mock_keystone_service_catalog, endpoint_type,
|
||||
service_type, 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
|
||||
mock_url_for = mock_keystone_service_catalog.url_for
|
||||
self.assertEqual(mock_url_for.return_value,
|
||||
osclient._get_endpoint(service_type))
|
||||
call_args = {
|
||||
"service_type": mock_choose_service_type.return_value,
|
||||
"region_name": region_name}
|
||||
if endpoint_type:
|
||||
call_args["interface"] = endpoint_type
|
||||
mock_url_for.assert_called_once_with(**call_args)
|
||||
mock_choose_service_type.assert_called_once_with(service_type)
|
||||
|
||||
@mock.patch("rally.osclients.Keystone.get_session")
|
||||
def test__get_session(self, mock_keystone_get_session):
|
||||
osclient = osclients.OSClient(None, None, None)
|
||||
auth_url = "auth_url"
|
||||
version = "version"
|
||||
import warnings
|
||||
with mock.patch.object(warnings, "warn") as mock_warn:
|
||||
self.assertEqual(mock_keystone_get_session.return_value,
|
||||
osclient._get_session(auth_url, version))
|
||||
self.assertFalse(mock_warn.called)
|
||||
mock_keystone_get_session.assert_called_once_with(version)
|
||||
|
||||
|
||||
class CachedTestCase(test.TestCase):
|
||||
|
||||
def test_cached(self):
|
||||
clients = osclients.Clients(mock.MagicMock())
|
||||
client_name = "CachedTestCase.test_cached"
|
||||
fake_client = osclients.configure(client_name)(osclients.OSClient)(
|
||||
clients.credential, clients.api_info, clients.cache)
|
||||
fake_client.create_client = mock.MagicMock()
|
||||
|
||||
self.assertEqual({}, clients.cache)
|
||||
fake_client()
|
||||
self.assertEqual(
|
||||
{client_name: fake_client.create_client.return_value},
|
||||
clients.cache)
|
||||
fake_client.create_client.assert_called_once_with()
|
||||
fake_client()
|
||||
fake_client.create_client.assert_called_once_with()
|
||||
fake_client("2")
|
||||
self.assertEqual(
|
||||
{client_name: fake_client.create_client.return_value,
|
||||
"%s('2',)" % client_name: fake_client.create_client.return_value},
|
||||
clients.cache)
|
||||
clients.clear()
|
||||
self.assertEqual({}, clients.cache)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class TestCreateKeystoneClient(test.TestCase, OSClientTestCaseUtils):
|
||||
|
||||
def setUp(self):
|
||||
super(TestCreateKeystoneClient, self).setUp()
|
||||
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
|
||||
# tightly couples the test implementation to the tested
|
||||
# function's implementation. Ideally, we'd use a fake keystone
|
||||
# but all that's happening here is that it's checking the right
|
||||
# parameters were passed to the various parts that create a
|
||||
# client. Hopefully one day we'll get a real fake from the
|
||||
# keystone guys.
|
||||
self.set_up_keystone_mocks()
|
||||
keystone = osclients.Keystone(self.credential, {}, mock.MagicMock())
|
||||
keystone.get_session = mock.Mock(
|
||||
return_value=(self.ksa_session, self.ksa_identity_plugin,))
|
||||
client = keystone.create_client(version=3)
|
||||
|
||||
kwargs_session = self.credential.to_dict()
|
||||
kwargs_session.update({
|
||||
"auth_url": "http://auth_url/",
|
||||
"session": self.ksa_session,
|
||||
"timeout": 180.0})
|
||||
keystone.get_session.assert_called_with()
|
||||
called_with = self.ksc_client.Client.call_args_list[0][1]
|
||||
self.assertEqual(
|
||||
{"session": self.ksa_session, "timeout": 180.0, "version": "3"},
|
||||
called_with)
|
||||
self.ksc_client.Client.assert_called_once_with(
|
||||
session=self.ksa_session, timeout=180.0, version="3")
|
||||
self.assertIs(client, self.ksc_client.Client())
|
||||
|
||||
def test_create_client_removes_url_path_if_version_specified(self):
|
||||
# If specifying a version on the client creation call, ensure
|
||||
# the auth_url is versionless and the version required is passed
|
||||
# into the Client() call.
|
||||
self.set_up_keystone_mocks()
|
||||
auth_kwargs, all_kwargs = self.make_auth_args()
|
||||
keystone = osclients.Keystone(
|
||||
self.credential, {}, mock.MagicMock())
|
||||
keystone.get_session = mock.Mock(
|
||||
return_value=(self.ksa_session, self.ksa_identity_plugin,))
|
||||
client = keystone.create_client(version="3")
|
||||
|
||||
self.assertIs(client, self.ksc_client.Client())
|
||||
called_with = self.ksc_client.Client.call_args_list[0][1]
|
||||
self.assertEqual(
|
||||
{"session": self.ksa_session, "timeout": 180.0, "version": "3"},
|
||||
called_with)
|
||||
|
||||
@ddt.data({"original": "https://example.com/identity/foo/v3",
|
||||
"cropped": "https://example.com/identity/foo"},
|
||||
{"original": "https://example.com/identity/foo/v3/",
|
||||
"cropped": "https://example.com/identity/foo"},
|
||||
{"original": "https://example.com/identity/foo/v2.0",
|
||||
"cropped": "https://example.com/identity/foo"},
|
||||
{"original": "https://example.com/identity/foo/v2.0/",
|
||||
"cropped": "https://example.com/identity/foo"},
|
||||
{"original": "https://example.com/identity/foo",
|
||||
"cropped": "https://example.com/identity/foo"})
|
||||
@ddt.unpack
|
||||
def test__remove_url_version(self, original, cropped):
|
||||
credential = oscredential.OpenStackCredential(
|
||||
original, "user", "pass", "tenant")
|
||||
keystone = osclients.Keystone(credential, {}, {})
|
||||
self.assertEqual(cropped, keystone._remove_url_version())
|
||||
|
||||
@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 = oscredential.OpenStackCredential(
|
||||
auth_url, "user", "pass", "tenant")
|
||||
self.set_up_keystone_mocks()
|
||||
keystone = osclients.Keystone(credential, {}, {})
|
||||
|
||||
version_data = mock.Mock(return_value=[{"version": (1, 0)}])
|
||||
self.ksa_auth.discover.Discover.return_value = (
|
||||
mock.Mock(version_data=version_data))
|
||||
|
||||
self.assertEqual((self.ksa_session.Session.return_value,
|
||||
self.ksa_identity_plugin),
|
||||
keystone.get_session())
|
||||
if auth_url.endswith("v2.0"):
|
||||
self.ksa_password.assert_called_once_with(
|
||||
auth_url=auth_url, password="pass",
|
||||
tenant_name="tenant", username="user")
|
||||
else:
|
||||
self.ksa_password.assert_called_once_with(
|
||||
auth_url=auth_url, password="pass",
|
||||
tenant_name="tenant", username="user",
|
||||
domain_name=None, project_domain_name=None,
|
||||
user_domain_name=None)
|
||||
self.ksa_session.Session.assert_has_calls(
|
||||
[mock.call(timeout=180.0, verify=True),
|
||||
mock.call(auth=self.ksa_identity_plugin, timeout=180.0,
|
||||
verify=True)])
|
||||
|
||||
def test_keystone_property(self):
|
||||
keystone = osclients.Keystone(None, None, None)
|
||||
self.assertRaises(exceptions.RallyException, lambda: keystone.keystone)
|
||||
|
||||
@mock.patch("rally.osclients.Keystone.get_session")
|
||||
def test_auth_ref(self, mock_keystone_get_session):
|
||||
session = mock.MagicMock()
|
||||
auth_plugin = mock.MagicMock()
|
||||
mock_keystone_get_session.return_value = (session, auth_plugin)
|
||||
cache = {}
|
||||
keystone = osclients.Keystone(None, None, cache)
|
||||
|
||||
self.assertEqual(auth_plugin.get_access.return_value,
|
||||
keystone.auth_ref)
|
||||
self.assertEqual(auth_plugin.get_access.return_value,
|
||||
cache["keystone_auth_ref"])
|
||||
|
||||
# check that auth_ref was cached.
|
||||
keystone.auth_ref
|
||||
mock_keystone_get_session.assert_called_once_with()
|
||||
|
||||
@mock.patch("keystoneauth1.identity.base.BaseIdentityPlugin.get_access")
|
||||
def test_auth_ref_fails(self, mock_get_access):
|
||||
mock_get_access.side_effect = Exception
|
||||
keystone = osclients.Keystone(self.credential, {}, {})
|
||||
|
||||
try:
|
||||
keystone.auth_ref
|
||||
except exceptions.AuthenticationFailed:
|
||||
pass
|
||||
else:
|
||||
self.fail("keystone.auth_ref didn't raise"
|
||||
" exceptions.AuthenticationFailed")
|
||||
|
||||
@mock.patch("rally.osclients.LOG.exception")
|
||||
@mock.patch("rally.osclients.logging.is_debug")
|
||||
@mock.patch("keystoneauth1.identity.base.BaseIdentityPlugin.get_access")
|
||||
def test_auth_ref_debug(self, mock_get_access,
|
||||
mock_is_debug, mock_log_exception):
|
||||
mock_is_debug.return_value = True
|
||||
mock_get_access.side_effect = Exception
|
||||
keystone = osclients.Keystone(self.credential, {}, {})
|
||||
|
||||
try:
|
||||
keystone.auth_ref
|
||||
except exceptions.AuthenticationFailed:
|
||||
pass
|
||||
else:
|
||||
self.fail("keystone.auth_ref didn't raise"
|
||||
" exceptions.AuthenticationFailed")
|
||||
|
||||
mock_log_exception.assert_called_once_with(mock.ANY)
|
||||
mock_is_debug.assert_called_once_with()
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class OSClientsTestCase(test.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(OSClientsTestCase, self).setUp()
|
||||
self.credential = oscredential.OpenStackCredential(
|
||||
"http://auth_url/v2.0", "user", "pass", "tenant")
|
||||
self.clients = osclients.Clients(self.credential, {})
|
||||
|
||||
self.fake_keystone = fakes.FakeKeystoneClient()
|
||||
|
||||
keystone_patcher = mock.patch(
|
||||
"rally.osclients.Keystone.create_client",
|
||||
return_value=self.fake_keystone)
|
||||
self.mock_create_keystone_client = keystone_patcher.start()
|
||||
|
||||
self.auth_ref_patcher = mock.patch("rally.osclients.Keystone.auth_ref")
|
||||
self.auth_ref = self.auth_ref_patcher.start()
|
||||
|
||||
self.service_catalog = self.auth_ref.service_catalog
|
||||
self.service_catalog.url_for = mock.MagicMock()
|
||||
|
||||
def test_create_from_env(self):
|
||||
with mock.patch.dict("os.environ",
|
||||
{"OS_AUTH_URL": "foo_auth_url",
|
||||
"OS_USERNAME": "foo_username",
|
||||
"OS_PASSWORD": "foo_password",
|
||||
"OS_TENANT_NAME": "foo_tenant_name",
|
||||
"OS_REGION_NAME": "foo_region_name"}):
|
||||
clients = osclients.Clients.create_from_env()
|
||||
|
||||
self.assertEqual("foo_auth_url", clients.credential.auth_url)
|
||||
self.assertEqual("foo_username", clients.credential.username)
|
||||
self.assertEqual("foo_password", clients.credential.password)
|
||||
self.assertEqual("foo_tenant_name", clients.credential.tenant_name)
|
||||
self.assertEqual("foo_region_name", clients.credential.region_name)
|
||||
|
||||
def test_keystone(self):
|
||||
self.assertNotIn("keystone", self.clients.cache)
|
||||
client = self.clients.keystone()
|
||||
self.assertEqual(self.fake_keystone, client)
|
||||
credential = {"timeout": cfg.CONF.openstack_client_http_timeout,
|
||||
"insecure": False, "cacert": None}
|
||||
kwargs = self.credential.to_dict()
|
||||
kwargs.update(credential)
|
||||
self.mock_create_keystone_client.assert_called_once_with()
|
||||
self.assertEqual(self.fake_keystone, self.clients.cache["keystone"])
|
||||
|
||||
def test_keystone_versions(self):
|
||||
self.clients.keystone.validate_version(2)
|
||||
self.clients.keystone.validate_version(3)
|
||||
|
||||
def test_keysonte_service_type(self):
|
||||
self.assertRaises(exceptions.RallyException,
|
||||
self.clients.keystone.is_service_type_configurable)
|
||||
|
||||
def test_verified_keystone(self):
|
||||
self.auth_ref.role_names = ["admin"]
|
||||
self.assertEqual(self.mock_create_keystone_client.return_value,
|
||||
self.clients.verified_keystone())
|
||||
|
||||
def test_verified_keystone_user_not_admin(self):
|
||||
self.auth_ref.role_names = ["notadmin"]
|
||||
self.assertRaises(exceptions.InvalidAdminException,
|
||||
self.clients.verified_keystone)
|
||||
|
||||
@mock.patch("rally.osclients.Keystone.get_session")
|
||||
def test_verified_keystone_authentication_fails(self,
|
||||
mock_keystone_get_session):
|
||||
self.auth_ref_patcher.stop()
|
||||
mock_keystone_get_session.side_effect = (
|
||||
exceptions.AuthenticationFailed(
|
||||
username=self.credential.username,
|
||||
project=self.credential.tenant_name,
|
||||
url=self.credential.auth_url,
|
||||
etype=KeyError,
|
||||
error="oops")
|
||||
)
|
||||
self.assertRaises(exceptions.AuthenticationFailed,
|
||||
self.clients.verified_keystone)
|
||||
|
||||
@mock.patch("rally.osclients.Nova._get_endpoint")
|
||||
def test_nova(self, mock_nova__get_endpoint):
|
||||
fake_nova = fakes.FakeNovaClient()
|
||||
mock_nova__get_endpoint.return_value = "http://fake.to:2/fake"
|
||||
mock_nova = mock.MagicMock()
|
||||
mock_nova.client.Client.return_value = fake_nova
|
||||
mock_keystoneauth1 = mock.MagicMock()
|
||||
self.assertNotIn("nova", self.clients.cache)
|
||||
with mock.patch.dict("sys.modules",
|
||||
{"novaclient": mock_nova,
|
||||
"keystoneauth1": mock_keystoneauth1}):
|
||||
mock_keystoneauth1.discover.Discover.return_value = (
|
||||
mock.Mock(version_data=mock.Mock(return_value=[
|
||||
{"version": (2, 0)}]))
|
||||
)
|
||||
client = self.clients.nova()
|
||||
self.assertEqual(fake_nova, client)
|
||||
kw = {
|
||||
"version": "2",
|
||||
"session": mock_keystoneauth1.session.Session(),
|
||||
"endpoint_override": mock_nova__get_endpoint.return_value}
|
||||
mock_nova.client.Client.assert_called_once_with(**kw)
|
||||
self.assertEqual(fake_nova, self.clients.cache["nova"])
|
||||
|
||||
def test_nova_validate_version(self):
|
||||
osclients.Nova.validate_version("2")
|
||||
self.assertRaises(exceptions.RallyException,
|
||||
osclients.Nova.validate_version, "foo")
|
||||
|
||||
def test_nova_service_type(self):
|
||||
self.clients.nova.is_service_type_configurable()
|
||||
|
||||
@mock.patch("rally.osclients.Neutron._get_endpoint")
|
||||
def test_neutron(self, mock_neutron__get_endpoint):
|
||||
fake_neutron = fakes.FakeNeutronClient()
|
||||
mock_neutron__get_endpoint.return_value = "http://fake.to:2/fake"
|
||||
mock_neutron = mock.MagicMock()
|
||||
mock_keystoneauth1 = mock.MagicMock()
|
||||
mock_neutron.client.Client.return_value = fake_neutron
|
||||
self.assertNotIn("neutron", self.clients.cache)
|
||||
with mock.patch.dict("sys.modules",
|
||||
{"neutronclient.neutron": mock_neutron,
|
||||
"keystoneauth1": mock_keystoneauth1}):
|
||||
client = self.clients.neutron()
|
||||
self.assertEqual(fake_neutron, client)
|
||||
kw = {
|
||||
"session": mock_keystoneauth1.session.Session(),
|
||||
"endpoint_override": mock_neutron__get_endpoint.return_value}
|
||||
mock_neutron.client.Client.assert_called_once_with("2.0", **kw)
|
||||
self.assertEqual(fake_neutron, self.clients.cache["neutron"])
|
||||
|
||||
@mock.patch("rally.osclients.Neutron._get_endpoint")
|
||||
def test_neutron_endpoint_type(self, mock_neutron__get_endpoint):
|
||||
fake_neutron = fakes.FakeNeutronClient()
|
||||
mock_neutron__get_endpoint.return_value = "http://fake.to:2/fake"
|
||||
mock_neutron = mock.MagicMock()
|
||||
mock_keystoneauth1 = mock.MagicMock()
|
||||
mock_neutron.client.Client.return_value = fake_neutron
|
||||
self.assertNotIn("neutron", self.clients.cache)
|
||||
self.credential.endpoint_type = "internal"
|
||||
with mock.patch.dict("sys.modules",
|
||||
{"neutronclient.neutron": mock_neutron,
|
||||
"keystoneauth1": mock_keystoneauth1}):
|
||||
client = self.clients.neutron()
|
||||
self.assertEqual(fake_neutron, client)
|
||||
kw = {
|
||||
"session": mock_keystoneauth1.session.Session(),
|
||||
"endpoint_override": mock_neutron__get_endpoint.return_value,
|
||||
"endpoint_type": "internal"}
|
||||
mock_neutron.client.Client.assert_called_once_with("2.0", **kw)
|
||||
self.assertEqual(fake_neutron, self.clients.cache["neutron"])
|
||||
|
||||
@mock.patch("rally.osclients.Heat._get_endpoint")
|
||||
def test_heat(self, mock_heat__get_endpoint):
|
||||
fake_heat = fakes.FakeHeatClient()
|
||||
mock_heat__get_endpoint.return_value = "http://fake.to:2/fake"
|
||||
mock_heat = mock.MagicMock()
|
||||
mock_keystoneauth1 = mock.MagicMock()
|
||||
mock_heat.client.Client.return_value = fake_heat
|
||||
self.assertNotIn("heat", self.clients.cache)
|
||||
with mock.patch.dict("sys.modules",
|
||||
{"heatclient": mock_heat,
|
||||
"keystoneauth1": mock_keystoneauth1}):
|
||||
client = self.clients.heat()
|
||||
self.assertEqual(fake_heat, client)
|
||||
kw = {
|
||||
"session": mock_keystoneauth1.session.Session(),
|
||||
"endpoint": mock_heat__get_endpoint.return_value,
|
||||
"endpoint_override": mock_heat__get_endpoint.return_value}
|
||||
mock_heat.client.Client.assert_called_once_with("1", **kw)
|
||||
self.assertEqual(fake_heat, self.clients.cache["heat"])
|
||||
|
||||
@mock.patch("rally.osclients.Heat._get_endpoint")
|
||||
def test_heat_endpoint_type_interface(self, mock_heat__get_endpoint):
|
||||
fake_heat = fakes.FakeHeatClient()
|
||||
mock_heat__get_endpoint.return_value = "http://fake.to:2/fake"
|
||||
mock_heat = mock.MagicMock()
|
||||
mock_keystoneauth1 = mock.MagicMock()
|
||||
mock_heat.client.Client.return_value = fake_heat
|
||||
self.assertNotIn("heat", self.clients.cache)
|
||||
self.credential.endpoint_type = "internal"
|
||||
self.credential.interface = "internal"
|
||||
with mock.patch.dict("sys.modules",
|
||||
{"heatclient": mock_heat,
|
||||
"keystoneauth1": mock_keystoneauth1}):
|
||||
client = self.clients.heat()
|
||||
self.assertEqual(fake_heat, client)
|
||||
kw = {
|
||||
"session": mock_keystoneauth1.session.Session(),
|
||||
"endpoint": mock_heat__get_endpoint.return_value,
|
||||
"endpoint_override": mock_heat__get_endpoint.return_value,
|
||||
"endpoint_type": "internal",
|
||||
"interface": "internal"}
|
||||
mock_heat.client.Client.assert_called_once_with("1", **kw)
|
||||
self.assertEqual(fake_heat, self.clients.cache["heat"])
|
||||
|
||||
@mock.patch("rally.osclients.Glance._get_endpoint")
|
||||
def test_glance(self, mock_glance__get_endpoint):
|
||||
fake_glance = fakes.FakeGlanceClient()
|
||||
mock_glance = mock.MagicMock()
|
||||
mock_glance__get_endpoint.return_value = "http://fake.to:2/fake"
|
||||
mock_keystoneauth1 = mock.MagicMock()
|
||||
mock_glance.Client = mock.MagicMock(return_value=fake_glance)
|
||||
with mock.patch.dict("sys.modules",
|
||||
{"glanceclient": mock_glance,
|
||||
"keystoneauth1": mock_keystoneauth1}):
|
||||
self.assertNotIn("glance", self.clients.cache)
|
||||
client = self.clients.glance()
|
||||
self.assertEqual(fake_glance, client)
|
||||
kw = {
|
||||
"version": "2",
|
||||
"session": mock_keystoneauth1.session.Session(),
|
||||
"endpoint_override": mock_glance__get_endpoint.return_value}
|
||||
mock_glance.Client.assert_called_once_with(**kw)
|
||||
self.assertEqual(fake_glance, self.clients.cache["glance"])
|
||||
|
||||
@mock.patch("rally.osclients.Cinder._get_endpoint")
|
||||
def test_cinder(self, mock_cinder__get_endpoint):
|
||||
fake_cinder = mock.MagicMock(client=fakes.FakeCinderClient())
|
||||
mock_cinder = mock.MagicMock()
|
||||
mock_cinder.client.Client.return_value = fake_cinder
|
||||
mock_cinder__get_endpoint.return_value = "http://fake.to:2/fake"
|
||||
mock_keystoneauth1 = mock.MagicMock()
|
||||
self.assertNotIn("cinder", self.clients.cache)
|
||||
with mock.patch.dict("sys.modules",
|
||||
{"cinderclient": mock_cinder,
|
||||
"keystoneauth1": mock_keystoneauth1}):
|
||||
client = self.clients.cinder()
|
||||
self.assertEqual(fake_cinder, client)
|
||||
kw = {
|
||||
"session": mock_keystoneauth1.session.Session(),
|
||||
"endpoint_override": mock_cinder__get_endpoint.return_value}
|
||||
mock_cinder.client.Client.assert_called_once_with(
|
||||
"2", **kw)
|
||||
self.assertEqual(fake_cinder, self.clients.cache["cinder"])
|
||||
|
||||
@mock.patch("rally.osclients.Manila._get_endpoint")
|
||||
def test_manila(self, mock_manila__get_endpoint):
|
||||
mock_manila = mock.MagicMock()
|
||||
mock_manila__get_endpoint.return_value = "http://fake.to:2/fake"
|
||||
mock_keystoneauth1 = mock.MagicMock()
|
||||
self.assertNotIn("manila", self.clients.cache)
|
||||
with mock.patch.dict("sys.modules",
|
||||
{"manilaclient": mock_manila,
|
||||
"keystoneauth1": mock_keystoneauth1}):
|
||||
client = self.clients.manila()
|
||||
self.assertEqual(mock_manila.client.Client.return_value, client)
|
||||
kw = {
|
||||
"session": mock_keystoneauth1.session.Session(),
|
||||
"service_catalog_url": mock_manila__get_endpoint.return_value
|
||||
}
|
||||
mock_manila.client.Client.assert_called_once_with("1", **kw)
|
||||
self.assertEqual(
|
||||
mock_manila.client.Client.return_value,
|
||||
self.clients.cache["manila"])
|
||||
|
||||
def test_manila_validate_version(self):
|
||||
osclients.Manila.validate_version("2.0")
|
||||
osclients.Manila.validate_version("2.32")
|
||||
self.assertRaises(exceptions.RallyException,
|
||||
osclients.Manila.validate_version, "foo")
|
||||
|
||||
@mock.patch("rally.osclients.Ceilometer._get_endpoint")
|
||||
def test_ceilometer(self, mock_ceilometer__get_endpoint):
|
||||
fake_ceilometer = fakes.FakeCeilometerClient()
|
||||
mock_ceilometer = mock.MagicMock()
|
||||
mock_ceilometer__get_endpoint.return_value = "http://fake.to:2/fake"
|
||||
mock_keystoneauth1 = mock.MagicMock()
|
||||
mock_ceilometer.client.get_client = mock.MagicMock(
|
||||
return_value=fake_ceilometer)
|
||||
self.assertNotIn("ceilometer", self.clients.cache)
|
||||
with mock.patch.dict("sys.modules",
|
||||
{"ceilometerclient": mock_ceilometer,
|
||||
"keystoneauth1": mock_keystoneauth1}):
|
||||
client = self.clients.ceilometer()
|
||||
self.assertEqual(fake_ceilometer, client)
|
||||
kw = {
|
||||
"session": mock_keystoneauth1.session.Session(),
|
||||
"endpoint_override": mock_ceilometer__get_endpoint.return_value
|
||||
}
|
||||
mock_ceilometer.client.get_client.assert_called_once_with("2",
|
||||
**kw)
|
||||
self.assertEqual(fake_ceilometer,
|
||||
self.clients.cache["ceilometer"])
|
||||
|
||||
def test_gnocchi(self):
|
||||
fake_gnocchi = fakes.FakeGnocchiClient()
|
||||
mock_gnocchi = mock.MagicMock()
|
||||
mock_gnocchi.client.Client.return_value = fake_gnocchi
|
||||
mock_keystoneauth1 = mock.MagicMock()
|
||||
self.assertNotIn("gnocchi", self.clients.cache)
|
||||
with mock.patch.dict("sys.modules",
|
||||
{"gnocchiclient": mock_gnocchi,
|
||||
"keystoneauth1": mock_keystoneauth1}):
|
||||
mock_keystoneauth1.discover.Discover.return_value = (
|
||||
mock.Mock(version_data=mock.Mock(return_value=[
|
||||
{"version": (1, 0)}]))
|
||||
)
|
||||
client = self.clients.gnocchi()
|
||||
|
||||
self.assertEqual(fake_gnocchi, client)
|
||||
kw = {"version": "1",
|
||||
"session": mock_keystoneauth1.session.Session(),
|
||||
"service_type": "metric"}
|
||||
mock_gnocchi.client.Client.assert_called_once_with(**kw)
|
||||
self.assertEqual(fake_gnocchi, self.clients.cache["gnocchi"])
|
||||
|
||||
def test_monasca(self):
|
||||
fake_monasca = fakes.FakeMonascaClient()
|
||||
mock_monasca = mock.MagicMock()
|
||||
mock_monasca.client.Client.return_value = fake_monasca
|
||||
self.assertNotIn("monasca", self.clients.cache)
|
||||
with mock.patch.dict("sys.modules",
|
||||
{"monascaclient": mock_monasca}):
|
||||
client = self.clients.monasca()
|
||||
self.assertEqual(fake_monasca, client)
|
||||
self.service_catalog.url_for.assert_called_once_with(
|
||||
service_type="monitoring",
|
||||
region_name=self.credential.region_name)
|
||||
os_endpoint = self.service_catalog.url_for.return_value
|
||||
kw = {"token": self.auth_ref.auth_token,
|
||||
"timeout": cfg.CONF.openstack_client_http_timeout,
|
||||
"insecure": False, "cacert": None,
|
||||
"username": self.credential.username,
|
||||
"password": self.credential.password,
|
||||
"tenant_name": self.credential.tenant_name,
|
||||
"auth_url": self.credential.auth_url
|
||||
}
|
||||
mock_monasca.client.Client.assert_called_once_with("2_0",
|
||||
os_endpoint,
|
||||
**kw)
|
||||
self.assertEqual(mock_monasca.client.Client.return_value,
|
||||
self.clients.cache["monasca"])
|
||||
|
||||
@mock.patch("rally.osclients.Ironic._get_endpoint")
|
||||
def test_ironic(self, mock_ironic__get_endpoint):
|
||||
fake_ironic = fakes.FakeIronicClient()
|
||||
mock_ironic = mock.MagicMock()
|
||||
mock_ironic.client.get_client = mock.MagicMock(
|
||||
return_value=fake_ironic)
|
||||
mock_ironic__get_endpoint.return_value = "http://fake.to:2/fake"
|
||||
mock_keystoneauth1 = mock.MagicMock()
|
||||
self.assertNotIn("ironic", self.clients.cache)
|
||||
with mock.patch.dict("sys.modules",
|
||||
{"ironicclient": mock_ironic,
|
||||
"keystoneauth1": mock_keystoneauth1}):
|
||||
client = self.clients.ironic()
|
||||
self.assertEqual(fake_ironic, client)
|
||||
kw = {
|
||||
"session": mock_keystoneauth1.session.Session(),
|
||||
"endpoint": mock_ironic__get_endpoint.return_value}
|
||||
mock_ironic.client.get_client.assert_called_once_with("1", **kw)
|
||||
self.assertEqual(fake_ironic, self.clients.cache["ironic"])
|
||||
|
||||
@mock.patch("rally.osclients.Sahara._get_endpoint")
|
||||
def test_sahara(self, mock_sahara__get_endpoint):
|
||||
fake_sahara = fakes.FakeSaharaClient()
|
||||
mock_sahara = mock.MagicMock()
|
||||
mock_sahara.client.Client = mock.MagicMock(return_value=fake_sahara)
|
||||
mock_sahara__get_endpoint.return_value = "http://fake.to:2/fake"
|
||||
mock_keystoneauth1 = mock.MagicMock()
|
||||
self.assertNotIn("sahara", self.clients.cache)
|
||||
with mock.patch.dict("sys.modules",
|
||||
{"saharaclient": mock_sahara,
|
||||
"keystoneauth1": mock_keystoneauth1}):
|
||||
client = self.clients.sahara()
|
||||
self.assertEqual(fake_sahara, client)
|
||||
kw = {
|
||||
"session": mock_keystoneauth1.session.Session(),
|
||||
"sahara_url": mock_sahara__get_endpoint.return_value}
|
||||
mock_sahara.client.Client.assert_called_once_with(1.1, **kw)
|
||||
self.assertEqual(fake_sahara, self.clients.cache["sahara"])
|
||||
|
||||
def test_zaqar(self):
|
||||
fake_zaqar = fakes.FakeZaqarClient()
|
||||
mock_zaqar = mock.MagicMock()
|
||||
mock_zaqar.client.Client = mock.MagicMock(return_value=fake_zaqar)
|
||||
self.assertNotIn("zaqar", self.clients.cache)
|
||||
mock_keystoneauth1 = mock.MagicMock()
|
||||
with mock.patch.dict("sys.modules", {"zaqarclient.queues":
|
||||
mock_zaqar,
|
||||
"keystoneauth1":
|
||||
mock_keystoneauth1}):
|
||||
client = self.clients.zaqar()
|
||||
self.assertEqual(fake_zaqar, client)
|
||||
self.service_catalog.url_for.assert_called_once_with(
|
||||
service_type="messaging",
|
||||
region_name=self.credential.region_name)
|
||||
fake_zaqar_url = self.service_catalog.url_for.return_value
|
||||
mock_zaqar.client.Client.assert_called_once_with(
|
||||
url=fake_zaqar_url, version=1.1,
|
||||
session=mock_keystoneauth1.session.Session())
|
||||
self.assertEqual(fake_zaqar, self.clients.cache["zaqar"],
|
||||
mock_keystoneauth1.session.Session())
|
||||
|
||||
@mock.patch("rally.osclients.Trove._get_endpoint")
|
||||
def test_trove(self, mock_trove__get_endpoint):
|
||||
fake_trove = fakes.FakeTroveClient()
|
||||
mock_trove = mock.MagicMock()
|
||||
mock_trove.client.Client = mock.MagicMock(return_value=fake_trove)
|
||||
mock_trove__get_endpoint.return_value = "http://fake.to:2/fake"
|
||||
mock_keystoneauth1 = mock.MagicMock()
|
||||
self.assertNotIn("trove", self.clients.cache)
|
||||
with mock.patch.dict("sys.modules",
|
||||
{"troveclient": mock_trove,
|
||||
"keystoneauth1": mock_keystoneauth1}):
|
||||
client = self.clients.trove()
|
||||
self.assertEqual(fake_trove, client)
|
||||
kw = {
|
||||
"session": mock_keystoneauth1.session.Session(),
|
||||
"endpoint": mock_trove__get_endpoint.return_value}
|
||||
mock_trove.client.Client.assert_called_once_with("1.0", **kw)
|
||||
self.assertEqual(fake_trove, self.clients.cache["trove"])
|
||||
|
||||
def test_mistral(self):
|
||||
fake_mistral = fakes.FakeMistralClient()
|
||||
mock_mistral = mock.Mock()
|
||||
mock_mistral.client.client.return_value = fake_mistral
|
||||
|
||||
self.assertNotIn("mistral", self.clients.cache)
|
||||
with mock.patch.dict(
|
||||
"sys.modules", {"mistralclient": mock_mistral,
|
||||
"mistralclient.api": mock_mistral}):
|
||||
client = self.clients.mistral()
|
||||
self.assertEqual(fake_mistral, client)
|
||||
self.service_catalog.url_for.assert_called_once_with(
|
||||
service_type="workflowv2",
|
||||
region_name=self.credential.region_name
|
||||
)
|
||||
fake_mistral_url = self.service_catalog.url_for.return_value
|
||||
mock_mistral.client.client.assert_called_once_with(
|
||||
mistral_url=fake_mistral_url,
|
||||
service_type="workflowv2",
|
||||
auth_token=self.auth_ref.auth_token
|
||||
)
|
||||
self.assertEqual(fake_mistral, self.clients.cache["mistral"])
|
||||
|
||||
def test_swift(self):
|
||||
fake_swift = fakes.FakeSwiftClient()
|
||||
mock_swift = mock.MagicMock()
|
||||
mock_swift.client.Connection = mock.MagicMock(return_value=fake_swift)
|
||||
self.assertNotIn("swift", self.clients.cache)
|
||||
with mock.patch.dict("sys.modules", {"swiftclient": mock_swift}):
|
||||
client = self.clients.swift()
|
||||
self.assertEqual(fake_swift, client)
|
||||
self.service_catalog.url_for.assert_called_once_with(
|
||||
service_type="object-store",
|
||||
region_name=self.credential.region_name)
|
||||
kw = {"retries": 1,
|
||||
"preauthurl": self.service_catalog.url_for.return_value,
|
||||
"preauthtoken": self.auth_ref.auth_token,
|
||||
"insecure": False,
|
||||
"cacert": None,
|
||||
"user": self.credential.username,
|
||||
"tenant_name": self.credential.tenant_name,
|
||||
}
|
||||
mock_swift.client.Connection.assert_called_once_with(**kw)
|
||||
self.assertEqual(fake_swift, self.clients.cache["swift"])
|
||||
|
||||
@mock.patch("rally.osclients.EC2._get_endpoint")
|
||||
def test_ec2(self, mock_ec2__get_endpoint):
|
||||
mock_boto = mock.Mock()
|
||||
self.fake_keystone.ec2 = mock.Mock()
|
||||
self.fake_keystone.ec2.create.return_value = mock.Mock(
|
||||
access="fake_access", secret="fake_secret")
|
||||
mock_ec2__get_endpoint.return_value = "http://fake.to:1/fake"
|
||||
fake_ec2 = fakes.FakeEC2Client()
|
||||
mock_boto.connect_ec2_endpoint.return_value = fake_ec2
|
||||
|
||||
self.assertNotIn("ec2", self.clients.cache)
|
||||
with mock.patch.dict("sys.modules", {"boto": mock_boto}):
|
||||
client = self.clients.ec2()
|
||||
|
||||
self.assertEqual(fake_ec2, client)
|
||||
kw = {
|
||||
"url": "http://fake.to:1/fake",
|
||||
"aws_access_key_id": "fake_access",
|
||||
"aws_secret_access_key": "fake_secret",
|
||||
"is_secure": self.credential.insecure,
|
||||
}
|
||||
mock_boto.connect_ec2_endpoint.assert_called_once_with(**kw)
|
||||
self.assertEqual(fake_ec2, self.clients.cache["ec2"])
|
||||
|
||||
@mock.patch("rally.osclients.Keystone.service_catalog")
|
||||
def test_services(self, mock_keystone_service_catalog):
|
||||
available_services = {consts.ServiceType.IDENTITY: {},
|
||||
consts.ServiceType.COMPUTE: {},
|
||||
"some_service": {}}
|
||||
mock_get_endpoints = mock_keystone_service_catalog.get_endpoints
|
||||
mock_get_endpoints.return_value = available_services
|
||||
clients = osclients.Clients(self.credential)
|
||||
|
||||
self.assertEqual(
|
||||
{consts.ServiceType.IDENTITY: consts.Service.KEYSTONE,
|
||||
consts.ServiceType.COMPUTE: consts.Service.NOVA,
|
||||
"some_service": "__unknown__"},
|
||||
clients.services())
|
||||
|
||||
def test_murano(self):
|
||||
fake_murano = fakes.FakeMuranoClient()
|
||||
mock_murano = mock.Mock()
|
||||
mock_murano.client.Client.return_value = fake_murano
|
||||
self.assertNotIn("murano", self.clients.cache)
|
||||
with mock.patch.dict("sys.modules", {"muranoclient": mock_murano}):
|
||||
client = self.clients.murano()
|
||||
self.assertEqual(fake_murano, client)
|
||||
self.service_catalog.url_for.assert_called_once_with(
|
||||
service_type="application-catalog",
|
||||
region_name=self.credential.region_name
|
||||
)
|
||||
kw = {"endpoint": self.service_catalog.url_for.return_value,
|
||||
"token": self.auth_ref.auth_token}
|
||||
mock_murano.client.Client.assert_called_once_with("1", **kw)
|
||||
self.assertEqual(fake_murano, self.clients.cache["murano"])
|
||||
|
||||
@mock.patch("rally.osclients.Keystone.get_session")
|
||||
@ddt.data(
|
||||
{},
|
||||
{"version": "2"},
|
||||
{"version": "1"},
|
||||
{"version": None}
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_designate(self, mock_keystone_get_session, version=None):
|
||||
fake_designate = fakes.FakeDesignateClient()
|
||||
mock_designate = mock.Mock()
|
||||
mock_designate.client.Client.return_value = fake_designate
|
||||
|
||||
mock_keystone_get_session.return_value = ("fake_session",
|
||||
"fake_auth_plugin")
|
||||
|
||||
self.assertNotIn("designate", self.clients.cache)
|
||||
with mock.patch.dict("sys.modules",
|
||||
{"designateclient": mock_designate}):
|
||||
if version is not None:
|
||||
client = self.clients.designate(version=version)
|
||||
else:
|
||||
client = self.clients.designate()
|
||||
self.assertEqual(fake_designate, client)
|
||||
self.service_catalog.url_for.assert_called_once_with(
|
||||
service_type="dns",
|
||||
region_name=self.credential.region_name
|
||||
)
|
||||
|
||||
default = version or "1"
|
||||
|
||||
# Check that we append /v<version>
|
||||
url = self.service_catalog.url_for.return_value
|
||||
url.__iadd__.assert_called_once_with("/v%s" % default)
|
||||
|
||||
mock_keystone_get_session.assert_called_once_with()
|
||||
|
||||
if version == "2":
|
||||
mock_designate.client.Client.assert_called_once_with(
|
||||
version,
|
||||
endpoint_override=url.__iadd__.return_value,
|
||||
session="fake_session")
|
||||
elif version == "1":
|
||||
mock_designate.client.Client.assert_called_once_with(
|
||||
version,
|
||||
endpoint=url.__iadd__.return_value,
|
||||
session="fake_session")
|
||||
|
||||
key = "designate"
|
||||
if version is not None:
|
||||
key += "%s" % {"version": version}
|
||||
self.assertEqual(fake_designate, self.clients.cache[key])
|
||||
|
||||
def test_senlin(self):
|
||||
mock_senlin = mock.MagicMock()
|
||||
self.assertNotIn("senlin", self.clients.cache)
|
||||
with mock.patch.dict("sys.modules", {"senlinclient": mock_senlin}):
|
||||
client = self.clients.senlin()
|
||||
self.assertEqual(mock_senlin.client.Client.return_value, client)
|
||||
mock_senlin.client.Client.assert_called_once_with(
|
||||
"1",
|
||||
username=self.credential.username,
|
||||
password=self.credential.password,
|
||||
project_name=self.credential.tenant_name,
|
||||
cert=self.credential.cacert,
|
||||
auth_url=self.credential.auth_url)
|
||||
self.assertEqual(
|
||||
mock_senlin.client.Client.return_value,
|
||||
self.clients.cache["senlin"])
|
||||
|
||||
@mock.patch("rally.osclients.Magnum._get_endpoint")
|
||||
def test_magnum(self, mock_magnum__get_endpoint):
|
||||
fake_magnum = fakes.FakeMagnumClient()
|
||||
mock_magnum = mock.MagicMock()
|
||||
mock_magnum.client.Client.return_value = fake_magnum
|
||||
|
||||
mock_magnum__get_endpoint.return_value = "http://fake.to:2/fake"
|
||||
mock_keystoneauth1 = mock.MagicMock()
|
||||
|
||||
self.assertNotIn("magnum", self.clients.cache)
|
||||
with mock.patch.dict("sys.modules",
|
||||
{"magnumclient": mock_magnum,
|
||||
"keystoneauth1": mock_keystoneauth1}):
|
||||
client = self.clients.magnum()
|
||||
|
||||
self.assertEqual(fake_magnum, client)
|
||||
kw = {
|
||||
"interface": self.credential.endpoint_type,
|
||||
"session": mock_keystoneauth1.session.Session(),
|
||||
"magnum_url": mock_magnum__get_endpoint.return_value}
|
||||
|
||||
mock_magnum.client.Client.assert_called_once_with(**kw)
|
||||
self.assertEqual(fake_magnum, self.clients.cache["magnum"])
|
||||
|
||||
@mock.patch("rally.osclients.Watcher._get_endpoint")
|
||||
def test_watcher(self, mock_watcher__get_endpoint):
|
||||
fake_watcher = fakes.FakeWatcherClient()
|
||||
mock_watcher = mock.MagicMock()
|
||||
mock_watcher__get_endpoint.return_value = "http://fake.to:2/fake"
|
||||
mock_keystoneauth1 = mock.MagicMock()
|
||||
mock_watcher.client.Client.return_value = fake_watcher
|
||||
self.assertNotIn("watcher", self.clients.cache)
|
||||
with mock.patch.dict("sys.modules",
|
||||
{"watcherclient": mock_watcher,
|
||||
"keystoneauth1": mock_keystoneauth1}):
|
||||
client = self.clients.watcher()
|
||||
|
||||
self.assertEqual(fake_watcher, client)
|
||||
kw = {
|
||||
"session": mock_keystoneauth1.session.Session(),
|
||||
"endpoint": mock_watcher__get_endpoint.return_value}
|
||||
|
||||
mock_watcher.client.Client.assert_called_once_with("1", **kw)
|
||||
self.assertEqual(fake_watcher, self.clients.cache["watcher"])
|
Loading…
Reference in New Issue