Fix serialization of OpenStack actions
* In the recent version 2.3.0 of mistral-lib there has been added the new serialization mechanism for actions since the communication schema between Mistral engine and Mistral remote executor will soon require it (once merged). All classes for OpenStack actions are eventually dynamically generated based on the static classes like NovaAction, HeatAction etc., so to make the serialization work correctly we have to take this into account. The newly added class OpenStackActionSerializer takes care of that. Change-Id: I8d7e2db0b17fb8f055f77363667ca4ab2c501b34
This commit is contained in:
parent
b5e08f2276
commit
f4272e3e3a
@ -5,7 +5,7 @@ doc8==0.6.0
|
||||
fixtures==3.0.0
|
||||
hacking==1.1.0
|
||||
keystoneauth1===3.18.0
|
||||
mistral-lib==1.4.0
|
||||
mistral-lib==2.3.0
|
||||
oslo.log==3.36.0
|
||||
oslotest==3.2.0
|
||||
pbr==2.0.0
|
||||
|
@ -33,14 +33,17 @@ def get_mapping():
|
||||
for key, value in map_part.items():
|
||||
if isinstance(value, dict):
|
||||
delete_comment(value)
|
||||
|
||||
if '_comment' in map_part:
|
||||
del map_part['_comment']
|
||||
|
||||
package = version.version_info.package
|
||||
|
||||
if os.path.isabs(CONF.openstack_actions_mapping_path):
|
||||
mapping_file_path = CONF.openstack_actions_mapping_path
|
||||
else:
|
||||
path = CONF.openstack_actions_mapping_path
|
||||
|
||||
mapping_file_path = pkg.resource_filename(package, path)
|
||||
|
||||
LOG.info(
|
||||
@ -99,11 +102,13 @@ class OpenStackActionGenerator(action_generator.ActionGenerator):
|
||||
return ", ".join(added)
|
||||
|
||||
inputs = [i.strip() for i in origin_inputs.split(',')]
|
||||
|
||||
kwarg_index = None
|
||||
|
||||
for index, input in enumerate(inputs):
|
||||
if "=" in input:
|
||||
kwarg_index = index
|
||||
|
||||
if "**" in input:
|
||||
kwarg_index = index - 1
|
||||
|
||||
@ -144,14 +149,17 @@ class OpenStackActionGenerator(action_generator.ActionGenerator):
|
||||
except Exception:
|
||||
LOG.exception(
|
||||
"Failed to create action: %s.%s",
|
||||
cls.action_namespace, action_name
|
||||
cls.action_namespace,
|
||||
action_name
|
||||
)
|
||||
|
||||
continue
|
||||
|
||||
arg_list = i_u.get_arg_list_as_str(client_method)
|
||||
|
||||
# Support specifying region for OpenStack actions.
|
||||
modules = CONF.openstack_actions.modules_support_region
|
||||
|
||||
if cls.action_namespace in modules:
|
||||
arg_list = cls.prepare_action_inputs(
|
||||
arg_list,
|
||||
|
@ -187,7 +187,6 @@ class HeatAction(base.OpenStackAction):
|
||||
return heatclient.Client
|
||||
|
||||
def _create_client(self, context):
|
||||
|
||||
LOG.debug("Heat action security context: %s", context)
|
||||
|
||||
heat_endpoint = self.get_service_endpoint()
|
||||
|
@ -22,6 +22,9 @@ from mistral_extra.actions.openstack.utils import exceptions as exc
|
||||
from mistral_extra.actions.openstack.utils import keystone as \
|
||||
keystone_utils
|
||||
from mistral_lib import actions
|
||||
from mistral_lib.actions import base as ml_actions_base
|
||||
from mistral_lib import serialization
|
||||
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
@ -39,6 +42,8 @@ class OpenStackAction(actions.Action):
|
||||
_client_class = None
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super(OpenStackAction, self).__init__()
|
||||
|
||||
self._kwargs_for_run = kwargs
|
||||
self.action_region = self._kwargs_for_run.pop('action_region', None)
|
||||
|
||||
@ -135,3 +140,24 @@ class OpenStackAction(actions.Action):
|
||||
return dict(
|
||||
zip(self._kwargs_for_run, ['test'] * len(self._kwargs_for_run))
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_serialization_key(cls):
|
||||
return "%s.%s" % (OpenStackAction.__module__, OpenStackAction.__name__)
|
||||
|
||||
|
||||
class OpenStackActionSerializer(ml_actions_base.ActionSerializer):
|
||||
def serialize_to_dict(self, entity):
|
||||
res = super(OpenStackActionSerializer, self).serialize_to_dict(entity)
|
||||
|
||||
# Since all OpenStack actions are dynamically generated with the
|
||||
# function type() we need to take the base class of the action
|
||||
# class (i.e. NovaAction) and write it to the result dict.
|
||||
base_cls = type(entity).__bases__[0]
|
||||
|
||||
res['cls'] = '%s.%s' % (base_cls.__module__, base_cls.__name__)
|
||||
|
||||
return res
|
||||
|
||||
|
||||
serialization.register_serializer(OpenStackAction, OpenStackActionSerializer())
|
||||
|
@ -0,0 +1,67 @@
|
||||
# Copyright 2020 Nokia Software.
|
||||
#
|
||||
# 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 unittest import mock
|
||||
|
||||
from mistral_extra.actions.openstack import actions
|
||||
from mistral_extra.actions.openstack import base as actions_base
|
||||
|
||||
from oslotest import base
|
||||
|
||||
|
||||
class OpenStackActionSerializationTest(base.BaseTestCase):
|
||||
@mock.patch.object(actions.NovaAction, '_get_client')
|
||||
def test_nova_action_serialization(self, mocked):
|
||||
mock_ctx = mock.Mock()
|
||||
|
||||
method_name = "servers.get"
|
||||
|
||||
# Create a dynamic action class.
|
||||
action_class = type(
|
||||
str(method_name),
|
||||
(actions.NovaAction,),
|
||||
{'client_method_name': method_name}
|
||||
)
|
||||
|
||||
params = {'server': '1234-abcd'}
|
||||
|
||||
# Just in case let's just make sure the action is functioning.
|
||||
action = action_class(**params)
|
||||
|
||||
action.run(mock_ctx)
|
||||
|
||||
self.assertTrue(mocked().servers.get.called)
|
||||
|
||||
mocked().servers.get.assert_called_once_with(server="1234-abcd")
|
||||
|
||||
# Now let's serialize the action.
|
||||
serializer = actions_base.OpenStackActionSerializer()
|
||||
|
||||
serialized_action = serializer.serialize(action)
|
||||
|
||||
self.assertIsNotNone(serialized_action)
|
||||
|
||||
deserialized_action = serializer.deserialize(serialized_action)
|
||||
|
||||
# Make sure that the action class is dynamic and it's still
|
||||
# functioning.
|
||||
self.assertNotEqual(actions.NovaAction, type(deserialized_action))
|
||||
|
||||
deserialized_action.run(mock_ctx)
|
||||
|
||||
self.assertTrue(mocked().servers.get.called)
|
||||
|
||||
mocked().servers.get.assert_called_with(server="1234-abcd")
|
||||
|
||||
self.assertEqual(2, mocked().servers.get.call_count)
|
@ -5,7 +5,7 @@
|
||||
pbr!=2.1.0,>=2.0.0 # Apache-2.0
|
||||
Babel!=2.4.0,>=2.3.4 # BSD
|
||||
oslo.log>=3.36.0 # Apache-2.0
|
||||
mistral-lib>=1.4.0 # Apache-2.0
|
||||
mistral-lib>=2.3.0 # Apache-2.0
|
||||
aodhclient>=0.9.0 # Apache-2.0
|
||||
gnocchiclient>=3.3.1 # Apache-2.0
|
||||
python-barbicanclient>=4.5.2 # Apache-2.0
|
||||
|
Loading…
Reference in New Issue
Block a user