Add Mistral action pack

This patch adds support for calling Mistral v2 APIs as actions in
Mistral.

There will be at least two more patch sets for this blueprint to
fully support these changes.

Change-Id: I0226482ddee1573232663e124837deb8a1985df8
Implements: blueprint mistral-mistral-actions
This commit is contained in:
Daryl Mowrer 2016-02-18 18:21:56 -06:00
parent 7795df0d0a
commit 812f1803a6
7 changed files with 120 additions and 3 deletions

View File

@ -19,7 +19,8 @@ from mistral.actions.openstack.action_generator import base
SUPPORTED_MODULES = [
'Nova', 'Glance', 'Keystone', 'Heat', 'Neutron', 'Cinder', 'Ceilometer',
'Trove', 'Ironic', 'Baremetal Introspection', 'Swift', 'Zaqar', 'Barbican'
'Trove', 'Ironic', 'Baremetal Introspection', 'Swift', 'Zaqar', 'Barbican',
'Mistral'
]

View File

@ -24,6 +24,7 @@ from ironicclient.v1 import client as ironicclient
from keystoneclient.auth import identity
from keystoneclient import httpclient
from keystoneclient.v3 import client as keystoneclient
from mistralclient.api.v2 import client as mistralclient
from neutronclient.v2_0 import client as neutronclient
from novaclient import client as novaclient
from oslo_config import cfg
@ -243,6 +244,40 @@ class CinderAction(base.OpenStackAction):
return cls._client_class()
class MistralAction(base.OpenStackAction):
_client_class = mistralclient.Client
def _get_client(self):
ctx = context.ctx()
LOG.debug("Mistral action security context: %s" % ctx)
# Check for trust scope token. This may occur if the action is
# called from a workflow triggered by a Mistral cron trigger.
if ctx.is_trust_scoped:
auth_url = None
mistral_endpoint = keystone_utils.get_endpoint_for_project(
'mistral'
)
mistral_url = mistral_endpoint.url
else:
keystone_endpoint = keystone_utils.get_keystone_endpoint_v2()
auth_url = keystone_endpoint.url
mistral_url = None
return self._client_class(
mistral_url=mistral_url,
auth_token=ctx.auth_token,
project_id=ctx.project_id,
user_id=ctx.user_id,
auth_url=auth_url
)
@classmethod
def _get_fake_client(cls):
return cls._client_class()
class TroveAction(base.OpenStackAction):
_client_class = troveclient.Client

View File

@ -965,5 +965,63 @@
"orders_delete": "orders.delete",
"orders_list": "orders.list",
"secrets_store": "secrets_store"
},
"mistral": {
"_comment": "It uses mistralclient.v2.",
"action_executions_create": "action_executions.create",
"action_executions_delete": "action_executions.delete",
"action_executions_find": "action_executions.find",
"action_executions_get": "action_executions.get",
"action_executions_list": "action_executions.list",
"action_executions_update": "action_executions.update",
"actions_create": "actions.create",
"actions_delete": "actions.delete",
"actions_find": "actions.find",
"actions_get": "actions.get",
"actions_list": "actions.list",
"actions_update": "actions.update",
"cron_triggers_create": "cron_triggers.create",
"cron_triggers_delete": "cron_triggers.delete",
"cron_triggers_find": "cron_triggers.find",
"cron_triggers_get": "cron_triggers.get",
"cron_triggers_list": "cron_triggers.list",
"environments_create": "environments.create",
"environments_delete": "environments.delete",
"environments_find": "environments.find",
"environments_get": "environments.get",
"environments_list": "environments.list",
"environments_update": "environments.update",
"executions_create": "executions.create",
"executions_delete": "executions.delete",
"executions_find": "executions.find",
"executions_get": "executions.get",
"executions_list": "executions.list",
"executions_update": "executions.update",
"members_create": "members.create",
"members_delete": "members.delete",
"members_find": "members.find",
"members_get": "members.get",
"members_list": "members.list",
"members_update": "members.update",
"services_find": "services.find",
"services_list": "services.list",
"tasks_find": "tasks.find",
"tasks_get": "tasks.get",
"tasks_list": "tasks.list",
"tasks_rerun": "tasks.rerun",
"workbooks_create": "workbooks.create",
"workbooks_delete": "workbooks.delete",
"workbooks_find": "workbooks.find",
"workbooks_get": "workbooks.get",
"workbooks_list": "workbooks.list",
"workbooks_update": "workbooks.update",
"workbooks_validate": "workbooks.validate",
"workflows_create": "workflows.create",
"workflows_delete": "workflows.delete",
"workflows_find": "workflows.find",
"workflows_get": "workflows.get",
"workflows_list": "workflows.list",
"workflows_update": "workflows.update",
"workflows_validate": "workflows.validate"
}
}

View File

@ -31,6 +31,7 @@ MODULE_MAPPING = {
'swift': ['swift.head_account', actions.SwiftAction],
'zaqar': ['zaqar.queue_messages', actions.ZaqarAction],
'barbican': ['barbican.orders_list', actions.BarbicanAction],
'mistral': ['mistral.workflows_get', actions.MistralAction],
}
EXTRA_MODULES = ['neutron', 'swift', 'zaqar']

View File

@ -139,6 +139,18 @@ class OpenStackActionTest(base.BaseTestCase):
self.assertTrue(mocked().get_status.called)
mocked().get_status.assert_called_once_with(uuid="1234")
@mock.patch.object(actions.MistralAction, '_get_client')
def test_mistral_action(self, mocked):
method_name = "workflows.get"
action_class = actions.MistralAction
action_class.client_method_name = method_name
params = {'name': '1234-abcd'}
action = action_class(**params)
action.run()
self.assertTrue(mocked().workflows.get.called)
mocked().workflows.get.assert_called_once_with(name="1234-abcd")
@mock.patch.object(actions.SwiftAction, '_get_client')
def test_swift_action(self, mocked):
method_name = "get_object"

View File

@ -28,6 +28,7 @@ python-cinderclient>=1.3.1 # Apache-2.0
python-glanceclient>=1.2.0 # Apache-2.0
python-heatclient>=0.6.0 # Apache-2.0
python-keystoneclient!=1.8.0,!=2.1.0,>=1.6.0 # Apache-2.0
python-mistralclient>=1.0.0 # Apache-2.0
python-neutronclient>=2.6.0 # Apache-2.0
python-novaclient!=2.33.0,>=2.29.0 # Apache-2.0
python-swiftclient>=2.2.0 # Apache-2.0

View File

@ -21,7 +21,7 @@ import os
from barbicanclient import base as barbican_base
from barbicanclient import client as barbicanclient
from ceilometerclient.v2 import client as ceilometerclient
from cinderclient import utils as cinder_base
from cinderclient.openstack.common.apiclient import base as cinder_base
from cinderclient.v2 import client as cinderclient
from glanceclient.v2 import client as glanceclient
from heatclient.openstack.common.apiclient import base as heat_base
@ -30,8 +30,10 @@ from ironicclient.common import base as ironic_base
from ironicclient.v1 import client as ironicclient
from keystoneclient import base as keystone_base
from keystoneclient.v3 import client as keystoneclient
from mistralclient.api import base as mistral_base
from mistralclient.api.v2 import client as mistralclient
from novaclient import base as nova_base
from novaclient import client as novaclient
from novaclient.openstack.common.apiclient import base as nova_base
from troveclient import base as trove_base
from troveclient.v1 import client as troveclient
@ -71,6 +73,7 @@ BASE_HEAT_MANAGER = heat_base.HookableMixin
BASE_NOVA_MANAGER = nova_base.HookableMixin
BASE_KEYSTONE_MANAGER = keystone_base.Manager
BASE_CINDER_MANAGER = cinder_base.HookableMixin
BASE_MISTRAL_MANAGER = mistral_base.ResourceManager
BASE_TROVE_MANAGER = trove_base.Manager
BASE_IRONIC_MANAGER = ironic_base.Manager
BASE_BARBICAN_MANAGER = barbican_base.BaseEntityManager
@ -149,6 +152,10 @@ def get_cinder_client(**kwargs):
return cinderclient.Client()
def get_mistral_client(**kwargs):
return mistralclient.Client()
def get_trove_client(**kwargs):
return troveclient.Client('username', 'password')
@ -174,6 +181,7 @@ CLIENTS = {
'trove': get_trove_client,
'ironic': get_ironic_client,
'barbican': get_barbican_client,
'mistral': get_mistral_client,
# 'neutron': get_nova_client
# 'baremetal_introspection': ...
# 'swift': ...
@ -189,6 +197,7 @@ BASE_MANAGERS = {
'trove': BASE_TROVE_MANAGER,
'ironic': BASE_IRONIC_MANAGER,
'barbican': BASE_BARBICAN_MANAGER,
'mistral': BASE_MISTRAL_MANAGER,
# 'neutron': BASE_NOVA_MANAGER
# 'baremetal_introspection': ...
# 'swift': ...