)]}'
{"watcher/applier/actions/volume_migration.py":[{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"4e86fbcfb31eec9eb7b4c536623c3d192fad2bf1","unresolved":false,"context_lines":[{"line_number":225,"context_line":"        \"\"\""},{"line_number":226,"context_line":"        try:"},{"line_number":227,"context_line":"            volume \u003d self.cinder_util.get_volume(self.volume_id)"},{"line_number":228,"context_line":"        except sdk_exc.NotFoundException:"},{"line_number":229,"context_line":"            raise exception.ActionSkipped("},{"line_number":230,"context_line":"                _(\"Volume %s not found\") % self.volume_id"},{"line_number":231,"context_line":"            )"}],"source_content_type":"text/x-python","patch_set":3,"id":"febabc16_74beb541","line":228,"updated":"2026-06-25 11:59:16.000000000","message":"pre_condition catches sdk_exc.NotFoundException but get_volume() is decorated with handle_cinder_error which transforms NotFoundException into exception.StorageResourceNotFound. The except clause will never match in production.\n\n**Severity**: HIGH | **Confidence**: 0.9\n\n**Risk**: When a volume does not exist during pre_condition, the StorageResourceNotFound exception propagates uncaught instead of being gracefully handled as ActionSkipped, causing an unexpected action execution failure rather than a clean skip.\n\n**Priority**: Before merge\n**Why This Matters**: This breaks the intended behavior: volume-not-found should skip the action gracefully. The existing test masks this because it mocks the entire CinderHelper class, bypassing the decorator that transforms the exception type.\n\n**Recommendation**:\nChange \u0027except sdk_exc.NotFoundException:\u0027 to \u0027except exception.StorageResourceNotFound:\u0027 and remove the now-unused \u0027from openstack import exceptions as sdk_exc\u0027 import at line 18.","commit_id":"a84585078b28a1cc3c71194a9381742e195e5442"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"715507cc7d01af17f2d8976d40369a02976e8548","unresolved":false,"context_lines":[{"line_number":68,"context_line":"    DESTINATION_NODE \u003d \"destination_node\""},{"line_number":69,"context_line":"    DESTINATION_TYPE \u003d \"destination_type\""},{"line_number":70,"context_line":""},{"line_number":71,"context_line":"    def __init__(self, config, osc\u003dNone):"},{"line_number":72,"context_line":"        super().__init__(config)"},{"line_number":73,"context_line":"        self.cinder_util \u003d cinder_helper.CinderHelper()"},{"line_number":74,"context_line":"        self.nova_util \u003d nova_helper.NovaHelper()"}],"source_content_type":"text/x-python","patch_set":6,"id":"98f7a102_b05bc99b","line":71,"updated":"2026-06-26 07:48:21.000000000","message":"VolumeMigrate.__init__ still accepts osc\u003dNone parameter but never passes it to the helpers, making it dead code.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: The osc parameter is misleading - callers may believe it is being used when it is silently ignored. The parent BaseAction stores it in self._osc, but CinderHelper and NovaHelper now create their own connections independently.\n\n**Suggestion**:\nRemove the osc\u003dNone parameter from VolumeMigrate.__init__ and call super().__init__(config) without osc, or add a comment explaining it is retained for BaseAction compatibility but unused.","commit_id":"c2c84f4bc74a73501d96faf324c4e41c2deeba68"}],"watcher/common/cinder_helper.py":[{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"d080ee00e3f683a4d74dd25c2fbd2d18b1b5794a","unresolved":false,"context_lines":[{"line_number":16,"context_line":"import functools"},{"line_number":17,"context_line":"import time"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"from openstack import exceptions as sdk_exc"},{"line_number":20,"context_line":"from oslo_log import log"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"from watcher import conf"}],"source_content_type":"text/x-python","patch_set":1,"id":"c64b3ad6_67c1fc3b","line":19,"updated":"2026-06-25 07:27:46.000000000","message":"python-cinderclient remains listed in requirements.txt despite CinderHelper being migrated to openstacksdk. The dependency is only retained by the unused osc.cinder() path.\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: The package is still installed in production environments unnecessarily. Keeping it in requirements.txt signals that the migration is incomplete and may confuse contributors who see CinderHelper using openstacksdk imports.\n\n**Suggestion**:\nOnce osc.cinder() is removed, remove python-cinderclient from requirements.txt. If it must stay for now, add a comment noting it is pending removal once the osc.cinder() method is deleted.","commit_id":"6fb688af13d5ea14cc90a072278d916f938be4a5"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"d080ee00e3f683a4d74dd25c2fbd2d18b1b5794a","unresolved":false,"context_lines":[{"line_number":33,"context_line":"    \"\"\"Decorator to handle exceptions from the block_storage proxy."},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"    This decorator catches the proxy exceptions and handles them as follows:"},{"line_number":36,"context_line":"    - NotFound exceptions: logs a debug message and raises"},{"line_number":37,"context_line":"      ComputeResourceNotFound"},{"line_number":38,"context_line":"    - Other novaclient exceptions: re-raises as NovaClientError"},{"line_number":39,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"9e14a539_89b2a83a","line":36,"updated":"2026-06-25 07:27:46.000000000","message":"The handle_cinder_error decorator docstring mentions \u0027novaclient exceptions\u0027 instead of \u0027openstacksdk block_storage proxy exceptions\u0027.\n\n**Severity**: SUGGESTION | **Confidence**: 0.9\n\n**Benefit**: Accurate documentation helps future contributors understand the exception flow correctly and avoids confusion about which client library is in use.\n\n**Recommendation**:\nUpdate the decorator docstring (lines 34-41) to reference openstacksdk exceptions rather than novaclient. Change \u0027Other novaclient exceptions\u0027 to \u0027Other openstacksdk exceptions\u0027.","commit_id":"6fb688af13d5ea14cc90a072278d916f938be4a5"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"d080ee00e3f683a4d74dd25c2fbd2d18b1b5794a","unresolved":false,"context_lines":[{"line_number":60,"context_line":"                msg \u003d f\"{resource_id} of type {resource_type}\""},{"line_number":61,"context_line":"                raise exception.StorageResourceNotFound(name\u003dmsg)"},{"line_number":62,"context_line":"            except sdk_exc.SDKException as e:"},{"line_number":63,"context_line":"                LOG.error(\"Nova client error: %s\", e)"},{"line_number":64,"context_line":"                raise exception.CinderClientError(reason\u003dstr(e))"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"        return wrapper"}],"source_content_type":"text/x-python","patch_set":1,"id":"52b9da0c_c336f09f","line":63,"updated":"2026-06-25 07:27:46.000000000","message":"Error log message in handle_cinder_error decorator says \u0027Nova client error\u0027 instead of \u0027Cinder client error\u0027, causing misleading log output during cinder failures.\n\n**Severity**: HIGH | **Confidence**: 1.0\n\n**Risk**: When a Cinder SDK exception occurs, operators see \u0027Nova client error\u0027 in the logs, leading them to investigate the wrong service. This is a copy-paste error from the equivalent decorator in nova_helper.py.\n\n**Priority**: Before merge\n**Why This Matters**: In production debugging, misattributed error messages cause significant time waste. The decorator catches SDKException and logs it as a Nova error before raising CinderClientError, so the exception type is correct but the log line preceding it is wrong.\n\n**Recommendation**:\nChange line 63 from LOG.error(\"Nova client error: %s\", e) to LOG.error(\"Cinder client error: %s\", e) to match the context of the handle_cinder_error decorator.","commit_id":"6fb688af13d5ea14cc90a072278d916f938be4a5"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"d080ee00e3f683a4d74dd25c2fbd2d18b1b5794a","unresolved":false,"context_lines":[{"line_number":258,"context_line":"        self._override_deprecated_configs()"},{"line_number":259,"context_line":"        self._create_sdk_connection(\u0027cinder\u0027, context\u003dcontext, session\u003dsession)"},{"line_number":260,"context_line":""},{"line_number":261,"context_line":"    def _override_deprecated_configs(self) -\u003e None:"},{"line_number":262,"context_line":"        \"\"\"Apply deprecated cinder_client config overrides.\"\"\""},{"line_number":263,"context_line":"        if self._config_overrides:"},{"line_number":264,"context_line":"            return"}],"source_content_type":"text/x-python","patch_set":1,"id":"bab4b7fc_270e2a82","line":261,"updated":"2026-06-25 07:27:46.000000000","message":"The _override_deprecated_configs method uses CONF.set_override which modifies global state at runtime, but this pattern is inherited from NovaHelper.\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: Using oslo_config built-in deprecated_opts mechanism in register_adapter_conf_options (as partially done in conf/cinder.py) would be cleaner, but the current approach is functional and consistent.\n\n**Recommendation**:\nConsider using oslo_config deprecated_opts for the endpoint_type to valid_interfaces migration rather than a runtime set_override. This is a minor improvement for future consideration.","commit_id":"6fb688af13d5ea14cc90a072278d916f938be4a5"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"d080ee00e3f683a4d74dd25c2fbd2d18b1b5794a","unresolved":false,"context_lines":[{"line_number":494,"context_line":"        \"\"\""},{"line_number":495,"context_line":"        volume \u003d self.get_volume(volume)"},{"line_number":496,"context_line":"        final_status \u003d (\u0027success\u0027, \u0027error\u0027)"},{"line_number":497,"context_line":"        while volume.migration_status not in final_status:"},{"line_number":498,"context_line":"            volume \u003d self.get_volume(volume.id)"},{"line_number":499,"context_line":"            LOG.debug(\u0027Waiting the migration of %s\u0027, volume)"},{"line_number":500,"context_line":"            time.sleep(retry_interval)"}],"source_content_type":"text/x-python","patch_set":1,"id":"bb1476c3_12ac3510","line":497,"updated":"2026-06-25 07:27:46.000000000","message":"check_migrated polling loop has no maximum retry count and can loop indefinitely if the volume stays in a non-terminal migration status.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: If Cinder reports a migration status that is neither \u0027success\u0027 nor \u0027error\u0027 for an extended period (e.g., a stalled migration or a new intermediate status), the while loop will never exit, blocking the watcher applier thread indefinitely.\n\n**Suggestion**:\nAdd a retry/timeout parameter to check_migrated (similar to check_volume_deleted which has retry\u003d120) and break with LOG.error and return False when the limit is reached. This is pre-existing but the method was rewritten, making it a good time to fix.","commit_id":"6fb688af13d5ea14cc90a072278d916f938be4a5"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"4e86fbcfb31eec9eb7b4c536623c3d192fad2bf1","unresolved":false,"context_lines":[{"line_number":35,"context_line":"    This decorator catches the proxy exceptions and handles them as follows:"},{"line_number":36,"context_line":"    - NotFound exceptions: logs a debug message and raises"},{"line_number":37,"context_line":"      StorageResourceNotFound"},{"line_number":38,"context_line":"    - Other cinderclient exceptions: re-raises as CinderClientError"},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"    Use this for methods that call the Cinder API where a missing"},{"line_number":41,"context_line":"    resource is a valid outcome but other errors should be propagated."}],"source_content_type":"text/x-python","patch_set":3,"id":"978b3d44_9d44a0d8","line":38,"updated":"2026-06-25 11:59:16.000000000","message":"Decorator docstring references \u0027cinderclient exceptions\u0027 but the decorator now handles openstacksdk (sdk_exc) exceptions, not cinderclient. This is leftover from the migration and is misleading.\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: Developers reading the docstring will be confused about which exception types are actually handled. Minor documentation accuracy issue in newly added code.\n\n**Suggestion**:\nChange \u0027Other cinderclient exceptions: re-raises as CinderClientError\u0027 to \u0027Other openstacksdk exceptions: re-raises as CinderClientError\u0027 to match the actual implementation.","commit_id":"a84585078b28a1cc3c71194a9381742e195e5442"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"98ed743c97bcc6813ce227f7bcc707b2b245e5d3","unresolved":false,"context_lines":[{"line_number":368,"context_line":"        ]"},{"line_number":369,"context_line":"        return volume_type"},{"line_number":370,"context_line":""},{"line_number":371,"context_line":"    @handle_cinder_error(\"Volume\")"},{"line_number":372,"context_line":"    def get_volume(self, volume: str | Volume) -\u003e Volume:"},{"line_number":373,"context_line":"        \"\"\"Get a volume by ID or Volume object."},{"line_number":374,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"31037485_44cf92bf","line":371,"updated":"2026-06-25 16:09:12.000000000","message":"get_volume() is decorated with @handle_cinder_error which catches sdk_exc.NotFoundException, but the method body also has its own try/except sdk_exc.NotFoundException that falls back from get_volume to find_volume. This two-tier fallback is correct but non-obvious to future maintainers.\n\n**Severity**: SUGGESTION | **Confidence**: 0.8\n\n**Benefit**: A clarifying comment would prevent future maintainers from incorrectly assuming the inner try/except is dead code given the decorator, improving long-term maintainability of the exception flow.\n\n**Recommendation**:\nAdd a one-line comment above the inner try block, e.g. \u0027# find_volume is a fallback; if it also 404s, the decorator converts it to StorageResourceNotFound\u0027. No functional change needed.","commit_id":"eb6787f9b5da991849de1821c3ad4a5a10d10a40"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"98ed743c97bcc6813ce227f7bcc707b2b245e5d3","unresolved":false,"context_lines":[{"line_number":485,"context_line":"        LOG.debug(\"Volume %s was deleted successfully.\", volume.id)"},{"line_number":486,"context_line":"        return True"},{"line_number":487,"context_line":""},{"line_number":488,"context_line":"    def check_migrated("},{"line_number":489,"context_line":"        self, volume: str | Volume, retry_interval: int \u003d 10"},{"line_number":490,"context_line":"    ) -\u003e bool:"},{"line_number":491,"context_line":"        \"\"\"Wait for volume migration to complete."}],"source_content_type":"text/x-python","patch_set":5,"id":"27b206f0_f9c94a2e","line":488,"updated":"2026-06-25 16:09:12.000000000","message":"check_migrated() polls volume.migration_status in a while loop with time.sleep but no maximum retry counter. If a volume gets stuck in a non-terminal migration status (e.g. a driver stuck in \u0027migrating\u0027), this loop runs forever, blocking the applier action indefinitely.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: A stuck Cinder migration will hang the Watcher applier with no timeout, requiring manual intervention. The sibling method check_volume_deleted() correctly bounds its loop with a retry parameter (default 120).\n\n**Suggestion**:\nAdd a retry parameter and maximum iteration count mirroring the check_volume_deleted() pattern at line 464. This is a pre-existing issue surfaced by the refactor, so a follow-up patch is acceptable.","commit_id":"eb6787f9b5da991849de1821c3ad4a5a10d10a40"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"98ed743c97bcc6813ce227f7bcc707b2b245e5d3","unresolved":false,"context_lines":[{"line_number":527,"context_line":"        )"},{"line_number":528,"context_line":"        return True"},{"line_number":529,"context_line":""},{"line_number":530,"context_line":"    def check_retyped("},{"line_number":531,"context_line":"        self, volume: str | Volume, dst_type: str, retry_interval: int \u003d 10"},{"line_number":532,"context_line":"    ) -\u003e bool:"},{"line_number":533,"context_line":"        \"\"\"Wait for volume retype to complete."}],"source_content_type":"text/x-python","patch_set":5,"id":"1f04d61f_bba03d49","line":530,"updated":"2026-06-25 16:09:12.000000000","message":"check_retyped() has the same unbounded while loop issue as check_migrated(). It polls volume.volume_type and volume.status with no retry counter. If a retype operation enters an unexpected non-terminal non-error status, the loop spins forever.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: A stuck Cinder retype will hang the Watcher applier indefinitely, same risk as check_migrated(). The method already checks for error status but has no timeout escape hatch.\n\n**Suggestion**:\nAdd a bounded retry counter parameter, consistent with check_volume_deleted(). Pre-existing issue, follow-up patch acceptable.","commit_id":"eb6787f9b5da991849de1821c3ad4a5a10d10a40"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"715507cc7d01af17f2d8976d40369a02976e8548","unresolved":false,"context_lines":[{"line_number":29,"context_line":"CONF \u003d conf.CONF"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"def handle_cinder_error(resource_type, id_arg_index\u003d1):"},{"line_number":33,"context_line":"    \"\"\"Decorator to handle exceptions from the block_storage proxy."},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"    This decorator catches the proxy exceptions and handles them as follows:"}],"source_content_type":"text/x-python","patch_set":6,"id":"f9bfeb4c_0a809427","line":32,"updated":"2026-06-26 07:48:21.000000000","message":"The handle_cinder_error decorator uses positional argument indexing (id_arg_index\u003d1) to extract resource IDs for logging. This is fragile if a decorated method\u0027s signature changes or if the resource ID is passed as a keyword argument.\n\n**Severity**: WARNING | **Confidence**: 0.7\n\n**Impact**: If get_storage_node_by_name(name) is ever refactored to accept additional positional parameters before name, the decorator will log the wrong value. The fallback to \u0027unknown\u0027 hides the issue silently.\n\n**Suggestion**:\nConsider using inspect.signature to resolve the parameter name, or simply log without the resource ID since the exception message already includes context. The NovaHelper has the same pattern.","commit_id":"c2c84f4bc74a73501d96faf324c4e41c2deeba68"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"715507cc7d01af17f2d8976d40369a02976e8548","unresolved":false,"context_lines":[{"line_number":145,"context_line":"            name\u003dpool.name,"},{"line_number":146,"context_line":"            pool_name\u003dcapabilities.get(\u0027pool_name\u0027),"},{"line_number":147,"context_line":"            total_volumes\u003dint(capabilities.get(\u0027total_volumes\u0027, 0) or 0),"},{"line_number":148,"context_line":"            max_over_subscription_ratio\u003dfloat("},{"line_number":149,"context_line":"                capabilities.get(\u0027max_over_subscription_ratio\u0027, 1.0)"},{"line_number":150,"context_line":"            ),"},{"line_number":151,"context_line":"            volume_backend_name\u003dcapabilities.get(\u0027volume_backend_name\u0027),"}],"source_content_type":"text/x-python","patch_set":6,"id":"e0bb7682_3ba3e432","line":148,"updated":"2026-06-26 07:48:21.000000000","message":"StoragePool.from_openstacksdk calls float(capabilities.get(\u0027max_over_subscription_ratio\u0027, 1.0)) which will raise ValueError if the value is a non-numeric string like \u0027unknown\u0027. This is inconsistent with the handling of other capacity fields.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: If a Cinder backend reports max_over_subscription_ratio as a non-numeric string, the dataclass construction will crash with ValueError, which the decorator converts to CinderClientError.\n\n**Suggestion**:\nApply the same \u0027unknown\u0027/None normalization to max_over_subscription_ratio as is done for the other capacity fields, or wrap the float() call in a try/except that defaults to 1.0.","commit_id":"c2c84f4bc74a73501d96faf324c4e41c2deeba68"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"715507cc7d01af17f2d8976d40369a02976e8548","unresolved":false,"context_lines":[{"line_number":201,"context_line":"            migration_status\u003dvolume.migration_status,"},{"line_number":202,"context_line":"            host\u003dvolume.host,"},{"line_number":203,"context_line":"            tenant_id\u003dvolume.project_id,"},{"line_number":204,"context_line":"            name_id\u003dvolume.migration_id,"},{"line_number":205,"context_line":"        )"},{"line_number":206,"context_line":""},{"line_number":207,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"79c2b4a9_2d6f4a26","line":204,"updated":"2026-06-26 07:48:21.000000000","message":"Volume.from_openstacksdk maps volume.migration_id to name_id. The openstacksdk attribute name for os-vol-mig-status-attr:name_id may differ from migration_id depending on the SDK version.\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: Ensuring the correct SDK attribute is used prevents silent None values for name_id, which would break get_deleting_volume\u0027s shadow volume lookup during migration.\n\n**Recommendation**:\nVerify that openstacksdk\u0027s Volume object exposes migration_id as the mapped attribute for os-vol-mig-status-attr:name_id. Add a unit test that creates a volume with this attribute set and asserts name_id is correctly populated.","commit_id":"c2c84f4bc74a73501d96faf324c4e41c2deeba68"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"715507cc7d01af17f2d8976d40369a02976e8548","unresolved":false,"context_lines":[{"line_number":247,"context_line":""},{"line_number":248,"context_line":""},{"line_number":249,"context_line":"class CinderHelper(base_helper.BaseConnectionMixin):"},{"line_number":250,"context_line":"    def __init__(self, session\u003dNone, context\u003dNone):"},{"line_number":251,"context_line":"        \"\"\"Create a helper to call the cinder service."},{"line_number":252,"context_line":""},{"line_number":253,"context_line":"        :param session: Optional keystone session to create"}],"source_content_type":"text/x-python","patch_set":6,"id":"adb95798_b431d20e","line":250,"updated":"2026-06-26 07:48:21.000000000","message":"CinderHelper.__init__ and NovaHelper.__init__ removed the osc parameter without backward compatibility. All call sites were updated, but any out-of-tree consumers or plugins that pass osc\u003d will break with TypeError.\n\n**Severity**: WARNING | **Confidence**: 0.7\n\n**Impact**: Third-party strategy plugins or custom actions that instantiate CinderHelper(osc\u003dself.osc) or NovaHelper(osc\u003dself.osc) will fail at runtime with an unexpected keyword argument error.\n\n**Suggestion**:\nConsider accepting osc\u003dNone parameter that is silently ignored for one release cycle with a deprecation warning, before fully removing it. This follows the OpenStack deprecation pattern used elsewhere in the patch for config options.","commit_id":"c2c84f4bc74a73501d96faf324c4e41c2deeba68"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"715507cc7d01af17f2d8976d40369a02976e8548","unresolved":false,"context_lines":[{"line_number":259,"context_line":"        self._override_deprecated_configs()"},{"line_number":260,"context_line":"        self._create_sdk_connection(\u0027cinder\u0027, context\u003dcontext, session\u003dsession)"},{"line_number":261,"context_line":""},{"line_number":262,"context_line":"    def _override_deprecated_configs(self) -\u003e None:"},{"line_number":263,"context_line":"        \"\"\"Apply deprecated cinder_client config overrides.\"\"\""},{"line_number":264,"context_line":"        if self._config_overrides:"},{"line_number":265,"context_line":"            return"}],"source_content_type":"text/x-python","patch_set":6,"id":"8879b7c4_bb076fe6","line":262,"updated":"2026-06-26 07:48:21.000000000","message":"_override_deprecated_configs mutates the global CONF singleton via CONF.set_override(\u0027valid_interfaces\u0027, ...). This is an instance method but its side effect persists globally across all CinderHelper instances and tests, violating isolation.\n\n**Severity**: HIGH | **Confidence**: 0.8\n\n**Risk**: Once any CinderHelper instance applies the override, every subsequent instance (including in other tests in the same test run) will see the overridden value. The _config_overrides flag only prevents re-entry within the same instance.\n\n**Priority**: Before merge\n**Why This Matters**: In production, multiple CinderHelper instances are created across the decision engine and applier. The first instance permanently mutates CONF.cinder.valid_interfaces for all others. In tests, this causes inter-test contamination unless explicitly reset.\n\n**Recommendation**:\nEither apply the deprecated config override once at module registration time (in conf/cinder.py register_opts), or use a class-level flag shared across all instances. Alternatively, pass the resolved endpoint type directly to _create_sdk_connection instead of mutating global CONF.","commit_id":"c2c84f4bc74a73501d96faf324c4e41c2deeba68"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"715507cc7d01af17f2d8976d40369a02976e8548","unresolved":false,"context_lines":[{"line_number":380,"context_line":"        else:"},{"line_number":381,"context_line":"            volume_id \u003d volume.id"},{"line_number":382,"context_line":""},{"line_number":383,"context_line":"        try:"},{"line_number":384,"context_line":"            v \u003d self.connection.block_storage.get_volume(volume_id)"},{"line_number":385,"context_line":"            return Volume.from_openstacksdk(v)"},{"line_number":386,"context_line":"        except sdk_exc.NotFoundException:"}],"source_content_type":"text/x-python","patch_set":6,"id":"e86bb822_0c0c7576","line":383,"updated":"2026-06-26 07:48:21.000000000","message":"get_volume fallback after NotFoundException calls find_volume(volume_id, ignore_missing\u003dFalse). In openstacksdk, find_volume searches by display name, not by ID. Passing the UUID as a name lookup will almost never succeed if get_volume by ID already failed.\n\n**Severity**: HIGH | **Confidence**: 0.8\n\n**Risk**: If a volume ID lookup fails (e.g. due to stale ID after migration), the name-based fallback will also fail, causing the NotFoundException to propagate via the decorator as StorageResourceNotFound.\n\n**Priority**: Before merge\n**Why This Matters**: The get_volume method is called extensively in migration and retype flows. A broken fallback means transient volume lookups during migration may fail when they previously had a chance of succeeding via name lookup.\n\n**Recommendation**:\nVerify that openstacksdk find_volume correctly searches by name when given a UUID. If the intent is to find by display_name, pass it explicitly. Consider whether the fallback is still needed post-migration, or document the expected behaviour. At minimum, add a unit test for the fallback path.","commit_id":"c2c84f4bc74a73501d96faf324c4e41c2deeba68"}],"watcher/common/nova_helper.py":[{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"d080ee00e3f683a4d74dd25c2fbd2d18b1b5794a","unresolved":false,"context_lines":[{"line_number":64,"context_line":"def handle_nova_error(resource_type, id_arg_index\u003d1):"},{"line_number":65,"context_line":"    \"\"\"Decorator to handle exceptions from novaclient."},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"    This decorator catches novaclient exceptions and handles them as follows:"},{"line_number":68,"context_line":"    - NotFound exceptions: logs a debug message and raises"},{"line_number":69,"context_line":"      ComputeResourceNotFound"},{"line_number":70,"context_line":"    - Other novaclient exceptions: re-raises as NovaClientError"}],"source_content_type":"text/x-python","patch_set":1,"id":"65dfa68f_d88b3cf6","line":67,"updated":"2026-06-25 07:27:46.000000000","message":"handle_nova_error decorator docstring in nova_helper.py still references \u0027novaclient exceptions\u0027 instead of \u0027openstacksdk exceptions\u0027.\n\n**Severity**: SUGGESTION | **Confidence**: 0.9\n\n**Benefit**: The decorator now catches openstacksdk SDKException, not novaclient exceptions. Accurate documentation aligns comments with the actual implementation.\n\n**Recommendation**:\nUpdate the docstring at lines 65-73 to say \u0027openstacksdk exceptions\u0027 instead of \u0027novaclient exceptions\u0027 to reflect the migration that already occurred.","commit_id":"6fb688af13d5ea14cc90a072278d916f938be4a5"}],"watcher/conf/cinder_client.py":[{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"d080ee00e3f683a4d74dd25c2fbd2d18b1b5794a","unresolved":false,"context_lines":[{"line_number":34,"context_line":"            \u0027openstacksdk block-storage proxy, the options need to \u0027"},{"line_number":35,"context_line":"            \u0027be under the [cinder] group.\u0027"},{"line_number":36,"context_line":"        ),"},{"line_number":37,"context_line":"        deprecated_since\u003d\u00272026.2\u0027,"},{"line_number":38,"context_line":"        help\u003d\u0027Version of Cinder API to use in cinderclient.\u0027,"},{"line_number":39,"context_line":"    ),"},{"line_number":40,"context_line":"    cfg.StrOpt("}],"source_content_type":"text/x-python","patch_set":1,"id":"69170cea_448ced46","line":37,"updated":"2026-06-25 07:27:46.000000000","message":"deprecated_since value \u00272026.2\u0027 is an unusual release identifier that may not match the OpenStack release naming convention (e.g., \u00272024.1\u0027, \u0027Zed\u0027).\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: If \u00272026.2\u0027 does not correspond to a recognized OpenStack release series, oslo.config deprecation tooling and documentation generation may produce confusing output. OpenStack typically uses calendar-versioned release names like \u00272026.1\u0027 (Slime).\n\n**Suggestion**:\nVerify that \u00272026.2\u0027 is the correct release identifier for the target OpenStack cycle. If the next release is \u00272026.1\u0027 or uses a different scheme, update all three deprecated_since values in cinder_client.py to match the actual release name.","commit_id":"6fb688af13d5ea14cc90a072278d916f938be4a5"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"715507cc7d01af17f2d8976d40369a02976e8548","unresolved":false,"context_lines":[{"line_number":35,"context_line":"            \u0027be under the [cinder] group.\u0027"},{"line_number":36,"context_line":"        ),"},{"line_number":37,"context_line":"        deprecated_since\u003d\u00272026.2\u0027,"},{"line_number":38,"context_line":"        help\u003d\u0027Version of Cinder API to use in cinderclient.\u0027,"},{"line_number":39,"context_line":"    ),"},{"line_number":40,"context_line":"    cfg.StrOpt("},{"line_number":41,"context_line":"        \u0027endpoint_type\u0027,"}],"source_content_type":"text/x-python","patch_set":6,"id":"d5bf41ee_adf80b6c","line":38,"updated":"2026-06-26 07:48:21.000000000","message":"The release note and config deprecation use deprecated_since\u003d\u00272026.2\u0027 which is a non-standard version format for OpenStack projects.\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: Using the correct release/cycle identifier for deprecated_since helps operators track deprecation timelines consistently across the OpenStack ecosystem.\n\n**Recommendation**:\nVerify whether \u00272026.2\u0027 is the correct format for watcher\u0027s versioning scheme. Most OpenStack projects use release cycle names or calendar version numbers. If this is intentional, document it.","commit_id":"c2c84f4bc74a73501d96faf324c4e41c2deeba68"}],"watcher/decision_engine/model/collector/cinder.py":[{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"d080ee00e3f683a4d74dd25c2fbd2d18b1b5794a","unresolved":false,"context_lines":[{"line_number":158,"context_line":"    def __init__(self, osc):"},{"line_number":159,"context_line":"        self.osc \u003d osc"},{"line_number":160,"context_line":"        self.model \u003d model_root.StorageModelRoot()"},{"line_number":161,"context_line":"        self.cinder \u003d osc.cinder()"},{"line_number":162,"context_line":"        self.cinder_helper \u003d cinder_helper.CinderHelper()"},{"line_number":163,"context_line":""},{"line_number":164,"context_line":"    def _add_physical_layer(self):"}],"source_content_type":"text/x-python","patch_set":1,"id":"003f4c4f_612ab188","line":161,"updated":"2026-06-25 07:27:46.000000000","message":"CinderModelBuilder.__init__ calls osc.cinder() and assigns to self.cinder, but self.cinder is never referenced in the class. This is dead code that unnecessarily instantiates python-cinderclient.\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: Every time the Cinder data model collector runs, it creates an unnecessary cinderclient connection that is never used. This adds latency, consumes a Keystone endpoint lookup, and keeps the python-cinderclient dependency alive.\n\n**Suggestion**:\nRemove the line \u0027self.cinder \u003d osc.cinder()\u0027 from CinderModelBuilder.__init__ since all Cinder operations go through self.cinder_helper which uses openstacksdk directly.","commit_id":"6fb688af13d5ea14cc90a072278d916f938be4a5"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"d080ee00e3f683a4d74dd25c2fbd2d18b1b5794a","unresolved":false,"context_lines":[{"line_number":158,"context_line":"    def __init__(self, osc):"},{"line_number":159,"context_line":"        self.osc \u003d osc"},{"line_number":160,"context_line":"        self.model \u003d model_root.StorageModelRoot()"},{"line_number":161,"context_line":"        self.cinder \u003d osc.cinder()"},{"line_number":162,"context_line":"        self.cinder_helper \u003d cinder_helper.CinderHelper()"},{"line_number":163,"context_line":""},{"line_number":164,"context_line":"    def _add_physical_layer(self):"}],"source_content_type":"text/x-python","patch_set":1,"id":"db82c431_88045739","line":161,"updated":"2026-06-25 07:27:46.000000000","message":"CinderModelBuilder.__init__ still calls osc.cinder() which instantiates python-cinderclient, making the migration incomplete and the dependency impossible to remove.\n\n**Severity**: HIGH | **Confidence**: 0.9\n\n**Risk**: osc.cinder() (in clients.py:190) still creates a ciclient.Client, and this line calls it. python-cinderclient remains a hard runtime dependency; removing it from requirements.txt would break at runtime.\n\n**Priority**: Before merge\n**Why This Matters**: The commit says it replaces python-cinderclient but osc.cinder() still instantiates it. Operators may remove the package believing it is no longer needed. The osc.cinder() result in CinderModelBuilder is assigned to self.cinder but never used, so this is dead code retaining the old dependency.\n\n**Recommendation**:\nEither (a) remove the osc.cinder() call from CinderModelBuilder.__init__ (line 161) since self.cinder is unused there, and remove or deprecate the cinder() method in OpenStackClients, or (b) if the cinder() method must remain for backward compatibility, add a comment explaining the transition plan and ensure the release notes clarify that python-cinderclient is still required.","commit_id":"6fb688af13d5ea14cc90a072278d916f938be4a5"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"98ed743c97bcc6813ce227f7bcc707b2b245e5d3","unresolved":false,"context_lines":[{"line_number":236,"context_line":"            \"allocated_capacity_gb\","},{"line_number":237,"context_line":"        ]"},{"line_number":238,"context_line":""},{"line_number":239,"context_line":"        node_attributes \u003d {\"name\": pool.name}"},{"line_number":240,"context_line":"        for attr in attrs:"},{"line_number":241,"context_line":"            try:"},{"line_number":242,"context_line":"                node_attributes[attr] \u003d int(getattr(pool, attr))"}],"source_content_type":"text/x-python","patch_set":5,"id":"77caa78c_8042b8b3","line":239,"updated":"2026-06-25 16:09:12.000000000","message":"StoragePool capacity fields can now be None (unknown capacity), but _build_storage_pool does int(getattr(pool, attr)) which raises TypeError on None. This is caught and converted to InvalidPoolAttributeValue, so such pools are rejected during model build.\n\n**Severity**: SUGGESTION | **Confidence**: 0.8\n\n**Benefit**: Confirming this behavioral change is intentional prevents unexpected model-build failures in production for backends that report unknown capacity, which may be valid in some storage configurations.\n\n**Recommendation**:\nVerify that raising InvalidPoolAttributeValue for \u0027unknown\u0027 capacity pools is desired. If such pools should be skipped, handle None by skipping the attribute (the code already does this for AttributeError at line 243).","commit_id":"eb6787f9b5da991849de1821c3ad4a5a10d10a40"},{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"715507cc7d01af17f2d8976d40369a02976e8548","unresolved":false,"context_lines":[{"line_number":155,"context_line":""},{"line_number":156,"context_line":"    \"\"\""},{"line_number":157,"context_line":""},{"line_number":158,"context_line":"    def __init__(self, osc):"},{"line_number":159,"context_line":"        self.osc \u003d osc"},{"line_number":160,"context_line":"        self.model \u003d model_root.StorageModelRoot()"},{"line_number":161,"context_line":"        self.cinder \u003d osc.cinder()"}],"source_content_type":"text/x-python","patch_set":6,"id":"d55e08b6_11af3ce0","line":158,"updated":"2026-06-26 07:48:21.000000000","message":"CinderModelBuilder.__init__ still stores self.cinder \u003d osc.cinder() but never uses self.cinder anywhere in the class. This creates an unnecessary client object.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: The self.cinder attribute is dead code that creates a potentially expensive client connection on every model build. It also means the collector still depends on osc.cinder() existing.\n\n**Suggestion**:\nRemove the self.cinder \u003d osc.cinder() line from CinderModelBuilder.__init__. The self.cinder_helper already handles all cinder interactions independently.","commit_id":"c2c84f4bc74a73501d96faf324c4e41c2deeba68"}],"watcher/tests/unit/common/test_cinder_helper.py":[{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"85955c68d1b4dfe776b2febb3fd000282edd40d8","unresolved":false,"context_lines":[{"line_number":86,"context_line":"    def test_get_storage_pool_by_name_failure(self):"},{"line_number":87,"context_line":"        pool1 \u003d self.create_openstacksdk_pool()"},{"line_number":88,"context_line":"        cinder_util \u003d cinder_helper.CinderHelper()"},{"line_number":89,"context_line":"        self.mock_connection.block_storage.services.return_value \u003d [pool1]"},{"line_number":90,"context_line":"        self.assertRaisesRegex("},{"line_number":91,"context_line":"            exception.PoolNotFound,"},{"line_number":92,"context_line":"            \"The pool failure could not be found\","}],"source_content_type":"text/x-python","patch_set":4,"id":"bf01d105_741939f4","line":89,"updated":"2026-06-25 14:13:47.000000000","message":"test_get_storage_pool_by_name_failure mocks block_storage.services instead of block_storage.backend_pools. The test passes accidentally because the unmocked backend_pools() returns an empty iterable MagicMock, so the pool list is empty and PoolNotFound is raised for the wrong reason.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: The test does not actually verify that get_storage_pool_by_name correctly filters pools by name. If the filtering logic breaks, this test would still pass because no pools are returned at all.\n\n**Suggestion**:\nChange line 89 to mock backend_pools instead of services: self.mock_connection.block_storage.backend_pools.return_value \u003d [pool1]. This ensures the test exercises the name-filtering logic.","commit_id":"e787633506c7217b1e55b9e9c15040433d293a96"}],"watcher/tests/unit/common/utils.py":[{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"715507cc7d01af17f2d8976d40369a02976e8548","unresolved":false,"context_lines":[{"line_number":242,"context_line":"        pool_info \u003d {\u0027name\u0027: name, \u0027capabilities\u0027: capabilities}"},{"line_number":243,"context_line":"        return stats.Pools(**pool_info)"},{"line_number":244,"context_line":""},{"line_number":245,"context_line":"    def create_openstacksdk_storage_service(self, **kwargs):"},{"line_number":246,"context_line":"        \"\"\"Create a real OpenStackSDK block_storage Service."},{"line_number":247,"context_line":""},{"line_number":248,"context_line":"        :param kwargs: service attributes"}],"source_content_type":"text/x-python","patch_set":6,"id":"6dfd688e_a6361718","line":245,"updated":"2026-06-26 07:48:21.000000000","message":"StorageService.from_openstacksdk maps service.availability_zone to zone, but the test factory create_openstacksdk_storage_service uses \u0027zone\u0027 as the kwarg name. The SDK Service object\u0027s attribute is availability_zone.\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: The test factory creates SDK objects with potentially incorrect attribute names (zone instead of availability_zone). This means the test SDK objects may not reflect real SDK behaviour.\n\n**Recommendation**:\nIn create_openstacksdk_storage_service, verify the block_service.Service constructor accepts \u0027zone\u0027 as a key. If not, change it to \u0027availability_zone\u0027 to match the real SDK attribute.","commit_id":"c2c84f4bc74a73501d96faf324c4e41c2deeba68"}],"watcher/tests/unit/decision_engine/cluster/test_cinder_cdmc.py":[{"author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"715507cc7d01af17f2d8976d40369a02976e8548","unresolved":false,"context_lines":[{"line_number":140,"context_line":"    def test_cinder_cdmc_total_capacity_gb_None(self, m_cinder_helper_cls):"},{"line_number":141,"context_line":"        m_cinder_helper \u003d m_cinder_helper_cls.return_value"},{"line_number":142,"context_line":""},{"line_number":143,"context_line":"        fake_storage_node \u003d cinder_helper.StorageService.from_cinderclient("},{"line_number":144,"context_line":"            self.create_cinder_storage_service(zone\u003d\u0027zone\u0027)"},{"line_number":145,"context_line":"        )"},{"line_number":146,"context_line":"        fake_storage_pool \u003d cinder_helper.StoragePool.from_cinderclient("}],"source_content_type":"text/x-python","patch_set":6,"id":"7f207ade_9c855baa","line":143,"updated":"2026-06-26 07:48:21.000000000","message":"test_cinder_cdmc_total_capacity_gb_None references non-existent methods: StorageService.from_cinderclient, StoragePool.from_cinderclient, self.create_cinder_storage_service, and self.create_cinder_pool. These do not exist anywhere in the codebase.\n\n**Severity**: CRITICAL | **Confidence**: 1.0\n\n**Risk**: The test will raise AttributeError at runtime, failing the CI gate. The test_cinder_cdmc_total_capacity_gb_None test is entirely broken and cannot pass.\n\n**Priority**: Before merge\n**Why This Matters**: This test is designed to verify that None capacity values are handled gracefully, but it cannot even execute. This defeats the purpose of having the test and will break the unit test suite.\n\n**Recommendation**:\nReplace from_cinderclient calls with from_openstacksdk, and replace create_cinder_storage_service/create_cinder_pool with create_openstacksdk_storage_service/create_openstacksdk_pool. The test should mirror the pattern used in test_cinder_cdmc_total_capacity_gb_not_integer above it, which correctly uses the openstacksdk factory methods with total_capacity_gb\u003dNone.","commit_id":"c2c84f4bc74a73501d96faf324c4e41c2deeba68"}]}
