diff --git a/ironic/api/controllers/v1/chassis.py b/ironic/api/controllers/v1/chassis.py index 1394a1b7ce..73f32c22d1 100644 --- a/ironic/api/controllers/v1/chassis.py +++ b/ironic/api/controllers/v1/chassis.py @@ -151,24 +151,29 @@ class ChassisController(rest.RestController): chassis = objects.Chassis.get_by_uuid(pecan.request.context, uuid) chassis_dict = chassis.as_dict() - # These are internal values that shouldn't be part of the patch - internal_attrs = ['id', 'updated_at', 'created_at'] - [chassis_dict.pop(attr, None) for attr in internal_attrs] - utils.validate_patch(patch) try: - final_patch = jsonpatch.apply_patch(chassis_dict, - jsonpatch.JsonPatch(patch)) + patched_chassis = jsonpatch.apply_patch(chassis_dict, + jsonpatch.JsonPatch(patch)) except jsonpatch.JsonPatchException as e: LOG.exception(e) raise wsme.exc.ClientSideError(_("Patching Error: %s") % e) - # In case of a remove operation, add the missing fields back to - # the document with their default value defaults = objects.Chassis.get_defaults() - defaults.update(final_patch) + for key in defaults: + # Internal values that shouldn't be part of the patch + if key in ['id', 'updated_at', 'created_at']: + continue + + # In case of a remove operation, add the missing fields back + # to the document with their default value + if key in chassis_dict and key not in patched_chassis: + patched_chassis[key] = defaults[key] + + # Update only the fields that have changed + if chassis[key] != patched_chassis[key]: + chassis[key] = patched_chassis[key] - chassis.update(defaults) chassis.save() return Chassis.convert_with_links(chassis) diff --git a/ironic/api/controllers/v1/node.py b/ironic/api/controllers/v1/node.py index bfa41124ee..b87108a118 100644 --- a/ironic/api/controllers/v1/node.py +++ b/ironic/api/controllers/v1/node.py @@ -337,10 +337,6 @@ class NodesController(rest.RestController): node = objects.Node.get_by_uuid(pecan.request.context, uuid) node_dict = node.as_dict() - # These are internal values that shouldn't be part of the patch - internal_attrs = ['id', 'updated_at', 'created_at'] - [node_dict.pop(attr, None) for attr in internal_attrs] - utils.validate_patch(patch) patch_obj = jsonpatch.JsonPatch(patch) @@ -362,19 +358,28 @@ class NodesController(rest.RestController): "progress.") % uuid) try: - final_patch = jsonpatch.apply_patch(node_dict, patch_obj) + patched_node = jsonpatch.apply_patch(node_dict, patch_obj) except jsonpatch.JsonPatchException as e: LOG.exception(e) raise wsme.exc.ClientSideError(_("Patching Error: %s") % e) response = wsme.api.Response(Node(), status_code=200) try: - # In case of a remove operation, add the missing fields back to - # the document with their default value defaults = objects.Node.get_defaults() - defaults.update(final_patch) + for key in defaults: + # Internal values that shouldn't be part of the patch + if key in ['id', 'updated_at', 'created_at']: + continue + + # In case of a remove operation, add the missing fields back + # to the document with their default value + if key in node_dict and key not in patched_node: + patched_node[key] = defaults[key] + + # Update only the fields that have changed + if node[key] != patched_node[key]: + node[key] = patched_node[key] - node.update(defaults) node = pecan.request.rpcapi.update_node(pecan.request.context, node) response.obj = node diff --git a/ironic/api/controllers/v1/port.py b/ironic/api/controllers/v1/port.py index 6300de9064..d4b6052b09 100644 --- a/ironic/api/controllers/v1/port.py +++ b/ironic/api/controllers/v1/port.py @@ -130,24 +130,29 @@ class PortsController(rest.RestController): port = objects.Port.get_by_uuid(pecan.request.context, uuid) port_dict = port.as_dict() - # These are internal values that shouldn't be part of the patch - internal_attrs = ['id', 'updated_at', 'created_at'] - [port_dict.pop(attr, None) for attr in internal_attrs] - utils.validate_patch(patch) try: - final_patch = jsonpatch.apply_patch(port_dict, - jsonpatch.JsonPatch(patch)) + patched_port = jsonpatch.apply_patch(port_dict, + jsonpatch.JsonPatch(patch)) except jsonpatch.JsonPatchException as e: LOG.exception(e) raise wsme.exc.ClientSideError(_("Patching Error: %s") % e) - # In case of a remove operation, add the missing fields back to - # the document with their default value defaults = objects.Port.get_defaults() - defaults.update(final_patch) + for key in defaults: + # Internal values that shouldn't be part of the patch + if key in ['id', 'updated_at', 'created_at']: + continue + + # In case of a remove operation, add the missing fields back + # to the document with their default value + if key in port_dict and key not in patched_port: + patched_port[key] = defaults[key] + + # Update only the fields that have changed + if port[key] != patched_port[key]: + port[key] = patched_port[key] - port.update(defaults) port.save() return Port.convert_with_links(port)