From 041c2b168880281da0abaff6e8f9166272915224 Mon Sep 17 00:00:00 2001 From: Hampapur Ajay Date: Fri, 2 Oct 2015 12:23:14 -0700 Subject: [PATCH] Ignore update request when nothing has changed in object. In api client library, do not send update to server if none of the attributes were updated. In api server, ignore PUTs when there is no body or empty body. Change-Id: Ia060380abb737c4ed7c869af15e23375f99fff41 Closes-Bug: #1502237 --- src/api-lib/vnc_api.py | 16 +++++++++------ .../api-server/tests/test_crud_basic.py | 20 +++++++++++++++++++ src/config/api-server/vnc_cfg_api_server.py | 7 +++++++ 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/api-lib/vnc_api.py b/src/api-lib/vnc_api.py index 35b344a3a6b..e0b41585bce 100644 --- a/src/api-lib/vnc_api.py +++ b/src/api-lib/vnc_api.py @@ -376,13 +376,17 @@ def _object_update(self, res_type, obj): if not obj.uuid: obj.uuid = self.fq_name_to_id(res_type, obj.get_fq_name()) - # Ignore fields with None value in json representation - json_param = json.dumps(obj, default=self._obj_serializer) - json_body = '{"%s":%s}' %(res_type, json_param) + # Generate PUT on object only if some attr was modified + content = None + if obj.get_pending_updates(): + # Ignore fields with None value in json representation + json_param = json.dumps(obj, default=self._obj_serializer) + json_body = '{"%s":%s}' %(res_type, json_param) + + id = obj.uuid + uri = obj_cls.resource_uri_base[res_type] + '/' + id + content = self._request_server(rest.OP_PUT, uri, data=json_body) - id = obj.uuid - uri = obj_cls.resource_uri_base[res_type] + '/' + id - content = self._request_server(rest.OP_PUT, uri, data=json_body) for ref_name in obj._pending_ref_updates: ref_orig = set([(x.get('uuid'), tuple(x.get('to', [])), x.get('attr')) diff --git a/src/config/api-server/tests/test_crud_basic.py b/src/config/api-server/tests/test_crud_basic.py index a382e949edc..89d2de51c5f 100644 --- a/src/config/api-server/tests/test_crud_basic.py +++ b/src/config/api-server/tests/test_crud_basic.py @@ -1614,6 +1614,26 @@ def test_vmi_links_to_native_ri(self): logger.info("...link to Native RI done.") # end test_vmi_links_to_native_ri + def test_nop_on_empty_body_update(self): + # library api test + vn_fq_name = VirtualNetwork().fq_name + vn_obj = self._vnc_lib.virtual_network_read(fq_name=vn_fq_name) + mod_time = vn_obj.id_perms.last_modified + resp = self._vnc_lib.virtual_network_update(vn_obj) + self.assertIsNone(resp) + vn_obj = self._vnc_lib.virtual_network_read(fq_name=vn_fq_name) + self.assertEqual(mod_time, vn_obj.id_perms.last_modified) + + # rest api test + listen_ip = self._api_server_ip + listen_port = self._api_server._args.listen_port + url = 'http://%s:%s/virtual-network/%s' %( + listen_ip, listen_port, vn_obj.uuid) + resp = requests.put(url) + self.assertEqual(resp.status_code, 200) + self.assertEqual(resp.text, '') + # end test_nop_on_empty_body_update + # end class TestVncCfgApiServer class TestVncCfgApiServerRequests(test_case.ApiServerTestCase): diff --git a/src/config/api-server/vnc_cfg_api_server.py b/src/config/api-server/vnc_cfg_api_server.py index 58c5fa4a94e..159b728e709 100644 --- a/src/config/api-server/vnc_cfg_api_server.py +++ b/src/config/api-server/vnc_cfg_api_server.py @@ -556,6 +556,13 @@ def http_resource_read(self, resource_type, id): def http_resource_update(self, resource_type, id): r_class = self.get_resource_class(resource_type) obj_type = resource_type.replace('-', '_') + # Early return if there is no body or an empty body + request = get_request() + if (not hasattr(request, 'json') or + not request.json or + not request.json[resource_type]): + return + obj_dict = get_request().json[resource_type] try: self._extension_mgrs['resourceApi'].map_method(