Added action_plan.create|update|delete notifs
In this changeset, I added 3 notifications: - action_plan.create - action_plan.update - action_plan.delete Partially Implements: blueprint action-plan-versioned-notifications-api Change-Id: I8821fc6f47e7486037839d81bed9e28020b02fdd
This commit is contained in:
parent
ea1fd5967a
commit
e51e7e4317
|
@ -0,0 +1,54 @@
|
||||||
|
{
|
||||||
|
"publisher_id": "infra-optim:node0",
|
||||||
|
"payload": {
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"strategy_uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"strategy": {
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"display_name": "test strategy",
|
||||||
|
"name": "TEST",
|
||||||
|
"updated_at": null,
|
||||||
|
"parameters_spec": {},
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"deleted_at": null
|
||||||
|
},
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.name": "StrategyPayload"
|
||||||
|
},
|
||||||
|
"created_at": null,
|
||||||
|
"audit_uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"audit": {
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"audit_type": "ONESHOT",
|
||||||
|
"scope": [],
|
||||||
|
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"goal_uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
|
"strategy_uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
|
||||||
|
"parameters": {},
|
||||||
|
"interval": null,
|
||||||
|
"deleted_at": null,
|
||||||
|
"state": "PENDING",
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"updated_at": null
|
||||||
|
},
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.name": "TerseAuditPayload"
|
||||||
|
},
|
||||||
|
"uuid": "76be87bd-3422-43f9-93a0-e85a577e3061",
|
||||||
|
"global_efficacy": {},
|
||||||
|
"deleted_at": null,
|
||||||
|
"state": "RECOMMENDED",
|
||||||
|
"updated_at": null
|
||||||
|
},
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.name": "ActionPlanCreatePayload"
|
||||||
|
},
|
||||||
|
"priority": "INFO",
|
||||||
|
"message_id": "5148bff1-ea06-4ad6-8e4e-8c85ca5eb629",
|
||||||
|
"event_type": "action_plan.create",
|
||||||
|
"timestamp": "2016-10-18 09:52:05.219414"
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
{
|
||||||
|
"publisher_id": "infra-optim:node0",
|
||||||
|
"timestamp": "2016-10-18 09:52:05.219414",
|
||||||
|
"payload": {
|
||||||
|
"watcher_object.data": {
|
||||||
|
"uuid": "76be87bd-3422-43f9-93a0-e85a577e3061",
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"audit_uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"audit": {
|
||||||
|
"watcher_object.data": {
|
||||||
|
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"goal_uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
|
"strategy_uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
|
||||||
|
"interval": null,
|
||||||
|
"audit_type": "ONESHOT",
|
||||||
|
"scope": [],
|
||||||
|
"updated_at": null,
|
||||||
|
"deleted_at": null,
|
||||||
|
"state": "PENDING",
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"parameters": {}
|
||||||
|
},
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.name": "TerseAuditPayload",
|
||||||
|
"watcher_object.namespace": "watcher"
|
||||||
|
},
|
||||||
|
"global_efficacy": {},
|
||||||
|
"updated_at": null,
|
||||||
|
"deleted_at": null,
|
||||||
|
"strategy_uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"strategy": {
|
||||||
|
"watcher_object.data": {
|
||||||
|
"uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"name": "TEST",
|
||||||
|
"display_name": "test strategy",
|
||||||
|
"deleted_at": null,
|
||||||
|
"updated_at": null,
|
||||||
|
"parameters_spec": {}
|
||||||
|
},
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.name": "StrategyPayload",
|
||||||
|
"watcher_object.namespace": "watcher"
|
||||||
|
},
|
||||||
|
"state": "DELETED"
|
||||||
|
},
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.name": "ActionPlanDeletePayload",
|
||||||
|
"watcher_object.namespace": "watcher"
|
||||||
|
},
|
||||||
|
"event_type": "action_plan.delete",
|
||||||
|
"message_id": "3d137686-a1fd-4683-ab40-c4210aac2140",
|
||||||
|
"priority": "INFO"
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
{
|
||||||
|
"payload": {
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"audit_uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"audit": {
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"audit_type": "ONESHOT",
|
||||||
|
"scope": [],
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"goal_uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
|
"strategy_uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
|
||||||
|
"interval": null,
|
||||||
|
"updated_at": null,
|
||||||
|
"state": "PENDING",
|
||||||
|
"deleted_at": null,
|
||||||
|
"parameters": {}
|
||||||
|
},
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.name": "TerseAuditPayload"
|
||||||
|
},
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"uuid": "76be87bd-3422-43f9-93a0-e85a577e3061",
|
||||||
|
"updated_at": null,
|
||||||
|
"state_update": {
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"old_state": "PENDING",
|
||||||
|
"state": "ONGOING"
|
||||||
|
},
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.name": "ActionPlanStateUpdatePayload"
|
||||||
|
},
|
||||||
|
"state": "ONGOING",
|
||||||
|
"deleted_at": null,
|
||||||
|
"strategy_uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"strategy": {
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"name": "TEST",
|
||||||
|
"uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"display_name": "test strategy",
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"updated_at": null,
|
||||||
|
"deleted_at": null,
|
||||||
|
"parameters_spec": {}
|
||||||
|
},
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.name": "StrategyPayload"
|
||||||
|
},
|
||||||
|
"global_efficacy": {}
|
||||||
|
},
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.name": "ActionPlanUpdatePayload"
|
||||||
|
},
|
||||||
|
"publisher_id": "infra-optim:node0",
|
||||||
|
"priority": "INFO",
|
||||||
|
"timestamp": "2016-10-18 09:52:05.219414",
|
||||||
|
"event_type": "action_plan.update",
|
||||||
|
"message_id": "0a8a7329-fd5a-4ec6-97d7-2b776ce51a4c"
|
||||||
|
}
|
|
@ -10,6 +10,7 @@
|
||||||
"state": "PENDING",
|
"state": "PENDING",
|
||||||
"updated_at": null,
|
"updated_at": null,
|
||||||
"deleted_at": null,
|
"deleted_at": null,
|
||||||
|
"goal_uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
"goal": {
|
"goal": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
|
@ -26,6 +27,7 @@
|
||||||
},
|
},
|
||||||
"interval": null,
|
"interval": null,
|
||||||
"scope": [],
|
"scope": [],
|
||||||
|
"strategy_uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
|
||||||
"strategy": {
|
"strategy": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"parameters_spec": {
|
"parameters_spec": {
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
"state": "DELETED",
|
"state": "DELETED",
|
||||||
"updated_at": null,
|
"updated_at": null,
|
||||||
"deleted_at": null,
|
"deleted_at": null,
|
||||||
|
"goal_uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
"goal": {
|
"goal": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
|
@ -26,6 +27,7 @@
|
||||||
},
|
},
|
||||||
"interval": null,
|
"interval": null,
|
||||||
"scope": [],
|
"scope": [],
|
||||||
|
"strategy_uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
|
||||||
"strategy": {
|
"strategy": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"parameters_spec": {
|
"parameters_spec": {
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
"updated_at": null,
|
"updated_at": null,
|
||||||
"deleted_at": null,
|
"deleted_at": null,
|
||||||
"fault": null,
|
"fault": null,
|
||||||
|
"goal_uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
"goal": {
|
"goal": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
|
@ -27,6 +28,7 @@
|
||||||
},
|
},
|
||||||
"interval": null,
|
"interval": null,
|
||||||
"scope": [],
|
"scope": [],
|
||||||
|
"strategy_uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
|
||||||
"strategy": {
|
"strategy": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"parameters_spec": {
|
"parameters_spec": {
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
"watcher_object.namespace": "watcher",
|
"watcher_object.namespace": "watcher",
|
||||||
"watcher_object.version": "1.0"
|
"watcher_object.version": "1.0"
|
||||||
},
|
},
|
||||||
|
"goal_uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
"goal": {
|
"goal": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
|
@ -37,6 +38,7 @@
|
||||||
},
|
},
|
||||||
"interval": null,
|
"interval": null,
|
||||||
"scope": [],
|
"scope": [],
|
||||||
|
"strategy_uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
|
||||||
"strategy": {
|
"strategy": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"parameters_spec": {
|
"parameters_spec": {
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
"updated_at": null,
|
"updated_at": null,
|
||||||
"deleted_at": null,
|
"deleted_at": null,
|
||||||
"fault": null,
|
"fault": null,
|
||||||
|
"goal_uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
"goal": {
|
"goal": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
|
@ -27,6 +28,7 @@
|
||||||
},
|
},
|
||||||
"interval": null,
|
"interval": null,
|
||||||
"scope": [],
|
"scope": [],
|
||||||
|
"strategy_uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
|
||||||
"strategy": {
|
"strategy": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"parameters_spec": {
|
"parameters_spec": {
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
"updated_at": null,
|
"updated_at": null,
|
||||||
"deleted_at": null,
|
"deleted_at": null,
|
||||||
"fault": null,
|
"fault": null,
|
||||||
|
"goal_uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
"goal": {
|
"goal": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
|
@ -27,6 +28,7 @@
|
||||||
},
|
},
|
||||||
"interval": null,
|
"interval": null,
|
||||||
"scope": [],
|
"scope": [],
|
||||||
|
"strategy_uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
|
||||||
"strategy": {
|
"strategy": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"parameters_spec": {
|
"parameters_spec": {
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
"watcher_object.namespace": "watcher",
|
"watcher_object.namespace": "watcher",
|
||||||
"watcher_object.version": "1.0"
|
"watcher_object.version": "1.0"
|
||||||
},
|
},
|
||||||
|
"goal_uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
"goal": {
|
"goal": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
|
@ -37,6 +38,7 @@
|
||||||
},
|
},
|
||||||
"interval": null,
|
"interval": null,
|
||||||
"scope": [],
|
"scope": [],
|
||||||
|
"strategy_uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
|
||||||
"strategy": {
|
"strategy": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"parameters_spec": {
|
"parameters_spec": {
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
"updated_at": null,
|
"updated_at": null,
|
||||||
"deleted_at": null,
|
"deleted_at": null,
|
||||||
"fault": null,
|
"fault": null,
|
||||||
|
"goal_uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
"goal": {
|
"goal": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
"uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
|
@ -27,6 +28,7 @@
|
||||||
},
|
},
|
||||||
"interval": null,
|
"interval": null,
|
||||||
"scope": [],
|
"scope": [],
|
||||||
|
"strategy_uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
|
||||||
"strategy": {
|
"strategy": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"parameters_spec": {
|
"parameters_spec": {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
"payload": {
|
"payload": {
|
||||||
"watcher_object.name": "AuditUpdatePayload",
|
"watcher_object.name": "AuditUpdatePayload",
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
|
"strategy_uuid": "75234dfe-87e3-4f11-a0e0-3c3305d86a39",
|
||||||
"strategy": {
|
"strategy": {
|
||||||
"watcher_object.name": "StrategyPayload",
|
"watcher_object.name": "StrategyPayload",
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
|
@ -36,6 +37,7 @@
|
||||||
"scope": [],
|
"scope": [],
|
||||||
"created_at": "2016-11-04T16:51:21Z",
|
"created_at": "2016-11-04T16:51:21Z",
|
||||||
"uuid": "f1e0d912-afd9-4bf2-91ef-c99cd08cc1ef",
|
"uuid": "f1e0d912-afd9-4bf2-91ef-c99cd08cc1ef",
|
||||||
|
"goal_uuid": "bc830f84-8ae3-4fc6-8bc6-e3dd15e8b49a",
|
||||||
"goal": {
|
"goal": {
|
||||||
"watcher_object.name": "GoalPayload",
|
"watcher_object.name": "GoalPayload",
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
|
|
|
@ -455,7 +455,8 @@ class ActionPlansController(rest.RestController):
|
||||||
:param action_plan_uuid: UUID of a action.
|
:param action_plan_uuid: UUID of a action.
|
||||||
"""
|
"""
|
||||||
context = pecan.request.context
|
context = pecan.request.context
|
||||||
action_plan = api_utils.get_resource('ActionPlan', action_plan_uuid)
|
action_plan = api_utils.get_resource(
|
||||||
|
'ActionPlan', action_plan_uuid, eager=True)
|
||||||
policy.enforce(context, 'action_plan:delete', action_plan,
|
policy.enforce(context, 'action_plan:delete', action_plan,
|
||||||
action='action_plan:delete')
|
action='action_plan:delete')
|
||||||
|
|
||||||
|
@ -474,8 +475,8 @@ class ActionPlansController(rest.RestController):
|
||||||
raise exception.OperationNotPermitted
|
raise exception.OperationNotPermitted
|
||||||
|
|
||||||
context = pecan.request.context
|
context = pecan.request.context
|
||||||
action_plan_to_update = api_utils.get_resource('ActionPlan',
|
action_plan_to_update = api_utils.get_resource(
|
||||||
action_plan_uuid)
|
'ActionPlan', action_plan_uuid, eager=True)
|
||||||
policy.enforce(context, 'action_plan:update', action_plan_to_update,
|
policy.enforce(context, 'action_plan:update', action_plan_to_update,
|
||||||
action='action_plan:update')
|
action='action_plan:update')
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,8 @@ class DefaultActionPlanHandler(base.BaseActionPlanHandler):
|
||||||
self.action_plan_uuid = action_plan_uuid
|
self.action_plan_uuid = action_plan_uuid
|
||||||
|
|
||||||
def update_action_plan(self, uuid, state):
|
def update_action_plan(self, uuid, state):
|
||||||
action_plan = objects.ActionPlan.get_by_uuid(self.ctx, uuid)
|
action_plan = objects.ActionPlan.get_by_uuid(
|
||||||
|
self.ctx, uuid, eager=True)
|
||||||
action_plan.state = state
|
action_plan.state = state
|
||||||
action_plan.save()
|
action_plan.save()
|
||||||
|
|
||||||
|
|
|
@ -174,6 +174,14 @@ class EagerlyLoadedAuditRequired(InvalidAudit):
|
||||||
msg_fmt = _("Audit %(audit)s was not eagerly loaded")
|
msg_fmt = _("Audit %(audit)s was not eagerly loaded")
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidActionPlan(Invalid):
|
||||||
|
msg_fmt = _("Action plan %(action_plan)s is invalid")
|
||||||
|
|
||||||
|
|
||||||
|
class EagerlyLoadedActionPlanRequired(InvalidActionPlan):
|
||||||
|
msg_fmt = _("Action plan %(action_plan)s was not eagerly loaded")
|
||||||
|
|
||||||
|
|
||||||
class InvalidUUID(Invalid):
|
class InvalidUUID(Invalid):
|
||||||
msg_fmt = _("Expected a uuid but received %(uuid)s")
|
msg_fmt = _("Expected a uuid but received %(uuid)s")
|
||||||
|
|
||||||
|
|
|
@ -350,7 +350,7 @@ class Syncer(object):
|
||||||
for strategy_id, synced_strategy in self.strategy_mapping.items():
|
for strategy_id, synced_strategy in self.strategy_mapping.items():
|
||||||
filters = {"strategy_id": strategy_id}
|
filters = {"strategy_id": strategy_id}
|
||||||
stale_action_plans = objects.ActionPlan.list(
|
stale_action_plans = objects.ActionPlan.list(
|
||||||
self.ctx, filters=filters)
|
self.ctx, filters=filters, eager=True)
|
||||||
|
|
||||||
# Update strategy IDs for all stale action plans (w/o saving)
|
# Update strategy IDs for all stale action plans (w/o saving)
|
||||||
for action_plan in stale_action_plans:
|
for action_plan in stale_action_plans:
|
||||||
|
@ -369,7 +369,7 @@ class Syncer(object):
|
||||||
for audit_id, synced_audit in self.stale_audits_map.items():
|
for audit_id, synced_audit in self.stale_audits_map.items():
|
||||||
filters = {"audit_id": audit_id}
|
filters = {"audit_id": audit_id}
|
||||||
stale_action_plans = objects.ActionPlan.list(
|
stale_action_plans = objects.ActionPlan.list(
|
||||||
self.ctx, filters=filters)
|
self.ctx, filters=filters, eager=True)
|
||||||
|
|
||||||
# Update audit IDs for all stale action plans (w/o saving)
|
# Update audit IDs for all stale action plans (w/o saving)
|
||||||
for action_plan in stale_action_plans:
|
for action_plan in stale_action_plans:
|
||||||
|
@ -448,7 +448,7 @@ class Syncer(object):
|
||||||
audit.id].state = objects.audit.State.CANCELLED
|
audit.id].state = objects.audit.State.CANCELLED
|
||||||
|
|
||||||
stale_action_plans = objects.ActionPlan.list(
|
stale_action_plans = objects.ActionPlan.list(
|
||||||
self.ctx, filters=filters)
|
self.ctx, filters=filters, eager=True)
|
||||||
for action_plan in stale_action_plans:
|
for action_plan in stale_action_plans:
|
||||||
LOG.warning(
|
LOG.warning(
|
||||||
_LW("Action Plan '%(action_plan)s' references a "
|
_LW("Action Plan '%(action_plan)s' references a "
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
# need to be changed after we moved these function inside the package
|
# need to be changed after we moved these function inside the package
|
||||||
# Todo(gibi): remove these imports after legacy notifications using these are
|
# Todo(gibi): remove these imports after legacy notifications using these are
|
||||||
# transformed to versioned notifications
|
# transformed to versioned notifications
|
||||||
|
from watcher.notifications import action_plan # noqa
|
||||||
from watcher.notifications import audit # noqa
|
from watcher.notifications import audit # noqa
|
||||||
from watcher.notifications import exception # noqa
|
from watcher.notifications import exception # noqa
|
||||||
from watcher.notifications import goal # noqa
|
from watcher.notifications import goal # noqa
|
||||||
|
|
|
@ -0,0 +1,267 @@
|
||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
# Copyright (c) 2017 b<>com
|
||||||
|
#
|
||||||
|
# Authors: Vincent FRANCOISE <vincent.francoise@b-com.com>
|
||||||
|
#
|
||||||
|
# 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 oslo_config import cfg
|
||||||
|
|
||||||
|
from watcher.common import context as wcontext
|
||||||
|
from watcher.common import exception
|
||||||
|
from watcher.notifications import audit as audit_notifications
|
||||||
|
from watcher.notifications import base as notificationbase
|
||||||
|
from watcher.notifications import strategy as strategy_notifications
|
||||||
|
from watcher import objects
|
||||||
|
from watcher.objects import base
|
||||||
|
from watcher.objects import fields as wfields
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
|
@base.WatcherObjectRegistry.register_notification
|
||||||
|
class ActionPlanPayload(notificationbase.NotificationPayloadBase):
|
||||||
|
SCHEMA = {
|
||||||
|
'uuid': ('action_plan', 'uuid'),
|
||||||
|
|
||||||
|
'state': ('action_plan', 'state'),
|
||||||
|
'global_efficacy': ('action_plan', 'global_efficacy'),
|
||||||
|
'audit_uuid': ('audit', 'uuid'),
|
||||||
|
'strategy_uuid': ('strategy', 'uuid'),
|
||||||
|
|
||||||
|
'created_at': ('action_plan', 'created_at'),
|
||||||
|
'updated_at': ('action_plan', 'updated_at'),
|
||||||
|
'deleted_at': ('action_plan', 'deleted_at'),
|
||||||
|
}
|
||||||
|
|
||||||
|
# Version 1.0: Initial version
|
||||||
|
VERSION = '1.0'
|
||||||
|
|
||||||
|
fields = {
|
||||||
|
'uuid': wfields.UUIDField(),
|
||||||
|
'state': wfields.StringField(),
|
||||||
|
'global_efficacy': wfields.FlexibleDictField(nullable=True),
|
||||||
|
'audit_uuid': wfields.UUIDField(),
|
||||||
|
'strategy_uuid': wfields.UUIDField(),
|
||||||
|
'audit': wfields.ObjectField('TerseAuditPayload'),
|
||||||
|
'strategy': wfields.ObjectField('StrategyPayload'),
|
||||||
|
|
||||||
|
'created_at': wfields.DateTimeField(nullable=True),
|
||||||
|
'updated_at': wfields.DateTimeField(nullable=True),
|
||||||
|
'deleted_at': wfields.DateTimeField(nullable=True),
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, action_plan, audit, strategy, **kwargs):
|
||||||
|
super(ActionPlanPayload, self).__init__(
|
||||||
|
audit=audit, strategy=strategy, **kwargs)
|
||||||
|
self.populate_schema(
|
||||||
|
action_plan=action_plan, audit=audit, strategy=strategy)
|
||||||
|
|
||||||
|
|
||||||
|
@base.WatcherObjectRegistry.register_notification
|
||||||
|
class ActionPlanStateUpdatePayload(notificationbase.NotificationPayloadBase):
|
||||||
|
# Version 1.0: Initial version
|
||||||
|
VERSION = '1.0'
|
||||||
|
|
||||||
|
fields = {
|
||||||
|
'old_state': wfields.StringField(nullable=True),
|
||||||
|
'state': wfields.StringField(nullable=True),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@base.WatcherObjectRegistry.register_notification
|
||||||
|
class ActionPlanCreatePayload(ActionPlanPayload):
|
||||||
|
# Version 1.0: Initial version
|
||||||
|
VERSION = '1.0'
|
||||||
|
fields = {}
|
||||||
|
|
||||||
|
def __init__(self, action_plan, audit, strategy):
|
||||||
|
super(ActionPlanCreatePayload, self).__init__(
|
||||||
|
action_plan=action_plan,
|
||||||
|
audit=audit,
|
||||||
|
strategy=strategy)
|
||||||
|
|
||||||
|
|
||||||
|
@base.WatcherObjectRegistry.register_notification
|
||||||
|
class ActionPlanUpdatePayload(ActionPlanPayload):
|
||||||
|
# Version 1.0: Initial version
|
||||||
|
VERSION = '1.0'
|
||||||
|
fields = {
|
||||||
|
'state_update': wfields.ObjectField('ActionPlanStateUpdatePayload'),
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, action_plan, state_update, audit, strategy):
|
||||||
|
super(ActionPlanUpdatePayload, self).__init__(
|
||||||
|
action_plan=action_plan,
|
||||||
|
state_update=state_update,
|
||||||
|
audit=audit,
|
||||||
|
strategy=strategy)
|
||||||
|
|
||||||
|
|
||||||
|
@base.WatcherObjectRegistry.register_notification
|
||||||
|
class ActionPlanActionPayload(ActionPlanPayload):
|
||||||
|
# Version 1.0: Initial version
|
||||||
|
VERSION = '1.0'
|
||||||
|
fields = {
|
||||||
|
'fault': wfields.ObjectField('ExceptionPayload', nullable=True),
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, action_plan, audit, strategy, **kwargs):
|
||||||
|
super(ActionPlanActionPayload, self).__init__(
|
||||||
|
action_plan=action_plan,
|
||||||
|
audit=audit,
|
||||||
|
strategy=strategy,
|
||||||
|
**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@base.WatcherObjectRegistry.register_notification
|
||||||
|
class ActionPlanDeletePayload(ActionPlanPayload):
|
||||||
|
# Version 1.0: Initial version
|
||||||
|
VERSION = '1.0'
|
||||||
|
fields = {}
|
||||||
|
|
||||||
|
def __init__(self, action_plan, audit, strategy):
|
||||||
|
super(ActionPlanDeletePayload, self).__init__(
|
||||||
|
action_plan=action_plan,
|
||||||
|
audit=audit,
|
||||||
|
strategy=strategy)
|
||||||
|
|
||||||
|
|
||||||
|
@notificationbase.notification_sample('action_plan-create.json')
|
||||||
|
@base.WatcherObjectRegistry.register_notification
|
||||||
|
class ActionPlanCreateNotification(notificationbase.NotificationBase):
|
||||||
|
# Version 1.0: Initial version
|
||||||
|
VERSION = '1.0'
|
||||||
|
|
||||||
|
fields = {
|
||||||
|
'payload': wfields.ObjectField('ActionPlanCreatePayload')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@notificationbase.notification_sample('action_plan-update.json')
|
||||||
|
@base.WatcherObjectRegistry.register_notification
|
||||||
|
class ActionPlanUpdateNotification(notificationbase.NotificationBase):
|
||||||
|
# Version 1.0: Initial version
|
||||||
|
VERSION = '1.0'
|
||||||
|
|
||||||
|
fields = {
|
||||||
|
'payload': wfields.ObjectField('ActionPlanUpdatePayload')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@notificationbase.notification_sample('action_plan-delete.json')
|
||||||
|
@base.WatcherObjectRegistry.register_notification
|
||||||
|
class ActionPlanDeleteNotification(notificationbase.NotificationBase):
|
||||||
|
# Version 1.0: Initial version
|
||||||
|
VERSION = '1.0'
|
||||||
|
|
||||||
|
fields = {
|
||||||
|
'payload': wfields.ObjectField('ActionPlanDeletePayload')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _get_common_payload(action_plan):
|
||||||
|
audit = None
|
||||||
|
strategy = None
|
||||||
|
try:
|
||||||
|
audit = action_plan.audit
|
||||||
|
strategy = action_plan.strategy
|
||||||
|
except NotImplementedError:
|
||||||
|
raise exception.EagerlyLoadedActionPlanRequired(
|
||||||
|
action_plan=action_plan.uuid)
|
||||||
|
|
||||||
|
goal = objects.Goal.get(
|
||||||
|
wcontext.make_context(show_deleted=True), audit.goal_id)
|
||||||
|
audit_payload = audit_notifications.TerseAuditPayload(
|
||||||
|
audit=audit, goal_uuid=goal.uuid)
|
||||||
|
|
||||||
|
strategy_payload = strategy_notifications.StrategyPayload(
|
||||||
|
strategy=strategy)
|
||||||
|
|
||||||
|
return audit_payload, strategy_payload
|
||||||
|
|
||||||
|
|
||||||
|
def send_create(context, action_plan, service='infra-optim', host=None):
|
||||||
|
"""Emit an action_plan.create notification."""
|
||||||
|
audit_payload, strategy_payload = _get_common_payload(action_plan)
|
||||||
|
|
||||||
|
versioned_payload = ActionPlanCreatePayload(
|
||||||
|
action_plan=action_plan,
|
||||||
|
audit=audit_payload,
|
||||||
|
strategy=strategy_payload,
|
||||||
|
)
|
||||||
|
|
||||||
|
notification = ActionPlanCreateNotification(
|
||||||
|
priority=wfields.NotificationPriority.INFO,
|
||||||
|
event_type=notificationbase.EventType(
|
||||||
|
object='action_plan',
|
||||||
|
action=wfields.NotificationAction.CREATE),
|
||||||
|
publisher=notificationbase.NotificationPublisher(
|
||||||
|
host=host or CONF.host,
|
||||||
|
binary=service),
|
||||||
|
payload=versioned_payload)
|
||||||
|
|
||||||
|
notification.emit(context)
|
||||||
|
|
||||||
|
|
||||||
|
def send_update(context, action_plan, service='infra-optim',
|
||||||
|
host=None, old_state=None):
|
||||||
|
"""Emit an action_plan.update notification."""
|
||||||
|
audit_payload, strategy_payload = _get_common_payload(action_plan)
|
||||||
|
|
||||||
|
state_update = ActionPlanStateUpdatePayload(
|
||||||
|
old_state=old_state,
|
||||||
|
state=action_plan.state if old_state else None)
|
||||||
|
|
||||||
|
versioned_payload = ActionPlanUpdatePayload(
|
||||||
|
action_plan=action_plan,
|
||||||
|
state_update=state_update,
|
||||||
|
audit=audit_payload,
|
||||||
|
strategy=strategy_payload,
|
||||||
|
)
|
||||||
|
|
||||||
|
notification = ActionPlanUpdateNotification(
|
||||||
|
priority=wfields.NotificationPriority.INFO,
|
||||||
|
event_type=notificationbase.EventType(
|
||||||
|
object='action_plan',
|
||||||
|
action=wfields.NotificationAction.UPDATE),
|
||||||
|
publisher=notificationbase.NotificationPublisher(
|
||||||
|
host=host or CONF.host,
|
||||||
|
binary=service),
|
||||||
|
payload=versioned_payload)
|
||||||
|
|
||||||
|
notification.emit(context)
|
||||||
|
|
||||||
|
|
||||||
|
def send_delete(context, action_plan, service='infra-optim', host=None):
|
||||||
|
"""Emit an action_plan.delete notification."""
|
||||||
|
audit_payload, strategy_payload = _get_common_payload(action_plan)
|
||||||
|
|
||||||
|
versioned_payload = ActionPlanDeletePayload(
|
||||||
|
action_plan=action_plan,
|
||||||
|
audit=audit_payload,
|
||||||
|
strategy=strategy_payload,
|
||||||
|
)
|
||||||
|
|
||||||
|
notification = ActionPlanDeleteNotification(
|
||||||
|
priority=wfields.NotificationPriority.INFO,
|
||||||
|
event_type=notificationbase.EventType(
|
||||||
|
object='action_plan',
|
||||||
|
action=wfields.NotificationAction.DELETE),
|
||||||
|
publisher=notificationbase.NotificationPublisher(
|
||||||
|
host=host or CONF.host,
|
||||||
|
binary=service),
|
||||||
|
payload=versioned_payload)
|
||||||
|
|
||||||
|
notification.emit(context)
|
|
@ -30,7 +30,7 @@ CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
@base.WatcherObjectRegistry.register_notification
|
@base.WatcherObjectRegistry.register_notification
|
||||||
class AuditPayload(notificationbase.NotificationPayloadBase):
|
class TerseAuditPayload(notificationbase.NotificationPayloadBase):
|
||||||
SCHEMA = {
|
SCHEMA = {
|
||||||
'uuid': ('audit', 'uuid'),
|
'uuid': ('audit', 'uuid'),
|
||||||
|
|
||||||
|
@ -57,19 +57,54 @@ class AuditPayload(notificationbase.NotificationPayloadBase):
|
||||||
'scope': wfields.FlexibleListOfDictField(nullable=True),
|
'scope': wfields.FlexibleListOfDictField(nullable=True),
|
||||||
'goal_uuid': wfields.UUIDField(),
|
'goal_uuid': wfields.UUIDField(),
|
||||||
'strategy_uuid': wfields.UUIDField(nullable=True),
|
'strategy_uuid': wfields.UUIDField(nullable=True),
|
||||||
'goal': wfields.ObjectField('GoalPayload'),
|
|
||||||
'strategy': wfields.ObjectField('StrategyPayload', nullable=True),
|
|
||||||
|
|
||||||
'created_at': wfields.DateTimeField(nullable=True),
|
'created_at': wfields.DateTimeField(nullable=True),
|
||||||
'updated_at': wfields.DateTimeField(nullable=True),
|
'updated_at': wfields.DateTimeField(nullable=True),
|
||||||
'deleted_at': wfields.DateTimeField(nullable=True),
|
'deleted_at': wfields.DateTimeField(nullable=True),
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, audit, **kwargs):
|
def __init__(self, audit, goal_uuid, strategy_uuid=None, **kwargs):
|
||||||
super(AuditPayload, self).__init__(**kwargs)
|
super(TerseAuditPayload, self).__init__(
|
||||||
|
goal_uuid=goal_uuid, strategy_uuid=strategy_uuid, **kwargs)
|
||||||
self.populate_schema(audit=audit)
|
self.populate_schema(audit=audit)
|
||||||
|
|
||||||
|
|
||||||
|
@base.WatcherObjectRegistry.register_notification
|
||||||
|
class AuditPayload(TerseAuditPayload):
|
||||||
|
SCHEMA = {
|
||||||
|
'uuid': ('audit', 'uuid'),
|
||||||
|
|
||||||
|
'audit_type': ('audit', 'audit_type'),
|
||||||
|
'state': ('audit', 'state'),
|
||||||
|
'parameters': ('audit', 'parameters'),
|
||||||
|
'interval': ('audit', 'interval'),
|
||||||
|
'scope': ('audit', 'scope'),
|
||||||
|
|
||||||
|
'created_at': ('audit', 'created_at'),
|
||||||
|
'updated_at': ('audit', 'updated_at'),
|
||||||
|
'deleted_at': ('audit', 'deleted_at'),
|
||||||
|
}
|
||||||
|
|
||||||
|
# Version 1.0: Initial version
|
||||||
|
VERSION = '1.0'
|
||||||
|
|
||||||
|
fields = {
|
||||||
|
'goal': wfields.ObjectField('GoalPayload'),
|
||||||
|
'strategy': wfields.ObjectField('StrategyPayload', nullable=True),
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, audit, goal, strategy=None, **kwargs):
|
||||||
|
if not kwargs.get('goal_uuid'):
|
||||||
|
kwargs['goal_uuid'] = goal.uuid
|
||||||
|
|
||||||
|
if strategy and not kwargs.get('strategy_uuid'):
|
||||||
|
kwargs['strategy_uuid'] = strategy.uuid
|
||||||
|
|
||||||
|
super(AuditPayload, self).__init__(
|
||||||
|
audit=audit, goal=goal,
|
||||||
|
strategy=strategy, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
@base.WatcherObjectRegistry.register_notification
|
@base.WatcherObjectRegistry.register_notification
|
||||||
class AuditStateUpdatePayload(notificationbase.NotificationPayloadBase):
|
class AuditStateUpdatePayload(notificationbase.NotificationPayloadBase):
|
||||||
# Version 1.0: Initial version
|
# Version 1.0: Initial version
|
||||||
|
@ -91,6 +126,7 @@ class AuditCreatePayload(AuditPayload):
|
||||||
super(AuditCreatePayload, self).__init__(
|
super(AuditCreatePayload, self).__init__(
|
||||||
audit=audit,
|
audit=audit,
|
||||||
goal=goal,
|
goal=goal,
|
||||||
|
goal_uuid=goal.uuid,
|
||||||
strategy=strategy)
|
strategy=strategy)
|
||||||
|
|
||||||
|
|
||||||
|
@ -107,6 +143,7 @@ class AuditUpdatePayload(AuditPayload):
|
||||||
audit=audit,
|
audit=audit,
|
||||||
state_update=state_update,
|
state_update=state_update,
|
||||||
goal=goal,
|
goal=goal,
|
||||||
|
goal_uuid=goal.uuid,
|
||||||
strategy=strategy)
|
strategy=strategy)
|
||||||
|
|
||||||
|
|
||||||
|
@ -122,6 +159,7 @@ class AuditActionPayload(AuditPayload):
|
||||||
super(AuditActionPayload, self).__init__(
|
super(AuditActionPayload, self).__init__(
|
||||||
audit=audit,
|
audit=audit,
|
||||||
goal=goal,
|
goal=goal,
|
||||||
|
goal_uuid=goal.uuid,
|
||||||
strategy=strategy,
|
strategy=strategy,
|
||||||
**kwargs)
|
**kwargs)
|
||||||
|
|
||||||
|
@ -136,6 +174,7 @@ class AuditDeletePayload(AuditPayload):
|
||||||
super(AuditDeletePayload, self).__init__(
|
super(AuditDeletePayload, self).__init__(
|
||||||
audit=audit,
|
audit=audit,
|
||||||
goal=goal,
|
goal=goal,
|
||||||
|
goal_uuid=goal.uuid,
|
||||||
strategy=strategy)
|
strategy=strategy)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
from oslo_log import log
|
||||||
|
|
||||||
from watcher.common import exception
|
from watcher.common import exception
|
||||||
from watcher.common import rpc
|
from watcher.common import rpc
|
||||||
|
@ -20,6 +21,7 @@ from watcher.objects import base
|
||||||
from watcher.objects import fields as wfields
|
from watcher.objects import fields as wfields
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
# Definition of notification levels in increasing order of severity
|
# Definition of notification levels in increasing order of severity
|
||||||
NOTIFY_LEVELS = {
|
NOTIFY_LEVELS = {
|
||||||
|
@ -59,7 +61,8 @@ class EventType(NotificationObject):
|
||||||
# Version 1.0: Initial version
|
# Version 1.0: Initial version
|
||||||
# Version 1.1: Added STRATEGY action in NotificationAction enum
|
# Version 1.1: Added STRATEGY action in NotificationAction enum
|
||||||
# Version 1.2: Added PLANNER action in NotificationAction enum
|
# Version 1.2: Added PLANNER action in NotificationAction enum
|
||||||
VERSION = '1.2'
|
# Version 1.3: Added EXECUTION action in NotificationAction enum
|
||||||
|
VERSION = '1.3'
|
||||||
|
|
||||||
fields = {
|
fields = {
|
||||||
'object': wfields.StringField(),
|
'object': wfields.StringField(),
|
||||||
|
@ -171,6 +174,7 @@ class NotificationBase(NotificationObject):
|
||||||
def _emit(self, context, event_type, publisher_id, payload):
|
def _emit(self, context, event_type, publisher_id, payload):
|
||||||
notifier = rpc.get_notifier(publisher_id)
|
notifier = rpc.get_notifier(publisher_id)
|
||||||
notify = getattr(notifier, self.priority)
|
notify = getattr(notifier, self.priority)
|
||||||
|
LOG.debug("Emitting notification `%s`", event_type)
|
||||||
notify(context, event_type=event_type, payload=payload)
|
notify(context, event_type=event_type, payload=payload)
|
||||||
|
|
||||||
def emit(self, context):
|
def emit(self, context):
|
||||||
|
|
|
@ -72,6 +72,7 @@ state may be one of the following:
|
||||||
from watcher.common import exception
|
from watcher.common import exception
|
||||||
from watcher.common import utils
|
from watcher.common import utils
|
||||||
from watcher.db import api as db_api
|
from watcher.db import api as db_api
|
||||||
|
from watcher import notifications
|
||||||
from watcher import objects
|
from watcher import objects
|
||||||
from watcher.objects import base
|
from watcher.objects import base
|
||||||
from watcher.objects import fields as wfields
|
from watcher.objects import fields as wfields
|
||||||
|
@ -117,6 +118,39 @@ class ActionPlan(base.WatcherPersistentObject, base.WatcherObject,
|
||||||
'strategy': (objects.Strategy, 'strategy_id'),
|
'strategy': (objects.Strategy, 'strategy_id'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Proxified field so we can keep the previous value after an update
|
||||||
|
_state = None
|
||||||
|
_old_state = None
|
||||||
|
|
||||||
|
# NOTE(v-francoise): The way oslo.versionedobjects works is by using a
|
||||||
|
# __new__ that will automatically create the attributes referenced in
|
||||||
|
# fields. These attributes are properties that raise an exception if no
|
||||||
|
# value has been assigned, which means that they store the actual field
|
||||||
|
# value in an "_obj_%(field)s" attribute. So because we want to proxify a
|
||||||
|
# value that is already proxified, we have to do what you see below.
|
||||||
|
@property
|
||||||
|
def _obj_state(self):
|
||||||
|
return self._state
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _obj_old_state(self):
|
||||||
|
return self._old_state
|
||||||
|
|
||||||
|
@property
|
||||||
|
def old_state(self):
|
||||||
|
return self._old_state
|
||||||
|
|
||||||
|
@_obj_old_state.setter
|
||||||
|
def _obj_old_state(self, value):
|
||||||
|
self._old_state = value
|
||||||
|
|
||||||
|
@_obj_state.setter
|
||||||
|
def _obj_state(self, value):
|
||||||
|
if self._old_state is None and self._state is None:
|
||||||
|
self._state = value
|
||||||
|
else:
|
||||||
|
self._old_state, self._state = self._state, value
|
||||||
|
|
||||||
@base.remotable_classmethod
|
@base.remotable_classmethod
|
||||||
def get(cls, context, action_plan_id, eager=False):
|
def get(cls, context, action_plan_id, eager=False):
|
||||||
"""Find a action_plan based on its id or uuid and return a Action object.
|
"""Find a action_plan based on its id or uuid and return a Action object.
|
||||||
|
@ -198,6 +232,11 @@ class ActionPlan(base.WatcherPersistentObject, base.WatcherObject,
|
||||||
# notifications containing information about the related relationships
|
# notifications containing information about the related relationships
|
||||||
self._from_db_object(self, db_action_plan, eager=True)
|
self._from_db_object(self, db_action_plan, eager=True)
|
||||||
|
|
||||||
|
def _notify():
|
||||||
|
notifications.action_plan.send_create(self._context, self)
|
||||||
|
|
||||||
|
_notify()
|
||||||
|
|
||||||
@base.remotable
|
@base.remotable
|
||||||
def destroy(self):
|
def destroy(self):
|
||||||
"""Delete the action plan from the DB"""
|
"""Delete the action plan from the DB"""
|
||||||
|
@ -221,8 +260,16 @@ class ActionPlan(base.WatcherPersistentObject, base.WatcherObject,
|
||||||
"""
|
"""
|
||||||
updates = self.obj_get_changes()
|
updates = self.obj_get_changes()
|
||||||
db_obj = self.dbapi.update_action_plan(self.uuid, updates)
|
db_obj = self.dbapi.update_action_plan(self.uuid, updates)
|
||||||
obj = self._from_db_object(self, db_obj, eager=False)
|
obj = self._from_db_object(
|
||||||
|
self.__class__(self._context), db_obj, eager=False)
|
||||||
self.obj_refresh(obj)
|
self.obj_refresh(obj)
|
||||||
|
|
||||||
|
def _notify():
|
||||||
|
notifications.action_plan.send_update(
|
||||||
|
self._context, self, old_state=self.old_state)
|
||||||
|
|
||||||
|
_notify()
|
||||||
|
|
||||||
self.obj_reset_changes()
|
self.obj_reset_changes()
|
||||||
|
|
||||||
@base.remotable
|
@base.remotable
|
||||||
|
@ -262,3 +309,8 @@ class ActionPlan(base.WatcherPersistentObject, base.WatcherObject,
|
||||||
obj = self._from_db_object(
|
obj = self._from_db_object(
|
||||||
self.__class__(self._context), db_obj, eager=False)
|
self.__class__(self._context), db_obj, eager=False)
|
||||||
self.obj_refresh(obj)
|
self.obj_refresh(obj)
|
||||||
|
|
||||||
|
def _notify():
|
||||||
|
notifications.action_plan.send_delete(self._context, self)
|
||||||
|
|
||||||
|
_notify()
|
||||||
|
|
|
@ -128,8 +128,9 @@ class NotificationAction(BaseWatcherEnum):
|
||||||
|
|
||||||
STRATEGY = 'strategy'
|
STRATEGY = 'strategy'
|
||||||
PLANNER = 'planner'
|
PLANNER = 'planner'
|
||||||
|
EXECUTION = 'execution'
|
||||||
|
|
||||||
ALL = (CREATE, UPDATE, EXCEPTION, DELETE, STRATEGY, PLANNER)
|
ALL = (CREATE, UPDATE, EXCEPTION, DELETE, STRATEGY, PLANNER, EXECUTION)
|
||||||
|
|
||||||
|
|
||||||
class NotificationPriorityField(BaseEnumField):
|
class NotificationPriorityField(BaseEnumField):
|
||||||
|
|
|
@ -89,7 +89,7 @@ def get_test_audit(**kwargs):
|
||||||
'updated_at': kwargs.get('updated_at'),
|
'updated_at': kwargs.get('updated_at'),
|
||||||
'deleted_at': kwargs.get('deleted_at'),
|
'deleted_at': kwargs.get('deleted_at'),
|
||||||
'parameters': kwargs.get('parameters', {}),
|
'parameters': kwargs.get('parameters', {}),
|
||||||
'interval': kwargs.get('period', 3600),
|
'interval': kwargs.get('interval', 3600),
|
||||||
'goal_id': kwargs.get('goal_id', 1),
|
'goal_id': kwargs.get('goal_id', 1),
|
||||||
'strategy_id': kwargs.get('strategy_id', None),
|
'strategy_id': kwargs.get('strategy_id', None),
|
||||||
'scope': kwargs.get('scope', []),
|
'scope': kwargs.get('scope', []),
|
||||||
|
|
|
@ -175,12 +175,19 @@ class TestAutoTriggerActionPlan(base.DbTestCase):
|
||||||
self.ongoing_action_plan = obj_utils.create_test_action_plan(
|
self.ongoing_action_plan = obj_utils.create_test_action_plan(
|
||||||
self.context,
|
self.context,
|
||||||
uuid=uuidutils.generate_uuid(),
|
uuid=uuidutils.generate_uuid(),
|
||||||
audit_id=self.audit.id)
|
audit_id=self.audit.id,
|
||||||
|
strategy_id=self.strategy.id,
|
||||||
|
audit=self.audit,
|
||||||
|
strategy=self.strategy,
|
||||||
|
)
|
||||||
self.recommended_action_plan = obj_utils.create_test_action_plan(
|
self.recommended_action_plan = obj_utils.create_test_action_plan(
|
||||||
self.context,
|
self.context,
|
||||||
uuid=uuidutils.generate_uuid(),
|
uuid=uuidutils.generate_uuid(),
|
||||||
state=objects.action_plan.State.ONGOING,
|
state=objects.action_plan.State.ONGOING,
|
||||||
audit_id=self.audit.id
|
audit_id=self.audit.id,
|
||||||
|
strategy_id=self.strategy.id,
|
||||||
|
audit=self.audit,
|
||||||
|
strategy=self.strategy,
|
||||||
)
|
)
|
||||||
|
|
||||||
@mock.patch.object(objects.action_plan.ActionPlan, 'list')
|
@mock.patch.object(objects.action_plan.ActionPlan, 'list')
|
||||||
|
|
|
@ -153,7 +153,6 @@ class FakeMonascaMetrics(object):
|
||||||
# measurements[uuid] = random.randint(1, 4)
|
# measurements[uuid] = random.randint(1, 4)
|
||||||
measurements[uuid] = 8
|
measurements[uuid] = 8
|
||||||
|
|
||||||
# import ipdb; ipdb.set_trace()
|
|
||||||
return [{'columns': ['avg'],
|
return [{'columns': ['avg'],
|
||||||
'statistics': [[float(measurements[str(uuid)])]]}]
|
'statistics': [[float(measurements[str(uuid)])]]}]
|
||||||
# return float(measurements[str(uuid)])
|
# return float(measurements[str(uuid)])
|
||||||
|
|
|
@ -60,6 +60,7 @@ class TestActionScheduling(base.DbTestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestActionScheduling, self).setUp()
|
super(TestActionScheduling, self).setUp()
|
||||||
|
self.goal = db_utils.create_test_goal(name="dummy")
|
||||||
self.strategy = db_utils.create_test_strategy(name="dummy")
|
self.strategy = db_utils.create_test_strategy(name="dummy")
|
||||||
self.audit = db_utils.create_test_audit(
|
self.audit = db_utils.create_test_audit(
|
||||||
uuid=utils.generate_uuid(), strategy_id=self.strategy.id)
|
uuid=utils.generate_uuid(), strategy_id=self.strategy.id)
|
||||||
|
|
|
@ -61,6 +61,7 @@ class TestActionScheduling(base.DbTestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestActionScheduling, self).setUp()
|
super(TestActionScheduling, self).setUp()
|
||||||
|
self.goal = db_utils.create_test_goal(name="dummy")
|
||||||
self.strategy = db_utils.create_test_strategy(name="dummy")
|
self.strategy = db_utils.create_test_strategy(name="dummy")
|
||||||
self.audit = db_utils.create_test_audit(
|
self.audit = db_utils.create_test_audit(
|
||||||
uuid=utils.generate_uuid(), strategy_id=self.strategy.id)
|
uuid=utils.generate_uuid(), strategy_id=self.strategy.id)
|
||||||
|
|
|
@ -0,0 +1,261 @@
|
||||||
|
# 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 freezegun
|
||||||
|
import mock
|
||||||
|
import oslo_messaging as om
|
||||||
|
|
||||||
|
from watcher.common import exception
|
||||||
|
from watcher.common import rpc
|
||||||
|
from watcher import notifications
|
||||||
|
from watcher import objects
|
||||||
|
from watcher.tests.db import base
|
||||||
|
from watcher.tests.objects import utils
|
||||||
|
|
||||||
|
|
||||||
|
@freezegun.freeze_time('2016-10-18T09:52:05.219414')
|
||||||
|
class TestActionPlanNotification(base.DbTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestActionPlanNotification, self).setUp()
|
||||||
|
p_get_notifier = mock.patch.object(rpc, 'get_notifier')
|
||||||
|
m_get_notifier = p_get_notifier.start()
|
||||||
|
self.addCleanup(p_get_notifier.stop)
|
||||||
|
self.m_notifier = mock.Mock(spec=om.Notifier)
|
||||||
|
|
||||||
|
def fake_get_notifier(publisher_id):
|
||||||
|
self.m_notifier.publisher_id = publisher_id
|
||||||
|
return self.m_notifier
|
||||||
|
|
||||||
|
m_get_notifier.side_effect = fake_get_notifier
|
||||||
|
self.goal = utils.create_test_goal(mock.Mock())
|
||||||
|
self.audit = utils.create_test_audit(mock.Mock(), interval=None)
|
||||||
|
self.strategy = utils.create_test_strategy(mock.Mock())
|
||||||
|
|
||||||
|
def test_send_invalid_action_plan(self):
|
||||||
|
action_plan = utils.get_test_action_plan(
|
||||||
|
mock.Mock(), state='DOESNOTMATTER', audit_id=1)
|
||||||
|
|
||||||
|
self.assertRaises(
|
||||||
|
exception.InvalidActionPlan,
|
||||||
|
notifications.action_plan.send_update,
|
||||||
|
mock.MagicMock(), action_plan, host='node0')
|
||||||
|
|
||||||
|
def test_send_action_plan_update(self):
|
||||||
|
action_plan = utils.create_test_action_plan(
|
||||||
|
mock.Mock(), state=objects.action_plan.State.ONGOING,
|
||||||
|
audit_id=self.audit.id, strategy_id=self.strategy.id,
|
||||||
|
audit=self.audit, strategy=self.strategy)
|
||||||
|
notifications.action_plan.send_update(
|
||||||
|
mock.MagicMock(), action_plan, host='node0',
|
||||||
|
old_state=objects.action_plan.State.PENDING)
|
||||||
|
|
||||||
|
# The 1st notification is because we created the object.
|
||||||
|
# The 2nd notification is because we created the action plan object.
|
||||||
|
self.assertEqual(3, self.m_notifier.info.call_count)
|
||||||
|
notification = self.m_notifier.info.call_args[1]
|
||||||
|
payload = notification['payload']
|
||||||
|
|
||||||
|
self.assertEqual("infra-optim:node0", self.m_notifier.publisher_id)
|
||||||
|
self.assertDictEqual(
|
||||||
|
{
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"global_efficacy": {},
|
||||||
|
"strategy_uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"strategy": {
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"updated_at": None,
|
||||||
|
"uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"name": "TEST",
|
||||||
|
"parameters_spec": {},
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"display_name": "test strategy",
|
||||||
|
"deleted_at": None
|
||||||
|
},
|
||||||
|
"watcher_object.name": "StrategyPayload"
|
||||||
|
},
|
||||||
|
"uuid": "76be87bd-3422-43f9-93a0-e85a577e3061",
|
||||||
|
"audit_uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"audit": {
|
||||||
|
"watcher_object.data": {
|
||||||
|
"interval": None,
|
||||||
|
"parameters": {},
|
||||||
|
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"strategy_uuid": None,
|
||||||
|
"goal_uuid": (
|
||||||
|
"f7ad87ae-4298-91cf-93a0-f35a852e3652"),
|
||||||
|
"deleted_at": None,
|
||||||
|
"scope": [],
|
||||||
|
"state": "PENDING",
|
||||||
|
"updated_at": None,
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"audit_type": "ONESHOT"
|
||||||
|
},
|
||||||
|
"watcher_object.name": "TerseAuditPayload",
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0"
|
||||||
|
},
|
||||||
|
"deleted_at": None,
|
||||||
|
"state": "ONGOING",
|
||||||
|
"updated_at": None,
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"state_update": {
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"old_state": "PENDING",
|
||||||
|
"state": "ONGOING"
|
||||||
|
},
|
||||||
|
"watcher_object.name": "ActionPlanStateUpdatePayload"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"watcher_object.name": "ActionPlanUpdatePayload"
|
||||||
|
},
|
||||||
|
payload
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_send_action_plan_create(self):
|
||||||
|
action_plan = utils.get_test_action_plan(
|
||||||
|
mock.Mock(), state=objects.action_plan.State.PENDING,
|
||||||
|
audit_id=self.audit.id, strategy_id=self.strategy.id,
|
||||||
|
audit=self.audit.as_dict(), strategy=self.strategy.as_dict())
|
||||||
|
notifications.action_plan.send_create(
|
||||||
|
mock.MagicMock(), action_plan, host='node0')
|
||||||
|
|
||||||
|
self.assertEqual(2, self.m_notifier.info.call_count)
|
||||||
|
notification = self.m_notifier.info.call_args[1]
|
||||||
|
payload = notification['payload']
|
||||||
|
|
||||||
|
self.assertEqual("infra-optim:node0", self.m_notifier.publisher_id)
|
||||||
|
self.assertDictEqual(
|
||||||
|
{
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"global_efficacy": {},
|
||||||
|
"strategy_uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"strategy": {
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"updated_at": None,
|
||||||
|
"uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"name": "TEST",
|
||||||
|
"parameters_spec": {},
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"display_name": "test strategy",
|
||||||
|
"deleted_at": None
|
||||||
|
},
|
||||||
|
"watcher_object.name": "StrategyPayload"
|
||||||
|
},
|
||||||
|
"uuid": "76be87bd-3422-43f9-93a0-e85a577e3061",
|
||||||
|
"audit_uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"audit": {
|
||||||
|
"watcher_object.data": {
|
||||||
|
"interval": None,
|
||||||
|
"parameters": {},
|
||||||
|
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"strategy_uuid": None,
|
||||||
|
"goal_uuid": (
|
||||||
|
"f7ad87ae-4298-91cf-93a0-f35a852e3652"),
|
||||||
|
"deleted_at": None,
|
||||||
|
"scope": [],
|
||||||
|
"state": "PENDING",
|
||||||
|
"updated_at": None,
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"audit_type": "ONESHOT"
|
||||||
|
},
|
||||||
|
"watcher_object.name": "TerseAuditPayload",
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0"
|
||||||
|
},
|
||||||
|
"deleted_at": None,
|
||||||
|
"state": "PENDING",
|
||||||
|
"updated_at": None,
|
||||||
|
"created_at": None,
|
||||||
|
},
|
||||||
|
"watcher_object.name": "ActionPlanCreatePayload"
|
||||||
|
},
|
||||||
|
payload
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_send_action_plan_delete(self):
|
||||||
|
action_plan = utils.create_test_action_plan(
|
||||||
|
mock.Mock(), state=objects.action_plan.State.DELETED,
|
||||||
|
audit_id=self.audit.id, strategy_id=self.strategy.id)
|
||||||
|
notifications.action_plan.send_delete(
|
||||||
|
mock.MagicMock(), action_plan, host='node0')
|
||||||
|
|
||||||
|
# The 1st notification is because we created the audit object.
|
||||||
|
# The 2nd notification is because we created the action plan object.
|
||||||
|
self.assertEqual(3, self.m_notifier.info.call_count)
|
||||||
|
notification = self.m_notifier.info.call_args[1]
|
||||||
|
payload = notification['payload']
|
||||||
|
|
||||||
|
self.assertEqual("infra-optim:node0", self.m_notifier.publisher_id)
|
||||||
|
self.assertDictEqual(
|
||||||
|
{
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"global_efficacy": {},
|
||||||
|
"strategy_uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"strategy": {
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0",
|
||||||
|
"watcher_object.data": {
|
||||||
|
"updated_at": None,
|
||||||
|
"uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
|
"name": "TEST",
|
||||||
|
"parameters_spec": {},
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"display_name": "test strategy",
|
||||||
|
"deleted_at": None
|
||||||
|
},
|
||||||
|
"watcher_object.name": "StrategyPayload"
|
||||||
|
},
|
||||||
|
"uuid": "76be87bd-3422-43f9-93a0-e85a577e3061",
|
||||||
|
"audit_uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"audit": {
|
||||||
|
"watcher_object.data": {
|
||||||
|
"interval": None,
|
||||||
|
"parameters": {},
|
||||||
|
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"strategy_uuid": None,
|
||||||
|
"goal_uuid": (
|
||||||
|
"f7ad87ae-4298-91cf-93a0-f35a852e3652"),
|
||||||
|
"deleted_at": None,
|
||||||
|
"scope": [],
|
||||||
|
"state": "PENDING",
|
||||||
|
"updated_at": None,
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
"audit_type": "ONESHOT"
|
||||||
|
},
|
||||||
|
"watcher_object.name": "TerseAuditPayload",
|
||||||
|
"watcher_object.namespace": "watcher",
|
||||||
|
"watcher_object.version": "1.0"
|
||||||
|
},
|
||||||
|
"deleted_at": None,
|
||||||
|
"state": "DELETED",
|
||||||
|
"updated_at": None,
|
||||||
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
},
|
||||||
|
"watcher_object.name": "ActionPlanDeletePayload"
|
||||||
|
},
|
||||||
|
payload
|
||||||
|
)
|
|
@ -43,8 +43,8 @@ class TestAuditNotification(base.DbTestCase):
|
||||||
self.strategy = utils.create_test_strategy(mock.Mock())
|
self.strategy = utils.create_test_strategy(mock.Mock())
|
||||||
|
|
||||||
def test_send_invalid_audit(self):
|
def test_send_invalid_audit(self):
|
||||||
audit = utils.get_test_audit(mock.Mock(), state='DOESNOTMATTER',
|
audit = utils.get_test_audit(
|
||||||
goal_id=1)
|
mock.Mock(), interval=None, state='DOESNOTMATTER', goal_id=1)
|
||||||
|
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.InvalidAudit,
|
exception.InvalidAudit,
|
||||||
|
@ -53,7 +53,7 @@ class TestAuditNotification(base.DbTestCase):
|
||||||
|
|
||||||
def test_send_audit_update_with_strategy(self):
|
def test_send_audit_update_with_strategy(self):
|
||||||
audit = utils.create_test_audit(
|
audit = utils.create_test_audit(
|
||||||
mock.Mock(), state=objects.audit.State.ONGOING,
|
mock.Mock(), interval=None, state=objects.audit.State.ONGOING,
|
||||||
goal_id=self.goal.id, strategy_id=self.strategy.id,
|
goal_id=self.goal.id, strategy_id=self.strategy.id,
|
||||||
goal=self.goal, strategy=self.strategy)
|
goal=self.goal, strategy=self.strategy)
|
||||||
notifications.audit.send_update(
|
notifications.audit.send_update(
|
||||||
|
@ -71,7 +71,8 @@ class TestAuditNotification(base.DbTestCase):
|
||||||
"watcher_object.namespace": "watcher",
|
"watcher_object.namespace": "watcher",
|
||||||
"watcher_object.version": "1.0",
|
"watcher_object.version": "1.0",
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"interval": 3600,
|
"interval": None,
|
||||||
|
"strategy_uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
"strategy": {
|
"strategy": {
|
||||||
"watcher_object.namespace": "watcher",
|
"watcher_object.namespace": "watcher",
|
||||||
"watcher_object.version": "1.0",
|
"watcher_object.version": "1.0",
|
||||||
|
@ -88,6 +89,7 @@ class TestAuditNotification(base.DbTestCase):
|
||||||
},
|
},
|
||||||
"parameters": {},
|
"parameters": {},
|
||||||
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"goal_uuid": "f7ad87ae-4298-91cf-93a0-f35a852e3652",
|
||||||
"goal": {
|
"goal": {
|
||||||
"watcher_object.namespace": "watcher",
|
"watcher_object.namespace": "watcher",
|
||||||
"watcher_object.version": "1.0",
|
"watcher_object.version": "1.0",
|
||||||
|
@ -125,7 +127,7 @@ class TestAuditNotification(base.DbTestCase):
|
||||||
|
|
||||||
def test_send_audit_update_without_strategy(self):
|
def test_send_audit_update_without_strategy(self):
|
||||||
audit = utils.get_test_audit(
|
audit = utils.get_test_audit(
|
||||||
mock.Mock(), state=objects.audit.State.ONGOING,
|
mock.Mock(), interval=None, state=objects.audit.State.ONGOING,
|
||||||
goal_id=self.goal.id, goal=self.goal)
|
goal_id=self.goal.id, goal=self.goal)
|
||||||
notifications.audit.send_update(
|
notifications.audit.send_update(
|
||||||
mock.MagicMock(), audit, host='node0',
|
mock.MagicMock(), audit, host='node0',
|
||||||
|
@ -141,9 +143,10 @@ class TestAuditNotification(base.DbTestCase):
|
||||||
"watcher_object.namespace": "watcher",
|
"watcher_object.namespace": "watcher",
|
||||||
"watcher_object.version": "1.0",
|
"watcher_object.version": "1.0",
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"interval": 3600,
|
"interval": None,
|
||||||
"parameters": {},
|
"parameters": {},
|
||||||
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"goal_uuid": "f7ad87ae-4298-91cf-93a0-f35a852e3652",
|
||||||
"goal": {
|
"goal": {
|
||||||
"watcher_object.namespace": "watcher",
|
"watcher_object.namespace": "watcher",
|
||||||
"watcher_object.version": "1.0",
|
"watcher_object.version": "1.0",
|
||||||
|
@ -158,6 +161,7 @@ class TestAuditNotification(base.DbTestCase):
|
||||||
},
|
},
|
||||||
"watcher_object.name": "GoalPayload"
|
"watcher_object.name": "GoalPayload"
|
||||||
},
|
},
|
||||||
|
"strategy_uuid": None,
|
||||||
"strategy": None,
|
"strategy": None,
|
||||||
"deleted_at": None,
|
"deleted_at": None,
|
||||||
"scope": [],
|
"scope": [],
|
||||||
|
@ -182,7 +186,7 @@ class TestAuditNotification(base.DbTestCase):
|
||||||
|
|
||||||
def test_send_audit_create(self):
|
def test_send_audit_create(self):
|
||||||
audit = utils.get_test_audit(
|
audit = utils.get_test_audit(
|
||||||
mock.Mock(), state=objects.audit.State.PENDING,
|
mock.Mock(), interval=None, state=objects.audit.State.PENDING,
|
||||||
goal_id=self.goal.id, strategy_id=self.strategy.id,
|
goal_id=self.goal.id, strategy_id=self.strategy.id,
|
||||||
goal=self.goal.as_dict(), strategy=self.strategy.as_dict())
|
goal=self.goal.as_dict(), strategy=self.strategy.as_dict())
|
||||||
notifications.audit.send_create(
|
notifications.audit.send_create(
|
||||||
|
@ -198,7 +202,8 @@ class TestAuditNotification(base.DbTestCase):
|
||||||
"watcher_object.namespace": "watcher",
|
"watcher_object.namespace": "watcher",
|
||||||
"watcher_object.version": "1.0",
|
"watcher_object.version": "1.0",
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"interval": 3600,
|
"interval": None,
|
||||||
|
"strategy_uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
"strategy": {
|
"strategy": {
|
||||||
"watcher_object.namespace": "watcher",
|
"watcher_object.namespace": "watcher",
|
||||||
"watcher_object.version": "1.0",
|
"watcher_object.version": "1.0",
|
||||||
|
@ -215,6 +220,7 @@ class TestAuditNotification(base.DbTestCase):
|
||||||
},
|
},
|
||||||
"parameters": {},
|
"parameters": {},
|
||||||
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"goal_uuid": "f7ad87ae-4298-91cf-93a0-f35a852e3652",
|
||||||
"goal": {
|
"goal": {
|
||||||
"watcher_object.namespace": "watcher",
|
"watcher_object.namespace": "watcher",
|
||||||
"watcher_object.version": "1.0",
|
"watcher_object.version": "1.0",
|
||||||
|
@ -243,7 +249,7 @@ class TestAuditNotification(base.DbTestCase):
|
||||||
|
|
||||||
def test_send_audit_delete(self):
|
def test_send_audit_delete(self):
|
||||||
audit = utils.create_test_audit(
|
audit = utils.create_test_audit(
|
||||||
mock.Mock(), state=objects.audit.State.DELETED,
|
mock.Mock(), interval=None, state=objects.audit.State.DELETED,
|
||||||
goal_id=self.goal.id, strategy_id=self.strategy.id)
|
goal_id=self.goal.id, strategy_id=self.strategy.id)
|
||||||
notifications.audit.send_delete(
|
notifications.audit.send_delete(
|
||||||
mock.MagicMock(), audit, host='node0')
|
mock.MagicMock(), audit, host='node0')
|
||||||
|
@ -259,7 +265,8 @@ class TestAuditNotification(base.DbTestCase):
|
||||||
"watcher_object.namespace": "watcher",
|
"watcher_object.namespace": "watcher",
|
||||||
"watcher_object.version": "1.0",
|
"watcher_object.version": "1.0",
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"interval": 3600,
|
"interval": None,
|
||||||
|
"strategy_uuid": "cb3d0b58-4415-4d90-b75b-1e96878730e3",
|
||||||
"strategy": {
|
"strategy": {
|
||||||
"watcher_object.namespace": "watcher",
|
"watcher_object.namespace": "watcher",
|
||||||
"watcher_object.version": "1.0",
|
"watcher_object.version": "1.0",
|
||||||
|
@ -276,6 +283,7 @@ class TestAuditNotification(base.DbTestCase):
|
||||||
},
|
},
|
||||||
"parameters": {},
|
"parameters": {},
|
||||||
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
"uuid": "10a47dd1-4874-4298-91cf-eff046dbdb8d",
|
||||||
|
"goal_uuid": "f7ad87ae-4298-91cf-93a0-f35a852e3652",
|
||||||
"goal": {
|
"goal": {
|
||||||
"watcher_object.namespace": "watcher",
|
"watcher_object.namespace": "watcher",
|
||||||
"watcher_object.version": "1.0",
|
"watcher_object.version": "1.0",
|
||||||
|
@ -304,7 +312,7 @@ class TestAuditNotification(base.DbTestCase):
|
||||||
|
|
||||||
def test_send_audit_action(self):
|
def test_send_audit_action(self):
|
||||||
audit = utils.create_test_audit(
|
audit = utils.create_test_audit(
|
||||||
mock.Mock(), state=objects.audit.State.ONGOING,
|
mock.Mock(), interval=None, state=objects.audit.State.ONGOING,
|
||||||
goal_id=self.goal.id, strategy_id=self.strategy.id,
|
goal_id=self.goal.id, strategy_id=self.strategy.id,
|
||||||
goal=self.goal, strategy=self.strategy)
|
goal=self.goal, strategy=self.strategy)
|
||||||
notifications.audit.send_action_notification(
|
notifications.audit.send_action_notification(
|
||||||
|
@ -326,6 +334,7 @@ class TestAuditNotification(base.DbTestCase):
|
||||||
"created_at": "2016-10-18T09:52:05Z",
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
"deleted_at": None,
|
"deleted_at": None,
|
||||||
"fault": None,
|
"fault": None,
|
||||||
|
"goal_uuid": "f7ad87ae-4298-91cf-93a0-f35a852e3652",
|
||||||
"goal": {
|
"goal": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"created_at": "2016-10-18T09:52:05Z",
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
@ -340,10 +349,12 @@ class TestAuditNotification(base.DbTestCase):
|
||||||
"watcher_object.namespace": "watcher",
|
"watcher_object.namespace": "watcher",
|
||||||
"watcher_object.version": "1.0"
|
"watcher_object.version": "1.0"
|
||||||
},
|
},
|
||||||
"interval": 3600,
|
"interval": None,
|
||||||
"parameters": {},
|
"parameters": {},
|
||||||
"scope": [],
|
"scope": [],
|
||||||
"state": "ONGOING",
|
"state": "ONGOING",
|
||||||
|
"strategy_uuid": (
|
||||||
|
"cb3d0b58-4415-4d90-b75b-1e96878730e3"),
|
||||||
"strategy": {
|
"strategy": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"created_at": "2016-10-18T09:52:05Z",
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
@ -371,7 +382,7 @@ class TestAuditNotification(base.DbTestCase):
|
||||||
|
|
||||||
def test_send_audit_action_with_error(self):
|
def test_send_audit_action_with_error(self):
|
||||||
audit = utils.create_test_audit(
|
audit = utils.create_test_audit(
|
||||||
mock.Mock(), state=objects.audit.State.ONGOING,
|
mock.Mock(), interval=None, state=objects.audit.State.ONGOING,
|
||||||
goal_id=self.goal.id, strategy_id=self.strategy.id,
|
goal_id=self.goal.id, strategy_id=self.strategy.id,
|
||||||
goal=self.goal, strategy=self.strategy)
|
goal=self.goal, strategy=self.strategy)
|
||||||
|
|
||||||
|
@ -407,6 +418,7 @@ class TestAuditNotification(base.DbTestCase):
|
||||||
"watcher_object.namespace": "watcher",
|
"watcher_object.namespace": "watcher",
|
||||||
"watcher_object.version": "1.0"
|
"watcher_object.version": "1.0"
|
||||||
},
|
},
|
||||||
|
"goal_uuid": "f7ad87ae-4298-91cf-93a0-f35a852e3652",
|
||||||
"goal": {
|
"goal": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"created_at": "2016-10-18T09:52:05Z",
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
@ -421,10 +433,12 @@ class TestAuditNotification(base.DbTestCase):
|
||||||
"watcher_object.namespace": "watcher",
|
"watcher_object.namespace": "watcher",
|
||||||
"watcher_object.version": "1.0"
|
"watcher_object.version": "1.0"
|
||||||
},
|
},
|
||||||
"interval": 3600,
|
"interval": None,
|
||||||
"parameters": {},
|
"parameters": {},
|
||||||
"scope": [],
|
"scope": [],
|
||||||
"state": "ONGOING",
|
"state": "ONGOING",
|
||||||
|
"strategy_uuid": (
|
||||||
|
"cb3d0b58-4415-4d90-b75b-1e96878730e3"),
|
||||||
"strategy": {
|
"strategy": {
|
||||||
"watcher_object.data": {
|
"watcher_object.data": {
|
||||||
"created_at": "2016-10-18T09:52:05Z",
|
"created_at": "2016-10-18T09:52:05Z",
|
||||||
|
|
|
@ -250,10 +250,11 @@ class TestNotificationBase(testbase.TestCase):
|
||||||
|
|
||||||
|
|
||||||
expected_notification_fingerprints = {
|
expected_notification_fingerprints = {
|
||||||
'EventType': '1.2-633c2d32fa849d2a6f8bda3b0db88332',
|
'EventType': '1.3-4258a2c86eca79fd34a7dffe1278eab9',
|
||||||
'ExceptionNotification': '1.0-9b69de0724fda8310d05e18418178866',
|
'ExceptionNotification': '1.0-9b69de0724fda8310d05e18418178866',
|
||||||
'ExceptionPayload': '1.0-4516ae282a55fe2fd5c754967ee6248b',
|
'ExceptionPayload': '1.0-4516ae282a55fe2fd5c754967ee6248b',
|
||||||
'NotificationPublisher': '1.0-bbbc1402fb0e443a3eb227cc52b61545',
|
'NotificationPublisher': '1.0-bbbc1402fb0e443a3eb227cc52b61545',
|
||||||
|
'TerseAuditPayload': '1.0-aaf31166b8698f08d12cae98c380b8e0',
|
||||||
'AuditPayload': '1.0-30c85c834648c8ca11f54fc5e084d86b',
|
'AuditPayload': '1.0-30c85c834648c8ca11f54fc5e084d86b',
|
||||||
'AuditStateUpdatePayload': '1.0-1a1b606bf14a2c468800c2b010801ce5',
|
'AuditStateUpdatePayload': '1.0-1a1b606bf14a2c468800c2b010801ce5',
|
||||||
'AuditUpdateNotification': '1.0-9b69de0724fda8310d05e18418178866',
|
'AuditUpdateNotification': '1.0-9b69de0724fda8310d05e18418178866',
|
||||||
|
@ -266,6 +267,15 @@ expected_notification_fingerprints = {
|
||||||
'AuditActionPayload': '1.0-09f5d005f94ba9e5f6b9200170332c52',
|
'AuditActionPayload': '1.0-09f5d005f94ba9e5f6b9200170332c52',
|
||||||
'GoalPayload': '1.0-fa1fecb8b01dd047eef808ded4d50d1a',
|
'GoalPayload': '1.0-fa1fecb8b01dd047eef808ded4d50d1a',
|
||||||
'StrategyPayload': '1.0-94f01c137b083ac236ae82573c1fcfc1',
|
'StrategyPayload': '1.0-94f01c137b083ac236ae82573c1fcfc1',
|
||||||
|
'ActionPlanActionPayload': '1.0-34871caf18e9b43a28899953c1c9733a',
|
||||||
|
'ActionPlanCreateNotification': '1.0-9b69de0724fda8310d05e18418178866',
|
||||||
|
'ActionPlanCreatePayload': '1.0-ffc3087acd73351b14f3dcc30e105027',
|
||||||
|
'ActionPlanDeleteNotification': '1.0-9b69de0724fda8310d05e18418178866',
|
||||||
|
'ActionPlanDeletePayload': '1.0-ffc3087acd73351b14f3dcc30e105027',
|
||||||
|
'ActionPlanPayload': '1.0-ffc3087acd73351b14f3dcc30e105027',
|
||||||
|
'ActionPlanStateUpdatePayload': '1.0-1a1b606bf14a2c468800c2b010801ce5',
|
||||||
|
'ActionPlanUpdateNotification': '1.0-9b69de0724fda8310d05e18418178866',
|
||||||
|
'ActionPlanUpdatePayload': '1.0-7912a45fe53775c721f42aa87f06a023',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ import mock
|
||||||
|
|
||||||
from watcher.common import exception
|
from watcher.common import exception
|
||||||
from watcher.db.sqlalchemy import api as db_api
|
from watcher.db.sqlalchemy import api as db_api
|
||||||
|
from watcher import notifications
|
||||||
from watcher import objects
|
from watcher import objects
|
||||||
from watcher.tests.db import base
|
from watcher.tests.db import base
|
||||||
from watcher.tests.db import utils
|
from watcher.tests.db import utils
|
||||||
|
@ -34,16 +35,19 @@ class TestActionPlanObject(base.DbTestCase):
|
||||||
('non_eager', dict(
|
('non_eager', dict(
|
||||||
eager=False,
|
eager=False,
|
||||||
fake_action_plan=utils.get_test_action_plan(
|
fake_action_plan=utils.get_test_action_plan(
|
||||||
|
created_at=datetime.datetime.utcnow(),
|
||||||
audit_id=audit_id,
|
audit_id=audit_id,
|
||||||
strategy_id=strategy_id))),
|
strategy_id=strategy_id))),
|
||||||
('eager_with_non_eager_load', dict(
|
('eager_with_non_eager_load', dict(
|
||||||
eager=True,
|
eager=True,
|
||||||
fake_action_plan=utils.get_test_action_plan(
|
fake_action_plan=utils.get_test_action_plan(
|
||||||
|
created_at=datetime.datetime.utcnow(),
|
||||||
audit_id=audit_id,
|
audit_id=audit_id,
|
||||||
strategy_id=strategy_id))),
|
strategy_id=strategy_id))),
|
||||||
('eager_with_eager_load', dict(
|
('eager_with_eager_load', dict(
|
||||||
eager=True,
|
eager=True,
|
||||||
fake_action_plan=utils.get_test_action_plan(
|
fake_action_plan=utils.get_test_action_plan(
|
||||||
|
created_at=datetime.datetime.utcnow(),
|
||||||
strategy_id=strategy_id,
|
strategy_id=strategy_id,
|
||||||
strategy=utils.get_test_strategy(id=strategy_id),
|
strategy=utils.get_test_strategy(id=strategy_id),
|
||||||
audit_id=audit_id,
|
audit_id=audit_id,
|
||||||
|
@ -52,6 +56,13 @@ class TestActionPlanObject(base.DbTestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestActionPlanObject, self).setUp()
|
super(TestActionPlanObject, self).setUp()
|
||||||
|
|
||||||
|
p_action_plan_notifications = mock.patch.object(
|
||||||
|
notifications, 'action_plan', autospec=True)
|
||||||
|
self.m_action_plan_notifications = p_action_plan_notifications.start()
|
||||||
|
self.addCleanup(p_action_plan_notifications.stop)
|
||||||
|
self.m_send_update = self.m_action_plan_notifications.send_update
|
||||||
|
|
||||||
self.fake_audit = utils.create_test_audit(id=self.audit_id)
|
self.fake_audit = utils.create_test_audit(id=self.audit_id)
|
||||||
self.fake_strategy = utils.create_test_strategy(
|
self.fake_strategy = utils.create_test_strategy(
|
||||||
id=self.strategy_id, name="DUMMY")
|
id=self.strategy_id, name="DUMMY")
|
||||||
|
@ -80,6 +91,7 @@ class TestActionPlanObject(base.DbTestCase):
|
||||||
self.context, action_plan_id, eager=self.eager)
|
self.context, action_plan_id, eager=self.eager)
|
||||||
self.assertEqual(self.context, action_plan._context)
|
self.assertEqual(self.context, action_plan._context)
|
||||||
self.eager_load_action_plan_assert(action_plan)
|
self.eager_load_action_plan_assert(action_plan)
|
||||||
|
self.assertEqual(0, self.m_send_update.call_count)
|
||||||
|
|
||||||
@mock.patch.object(db_api.Connection, 'get_action_plan_by_uuid')
|
@mock.patch.object(db_api.Connection, 'get_action_plan_by_uuid')
|
||||||
def test_get_by_uuid(self, mock_get_action_plan):
|
def test_get_by_uuid(self, mock_get_action_plan):
|
||||||
|
@ -91,6 +103,7 @@ class TestActionPlanObject(base.DbTestCase):
|
||||||
self.context, uuid, eager=self.eager)
|
self.context, uuid, eager=self.eager)
|
||||||
self.assertEqual(self.context, action_plan._context)
|
self.assertEqual(self.context, action_plan._context)
|
||||||
self.eager_load_action_plan_assert(action_plan)
|
self.eager_load_action_plan_assert(action_plan)
|
||||||
|
self.assertEqual(0, self.m_send_update.call_count)
|
||||||
|
|
||||||
def test_get_bad_id_and_uuid(self):
|
def test_get_bad_id_and_uuid(self):
|
||||||
self.assertRaises(exception.InvalidIdentity,
|
self.assertRaises(exception.InvalidIdentity,
|
||||||
|
@ -107,14 +120,26 @@ class TestActionPlanObject(base.DbTestCase):
|
||||||
self.assertEqual(self.context, action_plans[0]._context)
|
self.assertEqual(self.context, action_plans[0]._context)
|
||||||
for action_plan in action_plans:
|
for action_plan in action_plans:
|
||||||
self.eager_load_action_plan_assert(action_plan)
|
self.eager_load_action_plan_assert(action_plan)
|
||||||
|
self.assertEqual(0, self.m_send_update.call_count)
|
||||||
|
|
||||||
@mock.patch.object(db_api.Connection, 'update_action_plan')
|
@mock.patch.object(db_api.Connection, 'update_action_plan')
|
||||||
@mock.patch.object(db_api.Connection, 'get_action_plan_by_uuid')
|
@mock.patch.object(db_api.Connection, 'get_action_plan_by_uuid')
|
||||||
def test_save(self, mock_get_action_plan, mock_update_action_plan):
|
def test_save(self, mock_get_action_plan, mock_update_action_plan):
|
||||||
mock_get_action_plan.return_value = self.fake_action_plan
|
mock_get_action_plan.return_value = self.fake_action_plan
|
||||||
fake_saved_action_plan = self.fake_action_plan.copy()
|
fake_saved_action_plan = self.fake_action_plan.copy()
|
||||||
fake_saved_action_plan['deleted_at'] = datetime.datetime.utcnow()
|
fake_saved_action_plan['state'] = objects.action_plan.State.SUCCEEDED
|
||||||
|
fake_saved_action_plan['updated_at'] = datetime.datetime.utcnow()
|
||||||
|
|
||||||
mock_update_action_plan.return_value = fake_saved_action_plan
|
mock_update_action_plan.return_value = fake_saved_action_plan
|
||||||
|
|
||||||
|
expected_action_plan = fake_saved_action_plan.copy()
|
||||||
|
expected_action_plan[
|
||||||
|
'created_at'] = expected_action_plan['created_at'].replace(
|
||||||
|
tzinfo=iso8601.iso8601.Utc())
|
||||||
|
expected_action_plan[
|
||||||
|
'updated_at'] = expected_action_plan['updated_at'].replace(
|
||||||
|
tzinfo=iso8601.iso8601.Utc())
|
||||||
|
|
||||||
uuid = self.fake_action_plan['uuid']
|
uuid = self.fake_action_plan['uuid']
|
||||||
action_plan = objects.ActionPlan.get_by_uuid(
|
action_plan = objects.ActionPlan.get_by_uuid(
|
||||||
self.context, uuid, eager=self.eager)
|
self.context, uuid, eager=self.eager)
|
||||||
|
@ -127,6 +152,14 @@ class TestActionPlanObject(base.DbTestCase):
|
||||||
uuid, {'state': objects.action_plan.State.SUCCEEDED})
|
uuid, {'state': objects.action_plan.State.SUCCEEDED})
|
||||||
self.assertEqual(self.context, action_plan._context)
|
self.assertEqual(self.context, action_plan._context)
|
||||||
self.eager_load_action_plan_assert(action_plan)
|
self.eager_load_action_plan_assert(action_plan)
|
||||||
|
self.m_send_update.assert_called_once_with(
|
||||||
|
self.context, action_plan,
|
||||||
|
old_state=self.fake_action_plan['state'])
|
||||||
|
self.assertEqual(
|
||||||
|
{k: v for k, v in expected_action_plan.items()
|
||||||
|
if k not in action_plan.object_fields},
|
||||||
|
{k: v for k, v in action_plan.as_dict().items()
|
||||||
|
if k not in action_plan.object_fields})
|
||||||
|
|
||||||
@mock.patch.object(db_api.Connection, 'get_action_plan_by_uuid')
|
@mock.patch.object(db_api.Connection, 'get_action_plan_by_uuid')
|
||||||
def test_refresh(self, mock_get_action_plan):
|
def test_refresh(self, mock_get_action_plan):
|
||||||
|
@ -150,6 +183,13 @@ class TestCreateDeleteActionPlanObject(base.DbTestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestCreateDeleteActionPlanObject, self).setUp()
|
super(TestCreateDeleteActionPlanObject, self).setUp()
|
||||||
|
|
||||||
|
p_action_plan_notifications = mock.patch.object(
|
||||||
|
notifications, 'action_plan', autospec=True)
|
||||||
|
self.m_action_plan_notifications = p_action_plan_notifications.start()
|
||||||
|
self.addCleanup(p_action_plan_notifications.stop)
|
||||||
|
self.m_send_update = self.m_action_plan_notifications.send_update
|
||||||
|
|
||||||
self.fake_strategy = utils.create_test_strategy(name="DUMMY")
|
self.fake_strategy = utils.create_test_strategy(name="DUMMY")
|
||||||
self.fake_audit = utils.create_test_audit()
|
self.fake_audit = utils.create_test_audit()
|
||||||
self.fake_action_plan = utils.get_test_action_plan(
|
self.fake_action_plan = utils.get_test_action_plan(
|
||||||
|
@ -202,7 +242,8 @@ class TestCreateDeleteActionPlanObject(base.DbTestCase):
|
||||||
del expected_action_plan['strategy']
|
del expected_action_plan['strategy']
|
||||||
|
|
||||||
m_get_efficacy_indicator_list.return_value = [efficacy_indicator]
|
m_get_efficacy_indicator_list.return_value = [efficacy_indicator]
|
||||||
action_plan = objects.ActionPlan.get_by_uuid(self.context, uuid)
|
action_plan = objects.ActionPlan.get_by_uuid(
|
||||||
|
self.context, uuid, eager=False)
|
||||||
action_plan.soft_delete()
|
action_plan.soft_delete()
|
||||||
|
|
||||||
m_get_action_plan.assert_called_once_with(
|
m_get_action_plan.assert_called_once_with(
|
||||||
|
|
|
@ -282,6 +282,7 @@ class TestAuditObjectSendNotifications(base.DbTestCase):
|
||||||
def test_send_create_notification(self, m_create_audit):
|
def test_send_create_notification(self, m_create_audit):
|
||||||
audit = objutils.get_test_audit(
|
audit = objutils.get_test_audit(
|
||||||
self.context,
|
self.context,
|
||||||
|
id=1,
|
||||||
goal_id=self.fake_goal.id,
|
goal_id=self.fake_goal.id,
|
||||||
strategy_id=self.fake_strategy.id,
|
strategy_id=self.fake_strategy.id,
|
||||||
goal=self.fake_goal.as_dict(),
|
goal=self.fake_goal.as_dict(),
|
||||||
|
|
|
@ -30,21 +30,27 @@ def _load_related_objects(context, cls, db_data):
|
||||||
return obj_data
|
return obj_data
|
||||||
|
|
||||||
|
|
||||||
|
def _load_test_obj(context, cls, obj_data, **kw):
|
||||||
|
# Let DB generate ID if it isn't specified explicitly
|
||||||
|
if 'id' not in kw:
|
||||||
|
del obj_data['id']
|
||||||
|
obj = cls(context)
|
||||||
|
for key in obj_data:
|
||||||
|
setattr(obj, key, obj_data[key])
|
||||||
|
return obj
|
||||||
|
|
||||||
|
|
||||||
def get_test_audit_template(context, **kw):
|
def get_test_audit_template(context, **kw):
|
||||||
"""Return a AuditTemplate object with appropriate attributes.
|
"""Return a AuditTemplate object with appropriate attributes.
|
||||||
|
|
||||||
NOTE: The object leaves the attributes marked as changed, such
|
NOTE: The object leaves the attributes marked as changed, such
|
||||||
that a create() could be used to commit it to the DB.
|
that a create() could be used to commit it to the DB.
|
||||||
"""
|
"""
|
||||||
db_audit_template = db_utils.get_test_audit_template(**kw)
|
obj_cls = objects.AuditTemplate
|
||||||
# Let DB generate ID if it isn't specified explicitly
|
db_data = db_utils.get_test_audit_template(**kw)
|
||||||
if 'id' not in kw:
|
obj_data = _load_related_objects(context, obj_cls, db_data)
|
||||||
del db_audit_template['id']
|
|
||||||
audit_template = objects.AuditTemplate(context)
|
|
||||||
for key in db_audit_template:
|
|
||||||
setattr(audit_template, key, db_audit_template[key])
|
|
||||||
|
|
||||||
return audit_template
|
return _load_test_obj(context, obj_cls, obj_data, **kw)
|
||||||
|
|
||||||
|
|
||||||
def create_test_audit_template(context, **kw):
|
def create_test_audit_template(context, **kw):
|
||||||
|
@ -64,16 +70,11 @@ def get_test_audit(context, **kw):
|
||||||
NOTE: The object leaves the attributes marked as changed, such
|
NOTE: The object leaves the attributes marked as changed, such
|
||||||
that a create() could be used to commit it to the DB.
|
that a create() could be used to commit it to the DB.
|
||||||
"""
|
"""
|
||||||
db_audit = db_utils.get_test_audit(**kw)
|
obj_cls = objects.Audit
|
||||||
obj_data = _load_related_objects(context, objects.Audit, db_audit)
|
db_data = db_utils.get_test_audit(**kw)
|
||||||
|
obj_data = _load_related_objects(context, obj_cls, db_data)
|
||||||
|
|
||||||
# Let DB generate ID if it isn't specified explicitly
|
return _load_test_obj(context, obj_cls, obj_data, **kw)
|
||||||
if 'id' not in kw:
|
|
||||||
del db_audit['id']
|
|
||||||
audit = objects.Audit(context)
|
|
||||||
for key in obj_data:
|
|
||||||
setattr(audit, key, obj_data[key])
|
|
||||||
return audit
|
|
||||||
|
|
||||||
|
|
||||||
def create_test_audit(context, **kw):
|
def create_test_audit(context, **kw):
|
||||||
|
@ -93,14 +94,11 @@ def get_test_action_plan(context, **kw):
|
||||||
NOTE: The object leaves the attributes marked as changed, such
|
NOTE: The object leaves the attributes marked as changed, such
|
||||||
that a create() could be used to commit it to the DB.
|
that a create() could be used to commit it to the DB.
|
||||||
"""
|
"""
|
||||||
db_action_plan = db_utils.get_test_action_plan(**kw)
|
obj_cls = objects.ActionPlan
|
||||||
# Let DB generate ID if it isn't specified explicitly
|
db_data = db_utils.get_test_action_plan(**kw)
|
||||||
if 'id' not in kw:
|
obj_data = _load_related_objects(context, obj_cls, db_data)
|
||||||
del db_action_plan['id']
|
|
||||||
action_plan = objects.ActionPlan(context)
|
return _load_test_obj(context, obj_cls, obj_data, **kw)
|
||||||
for key in db_action_plan:
|
|
||||||
setattr(action_plan, key, db_action_plan[key])
|
|
||||||
return action_plan
|
|
||||||
|
|
||||||
|
|
||||||
def create_test_action_plan(context, **kw):
|
def create_test_action_plan(context, **kw):
|
||||||
|
@ -120,14 +118,11 @@ def get_test_action(context, **kw):
|
||||||
NOTE: The object leaves the attributes marked as changed, such
|
NOTE: The object leaves the attributes marked as changed, such
|
||||||
that a create() could be used to commit it to the DB.
|
that a create() could be used to commit it to the DB.
|
||||||
"""
|
"""
|
||||||
db_action = db_utils.get_test_action(**kw)
|
obj_cls = objects.Action
|
||||||
# Let DB generate ID if it isn't specified explicitly
|
db_data = db_utils.get_test_action(**kw)
|
||||||
if 'id' not in kw:
|
obj_data = _load_related_objects(context, obj_cls, db_data)
|
||||||
del db_action['id']
|
|
||||||
action = objects.Action(context)
|
return _load_test_obj(context, obj_cls, obj_data, **kw)
|
||||||
for key in db_action:
|
|
||||||
setattr(action, key, db_action[key])
|
|
||||||
return action
|
|
||||||
|
|
||||||
|
|
||||||
def create_test_action(context, **kw):
|
def create_test_action(context, **kw):
|
||||||
|
@ -147,14 +142,11 @@ def get_test_goal(context, **kw):
|
||||||
NOTE: The object leaves the attributes marked as changed, such
|
NOTE: The object leaves the attributes marked as changed, such
|
||||||
that a create() could be used to commit it to the DB.
|
that a create() could be used to commit it to the DB.
|
||||||
"""
|
"""
|
||||||
db_goal = db_utils.get_test_goal(**kw)
|
obj_cls = objects.Goal
|
||||||
# Let DB generate ID if it isn't specified explicitly
|
db_data = db_utils.get_test_goal(**kw)
|
||||||
if 'id' not in kw:
|
obj_data = _load_related_objects(context, obj_cls, db_data)
|
||||||
del db_goal['id']
|
|
||||||
goal = objects.Goal(context)
|
return _load_test_obj(context, obj_cls, obj_data, **kw)
|
||||||
for key in db_goal:
|
|
||||||
setattr(goal, key, db_goal[key])
|
|
||||||
return goal
|
|
||||||
|
|
||||||
|
|
||||||
def create_test_goal(context, **kw):
|
def create_test_goal(context, **kw):
|
||||||
|
@ -174,11 +166,11 @@ def get_test_scoring_engine(context, **kw):
|
||||||
NOTE: The object leaves the attributes marked as changed, such
|
NOTE: The object leaves the attributes marked as changed, such
|
||||||
that a create() could be used to commit it to the DB.
|
that a create() could be used to commit it to the DB.
|
||||||
"""
|
"""
|
||||||
db_scoring_engine = db_utils.get_test_scoring_engine(**kw)
|
obj_cls = objects.ScoringEngine
|
||||||
scoring_engine = objects.ScoringEngine(context)
|
db_data = db_utils.get_test_scoring_engine(**kw)
|
||||||
for key in db_scoring_engine:
|
obj_data = _load_related_objects(context, obj_cls, db_data)
|
||||||
setattr(scoring_engine, key, db_scoring_engine[key])
|
|
||||||
return scoring_engine
|
return _load_test_obj(context, obj_cls, obj_data, **kw)
|
||||||
|
|
||||||
|
|
||||||
def create_test_scoring_engine(context, **kw):
|
def create_test_scoring_engine(context, **kw):
|
||||||
|
@ -198,13 +190,11 @@ def get_test_service(context, **kw):
|
||||||
NOTE: The object leaves the attributes marked as changed, such
|
NOTE: The object leaves the attributes marked as changed, such
|
||||||
that a create() could be used to commit it to the DB.
|
that a create() could be used to commit it to the DB.
|
||||||
"""
|
"""
|
||||||
db_service = db_utils.get_test_service(**kw)
|
obj_cls = objects.Service
|
||||||
service = objects.Service(context)
|
db_data = db_utils.get_test_service(**kw)
|
||||||
for key in db_service:
|
obj_data = _load_related_objects(context, obj_cls, db_data)
|
||||||
if key == 'last_seen_up':
|
|
||||||
db_service[key] = None
|
return _load_test_obj(context, obj_cls, obj_data, **kw)
|
||||||
setattr(service, key, db_service[key])
|
|
||||||
return service
|
|
||||||
|
|
||||||
|
|
||||||
def create_test_service(context, **kw):
|
def create_test_service(context, **kw):
|
||||||
|
@ -224,22 +214,11 @@ def get_test_strategy(context, **kw):
|
||||||
NOTE: The object leaves the attributes marked as changed, such
|
NOTE: The object leaves the attributes marked as changed, such
|
||||||
that a create() could be used to commit it to the DB.
|
that a create() could be used to commit it to the DB.
|
||||||
"""
|
"""
|
||||||
db_strategy = db_utils.get_test_strategy(**kw)
|
obj_cls = objects.Strategy
|
||||||
# Let DB generate ID if it isn't specified explicitly
|
db_data = db_utils.get_test_strategy(**kw)
|
||||||
if 'id' not in kw:
|
obj_data = _load_related_objects(context, obj_cls, db_data)
|
||||||
del db_strategy['id']
|
|
||||||
strategy = objects.Strategy(context)
|
|
||||||
for key in db_strategy:
|
|
||||||
setattr(strategy, key, db_strategy[key])
|
|
||||||
|
|
||||||
# ObjectField checks for the object type, so if we want to simulate a
|
return _load_test_obj(context, obj_cls, obj_data, **kw)
|
||||||
# non-eager object loading, the field should not be referenced at all.
|
|
||||||
# Contrarily, eager loading need the data to be casted to the object type
|
|
||||||
# that was specified by the ObjectField.
|
|
||||||
if kw.get('goal'):
|
|
||||||
strategy.goal = objects.Goal(context, **kw.get('goal'))
|
|
||||||
|
|
||||||
return strategy
|
|
||||||
|
|
||||||
|
|
||||||
def create_test_strategy(context, **kw):
|
def create_test_strategy(context, **kw):
|
||||||
|
@ -259,14 +238,11 @@ def get_test_efficacy_indicator(context, **kw):
|
||||||
NOTE: The object leaves the attributes marked as changed, such
|
NOTE: The object leaves the attributes marked as changed, such
|
||||||
that a create() could be used to commit it to the DB.
|
that a create() could be used to commit it to the DB.
|
||||||
"""
|
"""
|
||||||
db_efficacy_indicator = db_utils.get_test_efficacy_indicator(**kw)
|
obj_cls = objects.EfficacyIndicator
|
||||||
# Let DB generate ID if it isn't specified explicitly
|
db_data = db_utils.get_test_efficacy_indicator(**kw)
|
||||||
if 'id' not in kw:
|
obj_data = _load_related_objects(context, obj_cls, db_data)
|
||||||
del db_efficacy_indicator['id']
|
|
||||||
efficacy_indicator = objects.EfficacyIndicator(context)
|
return _load_test_obj(context, obj_cls, obj_data, **kw)
|
||||||
for key in db_efficacy_indicator:
|
|
||||||
setattr(efficacy_indicator, key, db_efficacy_indicator[key])
|
|
||||||
return efficacy_indicator
|
|
||||||
|
|
||||||
|
|
||||||
def create_test_efficacy_indicator(context, **kw):
|
def create_test_efficacy_indicator(context, **kw):
|
||||||
|
|
Loading…
Reference in New Issue