The following patch fixes a bug in the snapshot object,
where fields that are not part of the Snapshot model,
i.e. name and volume_name, were not specified as
obj_extra_fields in the object. It also fixes the same
problem in the volume object, i.e. name and name_id.
With this patch, those extra fields are properly loaded,
e.g. snapshot.volume_name or volume.name.
Change-Id: Ie2b8dc66c897f89f941e9ad3b80ec4f4ab346430
Closes-Bug: #
1429889
fields = {
'id': fields.UUIDField(),
- 'name': fields.StringField(nullable=True),
- 'volume_name': fields.StringField(nullable=True),
'user_id': fields.UUIDField(nullable=True),
'project_id': fields.UUIDField(nullable=True),
'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 = {}
raise exception.OrphanedObjectError(method='obj_load_attr',
objtype=self.obj_name())
- self.volume = objects.Volume.get_by_id(self._context, self.volume_id)
- self.obj_reset_changes(fields=['volume'])
+ 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)
'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
import mock
from cinder.objects import snapshot as snapshot_obj
+from cinder.objects import volume as volume_obj
from cinder.tests import fake_volume
from cinder.tests.objects import test_objects
snapshot_metadata_delete.assert_called_once_with(self.context, '1',
'key2')
+ def test_obj_fields(self):
+ volume = volume_obj.Volume(context=self.context, id=2, _name_id=2)
+ snapshot = snapshot_obj.Snapshot(context=self.context, id=1,
+ volume=volume)
+ self.assertEqual(['name', 'volume_name'], snapshot.obj_extra_fields)
+ self.assertEqual('snapshot-1', snapshot.name)
+ self.assertEqual('volume-2', snapshot.volume_name)
+
+ @mock.patch('cinder.objects.volume.Volume.get_by_id')
+ def test_obj_load_attr(self, volume_get_by_id):
+ snapshot = snapshot_obj.Snapshot._from_db_object(
+ self.context, snapshot_obj.Snapshot(), fake_snapshot)
+ volume = volume_obj.Volume(context=self.context, id=2)
+ volume_get_by_id.return_value = volume
+ self.assertEqual(volume, snapshot.volume)
+ volume_get_by_id.assert_called_once_with(self.context,
+ snapshot.volume_id)
+
class TestSnapshotList(test_objects._LocalTest):
@mock.patch('cinder.db.snapshot_metadata_get', return_value={})
volume.destroy()
volume_destroy.assert_called_once_with(self.context, '1')
+ def test_obj_fields(self):
+ volume = objects.Volume(context=self.context, id=2, _name_id=2)
+ self.assertEqual(['name', 'name_id'], volume.obj_extra_fields)
+ self.assertEqual('volume-2', volume.name)
+ self.assertEqual('2', volume.name_id)
+
class TestVolumeList(test_objects._LocalTest):
@mock.patch('cinder.db.volume_get_all')