diff --git a/cinder/objects/base.py b/cinder/objects/base.py index d9a6af56664..fdfb7dffa40 100644 --- a/cinder/objects/base.py +++ b/cinder/objects/base.py @@ -410,14 +410,10 @@ class CinderPersistentObject(object): current = self.get_by_id(self._context, self.id) - for field in self.fields: - # Only update attributes that are already set. We do not want to - # unexpectedly trigger a lazy-load. - if self.obj_attr_is_set(field): - current_field = getattr(current, field) - if getattr(self, field) != current_field: - setattr(self, field, current_field) - self.obj_reset_changes() + # Copy contents retrieved from the DB into self + my_data = vars(self) + my_data.clear() + my_data.update(vars(current)) @classmethod def exists(cls, context, id_): diff --git a/cinder/tests/unit/objects/test_base.py b/cinder/tests/unit/objects/test_base.py index 072acaf2069..0a7781db433 100644 --- a/cinder/tests/unit/objects/test_base.py +++ b/cinder/tests/unit/objects/test_base.py @@ -94,6 +94,23 @@ class TestCinderObject(test_objects.BaseObjectsTestCase): test_obj.refresh() self._compare(self, refresh_obj, test_obj) + @mock.patch('cinder.objects.base.CinderPersistentObject.get_by_id') + def test_refresh_readonly(self, get_by_id_mock): + @objects.base.CinderObjectRegistry.register_if(False) + class MyTestObject(objects.base.CinderObject, + objects.base.CinderObjectDictCompat, + objects.base.CinderComparableObject, + objects.base.CinderPersistentObject): + fields = {'id': fields.UUIDField(), + 'name': fields.StringField(read_only=True)} + + test_obj = MyTestObject(id=fake.OBJECT_ID, name='foo') + refresh_obj = MyTestObject(id=fake.OBJECT_ID, name='bar') + get_by_id_mock.return_value = refresh_obj + + test_obj.refresh() + self._compare(self, refresh_obj, test_obj) + def test_refresh_no_id_field(self): @objects.base.CinderObjectRegistry.register_if(False) class MyTestObjectNoId(objects.base.CinderObject,