From 08fb09e878dcaedbb446e18502a6172fa4d43121 Mon Sep 17 00:00:00 2001 From: Balazs Gibizer Date: Fri, 8 Jun 2018 17:57:07 +0200 Subject: [PATCH] Fix unbound local when saving an unchanged RequestSpec RequestSpec._get_update_primitives() tried to return the unitialized db_updates field when the object has no changes. This patch initalizes that local to None and handles that None in create() and save() where the RequestSpec._get_update_primitives() is called. Change-Id: Iad256079945bf8b5745ebdcc393c55115dbcab75 Closes-Bug: #1775863 --- nova/objects/request_spec.py | 13 +++++++++---- nova/tests/unit/objects/test_request_spec.py | 10 ++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/nova/objects/request_spec.py b/nova/objects/request_spec.py index 5db3d26a89b7..2119f90bf205 100644 --- a/nova/objects/request_spec.py +++ b/nova/objects/request_spec.py @@ -513,6 +513,7 @@ class RequestSpec(base.NovaObject): it was originally scheduled with. """ updates = self.obj_get_changes() + db_updates = None # NOTE(alaski): The db schema is the full serialized object in a # 'spec' column. If anything has changed we rewrite the full thing. if updates: @@ -538,7 +539,9 @@ class RequestSpec(base.NovaObject): reason='already created') updates = self._get_update_primitives() - + if not updates: + raise exception.ObjectActionError(action='create', + reason='no fields are set') db_spec = self._create_in_db(self._context, updates) self._from_db_object(self._context, self, db_spec) @@ -556,9 +559,11 @@ class RequestSpec(base.NovaObject): @base.remotable def save(self): updates = self._get_update_primitives() - db_spec = self._save_in_db(self._context, self.instance_uuid, updates) - self._from_db_object(self._context, self, db_spec) - self.obj_reset_changes() + if updates: + db_spec = self._save_in_db(self._context, self.instance_uuid, + updates) + self._from_db_object(self._context, self, db_spec) + self.obj_reset_changes() @staticmethod @db.api_context_manager.writer diff --git a/nova/tests/unit/objects/test_request_spec.py b/nova/tests/unit/objects/test_request_spec.py index 2ae92adbe03a..4649327cbb87 100644 --- a/nova/tests/unit/objects/test_request_spec.py +++ b/nova/tests/unit/objects/test_request_spec.py @@ -667,6 +667,16 @@ class _TestRequestSpecObject(object): primitive = destination.obj_to_primitive(target_version='1.0') self.assertNotIn('aggregates', primitive['nova_object.data']) + def test_create_raises_on_unchanged_object(self): + ctxt = context.RequestContext(uuids.user_id, uuids.project_id) + req_obj = request_spec.RequestSpec(context=ctxt) + self.assertRaises(exception.ObjectActionError, req_obj.create) + + def test_save_can_be_called_on_unchanged_object(self): + req_obj = fake_request_spec.fake_spec_obj(remove_id=True) + req_obj.create() + req_obj.save() + class TestRequestSpecObject(test_objects._LocalTest, _TestRequestSpecObject):