def setUp(self): super(TestField, self).setUp() self.field = fields.StringField() self.coerce_good_values = [('foo', 'foo'), (1, '1'), (1L, '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 TestableObject(obj_base.CinderObject): fields = { 'uuid': fields.StringField(), } def __eq__(self, value): # NOTE(danms): Be rather lax about this equality thing to # satisfy the assertEqual() in test_from_primitive(). We # just want to make sure the right type of object is re-created return value.__class__.__name__ == TestableObject.__name__
class Volume(base.CinderPersistentObject, base.CinderObject, base.CinderObjectDictCompat): # Version 1.0: Initial version VERSION = '1.0' fields = { 'id': fields.UUIDField(), '_name_id': fields.UUIDField(nullable=True), 'ec2_id': fields.UUIDField(nullable=True), 'user_id': fields.UUIDField(nullable=True), 'project_id': fields.UUIDField(nullable=True), 'snapshot_id': fields.UUIDField(nullable=True), 'host': fields.StringField(nullable=True), 'size': fields.IntegerField(), 'availability_zone': fields.StringField(), 'status': fields.StringField(), 'attach_status': fields.StringField(), 'migration_status': fields.StringField(nullable=True), 'scheduled_at': fields.DateTimeField(nullable=True), 'launched_at': fields.DateTimeField(nullable=True), 'terminated_at': fields.DateTimeField(nullable=True), 'display_name': fields.StringField(nullable=True), 'display_description': fields.StringField(nullable=True), 'provider_id': fields.UUIDField(nullable=True), 'provider_location': fields.StringField(nullable=True), 'provider_auth': fields.StringField(nullable=True), 'provider_geometry': fields.StringField(nullable=True), 'volume_type_id': fields.UUIDField(nullable=True), 'source_volid': fields.UUIDField(nullable=True), 'encryption_key_id': fields.UUIDField(nullable=True), 'consistencygroup_id': fields.UUIDField(nullable=True), 'deleted': fields.BooleanField(default=False), 'bootable': fields.BooleanField(default=False), 'replication_status': fields.StringField(nullable=True), 'replication_extended_status': fields.StringField(nullable=True), 'replication_driver_data': fields.StringField(nullable=True), } # NOTE(thangp): obj_extra_fields is used to hold properties that are not # usually part of the model obj_extra_fields = ['name', 'name_id'] @property def name_id(self): return self.id if not self._name_id else self._name_id @name_id.setter def name_id(self, value): self._name_id = value @property def name(self): return CONF.volume_name_template % self.name_id def __init__(self, *args, **kwargs): super(Volume, self).__init__(*args, **kwargs) def obj_make_compatible(self, primitive, target_version): """Make an object representation compatible with a target version.""" target_version = utils.convert_version_to_tuple(target_version) @staticmethod def _from_db_object(context, volume, db_volume): for name, field in volume.fields.items(): value = db_volume[name] if isinstance(field, fields.IntegerField): value = value or 0 volume[name] = value volume._context = context volume.obj_reset_changes() return volume @base.remotable_classmethod def get_by_id(cls, context, id): db_volume = db.volume_get(context, id) return cls._from_db_object(context, cls(context), db_volume) @base.remotable def create(self, context): if self.obj_attr_is_set('id'): raise exception.ObjectActionError(action='create', reason=_('already created')) updates = self.obj_get_changes() db_volume = db.volume_create(context, updates) self._from_db_object(context, self, db_volume) @base.remotable def save(self, context): updates = self.obj_get_changes() if updates: db.volume_update(context, self.id, updates) self.obj_reset_changes() @base.remotable def destroy(self, context): db.volume_destroy(context, self.id)
class Bar(base.CinderObject): fields = {'uuid': fields.StringField()}
class Snapshot(base.CinderPersistentObject, base.CinderObject, base.CinderObjectDictCompat): # Version 1.0: Initial version VERSION = '1.0' fields = { 'id': fields.UUIDField(), 'user_id': fields.UUIDField(nullable=True), 'project_id': fields.UUIDField(nullable=True), 'volume_id': fields.UUIDField(), 'cgsnapshot_id': fields.UUIDField(nullable=True), 'status': fields.StringField(nullable=True), 'progress': fields.StringField(nullable=True), 'volume_size': fields.IntegerField(), 'display_name': fields.StringField(nullable=True), 'display_description': fields.StringField(nullable=True), 'encryption_key_id': fields.UUIDField(nullable=True), 'volume_type_id': fields.UUIDField(nullable=True), 'provider_location': fields.StringField(nullable=True), 'provider_id': fields.UUIDField(nullable=True), 'metadata': fields.DictOfStringsField(), 'volume': fields.ObjectField('Volume', nullable=True), } # NOTE(thangp): obj_extra_fields is used to hold properties that are not # usually part of the model obj_extra_fields = ['name', 'volume_name'] @property def name(self): return CONF.snapshot_name_template % self.id @property def volume_name(self): return self.volume.name def __init__(self, *args, **kwargs): super(Snapshot, self).__init__(*args, **kwargs) self._orig_metadata = {} self._reset_metadata_tracking() def obj_reset_changes(self, fields=None): super(Snapshot, self).obj_reset_changes(fields) self._reset_metadata_tracking(fields=fields) def _reset_metadata_tracking(self, fields=None): if fields is None or 'metadata' in fields: self._orig_metadata = (dict(self.metadata) if 'metadata' in self else {}) def obj_what_changed(self): changes = super(Snapshot, self).obj_what_changed() if 'metadata' in self and self.metadata != self._orig_metadata: changes.add('metadata') return changes def obj_make_compatible(self, primitive, target_version): """Make an object representation compatible with a target version.""" target_version = utils.convert_version_to_tuple(target_version) @staticmethod def _from_db_object(context, snapshot, db_snapshot, expected_attrs=None): if expected_attrs is None: expected_attrs = [] for name, field in snapshot.fields.items(): if name in OPTIONAL_FIELDS: continue value = db_snapshot.get(name) if isinstance(field, fields.IntegerField): value = value if value is not None else 0 snapshot[name] = value if 'volume' in expected_attrs: volume = objects.Volume(context) volume._from_db_object(context, volume, db_snapshot['volume']) snapshot.volume = volume if 'metadata' in expected_attrs: snapshot.metadata = db.snapshot_metadata_get( context, db_snapshot['id']) snapshot._context = context snapshot.obj_reset_changes() return snapshot @base.remotable_classmethod def get_by_id(cls, context, id): db_snapshot = db.snapshot_get(context, id) return cls._from_db_object(context, cls(context), db_snapshot, expected_attrs=['metadata']) @base.remotable def create(self, context): if self.obj_attr_is_set('id'): raise exception.ObjectActionError(action='create', reason=_('already created')) updates = self.obj_get_changes() if 'volume' in updates: raise exception.ObjectActionError(action='create', reason=_('volume assigned')) db_snapshot = db.snapshot_create(context, updates) self._from_db_object(context, self, db_snapshot) @base.remotable def save(self, context): updates = self.obj_get_changes() if updates: if 'volume' in updates: raise exception.ObjectActionError(action='save', reason=_('volume changed')) if 'metadata' in updates: # Metadata items that are not specified in the # self.metadata will be deleted metadata = updates.pop('metadata', None) self.metadata = db.snapshot_metadata_update( context, self.id, metadata, True) db.snapshot_update(context, self.id, updates) self.obj_reset_changes() @base.remotable def destroy(self, context): db.snapshot_destroy(context, self.id) def obj_load_attr(self, attrname): if attrname not in OPTIONAL_FIELDS: raise exception.ObjectActionError( action='obj_load_attr', reason=_('attribute %s not lazy-loadable') % attrname) if not self._context: raise exception.OrphanedObjectError(method='obj_load_attr', objtype=self.obj_name()) if attrname == 'volume': self.volume = objects.Volume.get_by_id(self._context, self.volume_id) self.obj_reset_changes(fields=[attrname]) def delete_metadata_key(self, context, key): db.snapshot_metadata_delete(context, self.id, key) md_was_changed = 'metadata' in self.obj_what_changed() del self.metadata[key] self._orig_metadata.pop(key, None) if not md_was_changed: self.obj_reset_changes(['metadata'])