)]}'
{"cinder/volume/drivers/netapp/dataontap/nfs_cmode.py":[{"author":{"_account_id":36171,"name":"jayaanand borra","display_name":"jayaanand borra","email":"jayaanand.borra@netapp.com","username":"jayaanan","status":"netapp"},"change_message_id":"20aabb212f677846a8775e66bd752faf16189242","unresolved":true,"context_lines":[{"line_number":624,"context_line":"                      \u0027via REST API.\u0027, volume[\u0027id\u0027])"},{"line_number":625,"context_line":"            try:"},{"line_number":626,"context_line":"                self._delete_flexgroup_volume_files(volume)"},{"line_number":627,"context_line":"            except Exception:"},{"line_number":628,"context_line":"                LOG.exception(\u0027Could not delete files for volume %s on \u0027"},{"line_number":629,"context_line":"                              \u0027FlexGroup backend via REST.\u0027, volume[\u0027id\u0027])"},{"line_number":630,"context_line":"        elif is_flexgroup and not self._is_flexgroup_clone_file_supported():"}],"source_content_type":"text/x-python","patch_set":5,"id":"0c2ca031_ccf2eb4c","line":627,"updated":"2026-10-25 16:29:49.000000000","message":"This except Exception makes the bug’s failure mode stick. VolumeManager.delete_volume sets error_deleting only when the driver raises (manager.py around line 1021). On a normal return it calls volume.destroy() (around line 1050). Logging here and returning still deletes the database row, so the operator cannot retry.\n\nFor a ZAPI-mode FlexGroup this branch also skips super().delete_volume(). That call is the NFS rm the old code used, both when clone support was false and as the fallback after _delete_file failed. Please keep that call when the REST delete does not remove the file, and re-raise if the file is still present. NetAppDriverException extends CinderException, so this handler already catches the REST version error below.","commit_id":"36d13974a8d7b83cc1865ac19b9452d08a4fc00a"},{"author":{"_account_id":36171,"name":"jayaanand borra","display_name":"jayaanand borra","email":"jayaanand.borra@netapp.com","username":"jayaanan","status":"netapp"},"change_message_id":"20aabb212f677846a8775e66bd752faf16189242","unresolved":true,"context_lines":[{"line_number":657,"context_line":"        (host_ip, junction_path) \u003d self._get_export_ip_path("},{"line_number":658,"context_line":"            volume_id\u003dvolume[\u0027id\u0027])"},{"line_number":659,"context_line":"        vserver \u003d self._get_vserver_for_ip(host_ip)"},{"line_number":660,"context_line":"        flexgroup_name \u003d self.zapi_client.get_vol_by_junc_vserver("},{"line_number":661,"context_line":"            vserver, junction_path)"},{"line_number":662,"context_line":""},{"line_number":663,"context_line":"        # Obtain a REST client regardless of netapp_use_legacy_client setting"}],"source_content_type":"text/x-python","patch_set":5,"id":"a6fc0bec_f6e89eed","line":660,"updated":"2026-10-25 16:29:49.000000000","message":"Bug 2171401 says this is the call that fails. The new helper still runs self.zapi_client.get_vol_by_junc_vserver() before any REST delete. get_vol_by_junc_vserver raises NotFound when volume-get-iter returns no record (client_cmode.py around line 1165). That exception is caught at line 627, REST never runs, and the volume is destroyed in Cinder. If this lookup is the failure you hit, resolve the FlexGroup with the REST client (nas.path plus the vserver from line 659) or the new code does not run on the failing path.","commit_id":"36d13974a8d7b83cc1865ac19b9452d08a4fc00a"},{"author":{"_account_id":36171,"name":"jayaanand borra","display_name":"jayaanand borra","email":"jayaanand.borra@netapp.com","username":"jayaanan","status":"netapp"},"change_message_id":"20aabb212f677846a8775e66bd752faf16189242","unresolved":true,"context_lines":[{"line_number":662,"context_line":""},{"line_number":663,"context_line":"        # Obtain a REST client regardless of netapp_use_legacy_client setting"},{"line_number":664,"context_line":"        backend_name \u003d self.failed_over_backend_name or self.backend_name"},{"line_number":665,"context_line":"        rest_client \u003d dot_utils.get_client_for_backend("},{"line_number":666,"context_line":"            backend_name, force_rest\u003dTrue)"},{"line_number":667,"context_line":""},{"line_number":668,"context_line":"        # List all files in the FlexGroup root and filter by volume ID prefix"}],"source_content_type":"text/x-python","patch_set":5,"id":"c72513c8_9b9f33ef","line":665,"updated":"2026-10-25 16:29:49.000000000","message":"get_client_for_backend(..., force_rest\u003dTrue) builds a new RestClient on every delete. RestClient.__init__ calls get_ontap_version(cached\u003dFalse) and raises NetAppDriverException when the version is below (9, 11, 1) (client_cmode_rest.py around line 122). The ZAPI client reports FlexGroup support at ONTAPI \u003e\u003d (1, 180), so a FlexGroup pool can exist on a cluster this constructor rejects. On those clusters the new branch always fails, and line 627 then drops the NFS delete that used to run.\n\nWhen the version check passes, __init__ still calls _get_cluster_nodes_info(), and with netapp_allow_zapi_fallback left at its default True it also constructs client_cmode.Client, whose constructor does its own uncached ONTAPI and ONTAP version calls. The API delete path holds {volume.id}-delete_volume for this whole call (manager.py line 927). Clone-from-volume takes that same lock on the source (manager.py line 800), so this init sits on that lock.\n\nvserver was computed on line 659 and is not passed. get_client_for_backend then uses config.netapp_vserver (utils.py around line 153). Pass vserver_name\u003dvserver. Please construct this client once per backend, not once per delete.","commit_id":"36d13974a8d7b83cc1865ac19b9452d08a4fc00a"},{"author":{"_account_id":36171,"name":"jayaanand borra","display_name":"jayaanand borra","email":"jayaanand.borra@netapp.com","username":"jayaanan","status":"netapp"},"change_message_id":"20aabb212f677846a8775e66bd752faf16189242","unresolved":true,"context_lines":[{"line_number":666,"context_line":"            backend_name, force_rest\u003dTrue)"},{"line_number":667,"context_line":""},{"line_number":668,"context_line":"        # List all files in the FlexGroup root and filter by volume ID prefix"},{"line_number":669,"context_line":"        vol_prefix \u003d \u0027volume-\u0027 + volume[\u0027id\u0027]"},{"line_number":670,"context_line":"        all_files \u003d rest_client.get_file_sizes_by_dir(flexgroup_name)"},{"line_number":671,"context_line":"        matching \u003d [f[\u0027name\u0027] for f in all_files"},{"line_number":672,"context_line":"                    if f[\u0027name\u0027].startswith(vol_prefix)]"}],"source_content_type":"text/x-python","patch_set":5,"id":"fd73ee87_485b6e6f","line":669,"updated":"2026-10-25 16:29:49.000000000","message":"Use volume[\u0027name\u0027] as the prefix, not \u0027volume-\u0027 + volume[\u0027id\u0027].\n\nVolume.name is CONF.volume_name_template % self.name_id (objects/volume.py). The template default is volume-%s (db/api.py). name_id is id only when _name_id is unset. The _delete_file call in the other branch of this same method already passes volume[\u0027name\u0027]. In ZAPI mode, FlexGroup snapshot create always uses the generic qcow2 path (nfs_base.py around line 331, because netapp_use_legacy_client is true), and those files are named from volume.name (volume.name.info and volume.name.\u003csnap\u003e). A custom template, or a set _name_id, makes this prefix miss them. Line 674 then logs a warning and returns, and line 627 turns that into a successful Cinder delete.\n\nDo not list the FlexGroup to find that one name. get_file_sizes_by_dir is the capacity helper: it follows REST pagination and returns every file, and the sizes are discarded here. Deletes of different volumes do not share {volume.id}-delete_volume, so parallel deletes of the same FlexGroup each list the whole directory. Delete volume[\u0027name\u0027] by path. For the qcow2 chain, also delete volume[\u0027name\u0027] + \u0027.info\u0027 and the files whose names start with volume[\u0027name\u0027] + \u0027.\u0027.","commit_id":"36d13974a8d7b83cc1865ac19b9452d08a4fc00a"},{"author":{"_account_id":36171,"name":"jayaanand borra","display_name":"jayaanand borra","email":"jayaanand.borra@netapp.com","username":"jayaanan","status":"netapp"},"change_message_id":"20aabb212f677846a8775e66bd752faf16189242","unresolved":true,"context_lines":[{"line_number":677,"context_line":"                        {\u0027fg\u0027: flexgroup_name, \u0027vol\u0027: volume[\u0027id\u0027]})"},{"line_number":678,"context_line":"            return"},{"line_number":679,"context_line":""},{"line_number":680,"context_line":"        for filename in matching:"},{"line_number":681,"context_line":"            path \u003d \u0027/vol/\u0027 + flexgroup_name + \u0027/\u0027 + filename"},{"line_number":682,"context_line":"            LOG.debug(\u0027Deleting FlexGroup file %(path)s for volume %(vol)s.\u0027,"},{"line_number":683,"context_line":"                      {\u0027path\u0027: path, \u0027vol\u0027: volume[\u0027id\u0027]})"}],"source_content_type":"text/x-python","patch_set":5,"id":"ff9b5ac9_a9359ef6","line":680,"updated":"2026-10-25 16:29:49.000000000","message":"delete_file does not treat a missing file as success (client_cmode_rest.py around line 1599). The first failure leaves the loop, so later matches are not attempted. The caller at line 627 logs that and still lets the manager destroy the volume. Delete every match, treat “file not found” as success, and raise only if a file that should be gone is still there.","commit_id":"36d13974a8d7b83cc1865ac19b9452d08a4fc00a"}]}
