# 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. # String literals representing events associated to data store operations BEFORE_CREATE = 'before_create' BEFORE_READ = 'before_read' BEFORE_UPDATE = 'before_update' BEFORE_DELETE = 'before_delete' PRECOMMIT_CREATE = 'precommit_create' PRECOMMIT_UPDATE = 'precommit_update' PRECOMMIT_DELETE = 'precommit_delete' PRECOMMIT_ADD_ASSOCIATION = 'precommit_add_association' PRECOMMIT_DELETE_ASSOCIATIONS = 'precommit_delete_associations' AFTER_CREATE = 'after_create' AFTER_READ = 'after_read' AFTER_UPDATE = 'after_update' AFTER_DELETE = 'after_delete' AFTER_STATUS_UPDATE = 'after_status_update' # String literals representing events associated to API operations BEFORE_RESPONSE = 'before_response' AFTER_REQUEST = 'after_request' # String literals representing events associated to process operations BEFORE_INIT = 'before_init' BEFORE_SPAWN = 'before_spawn' # sent per process AFTER_SPAWN = 'after_spawn' # sent per process AFTER_INIT = 'after_init' # sent per worker # String literals representing events associated to error conditions ABORT_CREATE = 'abort_create' ABORT_READ = 'abort_read' ABORT_UPDATE = 'abort_update' ABORT_DELETE = 'abort_delete' ABORT = 'abort_' BEFORE = 'before_' PRECOMMIT = 'precommit_' OVS_RESTARTED = 'ovs_restarted' def is_cancellable_event(event): """Return if an event is cancellable by definition""" return (event.startswith(BEFORE) or event.startswith(PRECOMMIT)) class EventPayload(object): """Base event payload object. This class is intended to be the super class for all event payloads. As such, it defines common attributes many events are likely to use in their payload. Note that event attributes are passed by reference; no copying of states, metadata or request_body is performed and thus consumers should not modify payload references. For more information, see the callbacks dev-ref documentation for this project. """ def __init__(self, context, metadata=None, request_body=None, states=None, resource_id=None): # the event context self.context = context # NOTE(boden): longer term we should consider removing metadata # optional 'unstructured' (key,value) pairs for special needs self.metadata = metadata if metadata else {} # the request body associated to the resource self.request_body = request_body # an iterable of states for the resource from the newest to the oldest # for example db states or api request/response # the actual object type for states will vary depending on event caller self.states = states if states else [] # a unique ID for the event resource; may be None if the resource # isn't created yet self.resource_id = resource_id @property def has_states(self): """Determines if this event payload has any states. :returns: True if this event payload has states, otherwise False. """ return len(self.states) > 0 @property def latest_state(self): """Returns the latest state for the event payload. :returns: The last state of this event payload if has_state else None. """ return self.states[-1] if self.has_states else None class DBEventPayload(EventPayload): """The payload for data store events payloads.""" def __init__(self, context, metadata=None, request_body=None, states=None, resource_id=None, desired_state=None): super().__init__( context, metadata=metadata, request_body=request_body, states=states, resource_id=resource_id) # the model object to be persisted in pre create/commit payloads self.desired_state = desired_state @property def is_persisted(self): """Determine if the resource for this event payload is persisted. :returns: True if this payload's resource is persisted, otherwise False. """ return self.resource_id is not None and self.has_states @property def is_to_be_committed(self): """"Determine if the event payload resource is to be committed. :returns: True if the desired state has been populated, else False. """ return self.desired_state is not None @property def latest_state(self): """Returns the latest state for the event payload resource. :returns: If this payload has a desired_state its returned, otherwise latest_state is returned. """ return (self.desired_state or super().latest_state) class APIEventPayload(EventPayload): """The payload for API events.""" def __init__(self, context, method_name, action, metadata=None, request_body=None, states=None, resource_id=None, collection_name=None): super().__init__( context, metadata=metadata, request_body=request_body, states=states, resource_id=resource_id) self.method_name = method_name self.action = action self.collection_name = collection_name