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 NotificationProgressDetails(base.MasakariObject, base.MasakariObjectDictCompat): VERSION = '1.0' fields = { 'name': fields.StringField(), 'progress': fields.FloatField(), 'progress_details': fields.ListOfDictOfNullableStringsField(default=[]), 'state': fields.StringField() } @classmethod def create( cls, name, progress, progress_details, state, ): return cls(name=name, progress=progress, progress_details=progress_details, state=state)
class ExceptionPayload(base.NotificationPayloadBase): # Version 1.0: Initial version VERSION = '1.0' fields = { 'module_name': fields.StringField(), 'function_name': fields.StringField(), 'exception': fields.StringField(), 'exception_message': fields.StringField(), 'traceback': fields.StringField() } @classmethod def from_exc_and_traceback(cls, fault, traceback): trace = inspect.trace()[-1] # TODO(gibi): apply strutils.mask_password on exception_message and # consider emitting the exception_message only if the safe flag is # true in the exception like in the REST API module = inspect.getmodule(trace[0]) module_name = module.__name__ if module else 'unknown' return cls( function_name=trace[3], module_name=module_name, exception=fault.__class__.__name__, exception_message=six.text_type(fault), traceback=traceback)
class SegmentApiPayloadBase(base.NotificationPayloadBase): SCHEMA = { 'id': ('segment', 'id'), 'uuid': ('segment', 'uuid'), 'name': ('segment', 'name'), 'service_type': ('segment', 'service_type'), 'description': ('segment', 'description'), 'recovery_method': ('segment', 'recovery_method'), 'enabled': ('segment', 'enabled'), } # Version 1.0: Initial version # Version 1.1: Add 'enabled' field VERSION = '1.1' fields = { 'id': fields.IntegerField(), 'uuid': fields.UUIDField(), 'name': fields.StringField(), 'service_type': fields.StringField(), 'description': fields.StringField(nullable=True), 'recovery_method': fields.FailoverSegmentRecoveryMethodField(), 'enabled': fields.BooleanField(), } def __init__(self, segment, **kwargs): super(SegmentApiPayloadBase, self).__init__(**kwargs) self.populate_schema(segment=segment)
class ExceptionPayload(base.NotificationPayloadBase): # Version 1.0: Initial version VERSION = '1.0' fields = { 'module_name': fields.StringField(), 'function_name': fields.StringField(), 'exception': fields.StringField(), 'exception_message': fields.StringField(), 'traceback': fields.StringField() } @classmethod def from_exc_and_traceback(cls, fault, traceback): trace = inspect.trace() # FIXME(mgoddard): In some code paths we reach this point without being # inside an exception handler. This results in inspect.trace() # returning an empty list. Ideally we should only end up here from an # exception handler. if trace: trace = trace[-1] # TODO(gibi): apply strutils.mask_password on exception_message and # consider emitting the exception_message only if the safe flag is # true in the exception like in the REST API module = inspect.getmodule(trace[0]) function_name = trace[3] else: module = None function_name = 'unknown' module_name = module.__name__ if module else 'unknown' return cls( function_name=function_name, module_name=module_name, exception=fault.__class__.__name__, exception_message=six.text_type(fault), traceback=traceback)
class NotificationPublisher(NotificationObject): # Version 1.0: Initial version VERSION = '1.0' fields = { 'host': fields.StringField(nullable=False), 'binary': fields.StringField(nullable=False), } @classmethod def from_service_obj(cls, service): return cls(host=service.host, binary=service.binary)
class TestNotificationPayload(notification.NotificationPayloadBase): VERSION = '1.0' SCHEMA = { 'field_1': ('source_field', 'field_1'), 'field_2': ('source_field', 'field_2'), } fields = { 'extra_field': fields.StringField(), # filled by ctor 'field_1': fields.StringField(), # filled by the schema 'field_2': fields.IntegerField(), # filled by the schema }
class TestNotificationPayloadEmptySchema( notification.NotificationPayloadBase): VERSION = '1.0' fields = { 'extra_field': fields.StringField(), # filled by ctor }
class TestObject(base.MasakariObject): VERSION = '1.0' fields = { 'field_1': fields.StringField(), 'field_2': fields.IntegerField(), 'not_important_field': fields.IntegerField(), }
def setUp(self): super(TestString, self).setUp() self.field = fields.StringField() self.coerce_good_values = [('foo', 'foo'), (1, '1'), (True, 'True')] self.coerce_bad_values = [None] self.to_primitive_values = self.coerce_good_values[0:1] self.from_primitive_values = self.coerce_good_values[0:1]
class TestNotificationPayload(notification.NotificationPayloadBase): VERSION = '1.0' SCHEMA = { 'field_1': ('source_field', 'field_1'), 'field_2': ('source_field', 'field_2'), } fields = { 'extra_field': fields.StringField(), # filled by ctor 'field_1': fields.StringField(), # filled by the schema 'field_2': fields.IntegerField(), # filled by the schema } def populate_schema(self, source_field): super(TestNotificationBase.TestNotificationPayload, self).populate_schema(source_field=source_field)
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 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 FailoverSegment(base.MasakariPersistentObject, base.MasakariObject, base.MasakariObjectDictCompat): # 1.0, init # 1.1, add enabled field VERSION = '1.1' fields = { 'id': fields.IntegerField(), 'uuid': fields.UUIDField(), 'name': fields.StringField(), 'service_type': fields.StringField(), 'enabled': fields.BooleanField(default=True), 'description': fields.StringField(nullable=True), 'recovery_method': fields.FailoverSegmentRecoveryMethodField(), } def obj_make_compatible(self, primitive, target_version): super(FailoverSegment, self).obj_make_compatible(primitive, target_version) target_version = versionutils.convert_version_to_tuple(target_version) if target_version < (1, 1) and 'enabled' in primitive: del primitive['enabled'] @staticmethod def _from_db_object(context, segment, db_segment): for key in segment.fields: setattr(segment, key, db_segment[key]) segment._context = context segment.obj_reset_changes() return segment @base.remotable_classmethod def get_by_id(cls, context, id): db_inst = db.failover_segment_get_by_id(context, id) return cls._from_db_object(context, cls(), db_inst) @base.remotable_classmethod def get_by_uuid(cls, context, uuid): db_inst = db.failover_segment_get_by_uuid(context, uuid) return cls._from_db_object(context, cls(), db_inst) @base.remotable_classmethod def get_by_name(cls, context, name): db_inst = db.failover_segment_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 failover segment', dict(uuid=updates['uuid'])) api_utils.notify_about_segment_api( self._context, self, action=fields.EventNotificationAction.SEGMENT_CREATE, phase=fields.EventNotificationPhase.START) db_segment = db.failover_segment_create(self._context, updates) api_utils.notify_about_segment_api( self._context, self, action=fields.EventNotificationAction.SEGMENT_CREATE, phase=fields.EventNotificationPhase.END) self._from_db_object(self._context, self, db_segment) @base.remotable def save(self): updates = self.masakari_obj_get_changes() updates.pop('id', None) api_utils.notify_about_segment_api( self._context, self, action=fields.EventNotificationAction.SEGMENT_UPDATE, phase=fields.EventNotificationPhase.START) db_segment = db.failover_segment_update(self._context, self.uuid, updates) api_utils.notify_about_segment_api( self._context, self, action=fields.EventNotificationAction.SEGMENT_UPDATE, phase=fields.EventNotificationPhase.END) self._from_db_object(self._context, self, db_segment) @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_segment_api( self._context, self, action=fields.EventNotificationAction.SEGMENT_DELETE, phase=fields.EventNotificationPhase.START) db.failover_segment_delete(self._context, self.uuid) api_utils.notify_about_segment_api( self._context, self, action=fields.EventNotificationAction.SEGMENT_DELETE, phase=fields.EventNotificationPhase.END) delattr(self, base.get_attrname('id')) def is_under_recovery(self, filters=None): return db.is_failover_segment_under_recovery(self._context, self.uuid, filters=filters)
class FailoverSegment(base.MasakariPersistentObject, base.MasakariObject, base.MasakariObjectDictCompat): VERSION = '1.0' fields = { 'id': fields.IntegerField(), 'uuid': fields.UUIDField(), 'name': fields.StringField(), 'service_type': fields.StringField(), 'description': fields.StringField(nullable=True), 'recovery_method': fields.FailoverSegmentRecoveryMethodField(), } @staticmethod def _from_db_object(context, segment, db_segment): for key in segment.fields: setattr(segment, key, db_segment[key]) segment._context = context segment.obj_reset_changes() return segment @base.remotable_classmethod def get_by_id(cls, context, id): db_inst = db.failover_segment_get_by_id(context, id) return cls._from_db_object(context, cls(), db_inst) @base.remotable_classmethod def get_by_uuid(cls, context, uuid): db_inst = db.failover_segment_get_by_uuid(context, uuid) return cls._from_db_object(context, cls(), db_inst) @base.remotable_classmethod def get_by_name(cls, context, name): db_inst = db.failover_segment_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 failover segment', dict(uuid=updates['uuid'])) db_segment = db.failover_segment_create(self._context, updates) self._from_db_object(self._context, self, db_segment) @base.remotable def save(self): updates = self.masakari_obj_get_changes() updates.pop('id', None) db_segment = db.failover_segment_update(self._context, self.uuid, updates) self._from_db_object(self._context, self, db_segment) @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') db.failover_segment_delete(self._context, self.uuid) delattr(self, base.get_attrname('id')) def is_under_recovery(self, filters=None): return db.is_failover_segment_under_recovery(self._context, self.uuid, filters=filters)