)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":16643,"name":"Goutham Pacha Ravi","email":"gouthampravi@gmail.com","username":"gouthamr"},"change_message_id":"5b15ff5b6be4554259958e81b5309ff4e8e4c360","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":3,"id":"6f4dfb22_4490c958","updated":"2026-06-29 19:28:12.000000000","message":"Hi Alexey, welcome and thanks for contributing a Lustre driver to Manila! This is really exciting to see.\nFor context, we have an ongoing effort to add LUSTRE as a first-class protocol in Manila along with a reference driver implementation that works with any Lustre filesystem (spec at [1], devstack plugin at [2]). Your EXAScaler driver and our reference driver in my view are complementary; similar to how Manila has both vendor-specific NFS drivers (NetApp, Dell/EMC) and a generic NFS driver.\nI\u0027d love to understand the motivation behind this patch. Was it inspired by the lustre-driver spec work, or are you seeing demand from EXAScaler customers wanting Manila integration independently? Either way, I\u0027d like your help designing and maintaining the reference LUSTRE implementation, and collaborating to deduplicate common parts between the two drivers (the LUSTRE protocol constant, export location format, etc).\nI have review comments inline; the biggest items are the missing access control, the project ID scheme, and a few things that need to follow Manila conventions.\n[1] https://review.opendev.org/c/openstack/manila-specs/+/987307\n[2] https://review.opendev.org/q/topic:bp/lustre-driver","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":16643,"name":"Goutham Pacha Ravi","email":"gouthampravi@gmail.com","username":"gouthamr"},"change_message_id":"5b15ff5b6be4554259958e81b5309ff4e8e4c360","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":3,"id":"3b4aa9b2_ae596027","updated":"2026-06-29 19:28:12.000000000","message":"This patch should include a release note (reno) for the new driver and the LUSTRE protocol addition. Something like: \"Added DDN EXAScaler share driver supporting the LUSTRE protocol with create, delete, extend, and shrink operations.\"","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":15439,"name":"Alexey Khodos","email":"akhodos@ddn.com","username":"Alexey"},"change_message_id":"24f8c5cd674f59e8481b5562ffdb108ec54b13d3","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"75f7bfbe_e91e65ed","in_reply_to":"3278da8d_99fdda0c","updated":"2026-06-30 18:39:21.000000000","message":"Done","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":15439,"name":"Alexey Khodos","email":"akhodos@ddn.com","username":"Alexey"},"change_message_id":"876964b4f8d6b63bcaddf207a05413f8bb472f48","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":3,"id":"3278da8d_99fdda0c","in_reply_to":"3b4aa9b2_ae596027","updated":"2026-06-29 23:29:34.000000000","message":"will add in next PS","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":15439,"name":"Alexey Khodos","email":"akhodos@ddn.com","username":"Alexey"},"change_message_id":"876964b4f8d6b63bcaddf207a05413f8bb472f48","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":3,"id":"a387f501_a62e8565","in_reply_to":"6f4dfb22_4490c958","updated":"2026-06-29 23:29:34.000000000","message":"Hi Goutham, thanks for your reply! Glad to see that there is work on a generic lustre driver. Our driver is inspired by the customer\u0027s demand, not this spec.\nI have addressed all the inline comments.","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":15439,"name":"Alexey Khodos","email":"akhodos@ddn.com","username":"Alexey"},"change_message_id":"24f8c5cd674f59e8481b5562ffdb108ec54b13d3","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"6ddd3f69_6bce62b2","in_reply_to":"a387f501_a62e8565","updated":"2026-06-30 18:39:21.000000000","message":"Done","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"}],"manila/share/drivers/exascaler/__init__.py":[{"author":{"_account_id":16643,"name":"Goutham Pacha Ravi","email":"gouthampravi@gmail.com","username":"gouthamr"},"change_message_id":"5b15ff5b6be4554259958e81b5309ff4e8e4c360","unresolved":true,"context_lines":[{"line_number":15,"context_line":""},{"line_number":16,"context_line":"\"\"\"DDN Exascaler Manila driver.\"\"\""},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"__version__ \u003d \u00271.0.0\u0027"}],"source_content_type":"text/x-python","patch_set":3,"id":"8771574a_4130533d","line":18,"updated":"2026-06-29 19:28:12.000000000","message":"Manila doesn\u0027t use per-module __version__ strings. The driver_version is reported in _update_share_stats, which is sufficient. This can be removed to match other drivers.","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":15439,"name":"Alexey Khodos","email":"akhodos@ddn.com","username":"Alexey"},"change_message_id":"876964b4f8d6b63bcaddf207a05413f8bb472f48","unresolved":true,"context_lines":[{"line_number":15,"context_line":""},{"line_number":16,"context_line":"\"\"\"DDN Exascaler Manila driver.\"\"\""},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"__version__ \u003d \u00271.0.0\u0027"}],"source_content_type":"text/x-python","patch_set":3,"id":"92137942_fdf92c84","line":18,"in_reply_to":"8771574a_4130533d","updated":"2026-06-29 23:29:34.000000000","message":"Acknowledged","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":15439,"name":"Alexey Khodos","email":"akhodos@ddn.com","username":"Alexey"},"change_message_id":"24f8c5cd674f59e8481b5562ffdb108ec54b13d3","unresolved":false,"context_lines":[{"line_number":15,"context_line":""},{"line_number":16,"context_line":"\"\"\"DDN Exascaler Manila driver.\"\"\""},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"__version__ \u003d \u00271.0.0\u0027"}],"source_content_type":"text/x-python","patch_set":3,"id":"9481148b_81675be1","line":18,"in_reply_to":"92137942_fdf92c84","updated":"2026-06-30 18:39:21.000000000","message":"Done","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"}],"manila/share/drivers/exascaler/driver.py":[{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":138,"context_line":"                \"%(share_id)s after %(attempts)s attempts\") % {"},{"line_number":139,"context_line":"                    \u0027share_id\u0027: share_id,"},{"line_number":140,"context_line":"                    \u0027attempts\u0027: max_attempts"},{"line_number":141,"context_line":"                }"},{"line_number":142,"context_line":"        raise exception.ShareBackendException(msg\u003dmsg)"},{"line_number":143,"context_line":""},{"line_number":144,"context_line":"    def create_share(self, context, share, share_server\u003dNone):"}],"source_content_type":"text/x-python","patch_set":1,"id":"1366b119_189e2266","line":141,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E126 continuation line over-indented for hanging indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":167,"context_line":""},{"line_number":168,"context_line":"        # Step 1: Create the volume/directory"},{"line_number":169,"context_line":"        LOG.debug(\"Creating Exascaler volume: path\u003d%(path)s, \""},{"line_number":170,"context_line":"                 \"size\u003d%(size)sGB, uid\u003d%(uid)s, gid\u003d%(gid)s, \""},{"line_number":171,"context_line":"                 \"projid\u003d%(projid)s\","},{"line_number":172,"context_line":"                 {\u0027path\u0027: share_path, \u0027size\u0027: share_size_gb,"},{"line_number":173,"context_line":"                  \u0027uid\u0027: uid, \u0027gid\u0027: gid, \u0027projid\u0027: projid})"}],"source_content_type":"text/x-python","patch_set":1,"id":"c47fbe3d_64496710","line":170,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E128 continuation line under-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":168,"context_line":"        # Step 1: Create the volume/directory"},{"line_number":169,"context_line":"        LOG.debug(\"Creating Exascaler volume: path\u003d%(path)s, \""},{"line_number":170,"context_line":"                 \"size\u003d%(size)sGB, uid\u003d%(uid)s, gid\u003d%(gid)s, \""},{"line_number":171,"context_line":"                 \"projid\u003d%(projid)s\","},{"line_number":172,"context_line":"                 {\u0027path\u0027: share_path, \u0027size\u0027: share_size_gb,"},{"line_number":173,"context_line":"                  \u0027uid\u0027: uid, \u0027gid\u0027: gid, \u0027projid\u0027: projid})"},{"line_number":174,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"294a5fe2_eca766e0","line":171,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E128 continuation line under-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":169,"context_line":"        LOG.debug(\"Creating Exascaler volume: path\u003d%(path)s, \""},{"line_number":170,"context_line":"                 \"size\u003d%(size)sGB, uid\u003d%(uid)s, gid\u003d%(gid)s, \""},{"line_number":171,"context_line":"                 \"projid\u003d%(projid)s\","},{"line_number":172,"context_line":"                 {\u0027path\u0027: share_path, \u0027size\u0027: share_size_gb,"},{"line_number":173,"context_line":"                  \u0027uid\u0027: uid, \u0027gid\u0027: gid, \u0027projid\u0027: projid})"},{"line_number":174,"context_line":""},{"line_number":175,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":1,"id":"16fbfd59_5789490f","line":172,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E128 continuation line under-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":188,"context_line":"            create_response \u003d self.api_client.create_volume(**create_kwargs)"},{"line_number":189,"context_line":""},{"line_number":190,"context_line":"            LOG.debug(\"Volume creation API call completed: %s\","},{"line_number":191,"context_line":"                     create_response)"},{"line_number":192,"context_line":""},{"line_number":193,"context_line":"            # Extract command ID from response"},{"line_number":194,"context_line":"            command_id \u003d create_response.get(\u0027id\u0027) if create_response else None"}],"source_content_type":"text/x-python","patch_set":1,"id":"2ce5ea2c_121c7517","line":191,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E128 continuation line under-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":223,"context_line":"        # Step 3: Set the quota for the project ID"},{"line_number":224,"context_line":"        try:"},{"line_number":225,"context_line":"            LOG.debug(\"Setting quota for projid\u003d%(projid)s to %(size)sGB\","},{"line_number":226,"context_line":"                     {\u0027projid\u0027: projid, \u0027size\u0027: share_size_gb})"},{"line_number":227,"context_line":"            quota_response \u003d self.api_client.set_quota(projid, share_size_gb)"},{"line_number":228,"context_line":"            LOG.debug(\"Quota set response: %s\", quota_response)"},{"line_number":229,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"0ae8b97c_3681a448","line":226,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E128 continuation line under-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":236,"context_line":"            }"},{"line_number":237,"context_line":"            raise exception.ShareBackendException(msg\u003dmsg)"},{"line_number":238,"context_line":""},{"line_number":239,"context_line":"        # TODO: Store projid in share metadata for later retrieval"},{"line_number":240,"context_line":"        # For now, we\u0027ll regenerate it during delete_share from the share UUID"},{"line_number":241,"context_line":""},{"line_number":242,"context_line":"        # Return Lustre export location"}],"source_content_type":"text/x-python","patch_set":1,"id":"968ecc54_d21ce5d8","line":239,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: H101: Use TODO(NAME)","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":248,"context_line":""},{"line_number":249,"context_line":"        # Return export location in simple list format"},{"line_number":250,"context_line":"        LOG.info(\"Share %(share_id)s created successfully.\","},{"line_number":251,"context_line":"                     {\u0027share_id\u0027: share[\u0027share_id\u0027]})"},{"line_number":252,"context_line":"        return [export_location]"},{"line_number":253,"context_line":""},{"line_number":254,"context_line":"    def _generate_projid_from_uuid(self, share_uuid, suffix_length\u003d5):"}],"source_content_type":"text/x-python","patch_set":1,"id":"2ce8d4f9_303c4dff","line":251,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E127 continuation line over-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":342,"context_line":""},{"line_number":343,"context_line":"        if uid is not None or gid is not None:"},{"line_number":344,"context_line":"            LOG.debug(\"Using UID\u003d%(uid)s, GID\u003d%(gid)s for share %(share_id)s\","},{"line_number":345,"context_line":"                     {\u0027uid\u0027: uid, \u0027gid\u0027: gid, \u0027share_id\u0027: share[\u0027share_id\u0027]})"},{"line_number":346,"context_line":"        else:"},{"line_number":347,"context_line":"            LOG.debug(\"Using API defaults for UID/GID for share %(share_id)s\","},{"line_number":348,"context_line":"                     {\u0027share_id\u0027: share[\u0027share_id\u0027]})"}],"source_content_type":"text/x-python","patch_set":1,"id":"d2659650_fce4bc62","line":345,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E128 continuation line under-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":345,"context_line":"                     {\u0027uid\u0027: uid, \u0027gid\u0027: gid, \u0027share_id\u0027: share[\u0027share_id\u0027]})"},{"line_number":346,"context_line":"        else:"},{"line_number":347,"context_line":"            LOG.debug(\"Using API defaults for UID/GID for share %(share_id)s\","},{"line_number":348,"context_line":"                     {\u0027share_id\u0027: share[\u0027share_id\u0027]})"},{"line_number":349,"context_line":""},{"line_number":350,"context_line":"        return uid, gid"},{"line_number":351,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"44b26472_1beb0e97","line":348,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E128 continuation line under-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":350,"context_line":"        return uid, gid"},{"line_number":351,"context_line":""},{"line_number":352,"context_line":"    def _wait_for_command_completion(self, command_id, timeout\u003d30,"},{"line_number":353,"context_line":"                                      poll_interval\u003d1):"},{"line_number":354,"context_line":"        \"\"\"Wait for a command to complete with automatic resume on failure."},{"line_number":355,"context_line":""},{"line_number":356,"context_line":"        Poll the command status to detect failures quickly. If a command"}],"source_content_type":"text/x-python","patch_set":1,"id":"2a59629d_c9f476de","line":353,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E127 continuation line over-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":387,"context_line":"                # Command failed - try to resume if we have attempts left"},{"line_number":388,"context_line":"                if resume_attempt \u003c max_resume_attempts - 1:"},{"line_number":389,"context_line":"                    LOG.info(\"Command %(cmd_id)s failed, resuming \""},{"line_number":390,"context_line":"                            \"(attempt %(attempt)s/%(max)s): %(error)s\","},{"line_number":391,"context_line":"                            {\u0027cmd_id\u0027: command_id,"},{"line_number":392,"context_line":"                             \u0027attempt\u0027: resume_attempt + 1,"},{"line_number":393,"context_line":"                             \u0027max\u0027: max_resume_attempts,"}],"source_content_type":"text/x-python","patch_set":1,"id":"0048dc2d_7063d374","line":390,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E128 continuation line under-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":388,"context_line":"                if resume_attempt \u003c max_resume_attempts - 1:"},{"line_number":389,"context_line":"                    LOG.info(\"Command %(cmd_id)s failed, resuming \""},{"line_number":390,"context_line":"                            \"(attempt %(attempt)s/%(max)s): %(error)s\","},{"line_number":391,"context_line":"                            {\u0027cmd_id\u0027: command_id,"},{"line_number":392,"context_line":"                             \u0027attempt\u0027: resume_attempt + 1,"},{"line_number":393,"context_line":"                             \u0027max\u0027: max_resume_attempts,"},{"line_number":394,"context_line":"                             \u0027error\u0027: str(e)})"}],"source_content_type":"text/x-python","patch_set":1,"id":"9334d364_3566ae83","line":391,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E128 continuation line under-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":398,"context_line":"                            self.api_client.resume_command(command_id))"},{"line_number":399,"context_line":"                        if not resume_response or \u0027id\u0027 not in resume_response:"},{"line_number":400,"context_line":"                            LOG.error(\"Failed to resume command %(cmd_id)s\","},{"line_number":401,"context_line":"                                     {\u0027cmd_id\u0027: command_id})"},{"line_number":402,"context_line":"                            raise"},{"line_number":403,"context_line":""},{"line_number":404,"context_line":"                        # Update to the resumed command ID and retry"}],"source_content_type":"text/x-python","patch_set":1,"id":"4a8b187a_0eb402eb","line":401,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E128 continuation line under-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":405,"context_line":"                        old_cmd_id \u003d command_id"},{"line_number":406,"context_line":"                        command_id \u003d resume_response[\u0027id\u0027]"},{"line_number":407,"context_line":"                        LOG.info(\"Command %(old_id)s resumed as %(new_id)s\","},{"line_number":408,"context_line":"                                {\u0027old_id\u0027: old_cmd_id, \u0027new_id\u0027: command_id})"},{"line_number":409,"context_line":"                        continue"},{"line_number":410,"context_line":""},{"line_number":411,"context_line":"                    except rest_client.ExascalerAPIException as resume_error:"}],"source_content_type":"text/x-python","patch_set":1,"id":"40ba7048_14af3d35","line":408,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E128 continuation line under-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":421,"context_line":"                    LOG.error("},{"line_number":422,"context_line":"                        \"Command %(cmd_id)s failed after %(attempts)s \""},{"line_number":423,"context_line":"                        \"attempts: %(error)s\","},{"line_number":424,"context_line":"                             {\u0027cmd_id\u0027: command_id,"},{"line_number":425,"context_line":"                              \u0027attempts\u0027: resume_attempt + 1,"},{"line_number":426,"context_line":"                              \u0027error\u0027: str(e)})"},{"line_number":427,"context_line":"                    raise"}],"source_content_type":"text/x-python","patch_set":1,"id":"bcfab28c_16046c5b","line":424,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E131 continuation line unaligned for hanging indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":441,"context_line":"            attempt +\u003d 1"},{"line_number":442,"context_line":"            LOG.debug("},{"line_number":443,"context_line":"                \"Checking command %(cmd_id)s status (attempt %(attempt)s)\","},{"line_number":444,"context_line":"                      {\u0027cmd_id\u0027: command_id, \u0027attempt\u0027: attempt})"},{"line_number":445,"context_line":""},{"line_number":446,"context_line":"            status \u003d self.api_client.get_command_status(command_id)"},{"line_number":447,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"3828fac0_450c6dca","line":444,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E131 continuation line unaligned for hanging indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":449,"context_line":"                # Command was purged from history, assume it completed"},{"line_number":450,"context_line":"                elapsed \u003d time.time() - start_time"},{"line_number":451,"context_line":"                LOG.debug(\"Command %(cmd_id)s no longer in history after \""},{"line_number":452,"context_line":"                         \"%(elapsed).1fs, assuming completed\","},{"line_number":453,"context_line":"                         {\u0027cmd_id\u0027: command_id, \u0027elapsed\u0027: elapsed})"},{"line_number":454,"context_line":"                return"},{"line_number":455,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"5572c074_b8cbe864","line":452,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E128 continuation line under-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":450,"context_line":"                elapsed \u003d time.time() - start_time"},{"line_number":451,"context_line":"                LOG.debug(\"Command %(cmd_id)s no longer in history after \""},{"line_number":452,"context_line":"                         \"%(elapsed).1fs, assuming completed\","},{"line_number":453,"context_line":"                         {\u0027cmd_id\u0027: command_id, \u0027elapsed\u0027: elapsed})"},{"line_number":454,"context_line":"                return"},{"line_number":455,"context_line":""},{"line_number":456,"context_line":"            state \u003d status.get(\u0027state\u0027)"}],"source_content_type":"text/x-python","patch_set":1,"id":"6102a159_dc9dd499","line":453,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E128 continuation line under-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":458,"context_line":"            if state \u003d\u003d \u0027completed\u0027:"},{"line_number":459,"context_line":"                elapsed \u003d time.time() - start_time"},{"line_number":460,"context_line":"                LOG.info(\"Command %(cmd_id)s completed successfully \""},{"line_number":461,"context_line":"                        \"(elapsed: %(elapsed).1fs)\","},{"line_number":462,"context_line":"                        {\u0027cmd_id\u0027: command_id, \u0027elapsed\u0027: elapsed})"},{"line_number":463,"context_line":"                return"},{"line_number":464,"context_line":"            elif state \u003d\u003d \u0027failed\u0027:"}],"source_content_type":"text/x-python","patch_set":1,"id":"4beccb36_da8771e1","line":461,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E128 continuation line under-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":459,"context_line":"                elapsed \u003d time.time() - start_time"},{"line_number":460,"context_line":"                LOG.info(\"Command %(cmd_id)s completed successfully \""},{"line_number":461,"context_line":"                        \"(elapsed: %(elapsed).1fs)\","},{"line_number":462,"context_line":"                        {\u0027cmd_id\u0027: command_id, \u0027elapsed\u0027: elapsed})"},{"line_number":463,"context_line":"                return"},{"line_number":464,"context_line":"            elif state \u003d\u003d \u0027failed\u0027:"},{"line_number":465,"context_line":"                # Extract error from plan nodes (detail API structure)"}],"source_content_type":"text/x-python","patch_set":1,"id":"32b026b5_eac63659","line":462,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E128 continuation line under-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":520,"context_line":"        # Timeout reached"},{"line_number":521,"context_line":"        elapsed \u003d time.time() - start_time"},{"line_number":522,"context_line":"        msg \u003d _(\"Command %(cmd_id)s did not complete within %(timeout)s \""},{"line_number":523,"context_line":"               \"seconds (elapsed: %(elapsed).1fs)\") % {"},{"line_number":524,"context_line":"            \u0027cmd_id\u0027: command_id,"},{"line_number":525,"context_line":"            \u0027timeout\u0027: timeout,"},{"line_number":526,"context_line":"            \u0027elapsed\u0027: elapsed"}],"source_content_type":"text/x-python","patch_set":1,"id":"d375b13c_1871e6a7","line":523,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E128 continuation line under-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":546,"context_line":"        if projid_str:"},{"line_number":547,"context_line":"            projid \u003d int(projid_str)"},{"line_number":548,"context_line":"            LOG.debug(\"Retrieved projid %(projid)s from share metadata\","},{"line_number":549,"context_line":"                     {\u0027projid\u0027: projid})"},{"line_number":550,"context_line":"        else:"},{"line_number":551,"context_line":"            # Fallback: regenerate projid from share ID"},{"line_number":552,"context_line":"            # We use the same algorithm as create, starting with the same"}],"source_content_type":"text/x-python","patch_set":1,"id":"7a3feee6_ea7eacb0","line":549,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E128 continuation line under-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":555,"context_line":"                      \"regenerating from UUID\","},{"line_number":556,"context_line":"                      {\u0027share_id\u0027: share[\u0027share_id\u0027]})"},{"line_number":557,"context_line":"            projid \u003d self._generate_projid_from_uuid(share[\u0027share_id\u0027],"},{"line_number":558,"context_line":"                                                      suffix_length\u003d5)"},{"line_number":559,"context_line":""},{"line_number":560,"context_line":"        try:"},{"line_number":561,"context_line":"            # Step 1: Delete the volume/directory"}],"source_content_type":"text/x-python","patch_set":1,"id":"223d41c1_bd6a6827","line":558,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E127 continuation line over-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":585,"context_line":""},{"line_number":586,"context_line":"            LOG.info("},{"line_number":587,"context_line":"                \"Volume deletion command %(cmd_id)s completed successfully\","},{"line_number":588,"context_line":"                     {\u0027cmd_id\u0027: command_id})"},{"line_number":589,"context_line":""},{"line_number":590,"context_line":"            # Step 3: Clear the quota (set to 0) for cleanup"},{"line_number":591,"context_line":"            try:"}],"source_content_type":"text/x-python","patch_set":1,"id":"e78a85fa_0a7e682e","line":588,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E131 continuation line unaligned for hanging indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":645,"context_line":"        if projid_str:"},{"line_number":646,"context_line":"            projid \u003d int(projid_str)"},{"line_number":647,"context_line":"            LOG.debug(\"Retrieved projid %(projid)s from share metadata\","},{"line_number":648,"context_line":"                     {\u0027projid\u0027: projid})"},{"line_number":649,"context_line":"        else:"},{"line_number":650,"context_line":"            # Fallback: regenerate projid from share ID"},{"line_number":651,"context_line":"            LOG.debug(\"No projid found in metadata for share %(share_id)s, \""}],"source_content_type":"text/x-python","patch_set":1,"id":"a2f11320_c0a3cf69","line":648,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E128 continuation line under-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":652,"context_line":"                      \"regenerating from UUID\","},{"line_number":653,"context_line":"                      {\u0027share_id\u0027: share[\u0027share_id\u0027]})"},{"line_number":654,"context_line":"            projid \u003d self._generate_projid_from_uuid(share[\u0027share_id\u0027],"},{"line_number":655,"context_line":"                                                      suffix_length\u003d5)"},{"line_number":656,"context_line":""},{"line_number":657,"context_line":"        LOG.info(\"Extending share %(share_id)s from %(old_size)sGB to \""},{"line_number":658,"context_line":"                 \"%(new_size)sGB, projid\u003d%(projid)s\","}],"source_content_type":"text/x-python","patch_set":1,"id":"cf8d4ae3_59d2cbd6","line":655,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E127 continuation line over-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":688,"context_line":"        if projid_str:"},{"line_number":689,"context_line":"            projid \u003d int(projid_str)"},{"line_number":690,"context_line":"            LOG.debug(\"Retrieved projid %(projid)s from share metadata\","},{"line_number":691,"context_line":"                     {\u0027projid\u0027: projid})"},{"line_number":692,"context_line":"        else:"},{"line_number":693,"context_line":"            # Fallback: regenerate projid from share ID"},{"line_number":694,"context_line":"            LOG.debug(\"No projid found in metadata for share %(share_id)s, \""}],"source_content_type":"text/x-python","patch_set":1,"id":"e9e59093_8d9eb975","line":691,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E128 continuation line under-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":695,"context_line":"                      \"regenerating from UUID\","},{"line_number":696,"context_line":"                      {\u0027share_id\u0027: share[\u0027share_id\u0027]})"},{"line_number":697,"context_line":"            projid \u003d self._generate_projid_from_uuid(share[\u0027share_id\u0027],"},{"line_number":698,"context_line":"                                                      suffix_length\u003d5)"},{"line_number":699,"context_line":""},{"line_number":700,"context_line":"        LOG.info(\"Shrinking share %(share_id)s from %(old_size)sGB to \""},{"line_number":701,"context_line":"                 \"%(new_size)sGB, projid\u003d%(projid)s\","}],"source_content_type":"text/x-python","patch_set":1,"id":"211973fe_87bf9ab7","line":698,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E127 continuation line over-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"e01812e15a2e92be9edc65a4cc0ee41cccd3cf14","unresolved":false,"context_lines":[{"line_number":17,"context_line":""},{"line_number":18,"context_line":"import time"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"from oslo_config import cfg"},{"line_number":21,"context_line":"from oslo_log import log"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"from manila import exception"}],"source_content_type":"text/x-python","patch_set":2,"id":"deb684d5_69f7b699","line":20,"updated":"2026-06-27 20:37:22.000000000","message":"pep8: F401 \u0027oslo_config.cfg\u0027 imported but unused","commit_id":"02009d6020f8009bc5264ca9219cca5ef8612244"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"e01812e15a2e92be9edc65a4cc0ee41cccd3cf14","unresolved":false,"context_lines":[{"line_number":153,"context_line":"                \"%(share_id)s after %(attempts)s attempts\") % {"},{"line_number":154,"context_line":"                    \u0027share_id\u0027: share_id,"},{"line_number":155,"context_line":"                    \u0027attempts\u0027: max_attempts"},{"line_number":156,"context_line":"                }"},{"line_number":157,"context_line":"        raise exception.ShareBackendException(msg\u003dmsg)"},{"line_number":158,"context_line":""},{"line_number":159,"context_line":"    def create_share(self, context, share, share_server\u003dNone):"}],"source_content_type":"text/x-python","patch_set":2,"id":"caffe5a1_296e3b8c","line":156,"updated":"2026-06-27 20:37:22.000000000","message":"pep8: E126 continuation line over-indented for hanging indent","commit_id":"02009d6020f8009bc5264ca9219cca5ef8612244"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"e01812e15a2e92be9edc65a4cc0ee41cccd3cf14","unresolved":false,"context_lines":[{"line_number":238,"context_line":"        # Step 3: Set the quota for the project ID"},{"line_number":239,"context_line":"        try:"},{"line_number":240,"context_line":"            LOG.debug(\"Setting quota for projid\u003d%(projid)s to %(size)sGB\","},{"line_number":241,"context_line":"                     {\u0027projid\u0027: projid, \u0027size\u0027: share_size_gb})"},{"line_number":242,"context_line":"            quota_response \u003d self.api_client.set_quota(projid, share_size_gb)"},{"line_number":243,"context_line":"            LOG.debug(\"Quota set response: %s\", quota_response)"},{"line_number":244,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"1c3930e7_a474b19e","line":241,"updated":"2026-06-27 20:37:22.000000000","message":"pep8: E128 continuation line under-indented for visual indent","commit_id":"02009d6020f8009bc5264ca9219cca5ef8612244"},{"author":{"_account_id":16643,"name":"Goutham Pacha Ravi","email":"gouthampravi@gmail.com","username":"gouthamr"},"change_message_id":"5b15ff5b6be4554259958e81b5309ff4e8e4c360","unresolved":true,"context_lines":[{"line_number":29,"context_line":"LOG \u003d log.getLogger(__name__)"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"class ExascalerShareDriver(driver.ShareDriver):"},{"line_number":33,"context_line":"    \"\"\"Manila share driver for DDN Exascaler."},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"    This driver manages shares on DDN Exascaler storage using the"}],"source_content_type":"text/x-python","patch_set":3,"id":"eac73d74_e2e84f9b","line":32,"updated":"2026-06-29 19:28:12.000000000","message":"The driver doesn\u0027t implement update_access. This is a required method on the ShareDriver base class; the share manager calls it after create_share and whenever access rules change. Without it, the driver will raise a NotImplementedError at runtime, and there\u0027s no tenant isolation at all. Any client that can mount the Lustre filesystem can access every share. Is this right?\nDoes the EXAScaler REST API support any form of access control (ACLs, nodemaps, NID filtering)?\nIf access control genuinely can\u0027t be supported on EXAScaler, the driver should explicitly override update_access, raise NotImplementedError, and document this limitation clearly. Operators need to understand that network-level isolation is the only security boundary.","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":15439,"name":"Alexey Khodos","email":"akhodos@ddn.com","username":"Alexey"},"change_message_id":"24f8c5cd674f59e8481b5562ffdb108ec54b13d3","unresolved":false,"context_lines":[{"line_number":29,"context_line":"LOG \u003d log.getLogger(__name__)"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"class ExascalerShareDriver(driver.ShareDriver):"},{"line_number":33,"context_line":"    \"\"\"Manila share driver for DDN Exascaler."},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"    This driver manages shares on DDN Exascaler storage using the"}],"source_content_type":"text/x-python","patch_set":3,"id":"0f6ed776_2444f196","line":32,"in_reply_to":"4bf96143_8aa35990","updated":"2026-06-30 18:39:21.000000000","message":"Done","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":15439,"name":"Alexey Khodos","email":"akhodos@ddn.com","username":"Alexey"},"change_message_id":"876964b4f8d6b63bcaddf207a05413f8bb472f48","unresolved":true,"context_lines":[{"line_number":29,"context_line":"LOG \u003d log.getLogger(__name__)"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"class ExascalerShareDriver(driver.ShareDriver):"},{"line_number":33,"context_line":"    \"\"\"Manila share driver for DDN Exascaler."},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"    This driver manages shares on DDN Exascaler storage using the"}],"source_content_type":"text/x-python","patch_set":3,"id":"4bf96143_8aa35990","line":32,"in_reply_to":"eac73d74_e2e84f9b","updated":"2026-06-29 23:29:34.000000000","message":"We use NID mappings to tenants to control access. Usually this is configured when a tenant is created on the ExaScaler, which is outside of the driver scope.\nWe have the APIs to add NIDs to a tenant, but the problem with using update_access is that it is per-share, while Lustre configures this per-tenant.\nHowever, we can implement user based access control per-share. I will add this in the next patch set.","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":16643,"name":"Goutham Pacha Ravi","email":"gouthampravi@gmail.com","username":"gouthamr"},"change_message_id":"5b15ff5b6be4554259958e81b5309ff4e8e4c360","unresolved":true,"context_lines":[{"line_number":42,"context_line":""},{"line_number":43,"context_line":"    def __init__(self, *args, **kwargs):"},{"line_number":44,"context_line":"        \"\"\"Initialize the Exascaler driver.\"\"\""},{"line_number":45,"context_line":"        super(ExascalerShareDriver, self).__init__(False, *args, **kwargs)"},{"line_number":46,"context_line":"        self.configuration.append_config_values(options.EXASCALER_OPTS)"},{"line_number":47,"context_line":"        self.api_client \u003d None"},{"line_number":48,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"1a8ca2f0_71f22b48","line":45,"updated":"2026-06-29 19:28:12.000000000","message":"Manila\u0027s minimum Python version is 3.x, so you can use the simpler super().__init__() form instead of super(ExascalerShareDriver, self).__init__().","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":15439,"name":"Alexey Khodos","email":"akhodos@ddn.com","username":"Alexey"},"change_message_id":"876964b4f8d6b63bcaddf207a05413f8bb472f48","unresolved":true,"context_lines":[{"line_number":42,"context_line":""},{"line_number":43,"context_line":"    def __init__(self, *args, **kwargs):"},{"line_number":44,"context_line":"        \"\"\"Initialize the Exascaler driver.\"\"\""},{"line_number":45,"context_line":"        super(ExascalerShareDriver, self).__init__(False, *args, **kwargs)"},{"line_number":46,"context_line":"        self.configuration.append_config_values(options.EXASCALER_OPTS)"},{"line_number":47,"context_line":"        self.api_client \u003d None"},{"line_number":48,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"1d70d22c_2cb26373","line":45,"in_reply_to":"1a8ca2f0_71f22b48","updated":"2026-06-29 23:29:34.000000000","message":"Acknowledged","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":15439,"name":"Alexey Khodos","email":"akhodos@ddn.com","username":"Alexey"},"change_message_id":"24f8c5cd674f59e8481b5562ffdb108ec54b13d3","unresolved":false,"context_lines":[{"line_number":42,"context_line":""},{"line_number":43,"context_line":"    def __init__(self, *args, **kwargs):"},{"line_number":44,"context_line":"        \"\"\"Initialize the Exascaler driver.\"\"\""},{"line_number":45,"context_line":"        super(ExascalerShareDriver, self).__init__(False, *args, **kwargs)"},{"line_number":46,"context_line":"        self.configuration.append_config_values(options.EXASCALER_OPTS)"},{"line_number":47,"context_line":"        self.api_client \u003d None"},{"line_number":48,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"013fd1ab_cff7193f","line":45,"in_reply_to":"1d70d22c_2cb26373","updated":"2026-06-30 18:39:21.000000000","message":"Done","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":16643,"name":"Goutham Pacha Ravi","email":"gouthampravi@gmail.com","username":"gouthamr"},"change_message_id":"5b15ff5b6be4554259958e81b5309ff4e8e4c360","unresolved":true,"context_lines":[{"line_number":110,"context_line":"        base_path \u003d self.configuration.exascaler_filesystem_path"},{"line_number":111,"context_line":"        return \"%s/manila-%s\" % (base_path, share[\u0027share_id\u0027])"},{"line_number":112,"context_line":""},{"line_number":113,"context_line":"    def _get_projid_from_share(self, share, max_attempts\u003d10):"},{"line_number":114,"context_line":"        \"\"\"Get or generate project ID for a share."},{"line_number":115,"context_line":""},{"line_number":116,"context_line":"        Uses last N digits of share UUID converted to integer."}],"source_content_type":"text/x-python","patch_set":3,"id":"d58897bf_7f6846a0","line":113,"updated":"2026-06-29 19:28:12.000000000","message":"The project ID generation scheme has a few concerns:\n1. The range is only 1-100,000, which limits the number of concurrent shares and makes collisions likely at scale. Lustre supports project IDs up to 2^32.\n2. On delete, the projid is regenerated from the UUID, but _generate_projid_from_uuid uses a fixed suffix_length\u003d5, while create may have used a different suffix_length (6-14) if collisions occurred. This means delete could try to clear the wrong project\u0027s quota.\n3. The fallback to share_metadata for projid retrieval in delete/extend/shrink suggests the projid should be persisted, but create_share doesn\u0027t store it anywhere.\nI\u0027d recommend using Manila\u0027s private_storage to persist the projid at create time (self.private_storage.update(share[\u0027id\u0027], {\u0027projid\u0027: projid})). This is how other drivers (e.g. NetApp ONTAP) persist backend-specific state. Then retrieval in delete/extend/shrink is reliable and you can drop the regeneration fallback.","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":15439,"name":"Alexey Khodos","email":"akhodos@ddn.com","username":"Alexey"},"change_message_id":"876964b4f8d6b63bcaddf207a05413f8bb472f48","unresolved":false,"context_lines":[{"line_number":110,"context_line":"        base_path \u003d self.configuration.exascaler_filesystem_path"},{"line_number":111,"context_line":"        return \"%s/manila-%s\" % (base_path, share[\u0027share_id\u0027])"},{"line_number":112,"context_line":""},{"line_number":113,"context_line":"    def _get_projid_from_share(self, share, max_attempts\u003d10):"},{"line_number":114,"context_line":"        \"\"\"Get or generate project ID for a share."},{"line_number":115,"context_line":""},{"line_number":116,"context_line":"        Uses last N digits of share UUID converted to integer."}],"source_content_type":"text/x-python","patch_set":3,"id":"e0ffca14_ebd114d3","line":113,"in_reply_to":"d58897bf_7f6846a0","updated":"2026-06-29 23:29:34.000000000","message":"This makes sense, I will use private_storage for this.","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":16643,"name":"Goutham Pacha Ravi","email":"gouthampravi@gmail.com","username":"gouthamr"},"change_message_id":"5b15ff5b6be4554259958e81b5309ff4e8e4c360","unresolved":true,"context_lines":[{"line_number":526,"context_line":"                raise exception.ShareBackendException(msg\u003dmsg)"},{"line_number":527,"context_line":""},{"line_number":528,"context_line":"            # Command still pending/running"},{"line_number":529,"context_line":"            time.sleep(poll_interval)"},{"line_number":530,"context_line":""},{"line_number":531,"context_line":"        # Timeout reached"},{"line_number":532,"context_line":"        elapsed \u003d time.time() - start_time"}],"source_content_type":"text/x-python","patch_set":3,"id":"2d63af40_89e11d4b","line":529,"updated":"2026-06-29 19:28:12.000000000","message":"time.sleep() in driver code blocks the share manager\u0027s threadpool. If multiple shares are being created/deleted simultaneously, each blocked thread reduces throughput. Consider using loopingcall from oslo_service for async polling, or at minimum document the threading impact. The command timeout defaults to 120s with 2s poll intervals, so that\u0027s potentially 60 sleep cycles per share operation.","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":15439,"name":"Alexey Khodos","email":"akhodos@ddn.com","username":"Alexey"},"change_message_id":"876964b4f8d6b63bcaddf207a05413f8bb472f48","unresolved":false,"context_lines":[{"line_number":526,"context_line":"                raise exception.ShareBackendException(msg\u003dmsg)"},{"line_number":527,"context_line":""},{"line_number":528,"context_line":"            # Command still pending/running"},{"line_number":529,"context_line":"            time.sleep(poll_interval)"},{"line_number":530,"context_line":""},{"line_number":531,"context_line":"        # Timeout reached"},{"line_number":532,"context_line":"        elapsed \u003d time.time() - start_time"}],"source_content_type":"text/x-python","patch_set":3,"id":"d5a31e3b_13f6d583","line":529,"in_reply_to":"2d63af40_89e11d4b","updated":"2026-06-29 23:29:34.000000000","message":"We actually want to block parallel creation, current API version is sensitive to mass parallel calls and we want to avoid it. I am also looking to add coordination.lock in next patch set.","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":16643,"name":"Goutham Pacha Ravi","email":"gouthampravi@gmail.com","username":"gouthamr"},"change_message_id":"5b15ff5b6be4554259958e81b5309ff4e8e4c360","unresolved":true,"context_lines":[{"line_number":617,"context_line":"                # Still try to clear quota"},{"line_number":618,"context_line":"                try:"},{"line_number":619,"context_line":"                    self.api_client.clear_quota(projid)"},{"line_number":620,"context_line":"                except Exception:"},{"line_number":621,"context_line":"                    pass"},{"line_number":622,"context_line":"                return"},{"line_number":623,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"f0046e70_e38842bc","line":620,"updated":"2026-06-29 19:28:12.000000000","message":"Bare \"except Exception\" that silently passes. This swallows all errors during quota cleanup on the \"not found\" path. At minimum, log the exception so operators can debug quota leaks.","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":15439,"name":"Alexey Khodos","email":"akhodos@ddn.com","username":"Alexey"},"change_message_id":"876964b4f8d6b63bcaddf207a05413f8bb472f48","unresolved":false,"context_lines":[{"line_number":617,"context_line":"                # Still try to clear quota"},{"line_number":618,"context_line":"                try:"},{"line_number":619,"context_line":"                    self.api_client.clear_quota(projid)"},{"line_number":620,"context_line":"                except Exception:"},{"line_number":621,"context_line":"                    pass"},{"line_number":622,"context_line":"                return"},{"line_number":623,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"945afb40_d53c1157","line":620,"in_reply_to":"f0046e70_e38842bc","updated":"2026-06-29 23:29:34.000000000","message":"Acknowledged","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":16643,"name":"Goutham Pacha Ravi","email":"gouthampravi@gmail.com","username":"gouthamr"},"change_message_id":"5b15ff5b6be4554259958e81b5309ff4e8e4c360","unresolved":true,"context_lines":[{"line_number":627,"context_line":"            }"},{"line_number":628,"context_line":"            raise exception.ShareBackendException(msg\u003dmsg)"},{"line_number":629,"context_line":""},{"line_number":630,"context_line":"    def ensure_share(self, context, share, share_server\u003dNone):"},{"line_number":631,"context_line":"        \"\"\"Ensure that share exists."},{"line_number":632,"context_line":""},{"line_number":633,"context_line":"        :param context: Current context"}],"source_content_type":"text/x-python","patch_set":3,"id":"4de079a0_79b2054c","line":630,"updated":"2026-06-29 19:28:12.000000000","message":"ensure_share is called during manila-share service restart to verify that shares still exist on the backend. This implementation just returns the export location without checking if the volume actually exists on EXAScaler. If a volume was deleted out-of-band, Manila would continue to report it as healthy. The API client already has volume_exists() and get_volumes(),could you use those to verify the share is actually present?","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":15439,"name":"Alexey Khodos","email":"akhodos@ddn.com","username":"Alexey"},"change_message_id":"876964b4f8d6b63bcaddf207a05413f8bb472f48","unresolved":false,"context_lines":[{"line_number":627,"context_line":"            }"},{"line_number":628,"context_line":"            raise exception.ShareBackendException(msg\u003dmsg)"},{"line_number":629,"context_line":""},{"line_number":630,"context_line":"    def ensure_share(self, context, share, share_server\u003dNone):"},{"line_number":631,"context_line":"        \"\"\"Ensure that share exists."},{"line_number":632,"context_line":""},{"line_number":633,"context_line":"        :param context: Current context"}],"source_content_type":"text/x-python","patch_set":3,"id":"a29c684c_89aa3ce8","line":630,"in_reply_to":"4de079a0_79b2054c","updated":"2026-06-29 23:29:34.000000000","message":"will add that.","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":16643,"name":"Goutham Pacha Ravi","email":"gouthampravi@gmail.com","username":"gouthamr"},"change_message_id":"5b15ff5b6be4554259958e81b5309ff4e8e4c360","unresolved":true,"context_lines":[{"line_number":726,"context_line":"            }"},{"line_number":727,"context_line":"            raise exception.ShareBackendException(msg\u003dmsg)"},{"line_number":728,"context_line":""},{"line_number":729,"context_line":"    def _update_share_stats(self):"},{"line_number":730,"context_line":"        \"\"\"Update backend stats.\"\"\""},{"line_number":731,"context_line":"        # Get capacity from quota API"},{"line_number":732,"context_line":"        total_capacity_gb \u003d \u0027unknown\u0027"}],"source_content_type":"text/x-python","patch_set":3,"id":"2079b9a7_9e8d4bbe","line":729,"updated":"2026-06-29 19:28:12.000000000","message":"When quota API fails, total_capacity_gb and free_capacity_gb are set to the string \u0027unknown\u0027. Manila\u0027s scheduler expects these to be numeric or \u0027unknown\u0027 (string), so the current code is correct, but a comment noting this is intentional would help. Also, the capacity calculation reports the sum of all project quotas as total capacity, which is the provisioned capacity, not the physical capacity of the filesystem. This means the scheduler sees only the currently allocated space, not the available space for new shares.","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":15439,"name":"Alexey Khodos","email":"akhodos@ddn.com","username":"Alexey"},"change_message_id":"876964b4f8d6b63bcaddf207a05413f8bb472f48","unresolved":false,"context_lines":[{"line_number":726,"context_line":"            }"},{"line_number":727,"context_line":"            raise exception.ShareBackendException(msg\u003dmsg)"},{"line_number":728,"context_line":""},{"line_number":729,"context_line":"    def _update_share_stats(self):"},{"line_number":730,"context_line":"        \"\"\"Update backend stats.\"\"\""},{"line_number":731,"context_line":"        # Get capacity from quota API"},{"line_number":732,"context_line":"        total_capacity_gb \u003d \u0027unknown\u0027"}],"source_content_type":"text/x-python","patch_set":3,"id":"45334678_07e887f3","line":729,"in_reply_to":"2079b9a7_9e8d4bbe","updated":"2026-06-29 23:29:34.000000000","message":"I\u0027ll a comment for \u0027unknown\u0027.\n\nCapacity calculation is based on the data returned by the API, which reports used bytes, not just allocated, so I think this is correct the way it is.","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"50a588f431bee17e78f91317a9aaea907f84fb6d","unresolved":false,"context_lines":[{"line_number":154,"context_line":"            start_pos \u003d (attempt * 3) % max(1, len(uuid_hex) - num_digits)"},{"line_number":155,"context_line":"            hex_suffix \u003d uuid_hex[start_pos:start_pos + num_digits]"},{"line_number":156,"context_line":""},{"line_number":157,"context_line":"            # Convert to int and constrain to Exascaler\u0027s valid range (1-100,000)"},{"line_number":158,"context_line":"            projid \u003d (int(hex_suffix, 16) % 99999) + 1"},{"line_number":159,"context_line":""},{"line_number":160,"context_line":"            LOG.debug(\"Generated projid %(projid)s from share \""}],"source_content_type":"text/x-python","patch_set":4,"id":"84fb8d34_b481fa82","line":157,"updated":"2026-06-30 09:02:02.000000000","message":"pep8: E501 line too long (81 \u003e 79 characters)","commit_id":"b1901f566a66cae474f6182b8f1f2da8044a3c71"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"50a588f431bee17e78f91317a9aaea907f84fb6d","unresolved":false,"context_lines":[{"line_number":303,"context_line":""},{"line_number":304,"context_line":""},{"line_number":305,"context_line":""},{"line_number":306,"context_line":"    def _get_extra_specs(self, share):"},{"line_number":307,"context_line":"        \"\"\"Get extra specs from share type."},{"line_number":308,"context_line":""},{"line_number":309,"context_line":"        Uses Manila\u0027s share_types API to retrieve extra specs."}],"source_content_type":"text/x-python","patch_set":4,"id":"4980f781_71faf241","line":306,"updated":"2026-06-30 09:02:02.000000000","message":"pep8: E303 too many blank lines (3)","commit_id":"b1901f566a66cae474f6182b8f1f2da8044a3c71"}],"manila/share/drivers/exascaler/options.py":[{"author":{"_account_id":16643,"name":"Goutham Pacha Ravi","email":"gouthampravi@gmail.com","username":"gouthamr"},"change_message_id":"5b15ff5b6be4554259958e81b5309ff4e8e4c360","unresolved":true,"context_lines":[{"line_number":32,"context_line":"               default\u003dNone,"},{"line_number":33,"context_line":"               secret\u003dTrue,"},{"line_number":34,"context_line":"               help\u003d\u0027Exascaler API password.\u0027),"},{"line_number":35,"context_line":"    cfg.BoolOpt(\u0027exascaler_mgmt_verify_ssl\u0027,"},{"line_number":36,"context_line":"                default\u003dFalse,"},{"line_number":37,"context_line":"                help\u003d\u0027Verify SSL certificates for API connections.\u0027),"},{"line_number":38,"context_line":"    cfg.IntOpt(\u0027exascaler_mgmt_api_timeout\u0027,"}],"source_content_type":"text/x-python","patch_set":3,"id":"37ad340a_8186da01","line":35,"updated":"2026-06-29 19:28:12.000000000","message":"exascaler_mgmt_verify_ssl defaults to False. This means SSL certificate verification is disabled by default, so credentials (username/password) are sent over an HTTPS connection that doesn\u0027t validate the server\u0027s identity, which is vulnerable to MITM attacks. This should default to True, consistent a \"secure by default\" stance. You should also add a companion option for a custom CA bundle path (like emc_ssl_cert_path) so deployers using internal CAs don\u0027t have to disable verification entirely.","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":15439,"name":"Alexey Khodos","email":"akhodos@ddn.com","username":"Alexey"},"change_message_id":"876964b4f8d6b63bcaddf207a05413f8bb472f48","unresolved":false,"context_lines":[{"line_number":32,"context_line":"               default\u003dNone,"},{"line_number":33,"context_line":"               secret\u003dTrue,"},{"line_number":34,"context_line":"               help\u003d\u0027Exascaler API password.\u0027),"},{"line_number":35,"context_line":"    cfg.BoolOpt(\u0027exascaler_mgmt_verify_ssl\u0027,"},{"line_number":36,"context_line":"                default\u003dFalse,"},{"line_number":37,"context_line":"                help\u003d\u0027Verify SSL certificates for API connections.\u0027),"},{"line_number":38,"context_line":"    cfg.IntOpt(\u0027exascaler_mgmt_api_timeout\u0027,"}],"source_content_type":"text/x-python","patch_set":3,"id":"e39de353_13f05bca","line":35,"in_reply_to":"37ad340a_8186da01","updated":"2026-06-29 23:29:34.000000000","message":"Acknowledged","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":16643,"name":"Goutham Pacha Ravi","email":"gouthampravi@gmail.com","username":"gouthamr"},"change_message_id":"5b15ff5b6be4554259958e81b5309ff4e8e4c360","unresolved":true,"context_lines":[{"line_number":76,"context_line":"]"},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"CONF \u003d cfg.CONF"},{"line_number":79,"context_line":"CONF.register_opts(EXASCALER_OPTS)"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"CONF \u003d cfg.CONF"},{"line_number":82,"context_line":"CONF.register_opts(EXASCALER_OPTS)"}],"source_content_type":"text/x-python","patch_set":3,"id":"0a25f86a_96d1baba","line":79,"updated":"2026-06-29 19:28:12.000000000","message":"CONF.register_opts(EXASCALER_OPTS) is called twice. Also, driver options should generally not be registered at module level, the driver constructor handles registration via self.configuration.append_config_values(). The module-level registration is only needed for oslo-config-generator (via opts.py), and even then, a single call is sufficient.","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":15439,"name":"Alexey Khodos","email":"akhodos@ddn.com","username":"Alexey"},"change_message_id":"876964b4f8d6b63bcaddf207a05413f8bb472f48","unresolved":false,"context_lines":[{"line_number":76,"context_line":"]"},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"CONF \u003d cfg.CONF"},{"line_number":79,"context_line":"CONF.register_opts(EXASCALER_OPTS)"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"CONF \u003d cfg.CONF"},{"line_number":82,"context_line":"CONF.register_opts(EXASCALER_OPTS)"}],"source_content_type":"text/x-python","patch_set":3,"id":"13f73a5d_ca7c6d6f","line":79,"in_reply_to":"0a25f86a_96d1baba","updated":"2026-06-29 23:29:34.000000000","message":"Acknowledged","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"}],"manila/share/drivers/exascaler/rest_client.py":[{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":16,"context_line":"\"\"\"REST API client for DDN Exascaler management API.\"\"\""},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"import requests"},{"line_number":19,"context_line":"from oslo_log import log"},{"line_number":20,"context_line":"from requests.auth import HTTPBasicAuth"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"LOG \u003d log.getLogger(__name__)"}],"source_content_type":"text/x-python","patch_set":1,"id":"766929ad_47006c7c","line":19,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: H306: imports not in alphabetical order (requests, oslo_log.log)","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":30,"context_line":"class ExascalerRESTClient:"},{"line_number":31,"context_line":"    \"\"\"Client for Exascaler REST API.\"\"\""},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"    def __init__(self, host, port, username, password, tenant, verify_ssl\u003dFalse, timeout\u003d60):"},{"line_number":34,"context_line":"        \"\"\"Initialize the REST client."},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"        :param host: Management API host"}],"source_content_type":"text/x-python","patch_set":1,"id":"44335911_e7631598","line":33,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E501 line too long (93 \u003e 79 characters)","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":48,"context_line":"        self.timeout \u003d timeout"},{"line_number":49,"context_line":"        self.auth \u003d HTTPBasicAuth(username, password)"},{"line_number":50,"context_line":"        self.base_url \u003d \"https://%s:%s/api/v2/tenants/%s\" % (host, port,"},{"line_number":51,"context_line":"                                                               tenant)"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"    def _request(self, method, endpoint, data\u003dNone):"},{"line_number":54,"context_line":"        \"\"\"Make HTTP request to the API."}],"source_content_type":"text/x-python","patch_set":1,"id":"37a30e87_d95e4cc1","line":51,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E127 continuation line over-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":213,"context_line":""},{"line_number":214,"context_line":"            # Project ID not found in quota list"},{"line_number":215,"context_line":"            LOG.debug(\"Project ID %(projid)s not found in quota list\","},{"line_number":216,"context_line":"                     {\u0027projid\u0027: projid})"},{"line_number":217,"context_line":"            return False"},{"line_number":218,"context_line":""},{"line_number":219,"context_line":"        except Exception as e:"}],"source_content_type":"text/x-python","patch_set":1,"id":"9b30d505_98a8a4a0","line":216,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E128 continuation line under-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":320,"context_line":"                return None"},{"line_number":321,"context_line":"            elif response.status_code !\u003d 200:"},{"line_number":322,"context_line":"                LOG.warning(\"Failed to get command %(id)s status: %(code)s\","},{"line_number":323,"context_line":"                           {\u0027id\u0027: command_id, \u0027code\u0027: response.status_code})"},{"line_number":324,"context_line":"                return None"},{"line_number":325,"context_line":""},{"line_number":326,"context_line":"            result \u003d response.json() if response.text else None"}],"source_content_type":"text/x-python","patch_set":1,"id":"9814ffa1_21ab73b8","line":323,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E128 continuation line under-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":358,"context_line":"            # Accept both 200 OK and 202 Accepted as success"},{"line_number":359,"context_line":"            if response.status_code not in (200, 202):"},{"line_number":360,"context_line":"                LOG.warning(\"Failed to resume command %(id)s: HTTP %(code)s\","},{"line_number":361,"context_line":"                           {\u0027id\u0027: command_id, \u0027code\u0027: response.status_code})"},{"line_number":362,"context_line":"                return None"},{"line_number":363,"context_line":""},{"line_number":364,"context_line":"            result \u003d response.json() if response.text else None"}],"source_content_type":"text/x-python","patch_set":1,"id":"ce37fc4d_38194a9c","line":361,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E128 continuation line under-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":363,"context_line":""},{"line_number":364,"context_line":"            result \u003d response.json() if response.text else None"},{"line_number":365,"context_line":"            if result and \u0027id\u0027 in result:"},{"line_number":366,"context_line":"                LOG.info(\"Command %(old_id)s resumed as new command %(new_id)s\","},{"line_number":367,"context_line":"                        {\u0027old_id\u0027: command_id, \u0027new_id\u0027: result[\u0027id\u0027]})"},{"line_number":368,"context_line":"            else:"},{"line_number":369,"context_line":"                LOG.warning(\"Resume command %(id)s returned %(code)s but no new ID in response\","}],"source_content_type":"text/x-python","patch_set":1,"id":"b391b83c_5b15c58f","line":366,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E501 line too long (80 \u003e 79 characters)","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":364,"context_line":"            result \u003d response.json() if response.text else None"},{"line_number":365,"context_line":"            if result and \u0027id\u0027 in result:"},{"line_number":366,"context_line":"                LOG.info(\"Command %(old_id)s resumed as new command %(new_id)s\","},{"line_number":367,"context_line":"                        {\u0027old_id\u0027: command_id, \u0027new_id\u0027: result[\u0027id\u0027]})"},{"line_number":368,"context_line":"            else:"},{"line_number":369,"context_line":"                LOG.warning(\"Resume command %(id)s returned %(code)s but no new ID in response\","},{"line_number":370,"context_line":"                           {\u0027id\u0027: command_id, \u0027code\u0027: response.status_code})"}],"source_content_type":"text/x-python","patch_set":1,"id":"99bf79f0_df03e012","line":367,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E128 continuation line under-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":366,"context_line":"                LOG.info(\"Command %(old_id)s resumed as new command %(new_id)s\","},{"line_number":367,"context_line":"                        {\u0027old_id\u0027: command_id, \u0027new_id\u0027: result[\u0027id\u0027]})"},{"line_number":368,"context_line":"            else:"},{"line_number":369,"context_line":"                LOG.warning(\"Resume command %(id)s returned %(code)s but no new ID in response\","},{"line_number":370,"context_line":"                           {\u0027id\u0027: command_id, \u0027code\u0027: response.status_code})"},{"line_number":371,"context_line":"            return result"},{"line_number":372,"context_line":"        except Exception as e:"}],"source_content_type":"text/x-python","patch_set":1,"id":"74b55d44_120de89e","line":369,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E501 line too long (96 \u003e 79 characters)","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":367,"context_line":"                        {\u0027old_id\u0027: command_id, \u0027new_id\u0027: result[\u0027id\u0027]})"},{"line_number":368,"context_line":"            else:"},{"line_number":369,"context_line":"                LOG.warning(\"Resume command %(id)s returned %(code)s but no new ID in response\","},{"line_number":370,"context_line":"                           {\u0027id\u0027: command_id, \u0027code\u0027: response.status_code})"},{"line_number":371,"context_line":"            return result"},{"line_number":372,"context_line":"        except Exception as e:"},{"line_number":373,"context_line":"            LOG.warning(\"Failed to resume command %(id)s: %(err)s\","}],"source_content_type":"text/x-python","patch_set":1,"id":"680b60b4_8454f39f","line":370,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E128 continuation line under-indented for visual indent","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"e01812e15a2e92be9edc65a4cc0ee41cccd3cf14","unresolved":false,"context_lines":[{"line_number":49,"context_line":"        self.timeout \u003d timeout"},{"line_number":50,"context_line":"        self.auth \u003d HTTPBasicAuth(username, password)"},{"line_number":51,"context_line":"        self.base_url \u003d \"https://%s:%s/api/v2/tenants/%s\" % (host, port,"},{"line_number":52,"context_line":"                                                              tenant)"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"    def _request(self, method, endpoint, data\u003dNone):"},{"line_number":55,"context_line":"        \"\"\"Make HTTP request to the API."}],"source_content_type":"text/x-python","patch_set":2,"id":"6da5e7e0_599c693f","line":52,"updated":"2026-06-27 20:37:22.000000000","message":"pep8: E127 continuation line over-indented for visual indent","commit_id":"02009d6020f8009bc5264ca9219cca5ef8612244"},{"author":{"_account_id":16643,"name":"Goutham Pacha Ravi","email":"gouthampravi@gmail.com","username":"gouthamr"},"change_message_id":"5b15ff5b6be4554259958e81b5309ff4e8e4c360","unresolved":true,"context_lines":[{"line_number":106,"context_line":"            LOG.error(error_msg)"},{"line_number":107,"context_line":"            raise ExascalerAPIException(error_msg)"},{"line_number":108,"context_line":""},{"line_number":109,"context_line":"    def create_volume(self, path, quota_gb, uid\u003d1073741824, gid\u003d1073741824,"},{"line_number":110,"context_line":"                      projid\u003dNone):"},{"line_number":111,"context_line":"        \"\"\"Create a volume (directory with quota)."},{"line_number":112,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"3e8a7b6c_aa7f9150","line":109,"updated":"2026-06-29 19:28:12.000000000","message":"The default uid/gid of 1073741824 (0x40000000) is unusual and EXAScaler-specific. A comment explaining why this value was chosen would help reviewers and future maintainers. Is this a \"nobody\" equivalent in EXAScaler?","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":15439,"name":"Alexey Khodos","email":"akhodos@ddn.com","username":"Alexey"},"change_message_id":"876964b4f8d6b63bcaddf207a05413f8bb472f48","unresolved":false,"context_lines":[{"line_number":106,"context_line":"            LOG.error(error_msg)"},{"line_number":107,"context_line":"            raise ExascalerAPIException(error_msg)"},{"line_number":108,"context_line":""},{"line_number":109,"context_line":"    def create_volume(self, path, quota_gb, uid\u003d1073741824, gid\u003d1073741824,"},{"line_number":110,"context_line":"                      projid\u003dNone):"},{"line_number":111,"context_line":"        \"\"\"Create a volume (directory with quota)."},{"line_number":112,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"46d3f103_a6efa98c","line":109,"in_reply_to":"3e8a7b6c_aa7f9150","updated":"2026-06-29 23:29:34.000000000","message":"This is a default uid/gid for a new volume created by ExaScaler API","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"}],"manila/tests/share/drivers/exascaler/test_driver.py":[{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":82,"context_line":"        self.assertEqual(self.driver.share_backend_name, \u0027Exascaler\u0027)"},{"line_number":83,"context_line":"        self.assertIsNotNone(self.driver.api_client)"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"    @mock.patch(\u0027manila.share.drivers.exascaler.rest_client.ExascalerRESTClient\u0027)"},{"line_number":86,"context_line":"    def test_do_setup(self, mock_client_class):"},{"line_number":87,"context_line":"        \"\"\"Test do_setup method.\"\"\""},{"line_number":88,"context_line":"        test_driver \u003d driver.ExascalerShareDriver("}],"source_content_type":"text/x-python","patch_set":1,"id":"2ea6715a_15f26076","line":85,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E501 line too long (81 \u003e 79 characters)","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"1df0d73d006aafe91b3cf04aab574fc02c6fd5ae","unresolved":false,"context_lines":[{"line_number":426,"context_line":""},{"line_number":427,"context_line":""},{"line_number":428,"context_line":""},{"line_number":429,"context_line":"    def test_update_share_stats(self):"},{"line_number":430,"context_line":"        \"\"\"Test _update_share_stats method.\"\"\""},{"line_number":431,"context_line":"        self.driver._update_share_stats()"},{"line_number":432,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"17affb29_a9a8e751","line":429,"updated":"2026-06-27 00:55:04.000000000","message":"pep8: E303 too many blank lines (3)","commit_id":"54ed67d43947be9f03035c6b60a93c3cc66ad6af"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"e01812e15a2e92be9edc65a4cc0ee41cccd3cf14","unresolved":false,"context_lines":[{"line_number":82,"context_line":"        self.assertEqual(self.driver.share_backend_name, \u0027Exascaler\u0027)"},{"line_number":83,"context_line":"        self.assertIsNotNone(self.driver.api_client)"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"    @mock.patch(\u0027manila.share.drivers.exascaler.rest_client.ExascalerRESTClient\u0027)"},{"line_number":86,"context_line":"    def test_do_setup(self, mock_client_class):"},{"line_number":87,"context_line":"        \"\"\"Test do_setup method.\"\"\""},{"line_number":88,"context_line":"        test_driver \u003d driver.ExascalerShareDriver("}],"source_content_type":"text/x-python","patch_set":2,"id":"86e8bf71_ea520243","line":85,"updated":"2026-06-27 20:37:22.000000000","message":"pep8: E501 line too long (81 \u003e 79 characters)","commit_id":"02009d6020f8009bc5264ca9219cca5ef8612244"},{"author":{"_account_id":16643,"name":"Goutham Pacha Ravi","email":"gouthampravi@gmail.com","username":"gouthamr"},"change_message_id":"5b15ff5b6be4554259958e81b5309ff4e8e4c360","unresolved":true,"context_lines":[{"line_number":27,"context_line":"CONF \u003d cfg.CONF"},{"line_number":28,"context_line":""},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"class ExascalerShareDriverTestCase(unittest.TestCase):"},{"line_number":31,"context_line":"    \"\"\"Test case for ExascalerShareDriver.\"\"\""},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"    def setUp(self):"}],"source_content_type":"text/x-python","patch_set":3,"id":"8511ec55_9901f26f","line":30,"updated":"2026-06-29 19:28:12.000000000","message":"Manila unit tests should inherit from manila.test.TestCase (or oslo_test.BaseTestCase), not unittest.TestCase. Manila\u0027s TestCase provides fixtures for oslo.config, logging, and database isolation. Using raw unittest.TestCase may cause test pollution or missing teardown.","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":15439,"name":"Alexey Khodos","email":"akhodos@ddn.com","username":"Alexey"},"change_message_id":"876964b4f8d6b63bcaddf207a05413f8bb472f48","unresolved":false,"context_lines":[{"line_number":27,"context_line":"CONF \u003d cfg.CONF"},{"line_number":28,"context_line":""},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"class ExascalerShareDriverTestCase(unittest.TestCase):"},{"line_number":31,"context_line":"    \"\"\"Test case for ExascalerShareDriver.\"\"\""},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"    def setUp(self):"}],"source_content_type":"text/x-python","patch_set":3,"id":"ff424cf1_0db27f8c","line":30,"in_reply_to":"8511ec55_9901f26f","updated":"2026-06-29 23:29:34.000000000","message":"Acknowledged","commit_id":"336972f64ae2268c44a01b7e1e44fa5257e994da"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"50a588f431bee17e78f91317a9aaea907f84fb6d","unresolved":false,"context_lines":[{"line_number":20,"context_line":"from manila import coordination"},{"line_number":21,"context_line":"from manila import exception"},{"line_number":22,"context_line":"from manila import test"},{"line_number":23,"context_line":"from manila.share.drivers.exascaler import driver"},{"line_number":24,"context_line":"from manila.share.drivers.exascaler import rest_client"},{"line_number":25,"context_line":"from oslo_config import cfg"},{"line_number":26,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"f2b70e63_3e33f98a","line":23,"updated":"2026-06-30 09:02:02.000000000","message":"pep8: H306: imports not in alphabetical order (manila.test, manila.share.drivers.exascaler.driver)","commit_id":"b1901f566a66cae474f6182b8f1f2da8044a3c71"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"50a588f431bee17e78f91317a9aaea907f84fb6d","unresolved":false,"context_lines":[{"line_number":144,"context_line":""},{"line_number":145,"context_line":""},{"line_number":146,"context_line":""},{"line_number":147,"context_line":"    def test_get_projid_from_share_success(self, get_lock):"},{"line_number":148,"context_line":"        \"\"\"Test _get_projid_from_share when projid is available.\"\"\""},{"line_number":149,"context_line":"        share \u003d {\u0027share_id\u0027: \u0027test1234-5678-9012-3456-789012345678\u0027}"},{"line_number":150,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"207273d7_20ca6b73","line":147,"updated":"2026-06-30 09:02:02.000000000","message":"pep8: E303 too many blank lines (3)","commit_id":"b1901f566a66cae474f6182b8f1f2da8044a3c71"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"50a588f431bee17e78f91317a9aaea907f84fb6d","unresolved":false,"context_lines":[{"line_number":440,"context_line":""},{"line_number":441,"context_line":"    @mock.patch(\u0027manila.share.share_types.get_share_type_extra_specs\u0027)"},{"line_number":442,"context_line":"    def test_get_extra_specs_with_share_type(self, mock_get_extra_specs,"},{"line_number":443,"context_line":"                                              get_lock):"},{"line_number":444,"context_line":"        \"\"\"Test _get_extra_specs when share has share_type.\"\"\""},{"line_number":445,"context_line":"        mock_get_extra_specs.return_value \u003d {"},{"line_number":446,"context_line":"            \u0027exascaler:uid\u0027: \u00271000\u0027,"}],"source_content_type":"text/x-python","patch_set":4,"id":"9900fe4f_428e0032","line":443,"updated":"2026-06-30 09:02:02.000000000","message":"pep8: E127 continuation line over-indented for visual indent","commit_id":"b1901f566a66cae474f6182b8f1f2da8044a3c71"}],"manila/tests/share/drivers/exascaler/test_rest_client.py":[{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"50a588f431bee17e78f91317a9aaea907f84fb6d","unresolved":false,"context_lines":[{"line_number":18,"context_line":"from unittest import mock"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"from manila import test"},{"line_number":21,"context_line":"from manila.share.drivers.exascaler import rest_client"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"class ExascalerRESTClientTestCase(test.TestCase):"}],"source_content_type":"text/x-python","patch_set":4,"id":"45a83ac7_350db272","line":21,"updated":"2026-06-30 09:02:02.000000000","message":"pep8: H306: imports not in alphabetical order (manila.test, manila.share.drivers.exascaler.rest_client)","commit_id":"b1901f566a66cae474f6182b8f1f2da8044a3c71"}]}
