Add cluster_id to action filter in API

Current, an action was created haven't information of a cluster.
When a specific action is created, we do not know what action this action takes
in a cluster and when we execute the query API:

GET http://senlin_host:8777/actions

so many actions are returned even though we can limit using parameters
such as name, target, action, status combined with limit and marker.
But, we can't just get the actions executed in a particular cluster.
So, I want us to be able to do this by enabling the query with a cluster_id parameter.
To accomplish this, I need to modify the schema of
action models and action tables in the database of senlin service.

Change-Id: I49d172414eecf9158192cf0869abb91822ee2226
This commit is contained in:
Bo Tran 2019-07-04 09:33:43 +07:00
parent ac49353899
commit 8a5460c591
26 changed files with 309 additions and 23 deletions

View File

@ -0,0 +1,6 @@
---
features:
- |
Add cluster_id as a parameter in query action APIs.
This allow we can filter result returned from API instead by received
so many result action.

View File

@ -126,3 +126,7 @@ it can be used by both users and developers.
1.13
----
- Added ``tainted`` to responses returned by node APIs.
1.14
----
- Added ``cluster_id`` to filters result returned action APIs.

View File

@ -14,6 +14,7 @@
from webob import exc
from senlin.api.common import util
from senlin.api.common import version_request as vr
from senlin.api.common import wsgi
from senlin.common import consts
from senlin.common.i18n import _
@ -54,10 +55,20 @@ class ActionController(wsgi.Controller):
# (must match what is in policy file and policies in code.)
REQUEST_SCOPE = 'actions'
def _remove_cluster_id(self, req, obj):
if req.version_request > vr.APIVersionRequest("1.13"):
return obj
if 'cluster_id' in obj:
obj.pop('cluster_id')
return obj
@util.policy_enforce
def index(self, req):
whitelist = {
consts.ACTION_NAME: 'mixed',
consts.ACTION_CLUSTER_ID: 'mixed',
consts.ACTION_TARGET: 'mixed',
consts.ACTION_ACTION: 'mixed',
consts.ACTION_STATUS: 'mixed',
@ -79,6 +90,7 @@ class ActionController(wsgi.Controller):
obj = util.parse_request('ActionListRequest', req, params)
actions = self.rpc_client.call(req.context, "action_list", obj)
actions = [self._remove_cluster_id(req, a) for a in actions]
return {'actions': actions}
@util.policy_enforce
@ -90,7 +102,7 @@ class ActionController(wsgi.Controller):
data.action(),
data.params())
return result
return self._remove_cluster_id(req, result)
@util.policy_enforce
def get(self, req, action_id):
@ -98,6 +110,7 @@ class ActionController(wsgi.Controller):
obj = util.parse_request('ActionGetRequest', req, params)
action = self.rpc_client.call(req.context, 'action_get', obj)
action = self._remove_cluster_id(req, action)
return {'action': action}
@wsgi.Controller.api_version('1.12')

View File

@ -23,7 +23,7 @@ class VersionController(object):
# This includes any semantic changes which may not affect the input or
# output formats or even originate in the API code layer.
_MIN_API_VERSION = "1.0"
_MAX_API_VERSION = "1.13"
_MAX_API_VERSION = "1.14"
DEFAULT_API_VERSION = _MIN_API_VERSION

View File

@ -211,13 +211,13 @@ EVENT_SORT_KEYS = [
]
ACTION_ATTRS = (
ACTION_NAME, ACTION_TARGET, ACTION_ACTION, ACTION_CAUSE,
ACTION_NAME, ACTION_CLUSTER_ID, ACTION_TARGET, ACTION_ACTION, ACTION_CAUSE,
ACTION_INTERVAL, ACTION_START_TIME, ACTION_END_TIME,
ACTION_TIMEOUT, ACTION_STATUS, ACTION_STATUS_REASON,
ACTION_INPUTS, ACTION_OUTPUTS, ACTION_DEPENDS_ON, ACTION_DEPENDED_BY,
ACTION_CREATED_AT, ACTION_UPDATED_AT,
) = (
'name', 'target', 'action', 'cause',
'name', 'cluster_id', 'target', 'action', 'cause',
'interval', 'start_time', 'end_time',
'timeout', 'status', 'status_reason',
'inputs', 'outputs', 'depends_on', 'depended_by',

View File

@ -0,0 +1,22 @@
# 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 sqlalchemy import Column, MetaData, String, Table
def upgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
action = Table('action', meta, autoload=True)
action_cluster_id = Column('cluster_id', String(36), default="")
action_cluster_id.create(action)

View File

@ -228,6 +228,7 @@ class Action(BASE, TimestampMixin, models.ModelBase):
id = Column('id', String(36), primary_key=True, default=lambda: UUID4())
name = Column(String(63))
cluster_id = Column(String(36))
context = Column(types.Dict)
target = Column(String(36))
action = Column(Text)

View File

@ -92,6 +92,7 @@ class Action(object):
self.id = kwargs.get('id', None)
self.name = kwargs.get('name', '')
self.cluster_id = kwargs.get('cluster_id', '')
self.context = ctx
self.user = ctx.user_id
@ -150,6 +151,7 @@ class Action(object):
values = {
'name': self.name,
'cluster_id': self.cluster_id,
'context': self.context.to_dict(),
'target': self.target,
'action': self.action,
@ -194,6 +196,7 @@ class Action(object):
kwargs = {
'id': obj.id,
'name': obj.name,
'cluster_id': obj.cluster_id,
'cause': obj.cause,
'owner': obj.owner,
'interval': obj.interval,
@ -625,6 +628,7 @@ class Action(object):
action_dict = {
'id': self.id,
'name': self.name,
'cluster_id': self.cluster_id,
'action': self.action,
'target': self.target,
'cause': self.cause,

View File

@ -168,6 +168,7 @@ class ClusterAction(base.Action):
kwargs = {
'name': 'node_create_%s' % node.id[:8],
'cluster_id': self.entity.id,
'cause': consts.CAUSE_DERIVED,
}
action_id = base.Action.create(self.context, node.id,
@ -243,6 +244,7 @@ class ClusterAction(base.Action):
for node in nodes:
kwargs = {
'name': 'node_update_%s' % node[:8],
'cluster_id': self.entity.id,
'cause': consts.CAUSE_DERIVED,
'inputs': {
'new_profile_id': profile_id,
@ -349,6 +351,7 @@ class ClusterAction(base.Action):
for node_id in node_ids:
kwargs = {
'name': 'node_delete_%s' % node_id[:8],
'cluster_id': self.entity.id,
'cause': consts.CAUSE_DERIVED_LCH,
'inputs': inputs or {},
}
@ -421,6 +424,7 @@ class ClusterAction(base.Action):
for node_id in node_ids:
kwargs = {
'name': 'node_delete_%s' % node_id[:8],
'cluster_id': self.entity.id,
'cause': consts.CAUSE_DERIVED,
'inputs': inputs or {},
}
@ -594,6 +598,7 @@ class ClusterAction(base.Action):
nid = node.id
kwargs = {
'name': 'node_join_%s' % nid[:8],
'cluster_id': self.entity.id,
'cause': consts.CAUSE_DERIVED,
'inputs': {'cluster_id': self.target},
}
@ -748,6 +753,7 @@ class ClusterAction(base.Action):
children = []
for (original, replacement) in node_dict.items():
kwargs = {
'cluster_id': self.entity.id,
'cause': consts.CAUSE_DERIVED,
}

View File

@ -788,6 +788,7 @@ class EngineService(service.Service):
# Build an Action for cluster creation
kwargs = {
'name': 'cluster_create_%s' % cluster.id[:8],
'cluster_id': cluster.id,
'cause': consts.CAUSE_RPC,
'status': action_mod.Action.READY,
}
@ -861,6 +862,7 @@ class EngineService(service.Service):
kwargs = {
'name': 'cluster_update_%s' % cluster.id[:8],
'cluster_id': cluster.id,
'cause': consts.CAUSE_RPC,
'status': action_mod.Action.READY,
'inputs': inputs,
@ -913,6 +915,7 @@ class EngineService(service.Service):
params = {
'name': 'cluster_delete_%s' % cluster.id[:8],
'cluster_id': cluster.id,
'cause': consts.CAUSE_RPC,
'status': action_mod.Action.READY,
}
@ -991,6 +994,7 @@ class EngineService(service.Service):
params = {
'name': 'cluster_add_nodes_%s' % db_cluster.id[:8],
'cluster_id': db_cluster.id,
'cause': consts.CAUSE_RPC,
'status': action_mod.Action.READY,
'inputs': {'nodes': found},
@ -1058,6 +1062,7 @@ class EngineService(service.Service):
params = {
'name': 'cluster_del_nodes_%s' % db_cluster.id[:8],
'cluster_id': db_cluster.id,
'cause': consts.CAUSE_RPC,
'status': action_mod.Action.READY,
'inputs': {
@ -1166,6 +1171,7 @@ class EngineService(service.Service):
nodes = self._validate_replace_nodes(ctx, db_cluster, req.nodes)
kwargs = {
'name': 'cluster_replace_nodes_%s' % db_cluster.id[:8],
'cluster_id': db_cluster.id,
'cause': consts.CAUSE_RPC,
'status': action_mod.Action.READY,
'inputs': {'candidates': nodes},
@ -1251,6 +1257,7 @@ class EngineService(service.Service):
params = {
'name': 'cluster_resize_%s' % db_cluster.id[:8],
'cluster_id': db_cluster.id,
'cause': consts.CAUSE_RPC,
'status': action_mod.Action.READY,
'inputs': {
@ -1297,6 +1304,7 @@ class EngineService(service.Service):
params = {
'name': 'cluster_scale_out_%s' % db_cluster.id[:8],
'cluster_id': db_cluster.id,
'cause': consts.CAUSE_RPC,
'status': action_mod.Action.READY,
'inputs': inputs,
@ -1337,6 +1345,7 @@ class EngineService(service.Service):
params = {
'name': 'cluster_scale_in_%s' % db_cluster.id[:8],
'cluster_id': db_cluster.id,
'cause': consts.CAUSE_RPC,
'status': action_mod.Action.READY,
'inputs': inputs,
@ -1393,6 +1402,7 @@ class EngineService(service.Service):
kwargs = {
'name': 'cluster_check_%s' % db_cluster.id[:8],
'cluster_id': db_cluster.id,
'cause': consts.CAUSE_RPC,
'status': action_mod.Action.READY,
'inputs': req.params if req.obj_attr_is_set('params') else {}
@ -1482,6 +1492,7 @@ class EngineService(service.Service):
params = {
'name': 'cluster_recover_%s' % db_cluster.id[:8],
'cluster_id': db_cluster.id,
'cause': consts.CAUSE_RPC,
'status': action_mod.Action.READY,
'inputs': inputs
@ -1557,6 +1568,7 @@ class EngineService(service.Service):
kwargs = {
'name': 'cluster_%s_%s' % (req.operation, cluster.id[:8]),
'cluster_id': db_cluster.id,
'cause': consts.CAUSE_RPC,
'status': action_mod.Action.READY,
'inputs': {
@ -1686,6 +1698,7 @@ class EngineService(service.Service):
params = {
'name': 'node_create_%s' % node.id[:8],
'cluster_id': cluster_id,
'cause': consts.CAUSE_RPC,
'status': action_mod.Action.READY,
}
@ -1766,6 +1779,7 @@ class EngineService(service.Service):
params = {
'name': 'node_update_%s' % node.id[:8],
'cluster_id': node.cluster_id,
'cause': consts.CAUSE_RPC,
'status': action_mod.Action.READY,
'inputs': inputs,
@ -1813,6 +1827,7 @@ class EngineService(service.Service):
params = {
'name': 'node_delete_%s' % node.id[:8],
'cluster_id': node.cluster_id,
'cause': consts.CAUSE_RPC,
'status': action_mod.Action.READY,
}
@ -1946,6 +1961,7 @@ class EngineService(service.Service):
kwargs = {
'name': 'node_check_%s' % db_node.id[:8],
'cluster_id': db_node.cluster_id,
'cause': consts.CAUSE_RPC,
'status': action_mod.Action.READY
}
@ -1973,6 +1989,7 @@ class EngineService(service.Service):
kwargs = {
'name': 'node_recover_%s' % db_node.id[:8],
'cluster_id': db_node.cluster_id,
'cause': consts.CAUSE_RPC,
'status': action_mod.Action.READY,
'inputs': {}
@ -2036,6 +2053,7 @@ class EngineService(service.Service):
kwargs = {
'name': 'node_%s_%s' % (req.operation, db_node.id[:8]),
'cluster_id': db_node.cluster_id,
'cause': consts.CAUSE_RPC,
'status': action_mod.Action.READY,
'inputs': {
@ -2120,6 +2138,7 @@ class EngineService(service.Service):
params = {
'name': 'attach_policy_%s' % db_cluster.id[:8],
'cluster_id': db_cluster.id,
'cause': consts.CAUSE_RPC,
'status': action_mod.Action.READY,
'inputs': {
@ -2165,6 +2184,7 @@ class EngineService(service.Service):
params = {
'name': 'detach_policy_%s' % db_cluster.id[:8],
'cluster_id': db_cluster.id,
'cause': consts.CAUSE_RPC,
'status': action_mod.Action.READY,
'inputs': {'policy_id': db_policy.id},
@ -2210,6 +2230,7 @@ class EngineService(service.Service):
params = {
'name': 'update_policy_%s' % db_cluster.id[:8],
'cluster_id': db_cluster.id,
'cause': consts.CAUSE_RPC,
'status': action_mod.Action.READY,
'inputs': inputs
@ -2246,6 +2267,17 @@ class EngineService(service.Service):
filters = {}
if req.obj_attr_is_set('name'):
filters['name'] = req.name
# add filter with cluster_id
if req.obj_attr_is_set('cluster_id'):
cluster_ids = []
for cid in req.cluster_id:
try:
cluster = co.Cluster.find(ctx, cid)
cluster_ids.append(cluster.id)
except exception.ResourceNotFound:
return []
if len(cluster_ids) > 0:
filters['cluster_id'] = cluster_ids
if req.obj_attr_is_set('action'):
filters['action'] = req.action
if req.obj_attr_is_set('target'):
@ -2280,6 +2312,7 @@ class EngineService(service.Service):
# Create an action instance
params = {
'name': req.name,
'cluster_id': target.id,
'cause': consts.CAUSE_RPC,
'status': action_mod.Action.READY,
'inputs': req.inputs or {},
@ -2572,6 +2605,7 @@ class EngineService(service.Service):
kwargs = {
'name': 'webhook_%s' % receiver.id[:8],
'cluster_id': db_cluster.id,
'cause': consts.CAUSE_RPC,
'status': action_mod.Action.READY,
'inputs': data

View File

@ -30,6 +30,7 @@ class Action(base.SenlinObject, base.VersionedObjectDictCompat):
'created_at': fields.DateTimeField(),
'updated_at': fields.DateTimeField(nullable=True),
'name': fields.StringField(),
'cluster_id': fields.StringField(),
'context': fields.JsonField(),
'target': fields.UUIDField(),
'action': fields.StringField(),
@ -191,6 +192,7 @@ class Action(base.SenlinObject, base.VersionedObjectDictCompat):
action_dict = {
'id': self.id,
'name': self.name,
'cluster_id': self.cluster_id,
'action': self.action,
'target': self.target,
'cause': self.cause,

View File

@ -10,6 +10,8 @@
# License for the specific language governing permissions and limitations
# under the License.
from oslo_utils import versionutils
from senlin.common import consts
from senlin.objects import base
from senlin.objects import fields
@ -39,8 +41,14 @@ class ActionListRequest(base.SenlinObject):
action_name_list = list(consts.CLUSTER_ACTION_NAMES)
action_name_list.extend(list(consts.NODE_ACTION_NAMES))
VERSION = '1.1'
VERSION_MAP = {
'1.14': '1.1'
}
fields = {
'name': fields.ListOfStringsField(nullable=True),
'cluster_id': fields.ListOfStringsField(nullable=True),
'action': fields.ListOfEnumField(
valid_values=action_name_list, nullable=True),
'target': fields.ListOfStringsField(nullable=True),
@ -53,6 +61,14 @@ class ActionListRequest(base.SenlinObject):
'project_safe': fields.FlexibleBooleanField(default=True)
}
def obj_make_compatible(self, primitive, target_version):
super(ActionListRequest, self).obj_make_compatible(
primitive, target_version)
target_version = versionutils.convert_version_to_tuple(target_version)
if target_version < (1, 14):
if 'cluster_id' in primitive['senlin_object.data']:
del primitive['senlin_object.data']['cluster_id']
@base.SenlinObjectRegistry.register
class ActionGetRequest(base.SenlinObject):

View File

@ -10,6 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import copy
import mock
import six
from webob import exc
@ -50,6 +51,7 @@ class ActionControllerTest(shared.ControllerTest, base.SenlinTestCase):
{
'action': 'NODE_CREATE',
'cause': 'RPC_Request',
'cluster_id': 'CLUSTER_FAKE_ID',
'depended_by': [],
'depends_on': [],
'end_time': 1425555000.0,
@ -79,6 +81,92 @@ class ActionControllerTest(shared.ControllerTest, base.SenlinTestCase):
mock_call.assert_called_once_with(
req.context, 'action_list', obj)
@mock.patch.object(util, 'parse_request')
@mock.patch.object(rpc_client.EngineClient, 'call')
def test_action_index_without_cluster_id(self, mock_call, mock_parse,
mock_enforce):
self._mock_enforce_setup(mock_enforce, 'index', True)
req = self._get('/actions', version='1.13')
engine_resp = [
{
'action': 'NODE_CREATE',
'cause': 'RPC_Request',
'cluster_id': 'CLUSTER_FAKE_ID',
'depended_by': [],
'depends_on': [],
'end_time': 1425555000.0,
'id': '2366d400-c7e3-4961-09254-6d1c3f7ac167',
'inputs': {},
'interval': -1,
'name': 'node_create_0df0931b',
'outputs': {},
'owner': None,
'start_time': 1425550000.0,
'status': 'SUCCEEDED',
'status_reason': 'Action completed successfully.',
'target': '0df0931b-e251-4f2e-8719-4effda3627ba',
'timeout': 3600
}
]
mock_call.return_value = copy.deepcopy(engine_resp)
obj = mock.Mock()
mock_parse.return_value = obj
result = self.controller.index(req)
# list call for version < 1.14 should have cluster_id field removed
# remove cluster_id field from expected response
engine_resp[0].pop('cluster_id')
self.assertEqual(engine_resp, result['actions'])
mock_parse.assert_called_once_with(
'ActionListRequest', req, {'project_safe': True})
mock_call.assert_called_once_with(
req.context, 'action_list', obj)
@mock.patch.object(util, 'parse_request')
@mock.patch.object(rpc_client.EngineClient, 'call')
def test_action_index_with_cluster_id(self, mock_call, mock_parse,
mock_enforce):
self._mock_enforce_setup(mock_enforce, 'index', True)
req = self._get('/actions', version='1.14')
engine_resp = [
{
'action': 'NODE_CREATE',
'cause': 'RPC_Request',
'cluster_id': 'CLUSTER_FAKE_ID',
'depended_by': [],
'depends_on': [],
'end_time': 1425555000.0,
'id': '2366d400-c7e3-4961-09254-6d1c3f7ac167',
'inputs': {},
'interval': -1,
'name': 'node_create_0df0931b',
'outputs': {},
'owner': None,
'start_time': 1425550000.0,
'status': 'SUCCEEDED',
'status_reason': 'Action completed successfully.',
'target': '0df0931b-e251-4f2e-8719-4effda3627ba',
'timeout': 3600
}
]
mock_call.return_value = copy.deepcopy(engine_resp)
obj = mock.Mock()
mock_parse.return_value = obj
result = self.controller.index(req)
self.assertEqual(engine_resp, result['actions'])
mock_parse.assert_called_once_with(
'ActionListRequest', req, {'project_safe': True})
mock_call.assert_called_once_with(
req.context, 'action_list', obj)
@mock.patch.object(util, 'parse_request')
@mock.patch.object(rpc_client.EngineClient, 'call')
def test_action_index_whitelists_params(self, mock_call,
@ -86,6 +174,7 @@ class ActionControllerTest(shared.ControllerTest, base.SenlinTestCase):
self._mock_enforce_setup(mock_enforce, 'index', True)
marker_uuid = '8216a86c-1bdc-442e-b493-329385d37cbc'
params = {
'cluster_id': 'CLUSTER_FAKE_ID',
'name': 'NODE_CREATE',
'status': 'SUCCEEDED',
'limit': 10,
@ -105,6 +194,7 @@ class ActionControllerTest(shared.ControllerTest, base.SenlinTestCase):
mock_parse.assert_called_once_with(
'ActionListRequest', req,
{
'cluster_id': ['CLUSTER_FAKE_ID'],
'status': ['SUCCEEDED'],
'sort': 'status',
'name': ['NODE_CREATE'],
@ -247,6 +337,7 @@ class ActionControllerTest(shared.ControllerTest, base.SenlinTestCase):
engine_resp = {
'action': 'NODE_CREATE',
'cause': 'RPC_Request',
'cluster_id': 'CLUSTER_FAKE_ID',
'depended_by': [],
'depends_on': [],
'end_time': 1425555000.0,

View File

@ -36,6 +36,7 @@ sample_action = """
target: cluster_001
action: create
cause: User Initiate
cluster_id: cluster_001_id
timeout: 60
control: READY
status: INIT

View File

@ -44,6 +44,7 @@ class DBAPIActionTest(base.SenlinTestCase):
self.assertIsNotNone(action)
self.assertEqual(data['name'], action.name)
self.assertEqual(data['cluster_id'], action.cluster_id)
self.assertEqual(data['target'], action.target)
self.assertEqual(data['action'], action.action)
self.assertEqual(data['cause'], action.cause)

View File

@ -62,6 +62,7 @@ class ActionBaseTest(base.SenlinTestCase):
self.ctx = utils.dummy_context(project=PROJECT_ID, user_id=USER_ID)
self.action_values = {
'name': 'FAKE_NAME',
'cluster_id': 'FAKE_CLUSTER_ID',
'cause': 'FAKE_CAUSE',
'owner': OWNER_ID,
'interval': 60,
@ -80,6 +81,7 @@ class ActionBaseTest(base.SenlinTestCase):
def _verify_new_action(self, obj, target, action):
self.assertIsNone(obj.id)
self.assertEqual('', obj.name)
self.assertEqual('', obj.cluster_id)
self.assertEqual(target, obj.target)
self.assertEqual(action, obj.action)
self.assertEqual('', obj.cause)
@ -123,6 +125,7 @@ class ActionBaseTest(base.SenlinTestCase):
self.assertEqual('FAKE_ID', obj.id)
self.assertEqual('FAKE_NAME', obj.name)
self.assertEqual('FAKE_CLUSTER_ID', obj.cluster_id)
self.assertEqual(OBJID, obj.target)
self.assertEqual('FAKE_CAUSE', obj.cause)
self.assertEqual(OWNER_ID, obj.owner)
@ -180,6 +183,7 @@ class ActionBaseTest(base.SenlinTestCase):
action_obj = ab.Action._from_object(record)
self.assertIsInstance(action_obj, ab.Action)
self.assertEqual(obj.id, action_obj.id)
self.assertEqual(obj.cluster_id, action_obj.cluster_id)
self.assertEqual(obj.action, action_obj.action)
self.assertEqual(obj.name, action_obj.name)
self.assertEqual(obj.target, action_obj.target)
@ -931,6 +935,7 @@ class ActionBaseTest(base.SenlinTestCase):
expected = {
'id': 'FAKE_ID',
'name': 'FAKE_NAME',
'cluster_id': 'FAKE_CLUSTER_ID',
'action': 'OBJECT_ACTION',
'target': OBJID,
'cause': 'FAKE_CAUSE',

View File

@ -68,7 +68,8 @@ class ClusterAddNodesTest(base.SenlinTestCase):
mock_count.assert_called_once_with(action.context, 'CLUSTER_ID')
mock_action.assert_called_once_with(
action.context, 'NODE_1', 'NODE_JOIN',
name='node_join_NODE_1', cause='Derived Action',
name='node_join_NODE_1',
cluster_id='CLUSTER_ID', cause='Derived Action',
inputs={'cluster_id': 'CLUSTER_ID'})
mock_dep.assert_called_once_with(action.context, ['NODE_ACTION_ID'],
'CLUSTER_ACTION_ID')
@ -130,9 +131,11 @@ class ClusterAddNodesTest(base.SenlinTestCase):
mock_action.assert_has_calls([
mock.call(action.context, 'NODE_1', 'NODE_JOIN',
name='node_join_NODE_1', cause='Derived Action',
cluster_id='CLUSTER_ID',
inputs={'cluster_id': 'CLUSTER_ID'}),
mock.call(action.context, 'NODE_2', 'NODE_JOIN',
name='node_join_NODE_2', cause='Derived Action',
cluster_id='CLUSTER_ID',
inputs={'cluster_id': 'CLUSTER_ID'})])
mock_dep.assert_called_once_with(
@ -277,7 +280,8 @@ class ClusterAddNodesTest(base.SenlinTestCase):
mock_count.assert_called_once_with(action.context, 'CLUSTER_ID')
mock_action.assert_called_once_with(
action.context, 'NODE_1', 'NODE_JOIN',
name='node_join_NODE_1', cause='Derived Action',
name='node_join_NODE_1', cluster_id='CLUSTER_ID',
cause='Derived Action',
inputs={'cluster_id': 'CLUSTER_ID'})
mock_dep.assert_called_once_with(action.context, ['NODE_ACTION_ID'],
'CLUSTER_ACTION_ID')

View File

@ -79,10 +79,11 @@ class ClusterCreateTest(base.SenlinTestCase):
mock_action.assert_called_once_with(action.context, 'NODE_ID',
'NODE_CREATE',
name='node_create_NODE_ID',
cluster_id='CLUSTER_ID',
cause='Derived Action')
mock_dep.assert_called_once_with(action.context, ['NODE_ACTION_ID'],
'CLUSTER_ACTION_ID')
mock_update.assert_called_once_with(
mock_update.assert_called_with(
action.context, 'NODE_ACTION_ID',
{'status': ab.Action.READY})
mock_start.assert_called_once_with()

View File

@ -49,6 +49,7 @@ class ClusterDeleteTest(base.SenlinTestCase):
action = ca.ClusterAction(cluster.id, 'CLUSTER_ACTION', self.ctx)
action.id = 'CLUSTER_ACTION_ID'
action.inputs = {'destroy_after_deletion': False}
action.context = self.ctx
mock_wait.return_value = (action.RES_OK, 'All dependents completed')
mock_action.return_value = 'NODE_ACTION_ID'
@ -60,11 +61,13 @@ class ClusterDeleteTest(base.SenlinTestCase):
self.assertEqual('All dependents completed', res_msg)
mock_action.assert_called_once_with(
action.context, 'NODE_ID', 'NODE_DELETE',
name='node_delete_NODE_ID', cause='Derived Action', inputs={})
name='node_delete_NODE_ID', cause='Derived Action',
cluster_id='FAKE_CLUSTER', inputs={})
mock_dep.assert_called_once_with(action.context, ['NODE_ACTION_ID'],
'CLUSTER_ACTION_ID')
mock_update.assert_called_once_with(action.context, 'NODE_ACTION_ID',
{'status': 'READY'})
mock_update.assert_called_with(action.context,
'NODE_ACTION_ID',
{'status': 'READY'})
mock_start.assert_called_once_with()
mock_wait.assert_called_once_with()
self.assertEqual(['NODE_ID'], action.outputs['nodes_removed'])
@ -100,10 +103,12 @@ class ClusterDeleteTest(base.SenlinTestCase):
mock.call(action.context, 'NODE_ID', 'NODE_OPERATION',
name='node_delete_NODE_ID',
cause='Derived Action',
cluster_id='FAKE_CLUSTER',
inputs={'operation': 'stop',
'update_parent_status': False}),
mock.call(action.context, 'NODE_ID', 'NODE_DELETE',
name='node_delete_NODE_ID',
cluster_id='FAKE_CLUSTER',
cause='Derived Action', inputs={})
]
mock_action.assert_has_calls(create_actions)
@ -203,7 +208,8 @@ class ClusterDeleteTest(base.SenlinTestCase):
self.assertEqual('All dependents completed', res_msg)
mock_action.assert_called_once_with(
action.context, 'NODE_ID', 'NODE_LEAVE',
name='node_delete_NODE_ID', cause='Derived Action', inputs={})
name='node_delete_NODE_ID', cluster_id='CLUSTER_ID',
cause='Derived Action', inputs={})
@mock.patch.object(ao.Action, 'update')
@mock.patch.object(ab.Action, 'create')
@ -249,6 +255,7 @@ class ClusterDeleteTest(base.SenlinTestCase):
action.context, 'NODE_ID', 'NODE_DELETE',
name='node_delete_NODE_ID',
cause='Derived Action with Lifecycle Hook',
cluster_id='CLUSTER_ID',
inputs={})
update_calls = [
mock.call(action.context, 'NODE_ACTION_ID',
@ -323,6 +330,7 @@ class ClusterDeleteTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
action.context, 'NODE_ID', 'NODE_DELETE',
name='node_delete_NODE_ID',
cluster_id='CLUSTER_ID',
cause='Derived Action with Lifecycle Hook', inputs={})
update_calls = [
mock.call(action.context, 'NODE_ACTION_ID',
@ -384,6 +392,7 @@ class ClusterDeleteTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
action.context, 'NODE_ID', 'NODE_DELETE',
name='node_delete_NODE_ID',
cluster_id='CLUSTER_ID',
cause='Derived Action with Lifecycle Hook', inputs={})
update_calls = [
mock.call(action.context, 'NODE_ACTION_ID',
@ -954,7 +963,7 @@ class ClusterDeleteTest(base.SenlinTestCase):
self.assertEqual(1, mock_dep.call_count)
mock_action.assert_called_once_with(
action.context, 'NODE_ID', 'NODE_DELETE',
name='node_delete_NODE_ID',
name='node_delete_NODE_ID', cluster_id='CLUSTER_ID',
cause='Derived Action with Lifecycle Hook', inputs={})
update_calls = [
mock.call(action.context, 'NODE_ACTION_ID',
@ -1084,9 +1093,11 @@ class ClusterDeleteTest(base.SenlinTestCase):
create_actions = [
mock.call(action.context, 'NODE_1', 'NODE_DELETE',
name='node_delete_NODE_1',
cluster_id='CLUSTER_ID',
cause='Derived Action with Lifecycle Hook', inputs={}),
mock.call(action.context, 'NODE_2', 'NODE_DELETE',
name='node_delete_NODE_2',
cluster_id='CLUSTER_ID',
cause='Derived Action with Lifecycle Hook', inputs={})
]
mock_action.assert_has_calls(create_actions)

View File

@ -72,9 +72,11 @@ class ClusterReplaceNodesTest(base.SenlinTestCase):
mock_action.assert_has_calls([
mock.call(action.context, 'O_NODE_1', 'NODE_LEAVE',
name='node_leave_O_NODE_1',
cluster_id='CLUSTER_ID',
cause='Derived Action'),
mock.call(action.context, 'R_NODE_1', 'NODE_JOIN',
name='node_join_R_NODE_1',
cluster_id='CLUSTER_ID',
cause='Derived Action',
inputs={'cluster_id': 'CLUSTER_ID'})])
@ -266,9 +268,11 @@ class ClusterReplaceNodesTest(base.SenlinTestCase):
mock_action.assert_has_calls([
mock.call(action.context, 'O_NODE_1', 'NODE_LEAVE',
name='node_leave_O_NODE_1',
cluster_id='CLUSTER_ID',
cause='Derived Action'),
mock.call(action.context, 'R_NODE_1', 'NODE_JOIN',
name='node_join_R_NODE_1',
cluster_id='CLUSTER_ID',
cause='Derived Action',
inputs={'cluster_id': 'CLUSTER_ID'})])

View File

@ -118,6 +118,7 @@ class ActionTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, 'FAKE_CLUSTER', 'CLUSTER_CREATE',
name='a1',
cluster_id='FAKE_CLUSTER',
cause=consts.CAUSE_RPC,
status=ab.Action.READY,
inputs={})

View File

@ -42,7 +42,7 @@ class ClusterOpTest(base.SenlinTestCase):
@mock.patch.object(co.Cluster, 'find')
def test_cluster_op(self, mock_find, mock_cluster, mock_nodes, mock_action,
mock_start):
x_db_cluster = mock.Mock()
x_db_cluster = mock.Mock(id='12345678AB')
mock_find.return_value = x_db_cluster
x_schema = mock.Mock()
x_profile = mock.Mock(OPERATIONS={'dance': x_schema})
@ -69,6 +69,7 @@ class ClusterOpTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, '12345678AB', consts.CLUSTER_OPERATION,
name='cluster_dance_12345678',
cluster_id='12345678AB',
cause=consts.CAUSE_RPC,
status=am.Action.READY,
inputs={
@ -147,7 +148,7 @@ class ClusterOpTest(base.SenlinTestCase):
@mock.patch.object(co.Cluster, 'find')
def test_cluster_op_no_parameters(self, mock_find, mock_cluster,
mock_nodes, mock_action, mock_start):
x_db_cluster = mock.Mock()
x_db_cluster = mock.Mock(id='12345678AB')
mock_find.return_value = x_db_cluster
x_schema = mock.Mock()
x_profile = mock.Mock(OPERATIONS={'dance': x_schema})
@ -172,6 +173,7 @@ class ClusterOpTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, '12345678AB', consts.CLUSTER_OPERATION,
name='cluster_dance_12345678',
cluster_id='12345678AB',
cause=consts.CAUSE_RPC,
status=am.Action.READY,
inputs={
@ -189,7 +191,7 @@ class ClusterOpTest(base.SenlinTestCase):
@mock.patch.object(co.Cluster, 'find')
def test_cluster_op_no_filters(self, mock_find, mock_cluster,
mock_nodes, mock_action, mock_start):
x_db_cluster = mock.Mock()
x_db_cluster = mock.Mock(id='12345678AB')
mock_find.return_value = x_db_cluster
x_schema = mock.Mock()
x_profile = mock.Mock(OPERATIONS={'dance': x_schema})
@ -211,6 +213,7 @@ class ClusterOpTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, '12345678AB', consts.CLUSTER_OPERATION,
name='cluster_dance_12345678',
cluster_id='12345678AB',
cause=consts.CAUSE_RPC,
status=am.Action.READY,
inputs={

View File

@ -194,6 +194,7 @@ class ClusterPolicyTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, '12345678abcd', consts.CLUSTER_ATTACH_POLICY,
name='attach_policy_12345678',
cluster_id='12345678abcd',
cause=consts.CAUSE_RPC,
status=action_mod.Action.READY,
inputs={'policy_id': '87654321abcd', 'enabled': True},
@ -258,6 +259,7 @@ class ClusterPolicyTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, '12345678abcd', consts.CLUSTER_DETACH_POLICY,
name='detach_policy_12345678',
cluster_id='12345678abcd',
cause=consts.CAUSE_RPC,
status=action_mod.Action.READY,
inputs={'policy_id': '87654321abcd'},
@ -345,6 +347,7 @@ class ClusterPolicyTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, '12345678abcd', consts.CLUSTER_UPDATE_POLICY,
name='update_policy_12345678',
cluster_id='12345678abcd',
cause=consts.CAUSE_RPC,
status=action_mod.Action.READY,
inputs={'policy_id': '87654321abcd', 'enabled': False},

View File

@ -152,6 +152,7 @@ class ClusterTest(base.SenlinTestCase):
self.ctx,
'12345678ABC', 'CLUSTER_CREATE',
name='cluster_create_12345678',
cluster_id='12345678ABC',
cause=consts.CAUSE_RPC,
status=am.Action.READY,
)
@ -196,6 +197,7 @@ class ClusterTest(base.SenlinTestCase):
self.ctx,
'12345678ABC', 'CLUSTER_CREATE',
name='cluster_create_12345678',
cluster_id='12345678ABC',
cause=consts.CAUSE_RPC,
status=am.Action.READY,
)
@ -330,6 +332,7 @@ class ClusterTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, '12345678AB', 'CLUSTER_UPDATE',
name='cluster_update_12345678',
cluster_id='12345678AB',
cause=consts.CAUSE_RPC,
status=am.Action.READY,
inputs={
@ -449,6 +452,7 @@ class ClusterTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, '12345678AB', 'CLUSTER_UPDATE',
name='cluster_update_12345678',
cluster_id='12345678AB',
cause=consts.CAUSE_RPC,
status=am.Action.READY,
inputs={
@ -479,6 +483,7 @@ class ClusterTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, '12345678AB', 'CLUSTER_UPDATE',
name='cluster_update_12345678',
cluster_id='12345678AB',
status=am.Action.READY,
cause=consts.CAUSE_RPC,
inputs={
@ -510,6 +515,7 @@ class ClusterTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, '12345678AB', 'CLUSTER_UPDATE',
name='cluster_update_12345678',
cluster_id='12345678AB',
status=am.Action.READY,
cause=consts.CAUSE_RPC,
inputs={
@ -541,6 +547,7 @@ class ClusterTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, '12345678AB', 'CLUSTER_UPDATE',
name='cluster_update_12345678',
cluster_id='12345678AB',
status=am.Action.READY,
cause=consts.CAUSE_RPC,
inputs={
@ -632,6 +639,7 @@ class ClusterTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, '12345678AB', consts.CLUSTER_ADD_NODES,
name='cluster_add_nodes_12345678',
cluster_id='12345678AB',
cause=consts.CAUSE_RPC,
status=am.Action.READY,
inputs={'nodes': ['NODE1', 'NODE2']},
@ -830,6 +838,7 @@ class ClusterTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, '1234', consts.CLUSTER_DEL_NODES,
name='cluster_del_nodes_1234',
cluster_id='1234',
status=am.Action.READY,
cause=consts.CAUSE_RPC,
inputs={
@ -999,6 +1008,7 @@ class ClusterTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, '12345678ABCDEFGH', consts.CLUSTER_RESIZE,
name='cluster_resize_12345678',
cluster_id='12345678ABCDEFGH',
cause=consts.CAUSE_RPC,
status=am.Action.READY,
inputs={
@ -1043,6 +1053,7 @@ class ClusterTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, '12345678ABCDEFGH', consts.CLUSTER_RESIZE,
name='cluster_resize_12345678',
cluster_id='12345678ABCDEFGH',
cause=consts.CAUSE_RPC,
status=am.Action.READY,
inputs={
@ -1087,6 +1098,7 @@ class ClusterTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, '12345678ABCDEFGH', consts.CLUSTER_RESIZE,
name='cluster_resize_12345678',
cluster_id='12345678ABCDEFGH',
cause=consts.CAUSE_RPC,
status=am.Action.READY,
inputs={
@ -1210,6 +1222,7 @@ class ClusterTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, '12345678ABCDEFGH', consts.CLUSTER_SCALE_OUT,
name='cluster_scale_out_12345678',
cluster_id='12345678ABCDEFGH',
cause=consts.CAUSE_RPC,
status=am.Action.READY,
inputs={'count': 1},
@ -1248,6 +1261,7 @@ class ClusterTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, '12345678ABCDEFGH', consts.CLUSTER_SCALE_OUT,
name='cluster_scale_out_12345678',
cluster_id='12345678ABCDEFGH',
cause=consts.CAUSE_RPC,
status=am.Action.READY,
inputs={},
@ -1305,6 +1319,7 @@ class ClusterTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, '12345678ABCD', consts.CLUSTER_SCALE_IN,
name='cluster_scale_in_12345678',
cluster_id='12345678ABCD',
cause=consts.CAUSE_RPC,
status=am.Action.READY,
inputs={'count': 2},
@ -1342,6 +1357,7 @@ class ClusterTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, 'FOO', consts.CLUSTER_SCALE_IN,
name='cluster_scale_in_FOO',
cluster_id='FOO',
cause=consts.CAUSE_RPC,
status=am.Action.READY,
inputs={},
@ -1395,6 +1411,7 @@ class ClusterTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, 'CID', consts.CLUSTER_CHECK,
name='cluster_check_CID',
cluster_id='CID',
cause=consts.CAUSE_RPC,
status=am.Action.READY,
inputs={'foo': 'bar'},
@ -1424,6 +1441,7 @@ class ClusterTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, 'CID', consts.CLUSTER_CHECK,
name='cluster_check_CID',
cluster_id='CID',
cause=consts.CAUSE_RPC,
status=am.Action.READY,
inputs={'delete_check_action': True},
@ -1447,6 +1465,7 @@ class ClusterTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, 'CID', consts.CLUSTER_CHECK,
name='cluster_check_CID',
cluster_id='CID',
cause=consts.CAUSE_RPC,
status=am.Action.READY,
inputs={},
@ -1471,6 +1490,7 @@ class ClusterTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, 'CID', consts.CLUSTER_CHECK,
name='cluster_check_CID',
cluster_id='CID',
cause=consts.CAUSE_RPC,
status=am.Action.READY,
inputs={},
@ -1509,6 +1529,7 @@ class ClusterTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, 'CID', consts.CLUSTER_RECOVER,
name='cluster_recover_CID',
cluster_id='CID',
cause=consts.CAUSE_RPC,
status=am.Action.READY,
inputs={'operation': 'RECREATE'},
@ -1532,6 +1553,7 @@ class ClusterTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, 'CID', consts.CLUSTER_RECOVER,
name='cluster_recover_CID',
cluster_id='CID',
cause=consts.CAUSE_RPC,
status=am.Action.READY,
inputs={'operation': 'REBUILD'},
@ -1555,6 +1577,7 @@ class ClusterTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, 'CID', consts.CLUSTER_RECOVER,
name='cluster_recover_CID',
cluster_id='CID',
cause=consts.CAUSE_RPC,
status=am.Action.READY,
inputs={'operation': 'REBOOT'},
@ -1577,6 +1600,7 @@ class ClusterTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, 'CID', consts.CLUSTER_RECOVER,
name='cluster_recover_CID',
cluster_id='CID',
cause=consts.CAUSE_RPC,
status=am.Action.READY,
inputs={}
@ -1673,6 +1697,7 @@ class ClusterTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, 'CID', consts.CLUSTER_RECOVER,
name='cluster_recover_CID',
cluster_id='CID',
cause=consts.CAUSE_RPC,
status=am.Action.READY,
inputs={},
@ -1892,6 +1917,7 @@ class ClusterTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, 'CID', consts.CLUSTER_REPLACE_NODES,
name='cluster_replace_nodes_CID',
cluster_id='CID',
cause=consts.CAUSE_RPC,
status=am.Action.READY,
inputs={'candidates': {'ORIGINAL': 'REPLACE'}})
@ -2060,6 +2086,7 @@ class ClusterTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, '12345678AB', 'CLUSTER_DELETE',
name='cluster_delete_12345678',
cluster_id='12345678AB',
cause=consts.CAUSE_RPC,
force=True,
status=am.Action.READY)
@ -2143,6 +2170,7 @@ class ClusterTest(base.SenlinTestCase):
mock_action.assert_called_with(
self.ctx, '12345678AB', 'CLUSTER_DELETE',
name='cluster_delete_12345678',
cluster_id='12345678AB',
cause=consts.CAUSE_RPC,
force=True,
status=am.Action.READY)

View File

@ -180,6 +180,7 @@ class NodeTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, 'NODE_ID', consts.NODE_CREATE,
name='node_create_NODE_ID',
cluster_id='',
cause=consts.CAUSE_RPC,
status=action_mod.Action.READY)
notify.assert_called_once_with()
@ -237,6 +238,7 @@ class NodeTest(base.SenlinTestCase):
})
mock_action.assert_called_once_with(
self.ctx, 'NODE_ID', consts.NODE_CREATE,
cluster_id='CLUSTER_ID',
name='node_create_NODE_ID',
cause=consts.CAUSE_RPC,
status=action_mod.Action.READY)
@ -301,6 +303,7 @@ class NodeTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, 'NODE_ID', consts.NODE_CREATE,
name='node_create_NODE_ID',
cluster_id='CLUSTER_ID',
cause=consts.CAUSE_RPC,
status=action_mod.Action.READY)
notify.assert_called_once_with()
@ -447,6 +450,7 @@ class NodeTest(base.SenlinTestCase):
@mock.patch.object(no.Node, 'find')
def test_node_update(self, mock_find, mock_action, mock_start):
x_obj = mock.Mock(id='FAKE_NODE_ID', name='NODE1', role='ROLE1',
cluster_id='FAKE_CLUSTER_ID',
metadata={'KEY': 'VALUE'})
x_obj.to_dict.return_value = {'foo': 'bar'}
mock_find.return_value = x_obj
@ -465,6 +469,7 @@ class NodeTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, 'FAKE_NODE_ID', consts.NODE_UPDATE,
name='node_update_FAKE_NOD',
cluster_id='FAKE_CLUSTER_ID',
cause=consts.CAUSE_RPC,
status=action_mod.Action.READY,
inputs={
@ -480,9 +485,11 @@ class NodeTest(base.SenlinTestCase):
@mock.patch.object(action_mod.Action, 'create')
@mock.patch.object(po.Profile, 'find')
@mock.patch.object(no.Node, 'find')
# @mock.patch.object(co.Cluster, 'find')
def test_node_update_new_profile(self, mock_find, mock_profile,
mock_action, mock_start):
x_obj = mock.Mock(id='FAKE_NODE_ID', role='ROLE1',
cluster_id='FAKE_CLUSTER_ID',
metadata={'KEY': 'VALUE'},
profile_id='OLD_PROFILE_ID')
x_obj.name = 'NODE1'
@ -494,7 +501,6 @@ class NodeTest(base.SenlinTestCase):
mock.Mock(id='OLD_PROFILE_ID', type='PROFILE_TYPE'),
]
mock_action.return_value = 'ACTION_ID'
# all properties are filtered out except for profile_id
req = orno.NodeUpdateRequest(identity='FAKE_NODE',
name='NODE1',
@ -512,6 +518,7 @@ class NodeTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, 'FAKE_NODE_ID', consts.NODE_UPDATE,
name='node_update_FAKE_NOD',
cluster_id='FAKE_CLUSTER_ID',
cause=consts.CAUSE_RPC,
status=action_mod.Action.READY,
inputs={
@ -623,6 +630,7 @@ class NodeTest(base.SenlinTestCase):
@mock.patch.object(no.Node, 'find')
def test_node_delete(self, mock_find, mock_action, mock_start):
mock_find.return_value = mock.Mock(id='12345678AB', status='ACTIVE',
cluster_id='',
dependents={})
mock_action.return_value = 'ACTION_ID'
@ -634,6 +642,7 @@ class NodeTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, '12345678AB', consts.NODE_DELETE,
name='node_delete_12345678',
cluster_id='',
cause=consts.CAUSE_RPC,
status=action_mod.Action.READY)
mock_start.assert_called_once_with()
@ -691,7 +700,8 @@ class NodeTest(base.SenlinTestCase):
mock_find.return_value = mock.Mock(id='12345678AB',
status=bad_status,
dependents={})
dependents={},
cluster_id='',)
mock_action.return_value = 'ACTION_ID'
req = orno.NodeDeleteRequest(identity='FAKE_NODE', force=True)
@ -702,6 +712,7 @@ class NodeTest(base.SenlinTestCase):
mock_action.assert_called_with(
self.ctx, '12345678AB', consts.NODE_DELETE,
name='node_delete_12345678',
cluster_id='',
cause=consts.CAUSE_RPC,
status=action_mod.Action.READY)
mock_start.assert_called_with()
@ -821,6 +832,7 @@ class NodeTest(base.SenlinTestCase):
@mock.patch.object(service.EngineService, '_node_adopt_preview')
def test_node_adopt(self, mock_preview, mock_create):
class FakeProfile(object):
@classmethod
def create(cls, ctx, name, spec):
obj = mock.Mock(spec=spec, id='PROFILE_ID')
@ -896,7 +908,8 @@ class NodeTest(base.SenlinTestCase):
@mock.patch.object(action_mod.Action, 'create')
@mock.patch.object(no.Node, 'find')
def test_node_check(self, mock_find, mock_action, mock_start):
mock_find.return_value = mock.Mock(id='12345678AB')
mock_find.return_value = mock.Mock(id='12345678AB',
cluster_id='FAKE_CLUSTER_ID')
mock_action.return_value = 'ACTION_ID'
params = {'k1': 'v1'}
@ -908,6 +921,7 @@ class NodeTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, '12345678AB', consts.NODE_CHECK,
name='node_check_12345678',
cluster_id='FAKE_CLUSTER_ID',
cause=consts.CAUSE_RPC,
status=action_mod.Action.READY,
inputs={'k1': 'v1'})
@ -931,7 +945,8 @@ class NodeTest(base.SenlinTestCase):
@mock.patch.object(action_mod.Action, 'create')
@mock.patch.object(no.Node, 'find')
def test_node_recover(self, mock_find, mock_action, mock_start):
mock_find.return_value = mock.Mock(id='12345678AB')
mock_find.return_value = mock.Mock(
id='12345678AB', cluster_id='FAKE_CLUSTER_ID')
mock_action.return_value = 'ACTION_ID'
params = {'operation': 'REBOOT'}
@ -943,6 +958,7 @@ class NodeTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, '12345678AB', consts.NODE_RECOVER,
name='node_recover_12345678',
cluster_id='FAKE_CLUSTER_ID',
cause=consts.CAUSE_RPC,
status=action_mod.Action.READY,
inputs={'operation': 'REBOOT'})
@ -952,7 +968,7 @@ class NodeTest(base.SenlinTestCase):
@mock.patch.object(action_mod.Action, 'create')
@mock.patch.object(no.Node, 'find')
def test_node_recover_with_check(self, mock_find, mock_action, mock_start):
mock_find.return_value = mock.Mock(id='12345678AB')
mock_find.return_value = mock.Mock(id='12345678AB', cluster_id='')
mock_action.return_value = 'ACTION_ID'
params = {'check': True, 'operation': 'REBUILD'}
@ -964,6 +980,7 @@ class NodeTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, '12345678AB', consts.NODE_RECOVER,
name='node_recover_12345678',
cluster_id='',
cause=consts.CAUSE_RPC,
status=action_mod.Action.READY,
inputs={'check': True, 'operation': 'REBUILD'})
@ -974,7 +991,7 @@ class NodeTest(base.SenlinTestCase):
@mock.patch.object(no.Node, 'find')
def test_node_recover_with_delete_timeout(self, mock_find, mock_action,
mock_start):
mock_find.return_value = mock.Mock(id='12345678AB')
mock_find.return_value = mock.Mock(id='12345678AB', cluster_id='',)
mock_action.return_value = 'ACTION_ID'
params = {'delete_timeout': 20, 'operation': 'RECREATE'}
@ -986,6 +1003,7 @@ class NodeTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, '12345678AB', consts.NODE_RECOVER,
name='node_recover_12345678',
cluster_id='',
cause=consts.CAUSE_RPC,
status=action_mod.Action.READY,
inputs={'delete_timeout': 20,
@ -997,7 +1015,8 @@ class NodeTest(base.SenlinTestCase):
@mock.patch.object(no.Node, 'find')
def test_node_recover_with_force_recreate(self, mock_find, mock_action,
mock_start):
mock_find.return_value = mock.Mock(id='12345678AB')
mock_find.return_value = mock.Mock(
id='12345678AB', cluster_id='FAKE_CLUSTER_ID')
mock_action.return_value = 'ACTION_ID'
params = {'force_recreate': True, 'operation': 'reboot',
@ -1010,6 +1029,7 @@ class NodeTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, '12345678AB', consts.NODE_RECOVER,
name='node_recover_12345678',
cluster_id='FAKE_CLUSTER_ID',
cause=consts.CAUSE_RPC,
status=action_mod.Action.READY,
inputs={'force_recreate': True,
@ -1095,7 +1115,7 @@ class NodeTest(base.SenlinTestCase):
@mock.patch.object(node_mod.Node, 'load')
@mock.patch.object(no.Node, 'find')
def test_node_op(self, mock_find, mock_node, mock_action, mock_start):
x_db_node = mock.Mock(id='12345678AB')
x_db_node = mock.Mock(id='12345678AB', cluster_id='FAKE_CLUSTER_ID')
mock_find.return_value = x_db_node
x_schema = mock.Mock()
x_profile = mock.Mock(OPERATIONS={'dance': x_schema})
@ -1117,6 +1137,7 @@ class NodeTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, '12345678AB', consts.NODE_OPERATION,
name='node_dance_12345678',
cluster_id='FAKE_CLUSTER_ID',
cause=consts.CAUSE_RPC,
status=action_mod.Action.READY,
inputs={'operation': 'dance', 'params': {'style': 'tango'}})

View File

@ -58,6 +58,7 @@ class WebhookTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, 'FAKE_CLUSTER', 'DANCE',
name='webhook_01234567',
cluster_id='FAKE_CLUSTER',
cause=consts.CAUSE_RPC,
status=action_mod.Action.READY,
inputs={'kee': 'vee', 'foo': 'bar'},
@ -89,6 +90,7 @@ class WebhookTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, 'FAKE_CLUSTER', 'DANCE',
name='webhook_01234567',
cluster_id='FAKE_CLUSTER',
cause=consts.CAUSE_RPC,
status=action_mod.Action.READY,
inputs={'foo': 'bar'},
@ -157,6 +159,7 @@ class WebhookTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, 'FAKE_CLUSTER', 'DANCE',
name='webhook_01234567',
cluster_id='FAKE_CLUSTER',
cause=consts.CAUSE_RPC,
status=action_mod.Action.READY,
inputs={'kee': 'vee', 'foo': 'bar'},
@ -188,6 +191,7 @@ class WebhookTest(base.SenlinTestCase):
mock_action.assert_called_once_with(
self.ctx, 'FAKE_CLUSTER', 'DANCE',
name='webhook_01234567',
cluster_id='FAKE_CLUSTER',
cause=consts.CAUSE_RPC,
status=action_mod.Action.READY,
inputs={'foo': 'bar'},