[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:
parent
91f22381a2
commit
7792aa71b7
@ -50,12 +50,16 @@ then
|
|||||||
cat >$1 <<EOF
|
cat >$1 <<EOF
|
||||||
{
|
{
|
||||||
"type": "ExistingCloud",
|
"type": "ExistingCloud",
|
||||||
"auth_url": "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v$IDENTITY_API_VERSION",
|
"creds": {
|
||||||
"region_name": "$REGION_NAME",
|
"openstack": {
|
||||||
"admin": {
|
"auth_url": "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v$IDENTITY_API_VERSION",
|
||||||
"username": "admin",
|
"region_name": "$REGION_NAME",
|
||||||
"password": "$ADMIN_PASSWORD",
|
"admin": {
|
||||||
"tenant_name": "admin",
|
"username": "admin",
|
||||||
|
"password": "$ADMIN_PASSWORD",
|
||||||
|
"tenant_name": "admin",
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
@ -65,14 +69,18 @@ then
|
|||||||
cat >$1 <<EOF
|
cat >$1 <<EOF
|
||||||
{
|
{
|
||||||
"type": "ExistingCloud",
|
"type": "ExistingCloud",
|
||||||
"auth_url": "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v$IDENTITY_API_VERSION",
|
"creds": {
|
||||||
"region_name": "$REGION_NAME",
|
"openstack": {
|
||||||
"admin": {
|
"auth_url": "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v$IDENTITY_API_VERSION",
|
||||||
"username": "admin",
|
"region_name": "$REGION_NAME",
|
||||||
"password": "$ADMIN_PASSWORD",
|
"admin": {
|
||||||
"project_name": "admin",
|
"username": "admin",
|
||||||
"user_domain_name": "Default",
|
"password": "$ADMIN_PASSWORD",
|
||||||
"project_domain_name": "Default"
|
"project_name": "admin",
|
||||||
|
"user_domain_name": "Default",
|
||||||
|
"project_domain_name": "Default"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
19
rally/api.py
19
rally/api.py
@ -33,7 +33,6 @@ from rally.common import version as rally_version
|
|||||||
from rally import consts
|
from rally import consts
|
||||||
from rally.deployment import engine as deploy_engine
|
from rally.deployment import engine as deploy_engine
|
||||||
from rally import exceptions
|
from rally import exceptions
|
||||||
from rally import osclients
|
|
||||||
from rally.task import engine
|
from rally.task import engine
|
||||||
from rally.verification import context as vcontext
|
from rally.verification import context as vcontext
|
||||||
from rally.verification import manager as vmanager
|
from rally.verification import manager as vmanager
|
||||||
@ -149,10 +148,9 @@ class _Deployment(object):
|
|||||||
:param deployment: Deployment object
|
:param deployment: Deployment object
|
||||||
:returns: Service list
|
: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"]
|
admin = deployment.get_credentials_for("openstack")["admin"]
|
||||||
clients = osclients.Clients(objects.Credential(**admin))
|
return admin.list_services()
|
||||||
return clients.services()
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def list(status=None, parent_uuid=None, name=None):
|
def list(status=None, parent_uuid=None, name=None):
|
||||||
@ -168,13 +166,12 @@ class _Deployment(object):
|
|||||||
|
|
||||||
:returns: Service list
|
:returns: Service list
|
||||||
"""
|
"""
|
||||||
# TODO(astudenov): put this work into Credential plugins
|
# TODO(astudenov): make this method platform independent
|
||||||
services = cls.service_list(deployment)
|
creds = deployment.get_credentials_for("openstack")
|
||||||
users = deployment.get_credentials_for("openstack")["users"]
|
creds["admin"].verify_connection()
|
||||||
for endpoint_dict in users:
|
for user in creds["users"]:
|
||||||
osclients.Clients(objects.Credential(**endpoint_dict)).keystone()
|
user.verify_connection()
|
||||||
|
return creds["admin"].list_services()
|
||||||
return services
|
|
||||||
|
|
||||||
|
|
||||||
class _Task(object):
|
class _Task(object):
|
||||||
|
@ -191,11 +191,13 @@ class DeploymentCommands(object):
|
|||||||
metavar="<uuid>", required=False,
|
metavar="<uuid>", required=False,
|
||||||
help="UUID or name of the deployment.")
|
help="UUID or name of the deployment.")
|
||||||
@envutils.with_default_deployment()
|
@envutils.with_default_deployment()
|
||||||
|
@plugins.ensure_plugins_are_loaded
|
||||||
def show(self, api, deployment=None):
|
def show(self, api, deployment=None):
|
||||||
"""Show the credentials of the deployment.
|
"""Show the credentials of the deployment.
|
||||||
|
|
||||||
:param deployment: UUID or name 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",
|
headers = ["auth_url", "username", "password", "tenant_name",
|
||||||
"region_name", "endpoint_type"]
|
"region_name", "endpoint_type"]
|
||||||
@ -208,7 +210,7 @@ class DeploymentCommands(object):
|
|||||||
credentials = users + [admin] if admin else users
|
credentials = users + [admin] if admin else users
|
||||||
|
|
||||||
for ep in credentials:
|
for ep in credentials:
|
||||||
data = ["***" if m == "password" else ep.get(m, "")
|
data = ["***" if m == "password" else getattr(ep, m, "")
|
||||||
for m in headers]
|
for m in headers]
|
||||||
table_rows.append(utils.Struct(**dict(zip(headers, data))))
|
table_rows.append(utils.Struct(**dict(zip(headers, data))))
|
||||||
cliutils.print_list(table_rows, headers)
|
cliutils.print_list(table_rows, headers)
|
||||||
@ -217,11 +219,13 @@ class DeploymentCommands(object):
|
|||||||
metavar="<uuid>", required=False,
|
metavar="<uuid>", required=False,
|
||||||
help="UUID or name of the deployment.")
|
help="UUID or name of the deployment.")
|
||||||
@envutils.with_default_deployment()
|
@envutils.with_default_deployment()
|
||||||
|
@plugins.ensure_plugins_are_loaded
|
||||||
def check(self, api, deployment=None):
|
def check(self, api, deployment=None):
|
||||||
"""Check keystone authentication and list all available services.
|
"""Check keystone authentication and list all available services.
|
||||||
|
|
||||||
:param deployment: UUID or name of the deployment
|
:param deployment: UUID or name of the deployment
|
||||||
"""
|
"""
|
||||||
|
# TODO(astudenov): make this method platform independent
|
||||||
headers = ["services", "type", "status"]
|
headers = ["services", "type", "status"]
|
||||||
table_rows = []
|
table_rows = []
|
||||||
try:
|
try:
|
||||||
@ -235,7 +239,7 @@ class DeploymentCommands(object):
|
|||||||
services = api.deployment.check(deployment)
|
services = api.deployment.check(deployment)
|
||||||
except keystone_exceptions.ConnectionRefused:
|
except keystone_exceptions.ConnectionRefused:
|
||||||
admin = deployment.get_credentials_for("openstack")["admin"]
|
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)
|
return(1)
|
||||||
|
|
||||||
except exceptions.InvalidArgumentsException:
|
except exceptions.InvalidArgumentsException:
|
||||||
@ -296,11 +300,13 @@ class DeploymentCommands(object):
|
|||||||
@cliutils.args("--deployment", dest="deployment", type=str,
|
@cliutils.args("--deployment", dest="deployment", type=str,
|
||||||
metavar="<uuid>", required=False,
|
metavar="<uuid>", required=False,
|
||||||
help="UUID or name of a deployment.")
|
help="UUID or name of a deployment.")
|
||||||
|
@plugins.ensure_plugins_are_loaded
|
||||||
def use(self, api, deployment):
|
def use(self, api, deployment):
|
||||||
"""Set active deployment.
|
"""Set active deployment.
|
||||||
|
|
||||||
:param deployment: UUID or name of the deployment
|
:param deployment: UUID or name of the deployment
|
||||||
"""
|
"""
|
||||||
|
# TODO(astudenov): make this method platform independent
|
||||||
try:
|
try:
|
||||||
deployment = api.deployment.get(deployment)
|
deployment = api.deployment.get(deployment)
|
||||||
print("Using deployment: %s" % deployment["uuid"])
|
print("Using deployment: %s" % deployment["uuid"])
|
||||||
@ -309,8 +315,9 @@ class DeploymentCommands(object):
|
|||||||
deployment["uuid"])
|
deployment["uuid"])
|
||||||
|
|
||||||
creds = deployment.get_credentials_for("openstack")
|
creds = deployment.get_credentials_for("openstack")
|
||||||
|
credential = creds["admin"] or creds["users"][0]
|
||||||
self._update_openrc_deployment_file(
|
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"
|
print("~/.rally/openrc was updated\n\nHINTS:\n"
|
||||||
"\n* To use standard OpenStack clients, set up your env by "
|
"\n* To use standard OpenStack clients, set up your env by "
|
||||||
"running:\n\tsource ~/.rally/openrc\n"
|
"running:\n\tsource ~/.rally/openrc\n"
|
||||||
|
@ -13,43 +13,16 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from rally import consts
|
from rally.plugins.openstack import credential
|
||||||
|
|
||||||
|
# TODO(astudenov): remove this class in future releases
|
||||||
|
|
||||||
|
|
||||||
class Credential(object):
|
class Credential(credential.OpenStackCredential):
|
||||||
|
"""Deprecated version of OpenStackCredential class"""
|
||||||
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
|
|
||||||
|
|
||||||
def to_dict(self, include_permission=False):
|
def to_dict(self, include_permission=False):
|
||||||
dct = {"auth_url": self.auth_url, "username": self.username,
|
dct = super(Credential, self).to_dict()
|
||||||
"password": self.password, "tenant_name": self.tenant_name,
|
if not include_permission:
|
||||||
"region_name": self.region_name,
|
dct.pop("permission")
|
||||||
"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
|
|
||||||
return dct
|
return dct
|
||||||
|
@ -21,6 +21,7 @@ from rally.common.i18n import _, _LW
|
|||||||
from rally.common import db
|
from rally.common import db
|
||||||
from rally.common import logging
|
from rally.common import logging
|
||||||
from rally import consts
|
from rally import consts
|
||||||
|
from rally.deployment import credential
|
||||||
from rally import exceptions
|
from rally import exceptions
|
||||||
|
|
||||||
|
|
||||||
@ -34,7 +35,7 @@ CREDENTIALS_SCHEMA = {
|
|||||||
"items": {
|
"items": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"admin": {"type": "object"},
|
"admin": {"type": ["object", "null"]},
|
||||||
"users": {
|
"users": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {"type": "object"}
|
"items": {"type": "object"}
|
||||||
@ -97,12 +98,17 @@ class Deployment(object):
|
|||||||
|
|
||||||
def get_credentials_for(self, namespace):
|
def get_credentials_for(self, namespace):
|
||||||
try:
|
try:
|
||||||
return self.deployment["credentials"][namespace][0]
|
creds = self.deployment["credentials"][namespace][0]
|
||||||
except (KeyError, IndexError) as e:
|
except (KeyError, IndexError) as e:
|
||||||
LOG.exception(e)
|
LOG.exception(e)
|
||||||
raise exceptions.RallyException(_(
|
raise exceptions.RallyException(_(
|
||||||
"No credentials found for %s") % namespace)
|
"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):
|
def set_started(self):
|
||||||
self._update({"started_at": dt.datetime.now(),
|
self._update({"started_at": dt.datetime.now(),
|
||||||
"status": consts.DeployStatus.DEPLOY_STARTED})
|
"status": consts.DeployStatus.DEPLOY_STARTED})
|
||||||
|
89
rally/deployment/credential.py
Normal file
89
rally/deployment/credential.py
Normal 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"""
|
@ -19,7 +19,6 @@ import six
|
|||||||
|
|
||||||
from rally.common.i18n import _
|
from rally.common.i18n import _
|
||||||
from rally.common import logging
|
from rally.common import logging
|
||||||
from rally.common import objects
|
|
||||||
from rally import consts
|
from rally import consts
|
||||||
from rally.deployment import engine
|
from rally.deployment import engine
|
||||||
from rally.deployment.serverprovider import provider
|
from rally.deployment.serverprovider import provider
|
||||||
@ -133,17 +132,13 @@ class DevstackEngine(engine.Engine):
|
|||||||
stdin=local_conf)
|
stdin=local_conf)
|
||||||
devstack_server.ssh.run("~/devstack/stack.sh")
|
devstack_server.ssh.run("~/devstack/stack.sh")
|
||||||
|
|
||||||
admin_credential = objects.Credential(
|
admin_dict = dict(
|
||||||
"http://%s:5000/v2.0/" % self.servers[0].host, "admin",
|
auth_url="http://%s:5000/v2.0/" % self.servers[0].host,
|
||||||
self.local_conf["ADMIN_PASSWORD"], "admin",
|
username="admin",
|
||||||
consts.EndpointPermission.ADMIN)
|
password=self.local_conf["ADMIN_PASSWORD"],
|
||||||
return {
|
tenant_name="admin",
|
||||||
"openstack": [
|
permission=consts.EndpointPermission.ADMIN)
|
||||||
{
|
return {"openstack": [{"admin": admin_dict, "users": []}]}
|
||||||
"admin": admin_credential.to_dict(include_permission=True),
|
|
||||||
"users": []
|
|
||||||
}
|
|
||||||
]}
|
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
for resource in self.deployment.get_resources(type="credentials"):
|
for resource in self.deployment.get_resources(type="credentials"):
|
||||||
|
@ -13,16 +13,61 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from rally.common import objects
|
import copy
|
||||||
|
|
||||||
|
from rally.common import logging
|
||||||
from rally import consts
|
from rally import consts
|
||||||
|
from rally.deployment import credential
|
||||||
from rally.deployment import engine
|
from rally.deployment import engine
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@engine.configure(name="ExistingCloud")
|
@engine.configure(name="ExistingCloud")
|
||||||
class ExistingCloud(engine.Engine):
|
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
|
.. code-block:: json
|
||||||
|
|
||||||
@ -40,7 +85,7 @@ class ExistingCloud(engine.Engine):
|
|||||||
"https_cacert": "",
|
"https_cacert": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
Or, using keystone v3 API endpoint:
|
keystone v3 API endpoint:
|
||||||
|
|
||||||
.. code-block:: json
|
.. code-block:: json
|
||||||
|
|
||||||
@ -60,114 +105,132 @@ class ExistingCloud(engine.Engine):
|
|||||||
"https_cacert": "",
|
"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",
|
"type": "object",
|
||||||
|
"oneOf": [
|
||||||
"definitions": {
|
{
|
||||||
"user": {
|
"description": "Keystone V2.0",
|
||||||
"type": "object",
|
"properties": {
|
||||||
"oneOf": [
|
"username": {"type": "string"},
|
||||||
{
|
"password": {"type": "string"},
|
||||||
"description": "Keystone V2.0",
|
"tenant_name": {"type": "string"},
|
||||||
"properties": {
|
},
|
||||||
"username": {"type": "string"},
|
"required": ["username", "password", "tenant_name"],
|
||||||
"password": {"type": "string"},
|
"additionalProperties": False
|
||||||
"tenant_name": {"type": "string"},
|
},
|
||||||
},
|
{
|
||||||
"required": ["username", "password", "tenant_name"],
|
"description": "Keystone V3.0",
|
||||||
"additionalProperties": False
|
"properties": {
|
||||||
},
|
"username": {"type": "string"},
|
||||||
{
|
"password": {"type": "string"},
|
||||||
"description": "Keystone V3.0",
|
"domain_name": {"type": "string"},
|
||||||
"properties": {
|
"user_domain_name": {"type": "string"},
|
||||||
"username": {"type": "string"},
|
"project_name": {"type": "string"},
|
||||||
"password": {"type": "string"},
|
"project_domain_name": {"type": "string"},
|
||||||
"domain_name": {"type": "string"},
|
},
|
||||||
"user_domain_name": {"type": "string"},
|
"required": ["username", "password", "project_name"],
|
||||||
"project_name": {"type": "string"},
|
"additionalProperties": False
|
||||||
"project_domain_name": {"type": "string"},
|
|
||||||
},
|
|
||||||
"required": ["username", "password", "project_name"],
|
|
||||||
"additionalProperties": False
|
|
||||||
}
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
},
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
OLD_CONFIG_SCHEMA = {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Deprecated schema (openstack only)",
|
||||||
"properties": {
|
"properties": {
|
||||||
"type": {"type": "string"},
|
"type": {"type": "string"},
|
||||||
"auth_url": {"type": "string"},
|
"auth_url": {"type": "string"},
|
||||||
"region_name": {"type": "string"},
|
"region_name": {"type": "string"},
|
||||||
"endpoint": {"oneOf": [
|
# NOTE(andreykurilin): it looks like we do not use endpoint
|
||||||
# NOTE(andreykurilin): it looks like we do not use endpoint
|
# var at all
|
||||||
# var at all
|
"endpoint": {"type": ["string", "null"]},
|
||||||
{"type": "string", "description": ""},
|
|
||||||
{"type": "null", "description": ""}]},
|
|
||||||
"endpoint_type": {"enum": [consts.EndpointType.ADMIN,
|
"endpoint_type": {"enum": [consts.EndpointType.ADMIN,
|
||||||
consts.EndpointType.INTERNAL,
|
consts.EndpointType.INTERNAL,
|
||||||
consts.EndpointType.PUBLIC,
|
consts.EndpointType.PUBLIC,
|
||||||
None]},
|
None]},
|
||||||
"https_insecure": {"type": "boolean"},
|
"https_insecure": {"type": "boolean"},
|
||||||
"https_cacert": {"type": "string"},
|
"https_cacert": {"type": "string"},
|
||||||
"admin": {"$ref": "#/definitions/user"},
|
"admin": USER_SCHEMA,
|
||||||
"users": {
|
"users": {"type": "array", "items": USER_SCHEMA},
|
||||||
"type": "array",
|
|
||||||
"items": {"$ref": "#/definitions/user"}
|
|
||||||
},
|
|
||||||
"extra": {"type": "object", "additionalProperties": True}
|
"extra": {"type": "object", "additionalProperties": True}
|
||||||
},
|
},
|
||||||
"required": ["type", "auth_url", "admin"],
|
"required": ["type", "auth_url", "admin"],
|
||||||
"additionalProperties": False
|
"additionalProperties": False
|
||||||
}
|
}
|
||||||
|
|
||||||
def _create_credential(self, common, user, permission):
|
NEW_CONFIG_SCHEMA = {
|
||||||
return objects.Credential(
|
"type": "object",
|
||||||
common["auth_url"], user["username"], user["password"],
|
"description": "New schema for multiplatform deployment",
|
||||||
tenant_name=user.get("project_name", user.get("tenant_name")),
|
"properties": {
|
||||||
permission=permission,
|
"type": {"enum": ["ExistingCloud"]},
|
||||||
region_name=common.get("region_name"),
|
"creds": {
|
||||||
endpoint_type=common.get("endpoint_type"),
|
"type": "object",
|
||||||
endpoint=common.get("endpoint"),
|
"patternProperties": {
|
||||||
domain_name=user.get("domain_name"),
|
"^[a-z0-9_-]+$": {
|
||||||
user_domain_name=user.get("user_domain_name", None),
|
"oneOf": [
|
||||||
project_domain_name=user.get("project_domain_name", None),
|
{
|
||||||
https_insecure=common.get("https_insecure", False),
|
"description": "Single credential",
|
||||||
https_cacert=common.get("https_cacert")
|
"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):
|
def deploy(self):
|
||||||
permissions = consts.EndpointPermission
|
if "creds" not in self.config:
|
||||||
|
LOG.warning("Old config schema is deprecated since Rally 0.10.0. "
|
||||||
users = [self._create_credential(self.config, user, permissions.USER)
|
"Please use new config schema for ExistingCloud")
|
||||||
for user in self.config.get("users", [])]
|
creds_config = self._get_creds(self.config)
|
||||||
users = [user.to_dict(include_permission=True) for user in users]
|
parsed_credentials = {}
|
||||||
|
for platform, config in creds_config.items():
|
||||||
admin = self._create_credential(self.config,
|
builder_cls = credential.get_builder(platform)
|
||||||
self.config.get("admin"),
|
credentials = []
|
||||||
permissions.ADMIN)
|
for creds in config:
|
||||||
admin = admin.to_dict(include_permission=True)
|
builder = builder_cls(creds)
|
||||||
|
credentials.append(builder.build_credentials())
|
||||||
return {"openstack": [{"admin": admin, "users": users}]}
|
parsed_credentials[platform] = credentials
|
||||||
|
return parsed_credentials
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
pass
|
pass
|
||||||
|
@ -150,9 +150,7 @@ class LxcEngine(engine.Engine):
|
|||||||
if network:
|
if network:
|
||||||
network += 1
|
network += 1
|
||||||
|
|
||||||
admin = objects.Credential("", "", "", "").to_dict(
|
return {"openstack": [{"admin": None, "users": []}]}
|
||||||
include_permission=True)
|
|
||||||
return {"openstack": [{"admin": admin, "users": []}]}
|
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
resources = self.deployment.get_resources()
|
resources = self.deployment.get_resources()
|
||||||
|
@ -21,10 +21,9 @@ import novaclient.exceptions
|
|||||||
|
|
||||||
from rally.common.i18n import _
|
from rally.common.i18n import _
|
||||||
from rally.common import logging
|
from rally.common import logging
|
||||||
from rally.common import objects
|
|
||||||
from rally.deployment.serverprovider import provider
|
from rally.deployment.serverprovider import provider
|
||||||
from rally import exceptions
|
from rally import exceptions
|
||||||
from rally import osclients
|
from rally.plugins.openstack import credential
|
||||||
from rally.task import utils
|
from rally.task import utils
|
||||||
|
|
||||||
|
|
||||||
@ -144,11 +143,13 @@ class OpenStackProvider(provider.ProviderFactory):
|
|||||||
|
|
||||||
def __init__(self, deployment, config):
|
def __init__(self, deployment, config):
|
||||||
super(OpenStackProvider, self).__init__(deployment, config)
|
super(OpenStackProvider, self).__init__(deployment, config)
|
||||||
user_credential = objects.Credential(
|
user_credential = credential.OpenStackCredential(
|
||||||
config["auth_url"], config["user"],
|
auth_url=config["auth_url"],
|
||||||
config["password"], config["tenant"],
|
username=config["user"],
|
||||||
|
password=config["password"],
|
||||||
|
tenant_name=config["tenant"],
|
||||||
region_name=config.get("region"))
|
region_name=config.get("region"))
|
||||||
clients = osclients.Clients(user_credential)
|
clients = user_credential.clients()
|
||||||
self.nova = clients.nova()
|
self.nova = clients.nova()
|
||||||
self.sg = None
|
self.sg = None
|
||||||
try:
|
try:
|
||||||
|
@ -22,7 +22,6 @@ from six.moves.urllib import parse
|
|||||||
from rally.cli import envutils
|
from rally.cli import envutils
|
||||||
from rally.common.i18n import _
|
from rally.common.i18n import _
|
||||||
from rally.common import logging
|
from rally.common import logging
|
||||||
from rally.common import objects
|
|
||||||
from rally.common.plugin import plugin
|
from rally.common.plugin import plugin
|
||||||
from rally import consts
|
from rally import consts
|
||||||
from rally import exceptions
|
from rally import exceptions
|
||||||
@ -687,10 +686,10 @@ class Watcher(OSClient):
|
|||||||
class Clients(object):
|
class Clients(object):
|
||||||
"""This class simplify and unify work with OpenStack python clients."""
|
"""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.credential = credential
|
||||||
self.api_info = api_info or {}
|
self.api_info = api_info or {}
|
||||||
self.cache = {}
|
self.cache = cache or {}
|
||||||
|
|
||||||
def __getattr__(self, client_name):
|
def __getattr__(self, client_name):
|
||||||
"""Lazy load of clients."""
|
"""Lazy load of clients."""
|
||||||
@ -700,20 +699,20 @@ class Clients(object):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def create_from_env(cls):
|
def create_from_env(cls):
|
||||||
creds = envutils.get_creds_from_env_vars()
|
creds = envutils.get_creds_from_env_vars()
|
||||||
return cls(
|
from rally.plugins.openstack import credential
|
||||||
objects.Credential(
|
oscred = credential.OpenStackCredential(
|
||||||
creds["auth_url"],
|
auth_url=creds["auth_url"],
|
||||||
creds["admin"]["username"],
|
username=creds["admin"]["username"],
|
||||||
creds["admin"]["password"],
|
password=creds["admin"]["password"],
|
||||||
creds["admin"]["tenant_name"],
|
tenant_name=creds["admin"]["tenant_name"],
|
||||||
endpoint_type=creds["endpoint_type"],
|
endpoint_type=creds["endpoint_type"],
|
||||||
user_domain_name=creds["admin"].get("user_domain_name"),
|
user_domain_name=creds["admin"].get("user_domain_name"),
|
||||||
project_domain_name=creds["admin"].get("project_domain_name"),
|
project_domain_name=creds["admin"].get("project_domain_name"),
|
||||||
endpoint=creds["endpoint"],
|
endpoint=creds["endpoint"],
|
||||||
region_name=creds["region_name"],
|
region_name=creds["region_name"],
|
||||||
https_cacert=creds["https_cacert"],
|
https_cacert=creds["https_cacert"],
|
||||||
https_insecure=creds["https_insecure"]
|
https_insecure=creds["https_insecure"])
|
||||||
))
|
return cls(oscred)
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
"""Remove all cached client handles."""
|
"""Remove all cached client handles."""
|
||||||
|
@ -21,7 +21,6 @@ from rally.common import logging
|
|||||||
from rally.common.plugin import discover
|
from rally.common.plugin import discover
|
||||||
from rally.common.plugin import plugin
|
from rally.common.plugin import plugin
|
||||||
from rally.common import utils as rutils
|
from rally.common import utils as rutils
|
||||||
from rally import osclients
|
|
||||||
from rally.plugins.openstack.cleanup import base
|
from rally.plugins.openstack.cleanup import base
|
||||||
|
|
||||||
|
|
||||||
@ -29,7 +28,6 @@ LOG = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
class SeekAndDestroy(object):
|
class SeekAndDestroy(object):
|
||||||
cache = {}
|
|
||||||
|
|
||||||
def __init__(self, manager_cls, admin, users, api_versions=None,
|
def __init__(self, manager_cls, admin, users, api_versions=None,
|
||||||
resource_classes=None, task_id=None):
|
resource_classes=None, task_id=None):
|
||||||
@ -58,15 +56,8 @@ class SeekAndDestroy(object):
|
|||||||
"""Simplifies initialization and caching OpenStack clients."""
|
"""Simplifies initialization and caching OpenStack clients."""
|
||||||
if not user:
|
if not user:
|
||||||
return None
|
return None
|
||||||
|
# NOTE(astudenov): Credential now supports caching by default
|
||||||
if self.api_versions:
|
return user["credential"].clients(api_info=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]
|
|
||||||
|
|
||||||
def _delete_single_resource(self, resource):
|
def _delete_single_resource(self, resource):
|
||||||
"""Safe resource deletion with retries and timeouts.
|
"""Safe resource deletion with retries and timeouts.
|
||||||
@ -170,7 +161,6 @@ class SeekAndDestroy(object):
|
|||||||
admin=admin_client,
|
admin=admin_client,
|
||||||
user=self._get_cached_client(user),
|
user=self._get_cached_client(user),
|
||||||
tenant_uuid=user["tenant_id"])
|
tenant_uuid=user["tenant_id"])
|
||||||
|
|
||||||
_publish(self.admin, user, manager)
|
_publish(self.admin, user, manager)
|
||||||
|
|
||||||
def _consumer(self, cache, args):
|
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
|
:param admin_required: If None -> return all plugins
|
||||||
If True -> return only admin plugins
|
If True -> return only admin plugins
|
||||||
If False -> return only non admin plugins
|
If False -> return only non admin plugins
|
||||||
:param admin: rally.common.objects.Credential that corresponds to OpenStack
|
:param admin: rally.deployment.credential.Credential that corresponds to
|
||||||
admin.
|
OpenStack admin.
|
||||||
:param users: List of OpenStack users that was used during benchmarking.
|
:param users: List of OpenStack users that was used during benchmarking.
|
||||||
Every user has next structure:
|
Every user has next structure:
|
||||||
{
|
{
|
||||||
"id": <uuid1>,
|
"id": <uuid1>,
|
||||||
"tenant_id": <uuid2>,
|
"tenant_id": <uuid2>,
|
||||||
"credential": <rally.common.objects.Credential>
|
"credential": <rally.deployment.credential.Credential>
|
||||||
}
|
}
|
||||||
:param superclass: The plugin superclass to perform cleanup
|
:param superclass: The plugin superclass to perform cleanup
|
||||||
for. E.g., this could be
|
for. E.g., this could be
|
||||||
|
@ -15,8 +15,6 @@
|
|||||||
|
|
||||||
from rally.common.i18n import _
|
from rally.common.i18n import _
|
||||||
from rally.common import logging
|
from rally.common import logging
|
||||||
from rally.common import objects
|
|
||||||
from rally import osclients
|
|
||||||
from rally.task import context
|
from rally.task import context
|
||||||
|
|
||||||
|
|
||||||
@ -46,10 +44,8 @@ class ExistingUsers(context.Context):
|
|||||||
self.context["tenants"] = {}
|
self.context["tenants"] = {}
|
||||||
self.context["user_choice_method"] = "random"
|
self.context["user_choice_method"] = "random"
|
||||||
|
|
||||||
for user in self.config:
|
for user_credential in self.config:
|
||||||
user_credential = objects.Credential(**user)
|
user_clients = user_credential.clients()
|
||||||
user_clients = osclients.Clients(user_credential)
|
|
||||||
|
|
||||||
user_id = user_clients.keystone.auth_ref.user_id
|
user_id = user_clients.keystone.auth_ref.user_id
|
||||||
tenant_id = user_clients.keystone.auth_ref.project_id
|
tenant_id = user_clients.keystone.auth_ref.project_id
|
||||||
|
|
||||||
|
@ -21,11 +21,11 @@ from oslo_config import cfg
|
|||||||
from rally.common import broker
|
from rally.common import broker
|
||||||
from rally.common.i18n import _
|
from rally.common.i18n import _
|
||||||
from rally.common import logging
|
from rally.common import logging
|
||||||
from rally.common import objects
|
|
||||||
from rally.common import utils as rutils
|
from rally.common import utils as rutils
|
||||||
from rally import consts
|
from rally import consts
|
||||||
from rally import exceptions
|
from rally import exceptions
|
||||||
from rally import osclients
|
from rally import osclients
|
||||||
|
from rally.plugins.openstack import credential
|
||||||
from rally.plugins.openstack.services.identity import identity
|
from rally.plugins.openstack.services.identity import identity
|
||||||
from rally.plugins.openstack.wrappers import network
|
from rally.plugins.openstack.wrappers import network
|
||||||
from rally.task import context
|
from rally.task import context
|
||||||
@ -207,10 +207,12 @@ class UserGenerator(context.Context):
|
|||||||
project_id=tenant_id,
|
project_id=tenant_id,
|
||||||
domain_name=user_dom,
|
domain_name=user_dom,
|
||||||
default_role=default_role)
|
default_role=default_role)
|
||||||
user_credential = objects.Credential(
|
user_credential = credential.OpenStackCredential(
|
||||||
self.credential.auth_url, user.name, password,
|
auth_url=self.credential.auth_url,
|
||||||
self.context["tenants"][tenant_id]["name"],
|
username=user.name,
|
||||||
consts.EndpointPermission.USER,
|
password=password,
|
||||||
|
tenant_name=self.context["tenants"][tenant_id]["name"],
|
||||||
|
permission=consts.EndpointPermission.USER,
|
||||||
project_domain_name=project_dom,
|
project_domain_name=project_dom,
|
||||||
user_domain_name=user_dom,
|
user_domain_name=user_dom,
|
||||||
endpoint_type=self.credential.endpoint_type,
|
endpoint_type=self.credential.endpoint_type,
|
||||||
|
173
rally/plugins/openstack/credential.py
Normal file
173
rally/plugins/openstack/credential.py
Normal 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
|
@ -108,9 +108,9 @@ class OpenStackScenario(scenario.Scenario):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def validate(cls, name, config, admin=None, users=None, deployment=None):
|
def validate(cls, name, config, admin=None, users=None, deployment=None):
|
||||||
if admin:
|
if admin:
|
||||||
admin = osclients.Clients(admin)
|
admin = admin.clients()
|
||||||
if users:
|
if users:
|
||||||
users = [osclients.Clients(user["credential"]) for user in users]
|
users = [user["credential"].clients() for user in users]
|
||||||
super(OpenStackScenario, cls).validate(
|
super(OpenStackScenario, cls).validate(
|
||||||
name=name, config=config, admin=admin, users=users,
|
name=name, config=config, admin=admin, users=users,
|
||||||
deployment=deployment)
|
deployment=deployment)
|
||||||
|
@ -21,8 +21,6 @@ import six
|
|||||||
from six.moves import configparser
|
from six.moves import configparser
|
||||||
from six.moves.urllib import parse
|
from six.moves.urllib import parse
|
||||||
|
|
||||||
from rally.common import objects
|
|
||||||
from rally import osclients
|
|
||||||
from rally.verification import utils
|
from rally.verification import utils
|
||||||
|
|
||||||
|
|
||||||
@ -88,7 +86,7 @@ class TempestConfigfileManager(object):
|
|||||||
|
|
||||||
def __init__(self, deployment):
|
def __init__(self, deployment):
|
||||||
self.credential = deployment.get_credentials_for("openstack")["admin"]
|
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.available_services = self.clients.services().values()
|
||||||
|
|
||||||
self.conf = configparser.ConfigParser()
|
self.conf = configparser.ConfigParser()
|
||||||
@ -100,14 +98,14 @@ class TempestConfigfileManager(object):
|
|||||||
|
|
||||||
def _configure_auth(self, section_name="auth"):
|
def _configure_auth(self, section_name="auth"):
|
||||||
self.conf.set(section_name, "admin_username",
|
self.conf.set(section_name, "admin_username",
|
||||||
self.credential["username"])
|
self.credential.username)
|
||||||
self.conf.set(section_name, "admin_password",
|
self.conf.set(section_name, "admin_password",
|
||||||
self.credential["password"])
|
self.credential.password)
|
||||||
self.conf.set(section_name, "admin_project_name",
|
self.conf.set(section_name, "admin_project_name",
|
||||||
self.credential["tenant_name"])
|
self.credential.tenant_name)
|
||||||
# Keystone v3 related parameter
|
# Keystone v3 related parameter
|
||||||
self.conf.set(section_name, "admin_domain_name",
|
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'.
|
# Sahara has two service types: 'data_processing' and 'data-processing'.
|
||||||
# 'data_processing' is deprecated, but it can be used in previous OpenStack
|
# '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"):
|
def _configure_identity(self, section_name="identity"):
|
||||||
self.conf.set(section_name, "region",
|
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:
|
if "/v2" not in auth_url and "/v3" not in auth_url:
|
||||||
auth_version = "v2"
|
auth_version = "v2"
|
||||||
auth_url_v2 = parse.urljoin(auth_url, "/v2.0")
|
auth_url_v2 = parse.urljoin(auth_url, "/v2.0")
|
||||||
@ -136,9 +134,9 @@ class TempestConfigfileManager(object):
|
|||||||
auth_url_v2.replace("/v2.0", "/v3"))
|
auth_url_v2.replace("/v2.0", "/v3"))
|
||||||
|
|
||||||
self.conf.set(section_name, "disable_ssl_certificate_validation",
|
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.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.
|
# The compute section is configured in context class for Tempest resources.
|
||||||
# Options which are configured there: 'image_ref', 'image_ref_alt',
|
# Options which are configured there: 'image_ref', 'image_ref_alt',
|
||||||
|
@ -21,9 +21,7 @@ from six.moves import configparser
|
|||||||
|
|
||||||
from rally.common.i18n import _
|
from rally.common.i18n import _
|
||||||
from rally.common import logging
|
from rally.common import logging
|
||||||
from rally.common import objects
|
|
||||||
from rally import exceptions
|
from rally import exceptions
|
||||||
from rally import osclients
|
|
||||||
from rally.plugins.openstack.verification.tempest import config as conf
|
from rally.plugins.openstack.verification.tempest import config as conf
|
||||||
from rally.plugins.openstack.wrappers import glance
|
from rally.plugins.openstack.wrappers import glance
|
||||||
from rally.plugins.openstack.wrappers import network
|
from rally.plugins.openstack.wrappers import network
|
||||||
@ -45,7 +43,7 @@ class TempestContext(context.VerifierContext):
|
|||||||
super(TempestContext, self).__init__(ctx)
|
super(TempestContext, self).__init__(ctx)
|
||||||
|
|
||||||
creds = self.verifier.deployment.get_credentials_for("openstack")
|
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.available_services = self.clients.services().values()
|
||||||
|
|
||||||
self.conf = configparser.ConfigParser()
|
self.conf = configparser.ConfigParser()
|
||||||
|
@ -326,13 +326,9 @@ class TaskEngine(object):
|
|||||||
for platform, workloads in platforms.items():
|
for platform, workloads in platforms.items():
|
||||||
creds = self.deployment.get_credentials_for(platform)
|
creds = self.deployment.get_credentials_for(platform)
|
||||||
|
|
||||||
admin = objects.Credential(**creds["admin"])
|
admin = creds["admin"]
|
||||||
|
if admin:
|
||||||
# TODO(astudenov): move this check to validator of Credential
|
admin.verify_connection()
|
||||||
if platform == "openstack":
|
|
||||||
from rally import osclients
|
|
||||||
clients = osclients.Clients(admin)
|
|
||||||
clients.verified_keystone()
|
|
||||||
|
|
||||||
workloads_with_users = []
|
workloads_with_users = []
|
||||||
workloads_with_existing_users = []
|
workloads_with_existing_users = []
|
||||||
@ -399,9 +395,6 @@ class TaskEngine(object):
|
|||||||
creds = self.deployment.get_credentials_for(namespace)
|
creds = self.deployment.get_credentials_for(namespace)
|
||||||
existing_users = creds["users"]
|
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())
|
scenario_context = copy.deepcopy(scenario_cls.get_default_context())
|
||||||
if existing_users and "users" not in ctx:
|
if existing_users and "users" not in ctx:
|
||||||
scenario_context.setdefault("existing_users", existing_users)
|
scenario_context.setdefault("existing_users", existing_users)
|
||||||
@ -411,7 +404,7 @@ class TaskEngine(object):
|
|||||||
scenario_context.update(ctx)
|
scenario_context.update(ctx)
|
||||||
context_obj = {
|
context_obj = {
|
||||||
"task": self.task,
|
"task": self.task,
|
||||||
"admin": {"credential": admin},
|
"admin": {"credential": creds["admin"]},
|
||||||
"scenario_name": name,
|
"scenario_name": name,
|
||||||
"config": scenario_context
|
"config": scenario_context
|
||||||
}
|
}
|
||||||
|
@ -23,11 +23,9 @@ from novaclient import exceptions as nova_exc
|
|||||||
import six
|
import six
|
||||||
|
|
||||||
from rally.common.i18n import _
|
from rally.common.i18n import _
|
||||||
from rally.common import objects
|
|
||||||
from rally.common import yamlutils as yaml
|
from rally.common import yamlutils as yaml
|
||||||
from rally import consts
|
from rally import consts
|
||||||
from rally import exceptions
|
from rally import exceptions
|
||||||
from rally import osclients
|
|
||||||
from rally.plugins.openstack.context.nova import flavors as flavors_ctx
|
from rally.plugins.openstack.context.nova import flavors as flavors_ctx
|
||||||
from rally.plugins.openstack import types as openstack_types
|
from rally.plugins.openstack import types as openstack_types
|
||||||
from rally.task import 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:
|
if consts.Service.NOVA_NET in required_services:
|
||||||
creds = deployment.get_credentials_for("openstack")
|
creds = deployment.get_credentials_for("openstack")
|
||||||
nova = osclients.Clients(
|
nova = creds["admin"].clients().nova()
|
||||||
objects.Credential(**creds["admin"])).nova()
|
|
||||||
for service in nova.services.list():
|
for service in nova.services.list():
|
||||||
if (service.binary == consts.Service.NOVA_NET and
|
if (service.binary == consts.Service.NOVA_NET and
|
||||||
service.status == "enabled"):
|
service.status == "enabled"):
|
||||||
@ -507,8 +504,7 @@ def required_cinder_services(config, clients, deployment, service_name):
|
|||||||
:param service_name: Cinder service name
|
:param service_name: Cinder service name
|
||||||
"""
|
"""
|
||||||
creds = deployment.get_credentials_for("openstack")
|
creds = deployment.get_credentials_for("openstack")
|
||||||
admin_client = osclients.Clients(
|
admin_client = creds["admin"].clients().cinder()
|
||||||
objects.Credential(**creds["admin"])).cinder()
|
|
||||||
|
|
||||||
for service in admin_client.services.list():
|
for service in admin_client.services.list():
|
||||||
if (service.binary == six.text_type(service_name) and
|
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):
|
if kwargs.get("admin", False):
|
||||||
creds = deployment.get_credentials_for("openstack")
|
creds = deployment.get_credentials_for("openstack")
|
||||||
clients = osclients.Clients(objects.Credential(**creds["admin"]))
|
clients = creds["admin"].clients()
|
||||||
|
|
||||||
for client_component in components:
|
for client_component in components:
|
||||||
try:
|
try:
|
||||||
|
@ -24,10 +24,9 @@ import sys
|
|||||||
import six
|
import six
|
||||||
|
|
||||||
from rally.cli import cliutils
|
from rally.cli import cliutils
|
||||||
from rally.common import objects
|
|
||||||
from rally.common.plugin import discover
|
from rally.common.plugin import discover
|
||||||
from rally import consts
|
from rally import consts
|
||||||
from rally import osclients
|
from rally.plugins.openstack import credential
|
||||||
|
|
||||||
|
|
||||||
def skip_if_service(service):
|
def skip_if_service(service):
|
||||||
@ -340,7 +339,7 @@ class CloudResources(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
self.clients = osclients.Clients(objects.Credential(**kwargs))
|
self.clients = credential.OpenStackCredential(**kwargs).clients()
|
||||||
|
|
||||||
def _deduplicate(self, lst):
|
def _deduplicate(self, lst):
|
||||||
"""Change list duplicates to make all items unique.
|
"""Change list duplicates to make all items unique.
|
||||||
@ -426,8 +425,8 @@ def main():
|
|||||||
out = subprocess.check_output(["rally", "deployment",
|
out = subprocess.check_output(["rally", "deployment",
|
||||||
"config"])
|
"config"])
|
||||||
config = json.loads(out if six.PY2 else out.decode("utf-8"))
|
config = json.loads(out if six.PY2 else out.decode("utf-8"))
|
||||||
|
config = config["creds"]["openstack"]
|
||||||
config.update(config.pop("admin"))
|
config.update(config.pop("admin"))
|
||||||
del config["type"]
|
|
||||||
if "users" in config:
|
if "users" in config:
|
||||||
del config["users"]
|
del config["users"]
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ function setUp () {
|
|||||||
DEPLOYMENT_CONFIG_FILE=~/.rally/with-existing-users-config
|
DEPLOYMENT_CONFIG_FILE=~/.rally/with-existing-users-config
|
||||||
|
|
||||||
rally deployment config > $DEPLOYMENT_CONFIG_FILE
|
rally deployment config > $DEPLOYMENT_CONFIG_FILE
|
||||||
sed -i '1a "users": [\
|
sed -i '3a "users": [\
|
||||||
{\
|
{\
|
||||||
"username": "rally-test-user-1",\
|
"username": "rally-test-user-1",\
|
||||||
"password": "rally-test-password-1",\
|
"password": "rally-test-password-1",\
|
||||||
|
@ -23,8 +23,7 @@ import sys
|
|||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from rally.cli import envutils
|
from rally.cli import envutils
|
||||||
from rally.common import objects
|
from rally.plugins.openstack import credential
|
||||||
from rally import osclients
|
|
||||||
from rally.ui import utils
|
from rally.ui import utils
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
@ -172,9 +171,9 @@ def main():
|
|||||||
|
|
||||||
config = json.loads(
|
config = json.loads(
|
||||||
subprocess.check_output(["rally", "deployment", "config"]))
|
subprocess.check_output(["rally", "deployment", "config"]))
|
||||||
|
config = config["creds"]["openstack"]
|
||||||
config.update(config.pop("admin"))
|
config.update(config.pop("admin"))
|
||||||
del config["type"]
|
clients = credential.OpenStackCredential(**config).clients()
|
||||||
clients = osclients.Clients(objects.Credential(**config))
|
|
||||||
|
|
||||||
if args.ctx_create_resources:
|
if args.ctx_create_resources:
|
||||||
# If the 'ctx-create-resources' arg is provided, delete images and
|
# If the 'ctx-create-resources' arg is provided, delete images and
|
||||||
|
@ -25,7 +25,6 @@ import six
|
|||||||
|
|
||||||
from rally import api
|
from rally import api
|
||||||
from rally.common import db
|
from rally.common import db
|
||||||
from rally.common import objects
|
|
||||||
from rally import plugins
|
from rally import plugins
|
||||||
from rally.plugins.openstack.context.keystone import users
|
from rally.plugins.openstack.context.keystone import users
|
||||||
from tests.functional import utils
|
from tests.functional import utils
|
||||||
@ -51,7 +50,7 @@ class TestTaskSamples(unittest.TestCase):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
@plugins.ensure_plugins_are_loaded
|
@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)
|
rally = utils.Rally(force_new_db=True)
|
||||||
# In TestTaskSamples, Rally API will be called directly (not via
|
# In TestTaskSamples, Rally API will be called directly (not via
|
||||||
# subprocess), so we need to change database options to temp database.
|
# 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
|
# let's use pre-created users to make TestTaskSamples quicker
|
||||||
deployment = api.Deployment.get("MAIN")
|
deployment = api.Deployment.get("MAIN")
|
||||||
creds = deployment.get_credentials_for("openstack")
|
admin_cred = deployment.get_credentials_for("openstack")["admin"]
|
||||||
admin_cred = objects.Credential(**creds["admin"])
|
|
||||||
|
|
||||||
ctx = {"admin": {"credential": admin_cred},
|
ctx = {"admin": {"credential": admin_cred},
|
||||||
"task": {"uuid": self.__class__.__name__}}
|
"task": {"uuid": self.__class__.__name__}}
|
||||||
@ -70,15 +68,16 @@ class TestTaskSamples(unittest.TestCase):
|
|||||||
self.addCleanup(user_ctx.cleanup)
|
self.addCleanup(user_ctx.cleanup)
|
||||||
|
|
||||||
config = deployment["config"]
|
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["username"] = ctx["users"][0]["credential"].username
|
||||||
user["password"] = ctx["users"][0]["credential"].password
|
user["password"] = ctx["users"][0]["credential"].password
|
||||||
if "project_name" in config["admin"]:
|
if "project_name" in os_creds["admin"]:
|
||||||
# it is Keystone
|
# it is Keystone
|
||||||
user["project_name"] = ctx["users"][0]["credential"].tenant_name
|
user["project_name"] = ctx["users"][0]["credential"].tenant_name
|
||||||
else:
|
else:
|
||||||
user["tenant_name"] = ctx["users"][0]["credential"].tenant_name
|
user["tenant_name"] = ctx["users"][0]["credential"].tenant_name
|
||||||
config["users"] = [user]
|
config["creds"]["openstack"]["users"] = [user]
|
||||||
|
|
||||||
rally("deployment destroy MAIN", write_report=False)
|
rally("deployment destroy MAIN", write_report=False)
|
||||||
deployment_cfg = os.path.join(rally.tmp_dir, "new_deployment.json")
|
deployment_cfg = os.path.join(rally.tmp_dir, "new_deployment.json")
|
||||||
|
@ -20,7 +20,6 @@ import mock
|
|||||||
|
|
||||||
from rally.cli.commands import deployment
|
from rally.cli.commands import deployment
|
||||||
from rally.cli import envutils
|
from rally.cli import envutils
|
||||||
from rally.common import objects
|
|
||||||
from rally import consts
|
from rally import consts
|
||||||
from rally import exceptions
|
from rally import exceptions
|
||||||
from tests.unit import fakes
|
from tests.unit import fakes
|
||||||
@ -231,14 +230,13 @@ class DeploymentCommandsTestCase(test.TestCase):
|
|||||||
def test_show(self, mock_struct, mock_print_list):
|
def test_show(self, mock_struct, mock_print_list):
|
||||||
deployment_id = "b1a6153e-a314-4cb3-b63b-cf08c1a416c3"
|
deployment_id = "b1a6153e-a314-4cb3-b63b-cf08c1a416c3"
|
||||||
value = {
|
value = {
|
||||||
"admin": {
|
"admin": fakes.fake_credential(
|
||||||
"auth_url": "url",
|
auth_url="url",
|
||||||
"username": "u",
|
username="u",
|
||||||
"password": "p",
|
password="p",
|
||||||
"tenant_name": "t",
|
tenant_name="t",
|
||||||
"region_name": "r",
|
region_name="r",
|
||||||
"endpoint_type": consts.EndpointType.INTERNAL
|
endpoint_type=consts.EndpointType.INTERNAL),
|
||||||
},
|
|
||||||
"users": []
|
"users": []
|
||||||
}
|
}
|
||||||
deployment = self.fake_api.deployment.get.return_value
|
deployment = self.fake_api.deployment.get.return_value
|
||||||
@ -267,12 +265,12 @@ class DeploymentCommandsTestCase(test.TestCase):
|
|||||||
deployment_id = "593b683c-4b16-4b2b-a56b-e162bd60f10b"
|
deployment_id = "593b683c-4b16-4b2b-a56b-e162bd60f10b"
|
||||||
self.fake_api.deployment.get.return_value = fakes.FakeDeployment(
|
self.fake_api.deployment.get.return_value = fakes.FakeDeployment(
|
||||||
uuid=deployment_id,
|
uuid=deployment_id,
|
||||||
admin={"auth_url": "fake_auth_url",
|
admin=fakes.fake_credential(**{"auth_url": "fake_auth_url",
|
||||||
"username": "fake_username",
|
"username": "fake_username",
|
||||||
"password": "fake_password",
|
"password": "fake_password",
|
||||||
"tenant_name": "fake_tenant_name",
|
"tenant_name": "fake_tenant_name",
|
||||||
"endpoint": "fake_endpoint",
|
"endpoint": "fake_endpoint",
|
||||||
"region_name": None})
|
"region_name": None}))
|
||||||
|
|
||||||
with mock.patch("rally.cli.commands.deployment.open", mock.mock_open(),
|
with mock.patch("rally.cli.commands.deployment.open", mock.mock_open(),
|
||||||
create=True) as mock_file:
|
create=True) as mock_file:
|
||||||
@ -304,7 +302,7 @@ class DeploymentCommandsTestCase(test.TestCase):
|
|||||||
|
|
||||||
self.fake_api.deployment.get.return_value = fakes.FakeDeployment(
|
self.fake_api.deployment.get.return_value = fakes.FakeDeployment(
|
||||||
uuid=deployment_id,
|
uuid=deployment_id,
|
||||||
admin={
|
admin=fakes.fake_credential(**{
|
||||||
"auth_url": "http://localhost:5000/v3",
|
"auth_url": "http://localhost:5000/v3",
|
||||||
"username": "fake_username",
|
"username": "fake_username",
|
||||||
"password": "fake_password",
|
"password": "fake_password",
|
||||||
@ -312,7 +310,7 @@ class DeploymentCommandsTestCase(test.TestCase):
|
|||||||
"endpoint": "fake_endpoint",
|
"endpoint": "fake_endpoint",
|
||||||
"region_name": None,
|
"region_name": None,
|
||||||
"user_domain_name": "fake_user_domain",
|
"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(),
|
with mock.patch("rally.cli.commands.deployment.open", mock.mock_open(),
|
||||||
create=True) as mock_file:
|
create=True) as mock_file:
|
||||||
@ -342,9 +340,10 @@ class DeploymentCommandsTestCase(test.TestCase):
|
|||||||
@mock.patch("rally.common.fileutils.update_globals_file")
|
@mock.patch("rally.common.fileutils.update_globals_file")
|
||||||
def test_use_by_name(self, mock_update_globals_file,
|
def test_use_by_name(self, mock_update_globals_file,
|
||||||
mock__update_openrc_deployment_file):
|
mock__update_openrc_deployment_file):
|
||||||
|
fake_credential = fakes.fake_credential(foo="fake_credentials")
|
||||||
fake_deployment = fakes.FakeDeployment(
|
fake_deployment = fakes.FakeDeployment(
|
||||||
uuid="fake_uuid",
|
uuid="fake_uuid",
|
||||||
admin="fake_credentials")
|
admin=fake_credential)
|
||||||
self.fake_api.deployment.list.return_value = [fake_deployment]
|
self.fake_api.deployment.list.return_value = [fake_deployment]
|
||||||
self.fake_api.deployment.get.return_value = fake_deployment
|
self.fake_api.deployment.get.return_value = fake_deployment
|
||||||
status = self.deployment.use(self.fake_api, deployment="fake_name")
|
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(
|
mock_update_globals_file.assert_called_once_with(
|
||||||
envutils.ENV_DEPLOYMENT, "fake_uuid")
|
envutils.ENV_DEPLOYMENT, "fake_uuid")
|
||||||
mock__update_openrc_deployment_file.assert_called_once_with(
|
mock__update_openrc_deployment_file.assert_called_once_with(
|
||||||
"fake_uuid", "fake_credentials")
|
"fake_uuid", {"foo": "fake_credentials"})
|
||||||
|
|
||||||
def test_deployment_not_found(self):
|
def test_deployment_not_found(self):
|
||||||
deployment_id = "e87e4dca-b515-4477-888d-5f6103f13b42"
|
deployment_id = "e87e4dca-b515-4477-888d-5f6103f13b42"
|
||||||
@ -364,9 +363,9 @@ class DeploymentCommandsTestCase(test.TestCase):
|
|||||||
@mock.patch("rally.cli.commands.deployment.cliutils.print_list")
|
@mock.patch("rally.cli.commands.deployment.cliutils.print_list")
|
||||||
def test_deployment_check(self, mock_print_list):
|
def test_deployment_check(self, mock_print_list):
|
||||||
deployment_id = "e87e4dca-b515-4477-888d-5f6103f13b42"
|
deployment_id = "e87e4dca-b515-4477-888d-5f6103f13b42"
|
||||||
sample_credential = objects.Credential("http://192.168.1.1:5000/v2.0/",
|
sample_credential = fakes.fake_credential(
|
||||||
"admin",
|
auth_url="http://192.168.1.1:5000/v2.0/",
|
||||||
"adminpass").to_dict()
|
username="admin", password="adminpass")
|
||||||
deployment = {"admin": sample_credential,
|
deployment = {"admin": sample_credential,
|
||||||
"users": [sample_credential]}
|
"users": [sample_credential]}
|
||||||
self.fake_api.deployment.get.return_value = deployment
|
self.fake_api.deployment.get.return_value = deployment
|
||||||
@ -388,10 +387,9 @@ class DeploymentCommandsTestCase(test.TestCase):
|
|||||||
|
|
||||||
def test_deployment_check_raise(self):
|
def test_deployment_check_raise(self):
|
||||||
deployment_id = "e87e4dca-b515-4477-888d-5f6103f13b42"
|
deployment_id = "e87e4dca-b515-4477-888d-5f6103f13b42"
|
||||||
sample_credential = objects.Credential("http://192.168.1.1:5000/v2.0/",
|
sample_credential = fakes.fake_credential(
|
||||||
"admin",
|
auth_url="http://192.168.1.1:5000/v2.0/",
|
||||||
"adminpass").to_dict()
|
username="admin", password="adminpass")
|
||||||
sample_credential["not-exist-key"] = "error"
|
|
||||||
deployment = self.fake_api.deployment.get.return_value
|
deployment = self.fake_api.deployment.get.return_value
|
||||||
deployment.get_credentials_for.return_value = {
|
deployment.get_credentials_for.return_value = {
|
||||||
"admin": sample_credential, "users": []}
|
"admin": sample_credential, "users": []}
|
||||||
|
@ -18,6 +18,8 @@ from rally import consts
|
|||||||
from tests.unit import test
|
from tests.unit import test
|
||||||
|
|
||||||
|
|
||||||
|
# TODO(astudenov): remove this class in future releases
|
||||||
|
|
||||||
class CredentialTestCase(test.TestCase):
|
class CredentialTestCase(test.TestCase):
|
||||||
|
|
||||||
def test_to_dict(self):
|
def test_to_dict(self):
|
||||||
|
@ -117,8 +117,10 @@ class DeploymentTestCase(test.TestCase):
|
|||||||
{"config": {"opt": "val"}},
|
{"config": {"opt": "val"}},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@mock.patch("rally.deployment.credential.get")
|
||||||
@mock.patch("rally.common.objects.deploy.db.deployment_update")
|
@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
|
mock_deployment_update.return_value = self.deployment
|
||||||
deploy = objects.Deployment(deployment=self.deployment)
|
deploy = objects.Deployment(deployment=self.deployment)
|
||||||
credentials = {"foo": [{"admin": {"fake_admin": True},
|
credentials = {"foo": [{"admin": {"fake_admin": True},
|
||||||
@ -132,23 +134,38 @@ class DeploymentTestCase(test.TestCase):
|
|||||||
"users": [{"fake_user": True}]}]}
|
"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},
|
credentials = {"foo": [{"admin": {"fake_admin": True},
|
||||||
"users": [{"fake_user": True}]}]}
|
"users": [{"fake_user": True}]}]}
|
||||||
self.deployment["credentials"] = credentials
|
self.deployment["credentials"] = credentials
|
||||||
deploy = objects.Deployment(deployment=self.deployment)
|
deploy = objects.Deployment(deployment=self.deployment)
|
||||||
|
|
||||||
creds = deploy.get_credentials_for("foo")
|
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},
|
credentials = {"openstack": [{"admin": {"fake_admin": True},
|
||||||
"users": [{"fake_user": True}]}]}
|
"users": [{"fake_user": True}]}]}
|
||||||
self.deployment["credentials"] = credentials
|
self.deployment["credentials"] = credentials
|
||||||
|
|
||||||
deploy = objects.Deployment(deployment=self.deployment)
|
deploy = objects.Deployment(deployment=self.deployment)
|
||||||
|
|
||||||
self.assertEqual(credentials["openstack"][0]["admin"], deploy["admin"])
|
self.assertEqual(credential_inst, deploy["admin"])
|
||||||
self.assertEqual(credentials["openstack"][0]["users"], deploy["users"])
|
self.assertEqual([credential_inst], deploy["users"])
|
||||||
|
|
||||||
def test_update_empty_credentials(self):
|
def test_update_empty_credentials(self):
|
||||||
deploy = objects.Deployment(deployment=self.deployment)
|
deploy = objects.Deployment(deployment=self.deployment)
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
import jsonschema
|
import jsonschema
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
|
from rally import consts
|
||||||
from rally.deployment.engines import devstack
|
from rally.deployment.engines import devstack
|
||||||
from tests.unit import test
|
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_updated_server")
|
||||||
@mock.patch("rally.deployment.engines.devstack.get_script")
|
@mock.patch("rally.deployment.engines.devstack.get_script")
|
||||||
@mock.patch("rally.deployment.serverprovider.provider.Server")
|
@mock.patch("rally.deployment.serverprovider.provider.Server")
|
||||||
@mock.patch("rally.deployment.engines.devstack.objects.Credential")
|
def test_deploy(self, mock_server, mock_get_script,
|
||||||
def test_deploy(self, mock_credential, mock_server, mock_get_script,
|
|
||||||
mock_get_updated_server, mock_engine_get_provider):
|
mock_get_updated_server, mock_engine_get_provider):
|
||||||
mock_engine_get_provider.return_value = fake_provider = (
|
mock_engine_get_provider.return_value = fake_provider = (
|
||||||
mock.Mock()
|
mock.Mock()
|
||||||
)
|
)
|
||||||
server = mock.Mock(host="host")
|
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_updated_server.return_value = ds_server = mock.Mock()
|
||||||
mock_get_script.return_value = "fake_script"
|
mock_get_script.return_value = "fake_script"
|
||||||
server.get_credentials.return_value = "fake_credentials"
|
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:
|
with mock.patch.object(self.engine, "deployment") as mock_deployment:
|
||||||
credentials = self.engine.deploy()
|
credentials = self.engine.deploy()
|
||||||
self.assertEqual(
|
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)
|
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(
|
mock_deployment.add_resource.assert_called_once_with(
|
||||||
info="fake_credentials",
|
info="fake_credentials",
|
||||||
provider_name="DevstackEngine",
|
provider_name="DevstackEngine",
|
||||||
|
@ -61,15 +61,35 @@ class TestExistingCloud(test.TestCase):
|
|||||||
"user_domain_name": "Default",
|
"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):
|
def test_init_and_valid_config(self, keystone_version):
|
||||||
engine = existing.ExistingCloud(self.deployments[keystone_version])
|
engine = existing.ExistingCloud(self.deployments[keystone_version])
|
||||||
engine.validate()
|
engine.validate()
|
||||||
|
|
||||||
@ddt.data("v2.0", "v3")
|
@ddt.data("v2.0", "v3", "abstract")
|
||||||
def test_invalid_config(self, keystone_version):
|
def test_invalid_config(self, keystone_version):
|
||||||
deployment = self.deployments[keystone_version]
|
deployment = self.deployments[keystone_version]
|
||||||
deployment["config"]["admin"] = 42
|
deployment["config"]["admin"] = 42
|
||||||
@ -77,7 +97,7 @@ class TestExistingCloud(test.TestCase):
|
|||||||
self.assertRaises(jsonschema.ValidationError,
|
self.assertRaises(jsonschema.ValidationError,
|
||||||
engine.validate)
|
engine.validate)
|
||||||
|
|
||||||
@ddt.data("v2.0", "v3")
|
@ddt.data("v2.0", "v3", "abstract")
|
||||||
def test_additional_vars(self, keystone_version):
|
def test_additional_vars(self, keystone_version):
|
||||||
deployment = self.deployments[keystone_version]
|
deployment = self.deployments[keystone_version]
|
||||||
deployment["extra"] = {}
|
deployment["extra"] = {}
|
||||||
@ -122,11 +142,36 @@ class TestExistingCloud(test.TestCase):
|
|||||||
self.assertEqual(admin_credential, actual_credentials)
|
self.assertEqual(admin_credential, actual_credentials)
|
||||||
self.assertEqual([], credentials["users"])
|
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):
|
def test_cleanup(self, keystone_version):
|
||||||
existing.ExistingCloud(self.deployments[keystone_version]).cleanup()
|
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):
|
def test_is_in_factory(self, keystone_version):
|
||||||
name = self.deployments[keystone_version]["config"]["type"]
|
name = self.deployments[keystone_version]["config"]["type"]
|
||||||
engine = deploy_engine.Engine.get_engine(
|
engine = deploy_engine.Engine.get_engine(
|
||||||
|
@ -27,6 +27,7 @@ from tests.unit import fakes
|
|||||||
from tests.unit import test
|
from tests.unit import test
|
||||||
|
|
||||||
MOD_NAME = "rally.deployment.serverprovider.providers.openstack"
|
MOD_NAME = "rally.deployment.serverprovider.providers.openstack"
|
||||||
|
OS_CREDENTIAL_NAME = "rally.plugins.openstack.credential"
|
||||||
OSProvider = provider.OpenStackProvider
|
OSProvider = provider.OpenStackProvider
|
||||||
|
|
||||||
|
|
||||||
@ -82,11 +83,10 @@ class OpenStackProviderTestCase(test.TestCase):
|
|||||||
|
|
||||||
self.clients.nova = mock.MagicMock(return_value=self.nova_client)
|
self.clients.nova = mock.MagicMock(return_value=self.nova_client)
|
||||||
|
|
||||||
@mock.patch(
|
@mock.patch("rally.osclients.Clients")
|
||||||
"rally.deployment.serverprovider.providers.openstack.osclients")
|
def test_openstack_provider_init(self, mock_clients):
|
||||||
def test_openstack_provider_init(self, mock_osclients):
|
|
||||||
cfg = self._get_valid_config()
|
cfg = self._get_valid_config()
|
||||||
mock_osclients.Clients = mock.MagicMock(return_value=FakeOSClients())
|
mock_clients.return_value = FakeOSClients()
|
||||||
os_provider = OSProvider(mock.MagicMock(), cfg)
|
os_provider = OSProvider(mock.MagicMock(), cfg)
|
||||||
self.assertEqual("nova", os_provider.nova)
|
self.assertEqual("nova", os_provider.nova)
|
||||||
self.assertEqual("glance", os_provider.glance)
|
self.assertEqual("glance", os_provider.glance)
|
||||||
@ -98,60 +98,53 @@ class OpenStackProviderTestCase(test.TestCase):
|
|||||||
provider = OSProvider(mock.MagicMock(), cfg)
|
provider = OSProvider(mock.MagicMock(), cfg)
|
||||||
self.assertIsNone(provider.glance)
|
self.assertIsNone(provider.glance)
|
||||||
|
|
||||||
@mock.patch(
|
@mock.patch("rally.osclients.Clients")
|
||||||
"rally.deployment.serverprovider.providers.openstack.osclients")
|
|
||||||
def test_openstack_provider_init_with_invalid_conf_no_user(self,
|
def test_openstack_provider_init_with_invalid_conf_no_user(self,
|
||||||
mock_osclients):
|
mock_clients):
|
||||||
cfg = self._get_valid_config()
|
cfg = self._get_valid_config()
|
||||||
cfg.pop("user")
|
cfg.pop("user")
|
||||||
self.assertRaises(jsonschema.ValidationError, OSProvider,
|
self.assertRaises(jsonschema.ValidationError, OSProvider,
|
||||||
mock.MagicMock(), cfg)
|
mock.MagicMock(), cfg)
|
||||||
|
|
||||||
@mock.patch(
|
@mock.patch("rally.osclients.Clients")
|
||||||
"rally.deployment.serverprovider.providers.openstack.osclients")
|
|
||||||
def test_openstack_provider_init_with_invalid_conf_no_url(self,
|
def test_openstack_provider_init_with_invalid_conf_no_url(self,
|
||||||
mock_osclients):
|
mock_clients):
|
||||||
cfg = self._get_valid_config()
|
cfg = self._get_valid_config()
|
||||||
del cfg["image"]["url"]
|
del cfg["image"]["url"]
|
||||||
del cfg["image"]["checksum"]
|
del cfg["image"]["checksum"]
|
||||||
self.assertRaises(jsonschema.ValidationError, OSProvider,
|
self.assertRaises(jsonschema.ValidationError, OSProvider,
|
||||||
mock.MagicMock(), cfg)
|
mock.MagicMock(), cfg)
|
||||||
|
|
||||||
@mock.patch(
|
@mock.patch("rally.osclients.Clients")
|
||||||
"rally.deployment.serverprovider.providers.openstack.osclients")
|
|
||||||
def test_openstack_provider_init_with_invalid_conf_extra_key(
|
def test_openstack_provider_init_with_invalid_conf_extra_key(
|
||||||
self, mock_osclients):
|
self, mock_clients):
|
||||||
cfg = self._get_valid_config()
|
cfg = self._get_valid_config()
|
||||||
cfg["aaaaa"] = "bbbbb"
|
cfg["aaaaa"] = "bbbbb"
|
||||||
self.assertRaises(jsonschema.ValidationError, OSProvider,
|
self.assertRaises(jsonschema.ValidationError, OSProvider,
|
||||||
mock.MagicMock(), cfg)
|
mock.MagicMock(), cfg)
|
||||||
|
|
||||||
@mock.patch(
|
@mock.patch("rally.osclients.Clients")
|
||||||
"rally.deployment.serverprovider.providers.openstack.osclients")
|
|
||||||
def test_openstack_provider_init_with_invalid_conf_flavor_(self,
|
def test_openstack_provider_init_with_invalid_conf_flavor_(self,
|
||||||
mock_osclients):
|
mock_clients):
|
||||||
cfg = self._get_valid_config()["user"] = 1111
|
cfg = self._get_valid_config()["user"] = 1111
|
||||||
self.assertRaises(jsonschema.ValidationError, OSProvider,
|
self.assertRaises(jsonschema.ValidationError, OSProvider,
|
||||||
mock.MagicMock(), cfg)
|
mock.MagicMock(), cfg)
|
||||||
|
|
||||||
@mock.patch(
|
@mock.patch("rally.osclients.Clients")
|
||||||
"rally.deployment.serverprovider.providers.openstack.osclients")
|
|
||||||
def test_openstack_provider_with_valid_config(self,
|
def test_openstack_provider_with_valid_config(self,
|
||||||
mock_osclients):
|
mock_clients):
|
||||||
cfg = self._get_valid_config()
|
cfg = self._get_valid_config()
|
||||||
OSProvider(mock.MagicMock(), cfg)
|
OSProvider(mock.MagicMock(), cfg)
|
||||||
|
|
||||||
@mock.patch(
|
@mock.patch("rally.osclients.Clients")
|
||||||
"rally.deployment.serverprovider.providers.openstack.osclients")
|
def test_openstack_provider_with_valid_config_uuid(self, mock_clients):
|
||||||
def test_openstack_provider_with_valid_config_uuid(self, mock_osclients):
|
|
||||||
cfg = self._get_valid_config()
|
cfg = self._get_valid_config()
|
||||||
cfg["image"] = dict(uuid="289D7A51-1A0C-43C4-800D-706EA8A3CDF3")
|
cfg["image"] = dict(uuid="289D7A51-1A0C-43C4-800D-706EA8A3CDF3")
|
||||||
OSProvider(mock.MagicMock(), cfg)
|
OSProvider(mock.MagicMock(), cfg)
|
||||||
|
|
||||||
@mock.patch(
|
@mock.patch("rally.osclients.Clients")
|
||||||
"rally.deployment.serverprovider.providers.openstack.osclients")
|
|
||||||
def test_openstack_provider_with_valid_config_checksum(self,
|
def test_openstack_provider_with_valid_config_checksum(self,
|
||||||
mock_osclients):
|
mock_clients):
|
||||||
cfg = self._get_valid_config()
|
cfg = self._get_valid_config()
|
||||||
cfg["image"] = dict(checksum="checksum")
|
cfg["image"] = dict(checksum="checksum")
|
||||||
OSProvider(mock.MagicMock(), cfg)
|
OSProvider(mock.MagicMock(), cfg)
|
||||||
@ -194,9 +187,9 @@ class OpenStackProviderTestCase(test.TestCase):
|
|||||||
|
|
||||||
@mock.patch("time.sleep")
|
@mock.patch("time.sleep")
|
||||||
@mock.patch(MOD_NAME + ".provider.Server")
|
@mock.patch(MOD_NAME + ".provider.Server")
|
||||||
@mock.patch(MOD_NAME + ".osclients")
|
@mock.patch("rally.osclients.Clients")
|
||||||
@mock.patch(MOD_NAME + ".utils")
|
@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):
|
mock_server, mock_sleep):
|
||||||
fake_keypair = mock.Mock()
|
fake_keypair = mock.Mock()
|
||||||
fake_keypair.name = "fake_key_name"
|
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,
|
nics="fake_nics", key_name="fake_key_name", config_drive=False,
|
||||||
security_groups=[provider.sg.name])
|
security_groups=[provider.sg.name])
|
||||||
|
|
||||||
@mock.patch(MOD_NAME + ".osclients")
|
@mock.patch("rally.osclients.Clients")
|
||||||
def test_get_image_found_by_checksum(self, mock_osclients):
|
def test_get_image_found_by_checksum(self, mock_clients):
|
||||||
self._init_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())
|
prov = OSProvider(mock.MagicMock(), self._get_valid_config())
|
||||||
image_uuid = prov.get_image_uuid()
|
image_uuid = prov.get_image_uuid()
|
||||||
self.assertEqual(image_uuid, "fake-uuid")
|
self.assertEqual(image_uuid, "fake-uuid")
|
||||||
|
|
||||||
@mock.patch(MOD_NAME + ".osclients")
|
@mock.patch("rally.osclients.Clients")
|
||||||
def test_get_image_download(self, mock_osclients):
|
def test_get_image_download(self, mock_clients):
|
||||||
self._init_mock_clients()
|
self._init_mock_clients()
|
||||||
self.glance_client.images.list = mock.Mock(return_value=[])
|
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())
|
prov = OSProvider(mock.MagicMock(), self._get_valid_config())
|
||||||
image_uuid = prov.get_image_uuid()
|
image_uuid = prov.get_image_uuid()
|
||||||
self.assertEqual(image_uuid, "fake-uuid")
|
self.assertEqual(image_uuid, "fake-uuid")
|
||||||
|
|
||||||
@mock.patch(MOD_NAME + ".osclients")
|
@mock.patch("rally.osclients.Clients")
|
||||||
def test_get_image_no_glance_exception(
|
def test_get_image_no_glance_exception(self, mock_clients):
|
||||||
self, mock_osclients):
|
|
||||||
prov = OSProvider(mock.MagicMock(), self._get_valid_config())
|
prov = OSProvider(mock.MagicMock(), self._get_valid_config())
|
||||||
prov.glance = None
|
prov.glance = None
|
||||||
self.assertRaises(exceptions.InvalidConfigException,
|
self.assertRaises(exceptions.InvalidConfigException,
|
||||||
prov.get_image_uuid)
|
prov.get_image_uuid)
|
||||||
|
|
||||||
@mock.patch(MOD_NAME + ".osclients")
|
@mock.patch("rally.osclients.Clients")
|
||||||
def test_get_image_from_uuid_no_glance(self, mock_osclients):
|
def test_get_image_from_uuid_no_glance(self, mock_clients):
|
||||||
conf = self._get_valid_config()
|
conf = self._get_valid_config()
|
||||||
conf["image"]["uuid"] = "EC7A1DB7-C5BD-49A2-8066-613809CB22F5"
|
conf["image"]["uuid"] = "EC7A1DB7-C5BD-49A2-8066-613809CB22F5"
|
||||||
prov = OSProvider(mock.MagicMock(), conf)
|
prov = OSProvider(mock.MagicMock(), conf)
|
||||||
prov.glance = True
|
prov.glance = True
|
||||||
self.assertEqual(conf["image"]["uuid"], prov.get_image_uuid())
|
self.assertEqual(conf["image"]["uuid"], prov.get_image_uuid())
|
||||||
|
|
||||||
@mock.patch(MOD_NAME + ".osclients")
|
@mock.patch("rally.osclients.Clients")
|
||||||
def test_destroy_servers(self, mock_osclients):
|
def test_destroy_servers(self, mock_clients):
|
||||||
prov = OSProvider(mock.MagicMock(), self._get_valid_config())
|
prov = OSProvider(mock.MagicMock(), self._get_valid_config())
|
||||||
prov.resources.get_all.side_effect = [
|
prov.resources.get_all.side_effect = [
|
||||||
[fakes.FakeResource(
|
[fakes.FakeResource(
|
||||||
|
84
tests/unit/deployment/test_credential.py
Normal file
84
tests/unit/deployment/test_credential.py
Normal 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"})
|
@ -151,7 +151,7 @@ class LxcEngineTestCase(test.TestCase):
|
|||||||
self.assertEqual(1, len(credentials["openstack"]))
|
self.assertEqual(1, len(credentials["openstack"]))
|
||||||
credential = credentials["openstack"][0]
|
credential = credentials["openstack"][0]
|
||||||
|
|
||||||
self.assertIsInstance(credential["admin"], dict)
|
self.assertIsNone(credential["admin"])
|
||||||
self.assertEqual([], credential["users"])
|
self.assertEqual([], credential["users"])
|
||||||
lxc_host_calls = [
|
lxc_host_calls = [
|
||||||
mock.call(fake_servers[0], {"network": "10.128.128.0/28",
|
mock.call(fake_servers[0], {"network": "10.128.128.0/28",
|
||||||
|
@ -115,11 +115,12 @@ class ConfigSchemasTestCase(test.TestCase):
|
|||||||
self.fail(p, schema, ("Found unexpected key(s) for integer/number "
|
self.fail(p, schema, ("Found unexpected key(s) for integer/number "
|
||||||
"type: %s." % ", ".join(unexpected_keys)))
|
"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"}
|
unexpected_keys = set(schema.keys()) - {"type", "description"}
|
||||||
if unexpected_keys:
|
if unexpected_keys:
|
||||||
self.fail(p, schema, ("Found unexpected key(s) for boolean type: "
|
self.fail(p, schema, ("Found unexpected key(s) for %s type: "
|
||||||
"%s." % ", ".join(unexpected_keys)))
|
"%s." % (type_name,
|
||||||
|
", ".join(unexpected_keys))))
|
||||||
|
|
||||||
def _check_item(self, p, schema, definitions):
|
def _check_item(self, p, schema, definitions):
|
||||||
if "type" in schema or "anyOf" in schema or "oneOf" in schema:
|
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"):
|
elif schema["type"] in ("number", "integer"):
|
||||||
self._check_number_type(p, schema)
|
self._check_number_type(p, schema)
|
||||||
elif schema["type"] in ("boolean", "null"):
|
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:
|
else:
|
||||||
self.fail(p, schema,
|
self.fail(p, schema,
|
||||||
"Wrong type is used: %s" % schema["type"])
|
"Wrong type is used: %s" % schema["type"])
|
||||||
|
@ -28,7 +28,6 @@ import six
|
|||||||
from swiftclient import exceptions as swift_exceptions
|
from swiftclient import exceptions as swift_exceptions
|
||||||
|
|
||||||
from rally import api
|
from rally import api
|
||||||
from rally.common import objects
|
|
||||||
from rally.common import utils as rally_utils
|
from rally.common import utils as rally_utils
|
||||||
from rally import consts
|
from rally import consts
|
||||||
from rally.task import context
|
from rally.task import context
|
||||||
@ -83,6 +82,14 @@ def setup_dict(data, required=None, defaults=None):
|
|||||||
return defaults
|
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):
|
class FakeResource(object):
|
||||||
|
|
||||||
def __init__(self, manager=None, name=None, status="ACTIVE", items=None,
|
def __init__(self, manager=None, name=None, status="ACTIVE", items=None,
|
||||||
@ -1594,11 +1601,11 @@ class FakeClients(object):
|
|||||||
self._ec2 = None
|
self._ec2 = None
|
||||||
self._senlin = None
|
self._senlin = None
|
||||||
self._watcher = None
|
self._watcher = None
|
||||||
self._credential = credential_ or objects.Credential(
|
self._credential = credential_ or fake_credential(
|
||||||
"http://fake.example.org:5000/v2.0/",
|
auth_url="http://fake.example.org:5000/v2.0/",
|
||||||
"fake_username",
|
username="fake_username",
|
||||||
"fake_password",
|
password="fake_password",
|
||||||
"fake_tenant_name")
|
tenant_name="fake_tenant_name")
|
||||||
|
|
||||||
def keystone(self, version=None):
|
def keystone(self, version=None):
|
||||||
if not self._keystone:
|
if not self._keystone:
|
||||||
@ -1806,11 +1813,19 @@ class FakeUserContext(FakeContext):
|
|||||||
|
|
||||||
admin = {
|
admin = {
|
||||||
"id": "adminuuid",
|
"id": "adminuuid",
|
||||||
"credential": objects.Credential("aurl", "aname", "apwd", "atenant")
|
"credential": fake_credential(
|
||||||
|
auth_url="aurl",
|
||||||
|
username="aname",
|
||||||
|
password="apwd",
|
||||||
|
tenant_name="atenant")
|
||||||
}
|
}
|
||||||
user = {
|
user = {
|
||||||
"id": "uuid",
|
"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"
|
"tenant_id": "uuid"
|
||||||
}
|
}
|
||||||
tenants = {"uuid": {"name": "tenant"}}
|
tenants = {"uuid": {"name": "tenant"}}
|
||||||
|
@ -31,86 +31,19 @@ class SeekAndDestroyTestCase(test.TestCase):
|
|||||||
# clear out the client cache
|
# clear out the client cache
|
||||||
manager.SeekAndDestroy.cache = {}
|
manager.SeekAndDestroy.cache = {}
|
||||||
|
|
||||||
@mock.patch("%s.osclients.Clients" % BASE,
|
def test__get_cached_client(self):
|
||||||
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
|
|
||||||
api_versions = {"cinder": {"version": "1", "service_type": "volume"}}
|
api_versions = {"cinder": {"version": "1", "service_type": "volume"}}
|
||||||
|
|
||||||
destroyer1 = manager.SeekAndDestroy(None, None, None,
|
destroyer = manager.SeekAndDestroy(None, None, None,
|
||||||
api_versions=api_versions)
|
api_versions=api_versions)
|
||||||
destroyer2 = manager.SeekAndDestroy(None, None, None,
|
cred = mock.Mock()
|
||||||
api_versions=api_versions)
|
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),
|
self.assertIsNone(destroyer._get_cached_client(None))
|
||||||
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])])
|
|
||||||
|
|
||||||
@mock.patch("%s.LOG" % BASE)
|
@mock.patch("%s.LOG" % BASE)
|
||||||
def test__delete_single_resource(self, mock_log):
|
def test__delete_single_resource(self, mock_log):
|
||||||
|
@ -22,9 +22,7 @@ CTX = "rally.plugins.openstack.context"
|
|||||||
|
|
||||||
class ExistingUserTestCase(test.TestCase):
|
class ExistingUserTestCase(test.TestCase):
|
||||||
|
|
||||||
@mock.patch("%s.keystone.existing_users.osclients.Clients" % CTX)
|
def test_setup(self):
|
||||||
@mock.patch("%s.keystone.existing_users.objects.Credential" % CTX)
|
|
||||||
def test_setup(self, mock_credential, mock_clients):
|
|
||||||
user1 = mock.MagicMock(tenant_id="1", user_id="1",
|
user1 = mock.MagicMock(tenant_id="1", user_id="1",
|
||||||
tenant_name="proj", username="usr")
|
tenant_name="proj", username="usr")
|
||||||
user2 = mock.MagicMock(tenant_id="1", user_id="2",
|
user2 = mock.MagicMock(tenant_id="1", user_id="2",
|
||||||
@ -48,8 +46,10 @@ class ExistingUserTestCase(test.TestCase):
|
|||||||
self.PROJECT_ID_COUNT += 1
|
self.PROJECT_ID_COUNT += 1
|
||||||
return user_list[self.PROJECT_ID_COUNT - 1].tenant_id
|
return user_list[self.PROJECT_ID_COUNT - 1].tenant_id
|
||||||
|
|
||||||
mock_clients.return_value.keystone.auth_ref = AuthRef()
|
auth_ref = AuthRef()
|
||||||
mock_credential.side_effect = user_list
|
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 = {
|
context = {
|
||||||
"task": mock.MagicMock(),
|
"task": mock.MagicMock(),
|
||||||
|
@ -15,10 +15,10 @@
|
|||||||
|
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
from rally.common import objects
|
|
||||||
from rally import consts
|
from rally import consts
|
||||||
from rally import exceptions
|
from rally import exceptions
|
||||||
from rally.plugins.openstack.context.keystone import users
|
from rally.plugins.openstack.context.keystone import users
|
||||||
|
from rally.plugins.openstack import credential as oscredential
|
||||||
from tests.unit import test
|
from tests.unit import test
|
||||||
|
|
||||||
CTX = "rally.plugins.openstack.context.keystone.users"
|
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):
|
def test_users_and_tenants_in_context(self, mock_identity):
|
||||||
identity_service = mock_identity.Identity.return_value
|
identity_service = mock_identity.Identity.return_value
|
||||||
|
|
||||||
credential = objects.Credential("foo_url", "foo", "foo_pass",
|
credential = oscredential.OpenStackCredential(
|
||||||
https_insecure=True,
|
"foo_url", "foo", "foo_pass",
|
||||||
https_cacert="cacert")
|
https_insecure=True,
|
||||||
|
https_cacert="cacert")
|
||||||
tmp_context = dict(self.context)
|
tmp_context = dict(self.context)
|
||||||
tmp_context["config"]["users"] = {"tenants": 1,
|
tmp_context["config"]["users"] = {"tenants": 1,
|
||||||
"users_per_tenant": 2,
|
"users_per_tenant": 2,
|
||||||
"resource_management_workers": 1}
|
"resource_management_workers": 1}
|
||||||
tmp_context["admin"]["credential"] = credential
|
tmp_context["admin"]["credential"] = credential
|
||||||
|
|
||||||
credential_dict = credential.to_dict(False)
|
credential_dict = credential.to_dict()
|
||||||
user_list = [mock.MagicMock(id="id_%d" % i)
|
user_list = [mock.MagicMock(id="id_%d" % i)
|
||||||
for i in range(self.users_num)]
|
for i in range(self.users_num)]
|
||||||
identity_service.create_user.side_effect = user_list
|
identity_service.create_user.side_effect = user_list
|
||||||
@ -302,7 +303,7 @@ class UserGeneratorTestCase(test.ScenarioTestCase):
|
|||||||
self.assertEqual(set(["id", "credential", "tenant_id"]),
|
self.assertEqual(set(["id", "credential", "tenant_id"]),
|
||||||
set(user.keys()))
|
set(user.keys()))
|
||||||
|
|
||||||
user_credential_dict = user["credential"].to_dict(False)
|
user_credential_dict = user["credential"].to_dict()
|
||||||
|
|
||||||
excluded_keys = ["auth_url", "username", "password",
|
excluded_keys = ["auth_url", "username", "password",
|
||||||
"tenant_name", "region_name",
|
"tenant_name", "region_name",
|
||||||
@ -323,7 +324,7 @@ class UserGeneratorTestCase(test.ScenarioTestCase):
|
|||||||
|
|
||||||
@mock.patch("%s.identity" % CTX)
|
@mock.patch("%s.identity" % CTX)
|
||||||
def test_users_contains_correct_endpoint_type(self, mock_identity):
|
def test_users_contains_correct_endpoint_type(self, mock_identity):
|
||||||
credential = objects.Credential(
|
credential = oscredential.OpenStackCredential(
|
||||||
"foo_url", "foo", "foo_pass",
|
"foo_url", "foo", "foo_pass",
|
||||||
endpoint_type=consts.EndpointType.INTERNAL)
|
endpoint_type=consts.EndpointType.INTERNAL)
|
||||||
config = {
|
config = {
|
||||||
@ -346,7 +347,8 @@ class UserGeneratorTestCase(test.ScenarioTestCase):
|
|||||||
|
|
||||||
@mock.patch("%s.identity" % CTX)
|
@mock.patch("%s.identity" % CTX)
|
||||||
def test_users_contains_default_endpoint_type(self, mock_identity):
|
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 = {
|
||||||
"config": {
|
"config": {
|
||||||
"users": {
|
"users": {
|
||||||
|
@ -14,8 +14,8 @@
|
|||||||
|
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
from rally.common import objects
|
|
||||||
from rally.plugins.openstack.context.sahara import sahara_output_data_sources
|
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 rally.plugins.openstack.scenarios.sahara import utils as sahara_utils
|
||||||
from tests.unit import test
|
from tests.unit import test
|
||||||
|
|
||||||
@ -26,8 +26,8 @@ class SaharaOutputDataSourcesTestCase(test.ScenarioTestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(SaharaOutputDataSourcesTestCase, self).setUp()
|
super(SaharaOutputDataSourcesTestCase, self).setUp()
|
||||||
fake_dict = objects.Credential("http://fake.example.org:5000/v2.0/",
|
fake_dict = oscredential.OpenStackCredential(
|
||||||
"user", "passwd")
|
"http://fake.example.org:5000/v2.0/", "user", "passwd")
|
||||||
self.tenants_num = 2
|
self.tenants_num = 2
|
||||||
self.users_per_tenant = 2
|
self.users_per_tenant = 2
|
||||||
self.users = self.tenants_num * self.users_per_tenant
|
self.users = self.tenants_num * self.users_per_tenant
|
||||||
|
149
tests/unit/plugins/openstack/test_credential.py
Normal file
149
tests/unit/plugins/openstack/test_credential.py
Normal 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)
|
@ -18,6 +18,7 @@ import mock
|
|||||||
from oslotest import mockpatch
|
from oslotest import mockpatch
|
||||||
|
|
||||||
from rally.plugins.openstack import scenario as base_scenario
|
from rally.plugins.openstack import scenario as base_scenario
|
||||||
|
from tests.unit import fakes
|
||||||
from tests.unit import test
|
from tests.unit import test
|
||||||
|
|
||||||
|
|
||||||
@ -130,27 +131,21 @@ class OpenStackScenarioTestCase(test.TestCase):
|
|||||||
|
|
||||||
@mock.patch("rally.task.scenario.Scenario.validate")
|
@mock.patch("rally.task.scenario.Scenario.validate")
|
||||||
def test_validate(self, mock_scenario_validate):
|
def test_validate(self, mock_scenario_validate):
|
||||||
cred1 = mock.Mock()
|
cred1 = fakes.fake_credential(foo="bar1")
|
||||||
cred2 = mock.Mock()
|
cred2 = fakes.fake_credential(foo="bar2")
|
||||||
cred3 = mock.Mock()
|
cred3 = fakes.fake_credential(foo="bar3")
|
||||||
self.osclients.mock.side_effect = [cred1, cred2, cred3]
|
|
||||||
|
|
||||||
base_scenario.OpenStackScenario.validate(
|
base_scenario.OpenStackScenario.validate(
|
||||||
name="foo_name",
|
name="foo_name",
|
||||||
config="foo_config",
|
config="foo_config",
|
||||||
admin="foo_admin",
|
admin=cred1,
|
||||||
users=[{"credential": "foo_user1"},
|
users=[{"credential": cred2},
|
||||||
{"credential": "foo_user2"}],
|
{"credential": cred3}],
|
||||||
deployment=None)
|
deployment=None)
|
||||||
|
|
||||||
mock_scenario_validate.assert_called_once_with(
|
mock_scenario_validate.assert_called_once_with(
|
||||||
name="foo_name",
|
name="foo_name",
|
||||||
config="foo_config",
|
config="foo_config",
|
||||||
admin=cred1,
|
admin=cred1.clients.return_value,
|
||||||
users=[cred2, cred3],
|
users=[cred2.clients.return_value, cred3.clients.return_value],
|
||||||
deployment=None)
|
deployment=None)
|
||||||
self.osclients.mock.assert_has_calls([
|
|
||||||
mock.call("foo_admin"),
|
|
||||||
mock.call("foo_user1"),
|
|
||||||
mock.call("foo_user2"),
|
|
||||||
])
|
|
||||||
|
@ -25,20 +25,17 @@ from tests.unit import test
|
|||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
CREDS = {
|
CRED = {
|
||||||
"admin": {
|
"username": "admin",
|
||||||
"username": "admin",
|
"tenant_name": "admin",
|
||||||
"tenant_name": "admin",
|
"password": "admin-12345",
|
||||||
"password": "admin-12345",
|
"auth_url": "http://test:5000/v2.0/",
|
||||||
"auth_url": "http://test:5000/v2.0/",
|
"permission": "admin",
|
||||||
"permission": "admin",
|
"region_name": "test",
|
||||||
"region_name": "test",
|
"https_insecure": False,
|
||||||
"https_insecure": False,
|
"https_cacert": "/path/to/cacert/file",
|
||||||
"https_cacert": "/path/to/cacert/file",
|
"user_domain_name": "admin",
|
||||||
"user_domain_name": "admin",
|
"project_domain_name": "admin"
|
||||||
"project_domain_name": "admin"
|
|
||||||
},
|
|
||||||
"uuid": "fake_deployment"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PATH = "rally.plugins.openstack.verification.tempest.config"
|
PATH = "rally.plugins.openstack.verification.tempest.config"
|
||||||
@ -49,10 +46,8 @@ class TempestConfigfileManagerTestCase(test.TestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TempestConfigfileManagerTestCase, self).setUp()
|
super(TempestConfigfileManagerTestCase, self).setUp()
|
||||||
|
deployment = fakes.FakeDeployment(uuid="fake_deployment",
|
||||||
mock.patch("rally.osclients.Clients").start()
|
admin=fakes.fake_credential(**CRED))
|
||||||
|
|
||||||
deployment = fakes.FakeDeployment(**CREDS)
|
|
||||||
self.tempest = config.TempestConfigfileManager(deployment)
|
self.tempest = config.TempestConfigfileManager(deployment)
|
||||||
|
|
||||||
def test__configure_auth(self):
|
def test__configure_auth(self):
|
||||||
@ -60,10 +55,10 @@ class TempestConfigfileManagerTestCase(test.TestCase):
|
|||||||
self.tempest._configure_auth()
|
self.tempest._configure_auth()
|
||||||
|
|
||||||
expected = (
|
expected = (
|
||||||
("admin_username", CREDS["admin"]["username"]),
|
("admin_username", CRED["username"]),
|
||||||
("admin_password", CREDS["admin"]["password"]),
|
("admin_password", CRED["password"]),
|
||||||
("admin_project_name", CREDS["admin"]["tenant_name"]),
|
("admin_project_name", CRED["tenant_name"]),
|
||||||
("admin_domain_name", CREDS["admin"]["user_domain_name"]))
|
("admin_domain_name", CRED["user_domain_name"]))
|
||||||
result = self.tempest.conf.items("auth")
|
result = self.tempest.conf.items("auth")
|
||||||
for item in expected:
|
for item in expected:
|
||||||
self.assertIn(item, result)
|
self.assertIn(item, result)
|
||||||
@ -85,13 +80,13 @@ class TempestConfigfileManagerTestCase(test.TestCase):
|
|||||||
self.tempest._configure_identity()
|
self.tempest._configure_identity()
|
||||||
|
|
||||||
expected = (
|
expected = (
|
||||||
("region", CREDS["admin"]["region_name"]),
|
("region", CRED["region_name"]),
|
||||||
("auth_version", "v2"),
|
("auth_version", "v2"),
|
||||||
("uri", CREDS["admin"]["auth_url"][:-1]),
|
("uri", CRED["auth_url"][:-1]),
|
||||||
("uri_v3", CREDS["admin"]["auth_url"].replace("/v2.0/", "/v3")),
|
("uri_v3", CRED["auth_url"].replace("/v2.0/", "/v3")),
|
||||||
("disable_ssl_certificate_validation",
|
("disable_ssl_certificate_validation",
|
||||||
str(CREDS["admin"]["https_insecure"])),
|
str(CRED["https_insecure"])),
|
||||||
("ca_certificates_file", CREDS["admin"]["https_cacert"]))
|
("ca_certificates_file", CRED["https_cacert"]))
|
||||||
result = self.tempest.conf.items("identity")
|
result = self.tempest.conf.items("identity")
|
||||||
for item in expected:
|
for item in expected:
|
||||||
self.assertIn(item, result)
|
self.assertIn(item, result)
|
||||||
|
@ -30,20 +30,17 @@ from tests.unit import test
|
|||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
CREDS = {
|
CRED = {
|
||||||
"admin": {
|
"username": "admin",
|
||||||
"username": "admin",
|
"tenant_name": "admin",
|
||||||
"tenant_name": "admin",
|
"password": "admin-12345",
|
||||||
"password": "admin-12345",
|
"auth_url": "http://test:5000/v2.0/",
|
||||||
"auth_url": "http://test:5000/v2.0/",
|
"permission": "admin",
|
||||||
"permission": "admin",
|
"region_name": "test",
|
||||||
"region_name": "test",
|
"https_insecure": False,
|
||||||
"https_insecure": False,
|
"https_cacert": "/path/to/cacert/file",
|
||||||
"https_cacert": "/path/to/cacert/file",
|
"user_domain_name": "admin",
|
||||||
"user_domain_name": "admin",
|
"project_domain_name": "admin"
|
||||||
"project_domain_name": "admin"
|
|
||||||
},
|
|
||||||
"uuid": "fake_deployment"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PATH = "rally.plugins.openstack.verification.tempest.context"
|
PATH = "rally.plugins.openstack.verification.tempest.context"
|
||||||
@ -55,11 +52,12 @@ class TempestContextTestCase(test.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TempestContextTestCase, self).setUp()
|
super(TempestContextTestCase, self).setUp()
|
||||||
|
|
||||||
mock.patch("rally.osclients.Clients").start()
|
|
||||||
self.mock_isfile = mock.patch("os.path.isfile",
|
self.mock_isfile = mock.patch("os.path.isfile",
|
||||||
return_value=True).start()
|
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),
|
cfg = {"verifier": mock.Mock(deployment=self.deployment),
|
||||||
"verification": {"uuid": "uuid"}}
|
"verification": {"uuid": "uuid"}}
|
||||||
cfg["verifier"].manager.home_dir = "/p/a/t/h"
|
cfg["verifier"].manager.home_dir = "/p/a/t/h"
|
||||||
@ -244,6 +242,7 @@ class TempestContextTestCase(test.TestCase):
|
|||||||
|
|
||||||
def test__discover_or_create_flavor(self):
|
def test__discover_or_create_flavor(self):
|
||||||
client = self.context.clients.nova()
|
client = self.context.clients.nova()
|
||||||
|
client.flavors.list.return_value = []
|
||||||
client.flavors.create.side_effect = [fakes.FakeFlavor(id="id1")]
|
client.flavors.create.side_effect = [fakes.FakeFlavor(id="id1")]
|
||||||
|
|
||||||
flavor = self.context._discover_or_create_flavor(64)
|
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_network.side_effect = [{"network": fake_network}]
|
||||||
client.create_router.side_effect = [{"router": {"id": "rid1"}}]
|
client.create_router.side_effect = [{"router": {"id": "rid1"}}]
|
||||||
client.create_subnet.side_effect = [{"subnet": {"id": "subid1"}}]
|
client.create_subnet.side_effect = [{"subnet": {"id": "subid1"}}]
|
||||||
|
client.list_networks.return_value = {"networks": []}
|
||||||
|
|
||||||
network = self.context._create_network_resources()
|
network = self.context._create_network_resources()
|
||||||
self.assertEqual("nid1", network["id"])
|
self.assertEqual("nid1", network["id"])
|
||||||
@ -333,16 +333,14 @@ class TempestContextTestCase(test.TestCase):
|
|||||||
@mock.patch("%s.TempestContext._configure_option" % PATH)
|
@mock.patch("%s.TempestContext._configure_option" % PATH)
|
||||||
@mock.patch("%s.TempestContext._create_tempest_roles" % PATH)
|
@mock.patch("%s.TempestContext._create_tempest_roles" % PATH)
|
||||||
@mock.patch("rally.verification.utils.create_dir")
|
@mock.patch("rally.verification.utils.create_dir")
|
||||||
@mock.patch("%s.osclients.Clients" % PATH)
|
def test_setup(self, mock_create_dir,
|
||||||
def test_setup(self, mock_clients, mock_create_dir,
|
|
||||||
mock__create_tempest_roles, mock__configure_option,
|
mock__create_tempest_roles, mock__configure_option,
|
||||||
mock_open):
|
mock_open):
|
||||||
self.deployment = fakes.FakeDeployment(**CREDS)
|
|
||||||
verifier = mock.Mock(deployment=self.deployment)
|
verifier = mock.Mock(deployment=self.deployment)
|
||||||
verifier.manager.home_dir = "/p/a/t/h"
|
verifier.manager.home_dir = "/p/a/t/h"
|
||||||
|
|
||||||
# case #1: no neutron and heat
|
# 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 = context.TempestContext({"verifier": verifier})
|
||||||
ctx.conf = mock.Mock()
|
ctx.conf = mock.Mock()
|
||||||
@ -377,10 +375,12 @@ class TempestContextTestCase(test.TestCase):
|
|||||||
mock__configure_option.reset_mock()
|
mock__configure_option.reset_mock()
|
||||||
|
|
||||||
# case #2: neutron and heat are presented
|
# 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"}
|
"network": "neutron", "orchestration": "heat"}
|
||||||
|
|
||||||
ctx = context.TempestContext({"verifier": verifier})
|
ctx = context.TempestContext({"verifier": verifier})
|
||||||
|
neutron = ctx.clients.neutron()
|
||||||
|
neutron.list_networks.return_value = {"networks": ["fake_net"]}
|
||||||
ctx.conf = mock.Mock()
|
ctx.conf = mock.Mock()
|
||||||
ctx.setup()
|
ctx.setup()
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
"""Tests for the Test engine."""
|
"""Tests for the Test engine."""
|
||||||
|
|
||||||
import collections
|
import collections
|
||||||
import copy
|
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
import jsonschema
|
import jsonschema
|
||||||
@ -286,10 +285,8 @@ class TaskEngineTestCase(test.TestCase):
|
|||||||
eng._validate_config_semantic_helper, "a",
|
eng._validate_config_semantic_helper, "a",
|
||||||
user_context, workloads, "fake_deployment")
|
user_context, workloads, "fake_deployment")
|
||||||
|
|
||||||
@mock.patch("rally.osclients.Clients")
|
|
||||||
@mock.patch("rally.task.engine.scenario.Scenario.get")
|
@mock.patch("rally.task.engine.scenario.Scenario.get")
|
||||||
@mock.patch("rally.task.engine.context.Context")
|
@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.TaskConfig")
|
||||||
@mock.patch("rally.task.engine.TaskEngine"
|
@mock.patch("rally.task.engine.TaskEngine"
|
||||||
"._validate_config_semantic_helper")
|
"._validate_config_semantic_helper")
|
||||||
@ -298,11 +295,12 @@ class TaskEngineTestCase(test.TestCase):
|
|||||||
def test__validate_config_semantic(
|
def test__validate_config_semantic(
|
||||||
self, mock_deployment_get,
|
self, mock_deployment_get,
|
||||||
mock__validate_config_semantic_helper,
|
mock__validate_config_semantic_helper,
|
||||||
mock_task_config, mock_credential, mock_context,
|
mock_task_config, mock_context,
|
||||||
mock_scenario_get, mock_clients):
|
mock_scenario_get):
|
||||||
|
admin = fakes.fake_credential(foo="admin")
|
||||||
|
users = [fakes.fake_credential(bar="user1")]
|
||||||
deployment = fakes.FakeDeployment(
|
deployment = fakes.FakeDeployment(
|
||||||
uuid="deployment_uuid", admin={"foo": "admin"},
|
uuid="deployment_uuid", admin=admin, users=users)
|
||||||
users=[{"bar": "user1"}])
|
|
||||||
|
|
||||||
scenario_cls = mock_scenario_get.return_value
|
scenario_cls = mock_scenario_get.return_value
|
||||||
scenario_cls.get_namespace.return_value = "default"
|
scenario_cls.get_namespace.return_value = "default"
|
||||||
@ -324,12 +322,8 @@ class TaskEngineTestCase(test.TestCase):
|
|||||||
|
|
||||||
eng._validate_config_semantic(mock_task_instance)
|
eng._validate_config_semantic(mock_task_instance)
|
||||||
|
|
||||||
admin = mock_credential.return_value
|
|
||||||
user_context = mock_context.get.return_value.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__validate_config_semantic_helper.assert_has_calls([
|
||||||
mock.call(admin, user_context, [wconf1], deployment),
|
mock.call(admin, user_context, [wconf1], deployment),
|
||||||
mock.call(admin, user_context, [wconf2, wconf3], deployment),
|
mock.call(admin, user_context, [wconf2, wconf3], deployment),
|
||||||
@ -356,7 +350,6 @@ class TaskEngineTestCase(test.TestCase):
|
|||||||
mock.call(consts.TaskStatus.FINISHED)
|
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.objects.task.Task.get_status")
|
||||||
@mock.patch("rally.task.engine.TaskConfig")
|
@mock.patch("rally.task.engine.TaskConfig")
|
||||||
@mock.patch("rally.task.engine.LOG")
|
@mock.patch("rally.task.engine.LOG")
|
||||||
@ -368,7 +361,7 @@ class TaskEngineTestCase(test.TestCase):
|
|||||||
def test_run_exception_is_logged(
|
def test_run_exception_is_logged(
|
||||||
self, mock_context_manager_setup, mock_context_manager_cleanup,
|
self, mock_context_manager_setup, mock_context_manager_cleanup,
|
||||||
mock_scenario_runner, mock_scenario, mock_result_consumer,
|
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 = mock_scenario.get.return_value
|
||||||
scenario_cls.get_namespace.return_value = "openstack"
|
scenario_cls.get_namespace.return_value = "openstack"
|
||||||
|
|
||||||
@ -394,7 +387,6 @@ class TaskEngineTestCase(test.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(2, mock_log.exception.call_count)
|
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.ResultConsumer")
|
||||||
@mock.patch("rally.task.engine.context.ContextManager.cleanup")
|
@mock.patch("rally.task.engine.context.ContextManager.cleanup")
|
||||||
@mock.patch("rally.task.engine.context.ContextManager.setup")
|
@mock.patch("rally.task.engine.context.ContextManager.setup")
|
||||||
@ -403,7 +395,7 @@ class TaskEngineTestCase(test.TestCase):
|
|||||||
def test_run__task_soft_aborted(
|
def test_run__task_soft_aborted(
|
||||||
self, mock_scenario_runner, mock_scenario,
|
self, mock_scenario_runner, mock_scenario,
|
||||||
mock_context_manager_setup, mock_context_manager_cleanup,
|
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 = mock_scenario.get.return_value
|
||||||
scenario_cls.get_namespace.return_value = "openstack"
|
scenario_cls.get_namespace.return_value = "openstack"
|
||||||
task = mock.MagicMock()
|
task = mock.MagicMock()
|
||||||
@ -455,11 +447,9 @@ class TaskEngineTestCase(test.TestCase):
|
|||||||
self.assertEqual(mock.call(consts.TaskStatus.ABORTED),
|
self.assertEqual(mock.call(consts.TaskStatus.ABORTED),
|
||||||
task.update_status.mock_calls[-1])
|
task.update_status.mock_calls[-1])
|
||||||
|
|
||||||
@mock.patch("rally.task.engine.objects.Credential")
|
|
||||||
@mock.patch("rally.task.engine.TaskConfig")
|
@mock.patch("rally.task.engine.TaskConfig")
|
||||||
@mock.patch("rally.task.engine.scenario.Scenario.get")
|
@mock.patch("rally.task.engine.scenario.Scenario.get")
|
||||||
def test__prepare_context(self, mock_scenario_get, mock_task_config,
|
def test__prepare_context(self, mock_scenario_get, mock_task_config):
|
||||||
mock_credential):
|
|
||||||
default_context = {"a": 1, "b": 2}
|
default_context = {"a": 1, "b": 2}
|
||||||
mock_scenario = mock_scenario_get.return_value
|
mock_scenario = mock_scenario_get.return_value
|
||||||
mock_scenario.get_default_context.return_value = default_context
|
mock_scenario.get_default_context.return_value = default_context
|
||||||
@ -470,28 +460,24 @@ class TaskEngineTestCase(test.TestCase):
|
|||||||
config = {
|
config = {
|
||||||
"a.task": [{"context": {"context_a": {"a": 1}}}],
|
"a.task": [{"context": {"context_a": {"a": 1}}}],
|
||||||
}
|
}
|
||||||
|
admin = fakes.fake_credential(foo="admin")
|
||||||
deployment = fakes.FakeDeployment(
|
deployment = fakes.FakeDeployment(
|
||||||
uuid="deployment_uuid", admin={"foo": "admin"})
|
uuid="deployment_uuid", admin=admin)
|
||||||
eng = engine.TaskEngine(config, task, deployment)
|
eng = engine.TaskEngine(config, task, deployment)
|
||||||
result = eng._prepare_context(context, name)
|
result = eng._prepare_context(context, name)
|
||||||
expected_context = copy.deepcopy(default_context)
|
|
||||||
expected_context.setdefault("users", {})
|
|
||||||
expected_context.update(context)
|
|
||||||
expected_result = {
|
expected_result = {
|
||||||
"task": task,
|
"task": task,
|
||||||
"admin": {"credential": mock_credential.return_value},
|
"admin": {"credential": admin},
|
||||||
"scenario_name": name,
|
"scenario_name": name,
|
||||||
"config": expected_context
|
"config": {"a": 1, "b": 3, "c": 4, "users": {}}
|
||||||
}
|
}
|
||||||
self.assertEqual(result, expected_result)
|
self.assertEqual(result, expected_result)
|
||||||
mock_scenario_get.assert_called_once_with(name)
|
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.TaskConfig")
|
||||||
@mock.patch("rally.task.engine.scenario.Scenario.get")
|
@mock.patch("rally.task.engine.scenario.Scenario.get")
|
||||||
def test__prepare_context_with_existing_users(self, mock_scenario_get,
|
def test__prepare_context_with_existing_users(self, mock_scenario_get,
|
||||||
mock_task_config,
|
mock_task_config):
|
||||||
mock_credential):
|
|
||||||
mock_scenario = mock_scenario_get.return_value
|
mock_scenario = mock_scenario_get.return_value
|
||||||
mock_scenario.get_default_context.return_value = {}
|
mock_scenario.get_default_context.return_value = {}
|
||||||
mock_scenario.get_namespace.return_value = "default"
|
mock_scenario.get_namespace.return_value = "default"
|
||||||
@ -501,18 +487,17 @@ class TaskEngineTestCase(test.TestCase):
|
|||||||
config = {
|
config = {
|
||||||
"a.task": [{"context": {"context_a": {"a": 1}}}],
|
"a.task": [{"context": {"context_a": {"a": 1}}}],
|
||||||
}
|
}
|
||||||
deployment = fakes.FakeDeployment(
|
admin = fakes.fake_credential(foo="admin")
|
||||||
uuid="deployment_uuid", admin={"foo": "admin"},
|
users = [fakes.fake_credential(bar="user1")]
|
||||||
users=[{"bar": "user1"}])
|
deployment = fakes.FakeDeployment(uuid="deployment_uuid",
|
||||||
|
admin=admin, users=users)
|
||||||
eng = engine.TaskEngine(config, task, deployment)
|
eng = engine.TaskEngine(config, task, deployment)
|
||||||
result = eng._prepare_context(context, name)
|
result = eng._prepare_context(context, name)
|
||||||
expected_context = {"existing_users": [{"bar": "user1"}]}
|
|
||||||
expected_context.update(context)
|
|
||||||
expected_result = {
|
expected_result = {
|
||||||
"task": task,
|
"task": task,
|
||||||
"admin": {"credential": mock_credential.return_value},
|
"admin": {"credential": admin},
|
||||||
"scenario_name": name,
|
"scenario_name": name,
|
||||||
"config": expected_context
|
"config": {"b": 3, "c": 4, "existing_users": users}
|
||||||
}
|
}
|
||||||
self.assertEqual(result, expected_result)
|
self.assertEqual(result, expected_result)
|
||||||
mock_scenario_get.assert_called_once_with(name)
|
mock_scenario_get.assert_called_once_with(name)
|
||||||
|
@ -24,7 +24,6 @@ import six
|
|||||||
from rally.common.plugin import plugin
|
from rally.common.plugin import plugin
|
||||||
from rally import consts
|
from rally import consts
|
||||||
from rally import exceptions
|
from rally import exceptions
|
||||||
import rally.osclients
|
|
||||||
from rally.task import validation
|
from rally.task import validation
|
||||||
from tests.unit import fakes
|
from tests.unit import fakes
|
||||||
from tests.unit import test
|
from tests.unit import test
|
||||||
@ -557,35 +556,32 @@ class ValidatorsTestCase(test.TestCase):
|
|||||||
result = validator({"args": {"a": 1, "c": 3}}, None, None)
|
result = validator({"args": {"a": 1, "c": 3}}, None, None)
|
||||||
self.assertFalse(result.is_valid, result.msg)
|
self.assertFalse(result.is_valid, result.msg)
|
||||||
|
|
||||||
@mock.patch("rally.common.objects.Credential")
|
def test_required_service(self):
|
||||||
def test_required_service(self, mock_credential):
|
|
||||||
validator = self._unwrap_validator(validation.required_services,
|
validator = self._unwrap_validator(validation.required_services,
|
||||||
consts.Service.KEYSTONE,
|
consts.Service.KEYSTONE,
|
||||||
consts.Service.NOVA,
|
consts.Service.NOVA,
|
||||||
consts.Service.NOVA_NET)
|
consts.Service.NOVA_NET)
|
||||||
clients = mock.MagicMock()
|
admin = fakes.fake_credential(foo="bar")
|
||||||
|
clients = mock.Mock()
|
||||||
clients.services().values.return_value = [consts.Service.KEYSTONE,
|
clients.services().values.return_value = [consts.Service.KEYSTONE,
|
||||||
consts.Service.NOVA,
|
consts.Service.NOVA,
|
||||||
consts.Service.NOVA_NET]
|
consts.Service.NOVA_NET]
|
||||||
|
|
||||||
fake_service = mock.Mock(binary="nova-network", status="enabled")
|
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)
|
self.assertTrue(result.is_valid, result.msg)
|
||||||
|
|
||||||
validator = self._unwrap_validator(validation.required_services,
|
validator = self._unwrap_validator(validation.required_services,
|
||||||
consts.Service.KEYSTONE,
|
consts.Service.KEYSTONE,
|
||||||
consts.Service.NOVA)
|
consts.Service.NOVA)
|
||||||
clients.services().values.return_value = [consts.Service.KEYSTONE]
|
clients.services().values.return_value = [consts.Service.KEYSTONE]
|
||||||
with mock.patch("rally.osclients.Clients") as clients_cls:
|
|
||||||
result = validator({}, clients, None)
|
result = validator({}, clients, None)
|
||||||
self.assertFalse(clients_cls.called)
|
|
||||||
self.assertFalse(result.is_valid, result.msg)
|
self.assertFalse(result.is_valid, result.msg)
|
||||||
|
|
||||||
def test_required_service_wrong_service(self):
|
def test_required_service_wrong_service(self):
|
||||||
@ -752,37 +748,33 @@ class ValidatorsTestCase(test.TestCase):
|
|||||||
result = validator(context, clients, mock.MagicMock())
|
result = validator(context, clients, mock.MagicMock())
|
||||||
self.assertFalse(result.is_valid, result.msg)
|
self.assertFalse(result.is_valid, result.msg)
|
||||||
|
|
||||||
@mock.patch(MODULE + "osclients")
|
def test_required_clients(self):
|
||||||
def test_required_clients(self, mock_osclients):
|
|
||||||
validator = self._unwrap_validator(validation.required_clients,
|
validator = self._unwrap_validator(validation.required_clients,
|
||||||
"keystone", "nova")
|
"keystone", "nova")
|
||||||
clients = mock.MagicMock()
|
clients = mock.Mock()
|
||||||
clients.keystone.return_value = "keystone"
|
clients.keystone.return_value = "keystone"
|
||||||
clients.nova.return_value = "nova"
|
clients.nova.return_value = "nova"
|
||||||
deployment = fakes.FakeDeployment()
|
deployment = fakes.FakeDeployment()
|
||||||
result = validator({}, clients, deployment)
|
result = validator({}, clients, deployment)
|
||||||
self.assertTrue(result.is_valid, result.msg)
|
self.assertTrue(result.is_valid, result.msg)
|
||||||
self.assertFalse(mock_osclients.Clients.called)
|
|
||||||
|
|
||||||
clients.nova.side_effect = ImportError
|
clients.nova.side_effect = ImportError
|
||||||
result = validator({}, clients, deployment)
|
result = validator({}, clients, deployment)
|
||||||
self.assertFalse(result.is_valid, result.msg)
|
self.assertFalse(result.is_valid, result.msg)
|
||||||
|
|
||||||
@mock.patch(MODULE + "objects")
|
def test_required_clients_with_admin(self):
|
||||||
@mock.patch(MODULE + "osclients")
|
|
||||||
def test_required_clients_with_admin(self, mock_osclients, mock_objects):
|
|
||||||
validator = self._unwrap_validator(validation.required_clients,
|
validator = self._unwrap_validator(validation.required_clients,
|
||||||
"keystone", "nova", admin=True)
|
"keystone", "nova", admin=True)
|
||||||
clients = mock.Mock()
|
admin = fakes.fake_credential(foo="bar")
|
||||||
|
|
||||||
|
clients = admin.clients.return_value
|
||||||
clients.keystone.return_value = "keystone"
|
clients.keystone.return_value = "keystone"
|
||||||
clients.nova.return_value = "nova"
|
clients.nova.return_value = "nova"
|
||||||
mock_osclients.Clients.return_value = clients
|
|
||||||
mock_objects.Credential.return_value = "foo_credential"
|
deployment = fakes.FakeDeployment(admin=admin)
|
||||||
deployment = fakes.FakeDeployment(admin={"foo": "bar"})
|
|
||||||
result = validator({}, clients, deployment)
|
result = validator({}, clients, deployment)
|
||||||
self.assertTrue(result.is_valid, result.msg)
|
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
|
clients.nova.side_effect = ImportError
|
||||||
result = validator({}, clients, deployment)
|
result = validator({}, clients, deployment)
|
||||||
self.assertFalse(result.is_valid, result.msg)
|
self.assertFalse(result.is_valid, result.msg)
|
||||||
@ -810,24 +802,17 @@ class ValidatorsTestCase(test.TestCase):
|
|||||||
validation.required_cinder_services,
|
validation.required_cinder_services,
|
||||||
service_name=six.text_type("cinder-service"))
|
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")
|
||||||
fake_service = mock.Mock(binary="cinder-service", state="up")
|
admin = fakes.fake_credential(foo="bar")
|
||||||
cinder_client = mock.Mock()
|
cinder = admin.clients.return_value.cinder.return_value
|
||||||
services = mock.Mock()
|
cinder.services.list.return_value = [fake_service]
|
||||||
services.list.return_value = [fake_service]
|
deployment = fakes.FakeDeployment(admin=admin)
|
||||||
cinder_client.services = services
|
result = validator({}, None, deployment)
|
||||||
c.return_value = cinder_client
|
self.assertTrue(result.is_valid, result.msg)
|
||||||
|
|
||||||
deployment = fakes.FakeDeployment(
|
fake_service.state = "down"
|
||||||
admin={"auth_url": "fake_credential",
|
result = validator({}, None, deployment)
|
||||||
"username": "username",
|
self.assertFalse(result.is_valid, result.msg)
|
||||||
"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)
|
|
||||||
|
|
||||||
def test_restricted_parameters(self):
|
def test_restricted_parameters(self):
|
||||||
validator = self._unwrap_validator(
|
validator = self._unwrap_validator(
|
||||||
|
@ -20,7 +20,6 @@ import os
|
|||||||
|
|
||||||
import ddt
|
import ddt
|
||||||
import jsonschema
|
import jsonschema
|
||||||
from keystoneclient import exceptions as keystone_exceptions
|
|
||||||
import mock
|
import mock
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
|
||||||
@ -349,8 +348,8 @@ class BaseDeploymentTestCase(test.TestCase):
|
|||||||
class DeploymentAPITestCase(BaseDeploymentTestCase):
|
class DeploymentAPITestCase(BaseDeploymentTestCase):
|
||||||
@mock.patch("rally.common.objects.deploy.db.deployment_update")
|
@mock.patch("rally.common.objects.deploy.db.deployment_update")
|
||||||
@mock.patch("rally.common.objects.deploy.db.deployment_create")
|
@mock.patch("rally.common.objects.deploy.db.deployment_create")
|
||||||
@mock.patch("rally.deployment.engine.Engine.validate")
|
@mock.patch("rally.deployment.engines.existing.ExistingCloud.validate")
|
||||||
def test_create(self, mock_engine_validate,
|
def test_create(self, mock_existing_cloud_validate,
|
||||||
mock_deployment_create, mock_deployment_update):
|
mock_deployment_create, mock_deployment_update):
|
||||||
mock_deployment_create.return_value = self.deployment
|
mock_deployment_create.return_value = self.deployment
|
||||||
mock_deployment_update.return_value = self.deployment
|
mock_deployment_update.return_value = self.deployment
|
||||||
@ -360,7 +359,7 @@ class DeploymentAPITestCase(BaseDeploymentTestCase):
|
|||||||
"name": "fake_deployment",
|
"name": "fake_deployment",
|
||||||
"config": self.deployment_config,
|
"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_deployment_update.assert_has_calls([
|
||||||
mock.call(self.deployment_uuid,
|
mock.call(self.deployment_uuid,
|
||||||
{"credentials": {"openstack": [self.credentials]}})
|
{"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_update")
|
||||||
@mock.patch("rally.common.objects.deploy.db.deployment_create")
|
@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"))
|
side_effect=jsonschema.ValidationError("ValidationError"))
|
||||||
def test_create_validation_error(
|
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_update):
|
||||||
mock_deployment_create.return_value = self.deployment
|
mock_deployment_create.return_value = self.deployment
|
||||||
self.assertRaises(jsonschema.ValidationError,
|
self.assertRaises(jsonschema.ValidationError,
|
||||||
@ -488,41 +487,25 @@ class DeploymentAPITestCase(BaseDeploymentTestCase):
|
|||||||
for key in self.deployment:
|
for key in self.deployment:
|
||||||
self.assertEqual(ret[key], self.deployment[key])
|
self.assertEqual(ret[key], self.deployment[key])
|
||||||
|
|
||||||
@mock.patch("rally.osclients.Clients.services")
|
def test_deployment_check(self):
|
||||||
@mock.patch("rally.osclients.Keystone.create_client")
|
fake_credential1 = fakes.fake_credential()
|
||||||
def test_deployment_check(self, mock_keystone_create_client,
|
fake_credential2 = fakes.fake_credential()
|
||||||
mock_clients_services):
|
|
||||||
sample_credential = objects.Credential("http://192.168.1.1:5000/v2.0/",
|
|
||||||
"admin",
|
|
||||||
"adminpass").to_dict()
|
|
||||||
deployment = mock.Mock(spec=objects.Deployment)
|
deployment = mock.Mock(spec=objects.Deployment)
|
||||||
deployment.get_credentials_for.return_value = {
|
deployment.get_credentials_for.return_value = {
|
||||||
"admin": sample_credential, "users": [sample_credential]}
|
"admin": fake_credential1, "users": [fake_credential2]}
|
||||||
api._Deployment.check(deployment)
|
result = api._Deployment.check(deployment)
|
||||||
mock_keystone_create_client.assert_called_with()
|
fake_credential1.verify_connection.assert_called_once_with()
|
||||||
mock_clients_services.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):
|
def test_service_list(self):
|
||||||
sample_credential = objects.Credential("http://192.168.1.1:5000/v2.0/",
|
fake_credential = fakes.fake_credential()
|
||||||
"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()
|
|
||||||
deployment = mock.Mock(spec=objects.Deployment)
|
deployment = mock.Mock(spec=objects.Deployment)
|
||||||
deployment.get_credentials_for.return_value = {
|
deployment.get_credentials_for.return_value = {
|
||||||
"admin": sample_credential, "users": []}
|
"admin": fake_credential, "users": []}
|
||||||
refused = keystone_exceptions.ConnectionRefused()
|
result = api._Deployment.service_list(deployment)
|
||||||
mock_clients_services.side_effect = refused
|
self.assertEqual(fake_credential.list_services.return_value, result)
|
||||||
self.assertRaises(
|
|
||||||
keystone_exceptions.ConnectionRefused,
|
|
||||||
api._Deployment.check, deployment)
|
|
||||||
|
|
||||||
|
|
||||||
class APITestCase(test.TestCase):
|
class APITestCase(test.TestCase):
|
||||||
|
@ -18,10 +18,10 @@ from keystoneclient import exceptions as keystone_exceptions
|
|||||||
import mock
|
import mock
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
|
||||||
from rally.common import objects
|
|
||||||
from rally import consts
|
from rally import consts
|
||||||
from rally import exceptions
|
from rally import exceptions
|
||||||
from rally import osclients
|
from rally import osclients
|
||||||
|
from rally.plugins.openstack import credential as oscredential
|
||||||
from tests.unit import fakes
|
from tests.unit import fakes
|
||||||
from tests.unit import test
|
from tests.unit import test
|
||||||
|
|
||||||
@ -91,9 +91,10 @@ class OSClientTestCase(test.TestCase, OSClientTestCaseUtils):
|
|||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
def test__get_endpoint(self, mock_keystone_service_catalog, endpoint_type,
|
def test__get_endpoint(self, mock_keystone_service_catalog, endpoint_type,
|
||||||
service_type, region_name):
|
service_type, region_name):
|
||||||
credential = objects.Credential("http://auth_url/v2.0", "user", "pass",
|
credential = oscredential.OpenStackCredential(
|
||||||
endpoint_type=endpoint_type,
|
"http://auth_url/v2.0", "user", "pass",
|
||||||
region_name=region_name)
|
endpoint_type=endpoint_type,
|
||||||
|
region_name=region_name)
|
||||||
mock_choose_service_type = mock.MagicMock()
|
mock_choose_service_type = mock.MagicMock()
|
||||||
osclient = osclients.OSClient(credential, {}, mock.MagicMock())
|
osclient = osclients.OSClient(credential, {}, mock.MagicMock())
|
||||||
osclient.choose_service_type = mock_choose_service_type
|
osclient.choose_service_type = mock_choose_service_type
|
||||||
@ -153,8 +154,8 @@ class TestCreateKeystoneClient(test.TestCase, OSClientTestCaseUtils):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestCreateKeystoneClient, self).setUp()
|
super(TestCreateKeystoneClient, self).setUp()
|
||||||
self.credential = objects.Credential("http://auth_url/v2.0", "user",
|
self.credential = oscredential.OpenStackCredential(
|
||||||
"pass", "tenant")
|
"http://auth_url/v2.0", "user", "pass", "tenant")
|
||||||
|
|
||||||
def test_create_client(self):
|
def test_create_client(self):
|
||||||
# NOTE(bigjools): This is a very poor testing strategy as it
|
# 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",
|
@ddt.data("http://auth_url/v2.0", "http://auth_url/v3",
|
||||||
"http://auth_url/", "auth_url")
|
"http://auth_url/", "auth_url")
|
||||||
def test_keystone_get_session(self, auth_url):
|
def test_keystone_get_session(self, auth_url):
|
||||||
credential = objects.Credential(auth_url, "user",
|
credential = oscredential.OpenStackCredential(
|
||||||
"pass", "tenant")
|
auth_url, "user", "pass", "tenant")
|
||||||
self.set_up_keystone_mocks()
|
self.set_up_keystone_mocks()
|
||||||
keystone = osclients.Keystone(credential, {}, {})
|
keystone = osclients.Keystone(credential, {}, {})
|
||||||
|
|
||||||
@ -255,8 +256,8 @@ class OSClientsTestCase(test.TestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(OSClientsTestCase, self).setUp()
|
super(OSClientsTestCase, self).setUp()
|
||||||
self.credential = objects.Credential("http://auth_url/v2.0", "user",
|
self.credential = oscredential.OpenStackCredential(
|
||||||
"pass", "tenant")
|
"http://auth_url/v2.0", "user", "pass", "tenant")
|
||||||
self.clients = osclients.Clients(self.credential, {})
|
self.clients = osclients.Clients(self.credential, {})
|
||||||
|
|
||||||
self.fake_keystone = fakes.FakeKeystoneClient()
|
self.fake_keystone = fakes.FakeKeystoneClient()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user