Add Mistral benchmark
- added Mistral client initialization - added Mistral scenarios - added unit tests Change-Id: Ie60a36504a970e6acb369adc570a556e549c20e1
This commit is contained in:
parent
bdbc127294
commit
717de8291e
1
optional-requirements.txt
Normal file
1
optional-requirements.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
git+git://github.com/stackforge/python-mistralclient.git
|
13
rally-jobs/extra/mistral_wb.yaml
Normal file
13
rally-jobs/extra/mistral_wb.yaml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
version: "2.0"
|
||||||
|
|
||||||
|
name: wb
|
||||||
|
|
||||||
|
workflows:
|
||||||
|
wf1:
|
||||||
|
type: direct
|
||||||
|
tasks:
|
||||||
|
hello:
|
||||||
|
action: std.echo output="Hello"
|
||||||
|
publish:
|
||||||
|
result: $
|
46
rally-jobs/rally-mistral.yaml
Normal file
46
rally-jobs/rally-mistral.yaml
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
---
|
||||||
|
MistralWorkbooks.list_workbooks:
|
||||||
|
-
|
||||||
|
runner:
|
||||||
|
type: "constant"
|
||||||
|
times: 50
|
||||||
|
concurrency: 10
|
||||||
|
context:
|
||||||
|
users:
|
||||||
|
tenants: 1
|
||||||
|
users_per_tenant: 1
|
||||||
|
sla:
|
||||||
|
failure_rate:
|
||||||
|
max: 0
|
||||||
|
|
||||||
|
MistralWorkbooks.create_workbook:
|
||||||
|
-
|
||||||
|
args:
|
||||||
|
definition: "/home/jenkins/.rally/extra/mistral_wb.yaml"
|
||||||
|
runner:
|
||||||
|
type: "constant"
|
||||||
|
times: 50
|
||||||
|
concurrency: 10
|
||||||
|
context:
|
||||||
|
users:
|
||||||
|
tenants: 1
|
||||||
|
users_per_tenant: 1
|
||||||
|
sla:
|
||||||
|
failure_rate:
|
||||||
|
max: 0
|
||||||
|
|
||||||
|
-
|
||||||
|
args:
|
||||||
|
definition: "/home/jenkins/.rally/extra/mistral_wb.yaml"
|
||||||
|
do_delete: true
|
||||||
|
runner:
|
||||||
|
type: "constant"
|
||||||
|
times: 50
|
||||||
|
concurrency: 10
|
||||||
|
context:
|
||||||
|
users:
|
||||||
|
tenants: 1
|
||||||
|
users_per_tenant: 1
|
||||||
|
sla:
|
||||||
|
failure_rate:
|
||||||
|
max: 0
|
@ -284,6 +284,14 @@ class DesignateServer(SynchronizedDeletion, base.ResourceManager):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# MISTRAL
|
||||||
|
|
||||||
|
@base.resource("mistral", "workbooks", order=1100, tenant_resource=True)
|
||||||
|
class MistralWorkbooks(SynchronizedDeletion, base.ResourceManager):
|
||||||
|
def delete(self):
|
||||||
|
self._manager().delete(self.raw_resource.name)
|
||||||
|
|
||||||
|
|
||||||
# KEYSTONE
|
# KEYSTONE
|
||||||
|
|
||||||
_keystone_order = get_order(9000)
|
_keystone_order = get_order(9000)
|
||||||
|
0
rally/benchmark/scenarios/mistral/__init__.py
Normal file
0
rally/benchmark/scenarios/mistral/__init__.py
Normal file
49
rally/benchmark/scenarios/mistral/utils.py
Normal file
49
rally/benchmark/scenarios/mistral/utils.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# Copyright 2015: 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 yaml
|
||||||
|
|
||||||
|
from rally.benchmark.scenarios import base
|
||||||
|
|
||||||
|
|
||||||
|
class MistralScenario(base.Scenario):
|
||||||
|
"""Base class for Mistral scenarios with basic atomic actions."""
|
||||||
|
|
||||||
|
@base.atomic_action_timer("mistral.list_workbooks")
|
||||||
|
def _list_workbooks(self):
|
||||||
|
"""Gets list of existing workbooks."""
|
||||||
|
return self.clients("mistral").workbooks.list()
|
||||||
|
|
||||||
|
@base.atomic_action_timer("mistral.create_workbook")
|
||||||
|
def _create_workbook(self, definition):
|
||||||
|
"""Create a new workbook.
|
||||||
|
|
||||||
|
:param definition: workbook description in string
|
||||||
|
(yaml string) format
|
||||||
|
:returns: workbook object
|
||||||
|
"""
|
||||||
|
definition = yaml.safe_load(definition)
|
||||||
|
definition["name"] = self._generate_random_name(definition["name"])
|
||||||
|
definition = yaml.safe_dump(definition)
|
||||||
|
|
||||||
|
return self.clients("mistral").workbooks.create(definition)
|
||||||
|
|
||||||
|
@base.atomic_action_timer("mistral.delete_workbook")
|
||||||
|
def _delete_workbook(self, wb_name):
|
||||||
|
"""Delete the given workbook.
|
||||||
|
|
||||||
|
:param wb_name: the name of workbook that would be deleted.
|
||||||
|
"""
|
||||||
|
self.clients("mistral").workbooks.delete(wb_name)
|
59
rally/benchmark/scenarios/mistral/workbooks.py
Normal file
59
rally/benchmark/scenarios/mistral/workbooks.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
# Copyright 2015: Mirantis Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
from rally.benchmark.scenarios import base
|
||||||
|
from rally.benchmark.scenarios.mistral import utils
|
||||||
|
from rally.benchmark import types as types
|
||||||
|
from rally.benchmark import validation
|
||||||
|
from rally import consts
|
||||||
|
|
||||||
|
|
||||||
|
class MistralWorkbooks(utils.MistralScenario):
|
||||||
|
"""Benchmark scenarios for Mistral workbook."""
|
||||||
|
|
||||||
|
@validation.required_clients("mistral")
|
||||||
|
@validation.required_openstack(users=True)
|
||||||
|
@validation.required_services(consts.Service.MISTRAL)
|
||||||
|
@base.scenario()
|
||||||
|
def list_workbooks(self):
|
||||||
|
"""Scenario test mistral workbook-list command.
|
||||||
|
|
||||||
|
This simple scenario tests the Mistral workbook-list
|
||||||
|
command by listing all the workbooks.
|
||||||
|
"""
|
||||||
|
self._list_workbooks()
|
||||||
|
|
||||||
|
@types.set(definition=types.FileType)
|
||||||
|
@validation.file_exists("definition")
|
||||||
|
@validation.required_parameters("definition")
|
||||||
|
@validation.required_clients("mistral")
|
||||||
|
@validation.required_openstack(users=True)
|
||||||
|
@validation.required_services(consts.Service.MISTRAL)
|
||||||
|
@base.scenario(context={"cleanup": ["mistral"]})
|
||||||
|
def create_workbook(self, definition, do_delete=False):
|
||||||
|
"""Scenario tests workbook creation and deletion.
|
||||||
|
|
||||||
|
This scenario is a very useful tool to measure the
|
||||||
|
"mistral workbook-create" and "mistral workbook-delete"
|
||||||
|
commands performance.
|
||||||
|
:param definition: string (yaml string) representation of given
|
||||||
|
file content (Mistral workbook definition)
|
||||||
|
:param do_delete: if False than it allows to check performance
|
||||||
|
in "create only" mode.
|
||||||
|
"""
|
||||||
|
wb = self._create_workbook(definition)
|
||||||
|
|
||||||
|
if do_delete:
|
||||||
|
self._delete_workbook(wb.name)
|
@ -236,3 +236,19 @@ class NeutronNetworkResourceType(ResourceType):
|
|||||||
raise exceptions.InvalidScenarioArgument(
|
raise exceptions.InvalidScenarioArgument(
|
||||||
"Neutron network with name '{name}' not found".format(
|
"Neutron network with name '{name}' not found".format(
|
||||||
name=resource_config.get("name")))
|
name=resource_config.get("name")))
|
||||||
|
|
||||||
|
|
||||||
|
class FileType(ResourceType):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def transform(cls, clients, resource_config):
|
||||||
|
"""Returns content of the file by its path.
|
||||||
|
|
||||||
|
:param clients: openstack admin client handles
|
||||||
|
:param resource_config: path to file
|
||||||
|
|
||||||
|
:returns: content of the file
|
||||||
|
"""
|
||||||
|
|
||||||
|
with open(resource_config, "r") as f:
|
||||||
|
return f.read()
|
||||||
|
@ -376,6 +376,23 @@ def required_services(config, clients, deployment, *required_services):
|
|||||||
False, _("Service is not available: %s") % service)
|
False, _("Service is not available: %s") % service)
|
||||||
|
|
||||||
|
|
||||||
|
@validator
|
||||||
|
def required_clients(config, clients, task, *components):
|
||||||
|
"""Validator checks if specified OpenStack clients are available.
|
||||||
|
|
||||||
|
:param *components: list of client components names
|
||||||
|
"""
|
||||||
|
for client_component in components:
|
||||||
|
try:
|
||||||
|
getattr(clients, client_component)()
|
||||||
|
except ImportError:
|
||||||
|
return ValidationResult(
|
||||||
|
False,
|
||||||
|
_("Client for %s is not installed. To install it run "
|
||||||
|
"`pip install -r"
|
||||||
|
" optional-requirements.txt`") % client_component)
|
||||||
|
|
||||||
|
|
||||||
@validator
|
@validator
|
||||||
def required_contexts(config, clients, deployment, *context_names):
|
def required_contexts(config, clients, deployment, *context_names):
|
||||||
"""Validator hecks if required benchmark contexts are specified.
|
"""Validator hecks if required benchmark contexts are specified.
|
||||||
|
@ -108,6 +108,7 @@ class _Service(utils.ImmutableMixin, utils.EnumMixin):
|
|||||||
TROVE = "trove"
|
TROVE = "trove"
|
||||||
SAHARA = "sahara"
|
SAHARA = "sahara"
|
||||||
SWIFT = "swift"
|
SWIFT = "swift"
|
||||||
|
MISTRAL = "mistral"
|
||||||
|
|
||||||
|
|
||||||
class _ServiceType(utils.ImmutableMixin, utils.EnumMixin):
|
class _ServiceType(utils.ImmutableMixin, utils.EnumMixin):
|
||||||
@ -130,6 +131,7 @@ class _ServiceType(utils.ImmutableMixin, utils.EnumMixin):
|
|||||||
DATABASE = "database"
|
DATABASE = "database"
|
||||||
DATA_PROCESSING = "data_processing"
|
DATA_PROCESSING = "data_processing"
|
||||||
OBJECT_STORE = "object-store"
|
OBJECT_STORE = "object-store"
|
||||||
|
WORKFLOW_EXECUTION = "workflowv2"
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.__names = {
|
self.__names = {
|
||||||
@ -149,7 +151,8 @@ class _ServiceType(utils.ImmutableMixin, utils.EnumMixin):
|
|||||||
self.S3: _Service.S3,
|
self.S3: _Service.S3,
|
||||||
self.DATABASE: _Service.TROVE,
|
self.DATABASE: _Service.TROVE,
|
||||||
self.DATA_PROCESSING: _Service.SAHARA,
|
self.DATA_PROCESSING: _Service.SAHARA,
|
||||||
self.OBJECT_STORE: _Service.SWIFT
|
self.OBJECT_STORE: _Service.SWIFT,
|
||||||
|
self.WORKFLOW_EXECUTION: _Service.MISTRAL,
|
||||||
}
|
}
|
||||||
|
|
||||||
def __getitem__(self, service_type):
|
def __getitem__(self, service_type):
|
||||||
|
@ -301,6 +301,23 @@ class Clients(object):
|
|||||||
cacert=CONF.https_cacert)
|
cacert=CONF.https_cacert)
|
||||||
return client
|
return client
|
||||||
|
|
||||||
|
@cached
|
||||||
|
def mistral(self):
|
||||||
|
"""Return Mistral client."""
|
||||||
|
from mistralclient.api import client
|
||||||
|
kc = self.keystone()
|
||||||
|
|
||||||
|
mistral_url = kc.service_catalog.url_for(
|
||||||
|
service_type="workflowv2",
|
||||||
|
endpoint_type=self.endpoint.endpoint_type,
|
||||||
|
region_name=self.endpoint.region_name)
|
||||||
|
|
||||||
|
client = client.client(mistral_url=mistral_url,
|
||||||
|
service_type="workflowv2",
|
||||||
|
auth_token=kc.auth_token)
|
||||||
|
|
||||||
|
return client
|
||||||
|
|
||||||
@cached
|
@cached
|
||||||
def services(self):
|
def services(self):
|
||||||
"""Return available services names and types.
|
"""Return available services names and types.
|
||||||
|
21
samples/tasks/scenarios/mistral/create-delete-workbook.json
Normal file
21
samples/tasks/scenarios/mistral/create-delete-workbook.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"MistralWorkbooks.create_workbook": [
|
||||||
|
{
|
||||||
|
"args": {
|
||||||
|
"definition": "rally-jobs/extra/mistral_wb.yaml",
|
||||||
|
"do_delete": true
|
||||||
|
},
|
||||||
|
"runner": {
|
||||||
|
"type": "constant",
|
||||||
|
"times": 50,
|
||||||
|
"concurrency": 10
|
||||||
|
},
|
||||||
|
"context": {
|
||||||
|
"users": {
|
||||||
|
"tenants": 1,
|
||||||
|
"users_per_tenant": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
15
samples/tasks/scenarios/mistral/create-delete-workbook.yaml
Normal file
15
samples/tasks/scenarios/mistral/create-delete-workbook.yaml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
MistralWorkbooks.create_workbook:
|
||||||
|
-
|
||||||
|
args:
|
||||||
|
definition: rally-jobs/extra/mistral_wb.yaml
|
||||||
|
do_delete: true
|
||||||
|
runner:
|
||||||
|
type: "constant"
|
||||||
|
times: 50
|
||||||
|
concurrency: 10
|
||||||
|
context:
|
||||||
|
users:
|
||||||
|
tenants: 1
|
||||||
|
users_per_tenant: 1
|
||||||
|
|
20
samples/tasks/scenarios/mistral/create-workbook.json
Normal file
20
samples/tasks/scenarios/mistral/create-workbook.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"MistralWorkbooks.create_workbook": [
|
||||||
|
{
|
||||||
|
"args": {
|
||||||
|
"definition": "rally-jobs/extra/mistral_wb.yaml"
|
||||||
|
},
|
||||||
|
"runner": {
|
||||||
|
"type": "constant",
|
||||||
|
"times": 50,
|
||||||
|
"concurrency": 10
|
||||||
|
},
|
||||||
|
"context": {
|
||||||
|
"users": {
|
||||||
|
"tenants": 1,
|
||||||
|
"users_per_tenant": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
14
samples/tasks/scenarios/mistral/create-workbook.yaml
Normal file
14
samples/tasks/scenarios/mistral/create-workbook.yaml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
MistralWorkbooks.create_workbook:
|
||||||
|
-
|
||||||
|
args:
|
||||||
|
definition: rally-jobs/extra/mistral_wb.yaml
|
||||||
|
runner:
|
||||||
|
type: "constant"
|
||||||
|
times: 50
|
||||||
|
concurrency: 10
|
||||||
|
context:
|
||||||
|
users:
|
||||||
|
tenants: 1
|
||||||
|
users_per_tenant: 1
|
||||||
|
|
17
samples/tasks/scenarios/mistral/list-workbooks.json
Normal file
17
samples/tasks/scenarios/mistral/list-workbooks.json
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"MistralWorkbooks.list_workbooks": [
|
||||||
|
{
|
||||||
|
"runner": {
|
||||||
|
"type": "constant",
|
||||||
|
"times": 50,
|
||||||
|
"concurrency": 10
|
||||||
|
},
|
||||||
|
"context": {
|
||||||
|
"users": {
|
||||||
|
"tenants": 1,
|
||||||
|
"users_per_tenant": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
11
samples/tasks/scenarios/mistral/list-workbooks.yaml
Normal file
11
samples/tasks/scenarios/mistral/list-workbooks.yaml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
MistralWorkbooks.list_workbooks:
|
||||||
|
-
|
||||||
|
runner:
|
||||||
|
type: "constant"
|
||||||
|
times: 50
|
||||||
|
concurrency: 10
|
||||||
|
context:
|
||||||
|
users:
|
||||||
|
tenants: 1
|
||||||
|
users_per_tenant: 1
|
66
tests/unit/benchmark/scenarios/mistral/test_utils.py
Normal file
66
tests/unit/benchmark/scenarios/mistral/test_utils.py
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
# Copyright 2015: Mirantis Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import mock
|
||||||
|
|
||||||
|
from rally.benchmark.scenarios.mistral import utils
|
||||||
|
from tests.unit import test
|
||||||
|
|
||||||
|
BM_UTILS = "rally.benchmark.utils"
|
||||||
|
MISTRAL_UTILS = "rally.benchmark.scenarios.mistral.utils"
|
||||||
|
|
||||||
|
|
||||||
|
class MistralScenarioTestCase(test.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(MistralScenarioTestCase, self).setUp()
|
||||||
|
|
||||||
|
def _test_atomic_action_timer(self, atomic_actions, name):
|
||||||
|
action_duration = atomic_actions.get(name)
|
||||||
|
self.assertIsNotNone(action_duration)
|
||||||
|
self.assertIsInstance(action_duration, float)
|
||||||
|
|
||||||
|
@mock.patch(MISTRAL_UTILS + ".MistralScenario.clients")
|
||||||
|
def test_list_workbooks(self, mock_clients):
|
||||||
|
wbs_list = []
|
||||||
|
mock_clients("mistral").workbooks.list.return_value = wbs_list
|
||||||
|
scenario = utils.MistralScenario()
|
||||||
|
return_wbs_list = scenario._list_workbooks()
|
||||||
|
self.assertEqual(wbs_list, return_wbs_list)
|
||||||
|
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||||
|
"mistral.list_workbooks")
|
||||||
|
|
||||||
|
@mock.patch(MISTRAL_UTILS + ".MistralScenario.clients")
|
||||||
|
def test_create_workbook(self, mock_clients):
|
||||||
|
definition = "version: \"2.0\"\nname: wb"
|
||||||
|
mock_clients("mistral").workbooks.create.return_value = "wb"
|
||||||
|
scenario = utils.MistralScenario()
|
||||||
|
wb = scenario._create_workbook(definition)
|
||||||
|
self.assertEqual("wb", wb)
|
||||||
|
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||||
|
"mistral.create_workbook")
|
||||||
|
|
||||||
|
@mock.patch(MISTRAL_UTILS + ".MistralScenario.clients")
|
||||||
|
def test_delete_workbook(self, mock_clients):
|
||||||
|
wb = mock.Mock()
|
||||||
|
wb.name = "wb"
|
||||||
|
mock_clients("mistral").workbooks.delete.return_value = "ok"
|
||||||
|
scenario = utils.MistralScenario()
|
||||||
|
scenario._delete_workbook(wb.name)
|
||||||
|
mock_clients("mistral").workbooks.delete.assert_called_once_with(
|
||||||
|
wb.name
|
||||||
|
)
|
||||||
|
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||||
|
"mistral.delete_workbook")
|
54
tests/unit/benchmark/scenarios/mistral/test_workbooks.py
Normal file
54
tests/unit/benchmark/scenarios/mistral/test_workbooks.py
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# Copyright 2015: Mirantis Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import mock
|
||||||
|
|
||||||
|
from rally.benchmark.scenarios.mistral import workbooks
|
||||||
|
from tests.unit import test
|
||||||
|
|
||||||
|
MISTRAL_WBS = "rally.benchmark.scenarios.mistral.workbooks.MistralWorkbooks"
|
||||||
|
|
||||||
|
|
||||||
|
class MistralWorkbooksTestCase(test.TestCase):
|
||||||
|
|
||||||
|
@mock.patch(MISTRAL_WBS + "._list_workbooks")
|
||||||
|
def test_list_workbooks(self, mock_list):
|
||||||
|
mistral_scenario = workbooks.MistralWorkbooks()
|
||||||
|
mistral_scenario.list_workbooks()
|
||||||
|
mock_list.assert_called_once_with()
|
||||||
|
|
||||||
|
@mock.patch(MISTRAL_WBS + "._create_workbook")
|
||||||
|
def test_create_workbook(self, mock_create):
|
||||||
|
mistral_scenario = workbooks.MistralWorkbooks()
|
||||||
|
definition = "---\nversion: \"2.0\"\nname: wb"
|
||||||
|
fake_wb = mock.MagicMock()
|
||||||
|
fake_wb.name = "wb"
|
||||||
|
mock_create.return_value = fake_wb
|
||||||
|
mistral_scenario.create_delete_workbook(definition)
|
||||||
|
|
||||||
|
self.assertEqual(1, mock_create.called)
|
||||||
|
|
||||||
|
@mock.patch(MISTRAL_WBS + "._delete_workbook")
|
||||||
|
@mock.patch(MISTRAL_WBS + "._create_workbook")
|
||||||
|
def test_create_delete_workbook(self, mock_create, mock_delete):
|
||||||
|
mistral_scenario = workbooks.MistralWorkbooks()
|
||||||
|
definition = "---\nversion: \"2.0\"\nname: wb"
|
||||||
|
fake_wb = mock.MagicMock()
|
||||||
|
fake_wb.name = "wb"
|
||||||
|
mock_create.return_value = fake_wb
|
||||||
|
mistral_scenario.create_delete_workbook(definition, do_delete=True)
|
||||||
|
|
||||||
|
self.assertEqual(1, mock_create.called)
|
||||||
|
mock_delete.assert_called_once_with(fake_wb.name)
|
@ -251,3 +251,26 @@ class PreprocessTestCase(test.TestCase):
|
|||||||
mock_osclients.Clients.assert_called_once_with(
|
mock_osclients.Clients.assert_called_once_with(
|
||||||
context["admin"]["endpoint"])
|
context["admin"]["endpoint"])
|
||||||
self.assertEqual({"a": 20, "b": 20}, result)
|
self.assertEqual({"a": 20, "b": 20}, result)
|
||||||
|
|
||||||
|
|
||||||
|
class FileTypeTestCase(test.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(FileTypeTestCase, self).setUp()
|
||||||
|
self.clients = fakes.FakeClients()
|
||||||
|
|
||||||
|
@mock.patch("rally.benchmark.types.open",
|
||||||
|
side_effect=mock.mock_open(read_data="file_context"),
|
||||||
|
create=True)
|
||||||
|
def test_transform_by_path(self, mock_open):
|
||||||
|
resource_config = "file.yaml"
|
||||||
|
file_context = types.FileType.transform(
|
||||||
|
clients=self.clients,
|
||||||
|
resource_config=resource_config)
|
||||||
|
self.assertEqual(file_context, "file_context")
|
||||||
|
|
||||||
|
def test_transform_by_path_no_match(self):
|
||||||
|
resource_config = "nonexistant.yaml"
|
||||||
|
self.assertRaises(IOError,
|
||||||
|
types.FileType.transform,
|
||||||
|
self.clients, resource_config)
|
||||||
|
@ -566,3 +566,17 @@ 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)
|
||||||
|
|
||||||
|
def test_required_clients(self):
|
||||||
|
validator = self._unwrap_validator(validation.required_clients,
|
||||||
|
"keystone", "nova")
|
||||||
|
|
||||||
|
clients = mock.MagicMock()
|
||||||
|
clients.keystone.return_value = "keystone"
|
||||||
|
clients.nova.return_value = "nova"
|
||||||
|
result = validator({}, clients, None)
|
||||||
|
self.assertTrue(result.is_valid, result.msg)
|
||||||
|
|
||||||
|
clients.nova.side_effect = ImportError
|
||||||
|
result = validator({}, clients, None)
|
||||||
|
self.assertFalse(result.is_valid, result.msg)
|
||||||
|
@ -279,6 +279,12 @@ class FakeAvailabilityZone(FakeResource):
|
|||||||
self.hosts = mock.MagicMock()
|
self.hosts = mock.MagicMock()
|
||||||
|
|
||||||
|
|
||||||
|
class FakeWorkbook(FakeResource):
|
||||||
|
def __init__(self, manager=None):
|
||||||
|
super(FakeWorkbook, self).__init__(manager)
|
||||||
|
self.workbook = mock.MagicMock()
|
||||||
|
|
||||||
|
|
||||||
class FakeManager(object):
|
class FakeManager(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -806,6 +812,15 @@ class FakeAvailabilityZonesManager(FakeManager):
|
|||||||
return [self.zones]
|
return [self.zones]
|
||||||
|
|
||||||
|
|
||||||
|
class FakeWorkbookManager(FakeManager):
|
||||||
|
def __init__(self):
|
||||||
|
super(FakeWorkbookManager, self).__init__()
|
||||||
|
self.workbook = FakeWorkbook()
|
||||||
|
|
||||||
|
def list(self):
|
||||||
|
return [self.workbook]
|
||||||
|
|
||||||
|
|
||||||
class FakeServiceCatalog(object):
|
class FakeServiceCatalog(object):
|
||||||
def get_endpoints(self):
|
def get_endpoints(self):
|
||||||
return {"image": [{"publicURL": "http://fake.to"}],
|
return {"image": [{"publicURL": "http://fake.to"}],
|
||||||
@ -1188,6 +1203,12 @@ class FakeTroveClient(object):
|
|||||||
self.instances = FakeDbInstanceManager()
|
self.instances = FakeDbInstanceManager()
|
||||||
|
|
||||||
|
|
||||||
|
class FakeMistralClient(object):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.workbook = FakeWorkbookManager()
|
||||||
|
|
||||||
|
|
||||||
class FakeClients(object):
|
class FakeClients(object):
|
||||||
|
|
||||||
def __init__(self, endpoint_=None):
|
def __init__(self, endpoint_=None):
|
||||||
@ -1202,6 +1223,7 @@ class FakeClients(object):
|
|||||||
self._ceilometer = None
|
self._ceilometer = None
|
||||||
self._zaqar = None
|
self._zaqar = None
|
||||||
self._trove = None
|
self._trove = None
|
||||||
|
self._mistral = None
|
||||||
self._endpoint = endpoint_ or objects.Endpoint(
|
self._endpoint = endpoint_ or objects.Endpoint(
|
||||||
"http://fake.example.org:5000/v2.0/",
|
"http://fake.example.org:5000/v2.0/",
|
||||||
"fake_username",
|
"fake_username",
|
||||||
@ -1266,6 +1288,11 @@ class FakeClients(object):
|
|||||||
self._trove = FakeTroveClient()
|
self._trove = FakeTroveClient()
|
||||||
return self._trove
|
return self._trove
|
||||||
|
|
||||||
|
def mistral(self):
|
||||||
|
if not self._mistral:
|
||||||
|
self._mistral = FakeMistralClient()
|
||||||
|
return self._mistral
|
||||||
|
|
||||||
|
|
||||||
class FakeRunner(object):
|
class FakeRunner(object):
|
||||||
|
|
||||||
|
@ -262,6 +262,30 @@ class OSClientsTestCase(test.TestCase):
|
|||||||
mock_trove.Client.assert_called_once_with("1.0", **kw)
|
mock_trove.Client.assert_called_once_with("1.0", **kw)
|
||||||
self.assertEqual(self.clients.cache["trove"], fake_trove)
|
self.assertEqual(self.clients.cache["trove"], fake_trove)
|
||||||
|
|
||||||
|
def test_mistral(self):
|
||||||
|
fake_mistral = fakes.FakeMistralClient()
|
||||||
|
mock_mistral = mock.Mock()
|
||||||
|
mock_mistral.client.client.return_value = fake_mistral
|
||||||
|
|
||||||
|
self.assertNotIn("mistral", self.clients.cache)
|
||||||
|
with mock.patch.dict(
|
||||||
|
"sys.modules", {"mistralclient": mock_mistral,
|
||||||
|
"mistralclient.api": mock_mistral}):
|
||||||
|
client = self.clients.mistral()
|
||||||
|
self.assertEqual(fake_mistral, client)
|
||||||
|
self.service_catalog.url_for.assert_called_once_with(
|
||||||
|
service_type="workflowv2",
|
||||||
|
endpoint_type=consts.EndpointType.PUBLIC,
|
||||||
|
region_name=self.endpoint.region_name
|
||||||
|
)
|
||||||
|
fake_mistral_url = self.service_catalog.url_for.return_value
|
||||||
|
mock_mistral.client.client.assert_called_once_with(
|
||||||
|
mistral_url=fake_mistral_url,
|
||||||
|
service_type="workflowv2",
|
||||||
|
auth_token=self.fake_keystone.auth_token
|
||||||
|
)
|
||||||
|
self.assertEqual(fake_mistral, self.clients.cache["mistral"])
|
||||||
|
|
||||||
@mock.patch("rally.osclients.Clients.keystone")
|
@mock.patch("rally.osclients.Clients.keystone")
|
||||||
def test_services(self, mock_keystone):
|
def test_services(self, mock_keystone):
|
||||||
available_services = {consts.ServiceType.IDENTITY: {},
|
available_services = {consts.ServiceType.IDENTITY: {},
|
||||||
|
Loading…
Reference in New Issue
Block a user