From 95b685e85264219e9c81c94cafdb72269f291a8d Mon Sep 17 00:00:00 2001 From: jonnary Date: Wed, 15 Feb 2017 09:20:32 +0800 Subject: [PATCH] Revise action_delete_by_target api This patch revises action_delete_by_target api. It's a prepare for deleting action. partial-blueprint: improve-action-event Change-Id: I70ff9d7bf10869c725021e096733fecb46d181c6 --- senlin/db/api.py | 7 +++- senlin/db/sqlalchemy/api.py | 34 ++++++++++++----- senlin/objects/action.py | 15 ++++++++ senlin/tests/unit/db/test_action_api.py | 50 ++++++++++++++++++++++++- 4 files changed, 93 insertions(+), 13 deletions(-) diff --git a/senlin/db/api.py b/senlin/db/api.py index 499b5761f..08e54d52a 100644 --- a/senlin/db/api.py +++ b/senlin/db/api.py @@ -344,8 +344,11 @@ def action_check_status(context, action_id, timestamp): return IMPL.action_check_status(context, action_id, timestamp) -def action_delete_by_target(context, target, exceptions=None): - return IMPL.action_check_status(context, target, exceptions=exceptions) +def action_delete_by_target(context, target, action=None, + action_excluded=None, status=None): + return IMPL.action_delete_by_target(context, target, action=action, + action_excluded=action_excluded, + status=status) def dependency_add(context, depended, dependent): diff --git a/senlin/db/sqlalchemy/api.py b/senlin/db/sqlalchemy/api.py index d310e5f72..53dea9c15 100644 --- a/senlin/db/sqlalchemy/api.py +++ b/senlin/db/sqlalchemy/api.py @@ -1038,15 +1038,6 @@ def action_check_status(context, action_id, timestamp): return action.status -def action_delete_by_target(context, target, exceptions=None): - with session_for_write() as session: - q = session.query(models.Action).\ - filter(models.Action.target == target) - if exceptions: - q = q.filter(~models.Action.action.in_(exceptions)) - return q.delete(synchronize_session='fetch') - - def dependency_get_depended(context, action_id): with session_for_read() as session: q = session.query(models.ActionDependency).filter_by( @@ -1270,6 +1261,31 @@ def action_delete(context, action_id): session.delete(action) +def action_delete_by_target(context, target, action=None, + action_excluded=None, status=None, + project_safe=True): + if action and action_excluded: + msg = _("action and action_excluded cannot be specified " + "both.") + LOG.warning(msg) + return None + + with session_for_write() as session: + q = session.query(models.Action).\ + filter_by(target=target) + + if project_safe: + q = q.filter_by(project=context.project) + + if action: + q = q.filter(models.Action.action.in_(action)) + if action_excluded: + q = q.filter(~models.Action.action.in_(action_excluded)) + if status: + q = q.filter(models.Action.status.in_(status)) + return q.delete(synchronize_session='fetch') + + # Receivers def receiver_create(context, values): with session_for_write() as session: diff --git a/senlin/objects/action.py b/senlin/objects/action.py index 42fc81e63..a5d98c703 100644 --- a/senlin/objects/action.py +++ b/senlin/objects/action.py @@ -153,6 +153,21 @@ class Action(base.SenlinObject, base.VersionedObjectDictCompat): def delete(cls, context, action_id): db_api.action_delete(context, action_id) + @classmethod + def delete_by_target(cls, context, target, action=None, + action_excluded=None, status=None): + """Delete an action with the target and other given params. + + :param target: The ID of the target cluster/node + :param action: A list of actions to be included. + :param action_excluded: A list of actions to be excluded. + :param status: A list of statuses to be delete filtered. + :return: None. + """ + return db_api.action_delete_by_target(context, target, action=action, + action_excluded=action_excluded, + status=status) + def to_dict(self): if self.id: dep_on = dobj.Dependency.get_depended(self.context, self.id) diff --git a/senlin/tests/unit/db/test_action_api.py b/senlin/tests/unit/db/test_action_api.py index 61225111d..4be64ab16 100644 --- a/senlin/tests/unit/db/test_action_api.py +++ b/senlin/tests/unit/db/test_action_api.py @@ -433,7 +433,21 @@ class DBAPIActionTest(base.SenlinTestCase): actions = db_api.action_get_all(self.ctx) self.assertEqual(3, len(actions)) - def test_action_delete_by_target_with_exceptions(self): + def test_action_delete_by_target_with_action(self): + for name in ['CLUSTER_CREATE', 'CLUSTER_DELETE', 'CLUSTER_DELETE']: + action = _create_action(self.ctx, action=name, target='CLUSTER_ID') + self.assertIsNotNone(action) + + actions = db_api.action_get_all(self.ctx) + self.assertEqual(3, len(actions)) + + db_api.action_delete_by_target(self.ctx, 'CLUSTER_ID', + action=['CLUSTER_DELETE']) + actions = db_api.action_get_all(self.ctx) + self.assertEqual(1, len(actions)) + self.assertEqual('CLUSTER_CREATE', actions[0].action) + + def test_action_delete_by_target_with_action_excluded(self): for name in ['CLUSTER_CREATE', 'CLUSTER_RESIZE', 'CLUSTER_DELETE']: action = _create_action(self.ctx, action=name, target='CLUSTER_ID') self.assertIsNotNone(action) @@ -442,7 +456,39 @@ class DBAPIActionTest(base.SenlinTestCase): self.assertEqual(3, len(actions)) db_api.action_delete_by_target(self.ctx, 'CLUSTER_ID', - ['CLUSTER_DELETE']) + action_excluded=['CLUSTER_DELETE']) actions = db_api.action_get_all(self.ctx) self.assertEqual(1, len(actions)) self.assertEqual('CLUSTER_DELETE', actions[0].action) + + def test_action_delete_by_target_with_status(self): + action1 = _create_action(self.ctx, action='CLUSTER_CREATE', + target='CLUSTER_ID', status='SUCCEEDED') + action2 = _create_action(self.ctx, action='CLUSTER_DELETE', + target='CLUSTER_ID', status='INIT') + self.assertIsNotNone(action1) + self.assertIsNotNone(action2) + + actions = db_api.action_get_all(self.ctx) + self.assertEqual(2, len(actions)) + + db_api.action_delete_by_target(self.ctx, 'CLUSTER_ID', + status=['SUCCEEDED']) + actions = db_api.action_get_all(self.ctx) + self.assertEqual(1, len(actions)) + self.assertEqual('CLUSTER_DELETE', actions[0].action) + + def test_action_delete_by_target_both_specified(self): + for name in ['CLUSTER_CREATE', 'CLUSTER_RESIZE', 'CLUSTER_DELETE']: + action = _create_action(self.ctx, action=name, target='CLUSTER_ID') + self.assertIsNotNone(action) + + actions = db_api.action_get_all(self.ctx) + self.assertEqual(3, len(actions)) + + db_api.action_delete_by_target(self.ctx, 'CLUSTER_ID', + action=['CLUSTER_CREATE'], + action_excluded=['CLUSTER_DELETE']) + + actions = db_api.action_get_all(self.ctx) + self.assertEqual(3, len(actions))