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:
Vincent Françoise 2017-01-24 11:08:08 +01:00
parent ea1fd5967a
commit e51e7e4317
33 changed files with 986 additions and 112 deletions

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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": {

View File

@ -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": {

View File

@ -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": {

View File

@ -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": {

View File

@ -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": {

View File

@ -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": {

View File

@ -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": {

View File

@ -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": {

View File

@ -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": {

View File

@ -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')

View File

@ -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()

View File

@ -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")

View File

@ -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 "

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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):

View File

@ -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()

View File

@ -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):

View File

@ -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', []),

View File

@ -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')

View File

@ -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)])

View File

@ -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)

View File

@ -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)

View File

@ -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
)

View File

@ -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",

View File

@ -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',
} }

View File

@ -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(

View File

@ -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(),

View File

@ -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):