class NotificationBase(NotificationObject): """Base class for versioned notifications. Every subclass shall define a 'payload' field. """ # Version 1.0: Initial version VERSION = '1.0' fields = { 'priority': fields.EventNotificationPriorityField(), 'event_type': fields.ObjectField('EventType'), 'publisher': fields.ObjectField('NotificationPublisher'), } def _emit(self, context, event_type, publisher_id, payload): notifier = rpc.get_versioned_notifier(publisher_id) notify = getattr(notifier, self.priority) notify(context, event_type=event_type, payload=payload) def emit(self, context): """Send the notification.""" assert self.payload.populated # notification payload will be a newly populated object # therefore every field of it will look changed so this does not carry # any extra information so we drop this from the payload. self.payload.obj_reset_changes(recursive=False) self._emit(context, event_type=self.event_type.to_notification_event_type_field(), publisher_id='%s:%s' % (self.publisher.binary, self.publisher.host), payload=self.payload.obj_to_primitive())
class HostApiPayloadBase(base.NotificationPayloadBase): SCHEMA = { 'id': ('host', 'id'), 'uuid': ('host', 'uuid'), 'name': ('host', 'name'), 'failover_segment_id': ('host', 'failover_segment_id'), 'failover_segment': ('host', 'failover_segment'), 'type': ('host', 'type'), 'reserved': ('host', 'reserved'), 'control_attributes': ('host', 'control_attributes'), 'on_maintenance': ('host', 'on_maintenance'), } # Version 1.0: Initial version VERSION = '1.0' fields = { 'id': fields.IntegerField(), 'uuid': fields.UUIDField(), 'name': fields.StringField(), 'failover_segment_id': fields.UUIDField(), 'failover_segment': fields.ObjectField('FailoverSegment'), 'type': fields.StringField(), 'reserved': fields.BooleanField(), 'control_attributes': fields.StringField(), 'on_maintenance': fields.BooleanField(), } def __init__(self, host, **kwargs): super(HostApiPayloadBase, self).__init__(**kwargs) self.populate_schema(host=host)
class HostApiPayload(HostApiPayloadBase): # No SCHEMA as all the additional fields are calculated VERSION = '1.0' fields = { 'fault': fields.ObjectField('ExceptionPayload', nullable=True), } def __init__(self, host, fault, **kwargs): super(HostApiPayload, self).__init__(host=host, fault=fault, **kwargs)
class NotificationApiPayload(NotificationApiPayloadBase): # No SCHEMA as all the additional fields are calculated VERSION = '1.0' fields = { 'fault': fields.ObjectField('ExceptionPayload', nullable=True), } def __init__(self, notification, fault, **kwargs): super(NotificationApiPayload, self).__init__(notification=notification, fault=fault, **kwargs)
class Host(base.MasakariPersistentObject, base.MasakariObject, base.MasakariObjectDictCompat): # Version 1.0: Initial version # Version 1.1: Added 'segment_uuid' parameter to 'get_by_uuid' method VERSION = '1.1' fields = { 'id': fields.IntegerField(), 'uuid': fields.UUIDField(), 'name': fields.StringField(), 'failover_segment_id': fields.UUIDField(), 'failover_segment': fields.ObjectField('FailoverSegment'), 'type': fields.StringField(), 'reserved': fields.BooleanField(), 'control_attributes': fields.StringField(), 'on_maintenance': fields.BooleanField(), } @staticmethod def _from_db_object(context, host, db_host): for key in host.fields: db_value = db_host.get(key) if key == "failover_segment": db_value = objects.FailoverSegment._from_db_object( host._context, objects.FailoverSegment(), db_value) setattr(host, key, db_value) host.obj_reset_changes() host._context = context return host @base.remotable_classmethod def get_by_id(cls, context, id): db_inst = db.host_get_by_id(context, id) return cls._from_db_object(context, cls(), db_inst) @base.remotable_classmethod def get_by_uuid(cls, context, uuid, segment_uuid=None): db_inst = db.host_get_by_uuid(context, uuid, segment_uuid=segment_uuid) return cls._from_db_object(context, cls(), db_inst) @base.remotable_classmethod def get_by_name(cls, context, name): db_inst = db.host_get_by_name(context, name) return cls._from_db_object(context, cls(), db_inst) @base.remotable def create(self): if self.obj_attr_is_set('id'): raise exception.ObjectActionError(action='create', reason='already created') updates = self.masakari_obj_get_changes() if 'uuid' not in updates: updates['uuid'] = uuidutils.generate_uuid() LOG.debug('Generated uuid %(uuid)s for host', dict(uuid=updates['uuid'])) if 'failover_segment' in updates: raise exception.ObjectActionError(action='create', reason='failover segment ' 'assigned') api_utils.notify_about_host_api( self._context, self, action=fields.EventNotificationAction.HOST_CREATE, phase=fields.EventNotificationPhase.START) db_host = db.host_create(self._context, updates) api_utils.notify_about_host_api( self._context, self, action=fields.EventNotificationAction.HOST_CREATE, phase=fields.EventNotificationPhase.END) self._from_db_object(self._context, self, db_host) @base.remotable def save(self): updates = self.masakari_obj_get_changes() if 'failover_segment' in updates: raise exception.ObjectActionError(action='save', reason='failover segment ' 'changed') updates.pop('id', None) api_utils.notify_about_host_api( self._context, self, action=fields.EventNotificationAction.HOST_UPDATE, phase=fields.EventNotificationPhase.START) db_host = db.host_update(self._context, self.uuid, updates) api_utils.notify_about_host_api( self._context, self, action=fields.EventNotificationAction.HOST_UPDATE, phase=fields.EventNotificationPhase.END) self._from_db_object(self._context, self, db_host) @base.remotable def destroy(self): if not self.obj_attr_is_set('id'): raise exception.ObjectActionError(action='destroy', reason='already destroyed') if not self.obj_attr_is_set('uuid'): raise exception.ObjectActionError(action='destroy', reason='no uuid') api_utils.notify_about_host_api( self._context, self, action=fields.EventNotificationAction.HOST_DELETE, phase=fields.EventNotificationPhase.START) db.host_delete(self._context, self.uuid) api_utils.notify_about_host_api( self._context, self, action=fields.EventNotificationAction.HOST_DELETE, phase=fields.EventNotificationPhase.END) delattr(self, base.get_attrname('id'))
class NotificationApiNotification(base.NotificationBase): # Version 1.0: Initial version VERSION = '1.0' fields = {'payload': fields.ObjectField('NotificationApiPayload')}
class MyOwner(base.MasakariObject): VERSION = '1.2' fields = {'mylist': fields.ObjectField('MyList')} obj_relationships = { 'mylist': [('1.1', '1.1')], }
class ParentObject(base.MasakariObject): fields = { 'foo': fields.IntegerField(), 'bar': fields.ObjectField('MyObj'), }
class MyObj(base.MasakariPersistentObject, base.MasakariObject, base.MasakariObjectDictCompat): VERSION = '1.6' fields = { 'foo': fields.IntegerField(default=1), 'bar': fields.StringField(), 'missing': fields.StringField(), 'readonly': fields.IntegerField(read_only=True), 'rel_object': fields.ObjectField('MyOwnedObject', nullable=True), 'rel_objects': fields.ListOfObjectsField('MyOwnedObject', nullable=True), 'mutable_default': fields.ListOfStringsField(default=[]), } @staticmethod def _from_db_object(context, obj, db_obj): self = MyObj() self.foo = db_obj['foo'] self.bar = db_obj['bar'] self.missing = db_obj['missing'] self.readonly = 1 self._context = context return self def obj_load_attr(self, attrname): setattr(self, attrname, 'loaded!') @base.remotable_classmethod def query(cls, context): obj = cls(context=context, foo=1, bar='bar') obj.obj_reset_changes() return obj @base.remotable def marco(self): return 'polo' @base.remotable def _update_test(self): self.bar = 'updated' @base.remotable def save(self): self.obj_reset_changes() @base.remotable def refresh(self): self.foo = 321 self.bar = 'refreshed' self.obj_reset_changes() @base.remotable def modify_save_modify(self): self.bar = 'meow' self.save() self.foo = 42 self.rel_object = MyOwnedObject(baz=42) def obj_make_compatible(self, primitive, target_version): super(MyObj, self).obj_make_compatible(primitive, target_version) if target_version == '1.0' and 'bar' in primitive: primitive['bar'] = 'old%s' % primitive['bar']
class TestNotificationEmptySchema(notification.NotificationBase): VERSION = '1.0' fields = { 'payload': fields.ObjectField('TestNotificationPayloadEmptySchema') }
class ExceptionNotification(base.NotificationBase): # Version 1.0: Initial version VERSION = '1.0' fields = { 'payload': fields.ObjectField('ExceptionPayload') }