284 lines
8.7 KiB
Python
284 lines
8.7 KiB
Python
# 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 inspect
|
|
|
|
from senlin.common import messaging
|
|
from senlin.objects import base
|
|
from senlin.objects import fields
|
|
|
|
|
|
@base.SenlinObjectRegistry.register_if(False)
|
|
class NotificationObject(base.SenlinObject):
|
|
"""Base class for all notification related versioned objects."""
|
|
VERSION = '1.0'
|
|
|
|
def __init__(self, **kwargs):
|
|
# The notification objects are created on the fly so every field is
|
|
# shown as changed. We reset the object after creation to avoid
|
|
# sending such meaningless information.
|
|
super(NotificationObject, self).__init__(**kwargs)
|
|
self.obj_reset_changes(recursive=False)
|
|
|
|
|
|
@base.SenlinObjectRegistry.register_notification
|
|
class EventType(NotificationObject):
|
|
VERSION = '1.0'
|
|
|
|
fields = {
|
|
'object': fields.StringField(nullable=False),
|
|
'action': fields.StringField(nullable=False),
|
|
'phase': fields.NotificationPhaseField(nullable=True),
|
|
}
|
|
|
|
def to_notification_field(self):
|
|
"""Serialize the object to the wire format."""
|
|
s = '%s.%s' % (self.object, self.action)
|
|
if self.obj_attr_is_set('phase'):
|
|
s += '.%s' % self.phase
|
|
return s
|
|
|
|
|
|
@base.SenlinObjectRegistry.register_notification
|
|
class NotificationPublisher(NotificationObject):
|
|
VERSION = '1.0'
|
|
|
|
fields = {
|
|
'host': fields.StringField(),
|
|
'binary': fields.StringField(),
|
|
}
|
|
|
|
@classmethod
|
|
def from_service(cls, service):
|
|
return cls(host=service.host, binary=service.binary)
|
|
|
|
@property
|
|
def publisher_id(self):
|
|
return '%s:%s' % (self.binary, self.host)
|
|
|
|
|
|
@base.SenlinObjectRegistry.register_if(False)
|
|
class NotificationBase(NotificationObject):
|
|
"""Base class for versioned notifications.
|
|
|
|
Every subclass shall define a 'payload' field.
|
|
"""
|
|
VERSION = '1.0'
|
|
|
|
fields = {
|
|
'priority': fields.NotificationPriorityField(),
|
|
'event_type': fields.ObjectField('EventType'),
|
|
'publisher': fields.ObjectField('NotificationPublisher'),
|
|
}
|
|
|
|
def _emit(self, context, event_type, publisher_id, payload):
|
|
notifier = messaging.get_notifier(publisher_id)
|
|
notify = getattr(notifier, self.priority)
|
|
notify(context, event_type, payload)
|
|
|
|
def emit(self, context):
|
|
"""Send the notification."""
|
|
self.payload.obj_reset_changes(recursive=False)
|
|
self._emit(context,
|
|
self.event_type.to_notification_field(),
|
|
self.publisher.publisher_id,
|
|
self.payload.obj_to_primitive())
|
|
|
|
|
|
@base.SenlinObjectRegistry.register_notification
|
|
class ExceptionPayload(NotificationObject):
|
|
|
|
VERSION = '1.0'
|
|
|
|
fields = {
|
|
'module': fields.StringField(),
|
|
'function': fields.StringField(),
|
|
'exception': fields.StringField(),
|
|
'message': fields.StringField(),
|
|
}
|
|
|
|
@classmethod
|
|
def from_exception(cls, exc):
|
|
if exc is None:
|
|
return None
|
|
trace = inspect.trace()[-1]
|
|
module = inspect.getmodule(trace[0])
|
|
module_name = module.__name__ if module else 'unknown'
|
|
return cls(function=trace[3], module=module_name,
|
|
exception=exc.__class__.__name__,
|
|
message=str(exc))
|
|
|
|
|
|
@base.SenlinObjectRegistry.register_notification
|
|
class ClusterPayload(NotificationObject):
|
|
|
|
VERSION = '1.0'
|
|
|
|
fields = {
|
|
'id': fields.UUIDField(),
|
|
'name': fields.StringField(),
|
|
'profile_id': fields.UUIDField(),
|
|
'init_at': fields.DateTimeField(),
|
|
'created_at': fields.DateTimeField(nullable=True),
|
|
'updated_at': fields.DateTimeField(nullable=True),
|
|
'min_size': fields.IntegerField(),
|
|
'max_size': fields.IntegerField(),
|
|
'desired_capacity': fields.IntegerField(),
|
|
'timeout': fields.IntegerField(),
|
|
'status': fields.StringField(),
|
|
'status_reason': fields.StringField(),
|
|
'metadata': fields.JsonField(nullable=True),
|
|
'data': fields.JsonField(nullable=True),
|
|
'user': fields.StringField(),
|
|
'project': fields.StringField(),
|
|
'domain': fields.StringField(nullable=True),
|
|
'dependents': fields.JsonField(nullable=True),
|
|
}
|
|
|
|
@classmethod
|
|
def from_cluster(cls, cluster):
|
|
values = {}
|
|
for field in cls.fields:
|
|
values[field] = getattr(cluster, field)
|
|
obj = cls(**values)
|
|
obj.obj_reset_changes(recursive=False)
|
|
return obj
|
|
|
|
|
|
@base.SenlinObjectRegistry.register_notification
|
|
class NodePayload(NotificationObject):
|
|
|
|
VERSION = '1.0'
|
|
|
|
fields = {
|
|
'id': fields.UUIDField(),
|
|
'name': fields.StringField(),
|
|
'profile_id': fields.UUIDField(),
|
|
'cluster_id': fields.StringField(),
|
|
'physical_id': fields.StringField(nullable=True),
|
|
'index': fields.IntegerField(),
|
|
'role': fields.StringField(nullable=True),
|
|
'init_at': fields.DateTimeField(),
|
|
'created_at': fields.DateTimeField(nullable=True),
|
|
'updated_at': fields.DateTimeField(nullable=True),
|
|
'status': fields.StringField(),
|
|
'status_reason': fields.StringField(),
|
|
'metadata': fields.JsonField(nullable=True),
|
|
'data': fields.JsonField(nullable=True),
|
|
'user': fields.StringField(),
|
|
'project': fields.StringField(),
|
|
'domain': fields.StringField(nullable=True),
|
|
'dependents': fields.JsonField(nullable=True),
|
|
}
|
|
|
|
@classmethod
|
|
def from_node(cls, node):
|
|
values = {}
|
|
for field in cls.fields:
|
|
values[field] = getattr(node, field)
|
|
obj = cls(**values)
|
|
obj.obj_reset_changes(recursive=False)
|
|
return obj
|
|
|
|
|
|
@base.SenlinObjectRegistry.register_notification
|
|
class ActionPayload(NotificationObject):
|
|
|
|
VERSION = '1.0'
|
|
|
|
fields = {
|
|
'id': fields.UUIDField(),
|
|
'name': fields.StringField(),
|
|
'created_at': fields.DateTimeField(nullable=True),
|
|
'target': fields.UUIDField(),
|
|
'action': fields.StringField(),
|
|
'start_time': fields.FloatField(),
|
|
'end_time': fields.FloatField(nullable=True),
|
|
'timeout': fields.IntegerField(nullable=True),
|
|
'status': fields.StringField(),
|
|
'status_reason': fields.StringField(),
|
|
'inputs': fields.JsonField(nullable=True),
|
|
'outputs': fields.JsonField(nullable=True),
|
|
'data': fields.JsonField(nullable=True),
|
|
'user': fields.StringField(),
|
|
'project': fields.StringField(),
|
|
}
|
|
|
|
@classmethod
|
|
def from_action(cls, action):
|
|
values = {}
|
|
for field in cls.fields:
|
|
values[field] = getattr(action, field)
|
|
obj = cls(**values)
|
|
obj.obj_reset_changes(recursive=False)
|
|
return obj
|
|
|
|
|
|
@base.SenlinObjectRegistry.register_notification
|
|
class ClusterActionPayload(NotificationObject):
|
|
|
|
VERSION = '1.0'
|
|
|
|
fields = {
|
|
'cluster': fields.ObjectField('ClusterPayload'),
|
|
'action': fields.ObjectField('ActionPayload'),
|
|
'exception': fields.ObjectField('ExceptionPayload', nullable=True),
|
|
}
|
|
|
|
def __init__(self, cluster, action, **kwargs):
|
|
ex = kwargs.pop('exception', None)
|
|
super(ClusterActionPayload, self).__init__(
|
|
cluster=ClusterPayload.from_cluster(cluster),
|
|
action=ActionPayload.from_action(action),
|
|
exception=ex,
|
|
**kwargs)
|
|
|
|
|
|
@base.SenlinObjectRegistry.register_notification
|
|
class NodeActionPayload(NotificationObject):
|
|
|
|
VERSION = '1.0'
|
|
|
|
fields = {
|
|
'node': fields.ObjectField('NodePayload'),
|
|
'action': fields.ObjectField('ActionPayload'),
|
|
'exception': fields.ObjectField('ExceptionPayload', nullable=True),
|
|
}
|
|
|
|
def __init__(self, node, action, **kwargs):
|
|
ex = kwargs.pop('exception', None)
|
|
super(NodeActionPayload, self).__init__(
|
|
node=NodePayload.from_node(node),
|
|
action=ActionPayload.from_action(action),
|
|
exception=ex,
|
|
**kwargs)
|
|
|
|
|
|
@base.SenlinObjectRegistry.register_notification
|
|
class ClusterActionNotification(NotificationBase):
|
|
|
|
VERSION = '1.0'
|
|
|
|
fields = {
|
|
'payload': fields.ObjectField('ClusterActionPayload')
|
|
}
|
|
|
|
|
|
@base.SenlinObjectRegistry.register_notification
|
|
class NodeActionNotification(NotificationBase):
|
|
|
|
VERSION = '1.0'
|
|
|
|
fields = {
|
|
'payload': fields.ObjectField('NodeActionPayload')
|
|
}
|