)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"7ec487ae8eed4d4212932518a1a6dbdc285f77a5","unresolved":true,"context_lines":[{"line_number":60,"context_line":""},{"line_number":61,"context_line":"APIImpact"},{"line_number":62,"context_line":"Partial-Implements: blueprint replication-v3"},{"line_number":63,"context_line":"Generated-By: Claude Code / claude-opus-4-6, claude-sonnet-4-5 (claude.ai/code)"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"Change-Id: Ib998143680b41464a7618f4bf2b68d5b8a4e91d2"},{"line_number":66,"context_line":"Signed-off-by: rajathere \u003crajatdhasmana@gmail.com\u003e"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":7,"id":"58326d96_deebb557","line":63,"updated":"2026-10-14 18:31:25.000000000","message":"`Generated-By:` and `Co-Authored-By: Claude ...` are not the agreed form for AI-assisted cinder changes; please use `Assisted-By:` only. The \"AI-modified files\" list can go. Also worth adding that this depends on spec 985952 being approved first.","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":60,"context_line":""},{"line_number":61,"context_line":"APIImpact"},{"line_number":62,"context_line":"Partial-Implements: blueprint replication-v3"},{"line_number":63,"context_line":"Generated-By: Claude Code / claude-opus-4-6, claude-sonnet-4-5 (claude.ai/code)"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"Change-Id: Ib998143680b41464a7618f4bf2b68d5b8a4e91d2"},{"line_number":66,"context_line":"Signed-off-by: rajathere \u003crajatdhasmana@gmail.com\u003e"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":7,"id":"75617b10_6476a419","line":63,"in_reply_to":"58326d96_deebb557","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"}],"/PATCHSET_LEVEL":[{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"7ec487ae8eed4d4212932518a1a6dbdc285f77a5","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":7,"id":"f9382ada_a360eacc","updated":"2026-10-14 18:31:25.000000000","message":"The approach (volume actions over the manage_existing flow with a dedicated task, driver hooks in BaseVD) is sound and the RBD implementation is a good reference. But as it stands: `clear_existing` destroys the DB row without releasing quota or checking snapshots/attachments, import bypasses the scheduler, a `secret\u003dTrue` config option is registered and never read, and the microversion is missing its history entry, api-ref and samples (which is also why the functional versions tests fail). Two existing unit tests were broken by the `get_flow` signature change and not updated.\n\n-1 for the quota/scheduler items and the missing microversion artefacts. This also needs to wait for spec 985952 to be approved; I have comments there on the pieces this code mirrors (`target_os`, teardown, the encryption option).","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":9,"id":"6ea55938_72437d41","updated":"2026-10-26 19:06:48.000000000","message":"The new comments below come from a deeper pass over the import and export paths. The one I would fix first is at `manager.py:5559`: nothing stops the same exported document being imported twice, and because RBD does not rename and sets `_name_id` from the image name, two available volumes end up on one image and deleting either destroys the other\u0027s data. The `clear_existing` path also needs restructuring (5546): it destroys the row inside a synchronous RPC before the caller has the document, and the destroy cascades to snapshots, attachments and transfers with no status gate. Several import-side checks that `manage_existing` and `create` already perform are missing: unknown exported type, encrypted type, volumes quota, group status, multiattach. And the asynchronous 201 conflicts with the 400 the spec promises; that needs settling against 985952 before either merges.","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":12,"id":"5e42df68_c97865d9","updated":"2026-10-29 21:15:04.000000000","message":"Thanks Simon for the detailed review and finding some critical bugs!","commit_id":"563b81f44f25b6d9b6acbe0b99bee43c6c04f17d"}],"cinder/api/contrib/volume_actions.py":[{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"5899fa5a8a132e65d59110e771002e21068450f7","unresolved":false,"context_lines":[{"line_number":391,"context_line":"            raise webob.exc.HTTPBadRequest(explanation\u003derror.msg)"},{"line_number":392,"context_line":""},{"line_number":393,"context_line":""},{"line_number":394,"context_line":"    @wsgi.Controller.api_version(mv.EXPORT_IMPORT_REPLICA)"},{"line_number":395,"context_line":"    @wsgi.action(\u0027export-replica\u0027)"},{"line_number":396,"context_line":"    @validation.schema(schema.export_replica, mv.EXPORT_IMPORT_REPLICA)"},{"line_number":397,"context_line":"    def _export_replica(self, req, id, body):"}],"source_content_type":"text/x-python","patch_set":1,"id":"77454051_15e97094","line":394,"updated":"2026-08-13 23:54:55.000000000","message":"pep8: E303 too many blank lines (2)","commit_id":"e09062093764509c9e76b53265801c588e274540"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"35370d49fc9a242dd43c6eab0fee9596c7e82776","unresolved":false,"context_lines":[{"line_number":391,"context_line":"            raise webob.exc.HTTPBadRequest(explanation\u003derror.msg)"},{"line_number":392,"context_line":""},{"line_number":393,"context_line":""},{"line_number":394,"context_line":"    @wsgi.Controller.api_version(mv.EXPORT_IMPORT_REPLICA)"},{"line_number":395,"context_line":"    @wsgi.action(\u0027export-replica\u0027)"},{"line_number":396,"context_line":"    @validation.schema(schema.export_replica, mv.EXPORT_IMPORT_REPLICA)"},{"line_number":397,"context_line":"    def _export_replica(self, req, id, body):"}],"source_content_type":"text/x-python","patch_set":2,"id":"157843c7_7dd003e4","line":394,"updated":"2026-08-18 20:03:21.000000000","message":"pep8: E303 too many blank lines (2)","commit_id":"5df57325110ed383d4141d222f4b564469b2bd6d"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"bde5a6571dcadc404fcfe444f8f022425a691c98","unresolved":false,"context_lines":[{"line_number":391,"context_line":"            raise webob.exc.HTTPBadRequest(explanation\u003derror.msg)"},{"line_number":392,"context_line":""},{"line_number":393,"context_line":""},{"line_number":394,"context_line":"    @wsgi.Controller.api_version(mv.EXPORT_IMPORT_REPLICA)"},{"line_number":395,"context_line":"    @wsgi.action(\u0027export-replica\u0027)"},{"line_number":396,"context_line":"    @validation.schema(schema.export_replica, mv.EXPORT_IMPORT_REPLICA)"},{"line_number":397,"context_line":"    def _export_replica(self, req, id, body):"}],"source_content_type":"text/x-python","patch_set":3,"id":"4ef3213c_a65af19a","line":394,"updated":"2026-08-20 00:23:16.000000000","message":"pep8: E303 too many blank lines (2)","commit_id":"c12da181319252a913c230664bdc2fc5177d8cec"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"5f448ed0181b3e695362ddc18115676f8159eb58","unresolved":false,"context_lines":[{"line_number":391,"context_line":"            raise webob.exc.HTTPBadRequest(explanation\u003derror.msg)"},{"line_number":392,"context_line":""},{"line_number":393,"context_line":""},{"line_number":394,"context_line":"    @wsgi.Controller.api_version(mv.EXPORT_IMPORT_REPLICA)"},{"line_number":395,"context_line":"    @wsgi.action(\u0027export-replica\u0027)"},{"line_number":396,"context_line":"    @validation.schema(schema.export_replica, mv.EXPORT_IMPORT_REPLICA)"},{"line_number":397,"context_line":"    def _export_replica(self, req, id, body):"}],"source_content_type":"text/x-python","patch_set":4,"id":"0d3c9631_a3378730","line":394,"updated":"2026-08-21 16:01:25.000000000","message":"pep8: E303 too many blank lines (2)","commit_id":"70810156d10fcddf30b1f7c6a2d5809aee5e7068"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"d0d9ad1652290ec9575b3ef013501a9144dbc6ae","unresolved":false,"context_lines":[{"line_number":391,"context_line":"            raise webob.exc.HTTPBadRequest(explanation\u003derror.msg)"},{"line_number":392,"context_line":""},{"line_number":393,"context_line":""},{"line_number":394,"context_line":"    @wsgi.Controller.api_version(mv.EXPORT_IMPORT_REPLICA)"},{"line_number":395,"context_line":"    @wsgi.action(\u0027export-replica\u0027)"},{"line_number":396,"context_line":"    @validation.schema(schema.export_replica, mv.EXPORT_IMPORT_REPLICA)"},{"line_number":397,"context_line":"    def _export_replica(self, req, id, body):"}],"source_content_type":"text/x-python","patch_set":5,"id":"5618ff56_136fabe6","line":394,"updated":"2026-08-25 06:32:26.000000000","message":"pep8: E303 too many blank lines (2)","commit_id":"38845cf60edbcfb79f3871ea171c32324b24f3d9"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"003f1925daa5164410b5fc771ac1ef6775bd914f","unresolved":false,"context_lines":[{"line_number":391,"context_line":"            raise webob.exc.HTTPBadRequest(explanation\u003derror.msg)"},{"line_number":392,"context_line":""},{"line_number":393,"context_line":""},{"line_number":394,"context_line":"    @wsgi.Controller.api_version(mv.EXPORT_IMPORT_REPLICA)"},{"line_number":395,"context_line":"    @wsgi.action(\u0027export-replica\u0027)"},{"line_number":396,"context_line":"    @validation.schema(schema.export_replica, mv.EXPORT_IMPORT_REPLICA)"},{"line_number":397,"context_line":"    def _export_replica(self, req, id, body):"}],"source_content_type":"text/x-python","patch_set":6,"id":"3cdc6019_077587f3","line":394,"updated":"2026-09-15 11:52:42.000000000","message":"pep8: E303 too many blank lines (2)","commit_id":"a0fcff75930ce2ecb105d2e060762d5633c40539"}],"cinder/api/openstack/api_version_request.py":[{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"7ec487ae8eed4d4212932518a1a6dbdc285f77a5","unresolved":true,"context_lines":[{"line_number":165,"context_line":"# The default api version request is defined to be the"},{"line_number":166,"context_line":"# minimum version of the API supported."},{"line_number":167,"context_line":"_MIN_API_VERSION \u003d \"3.0\""},{"line_number":168,"context_line":"_MAX_API_VERSION \u003d \"3.72\""},{"line_number":169,"context_line":"UPDATED \u003d \"2023-08-31T00:00:00Z\""},{"line_number":170,"context_line":""},{"line_number":171,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"876dce66_7d437eba","line":168,"updated":"2026-10-14 18:31:25.000000000","message":"Bumping `_MAX_API_VERSION` needs the matching artefacts: a `3.72` section in `cinder/api/openstack/rest_api_version_history.rst`, api-ref entries in `api-ref/source/v3/volumes-v3-volumes-actions.inc` and `volumes-v3-volumes.inc` with request/response samples, and whatever the functional versions samples need. The deterministic `test_versions_get_all`/`test_versions_get_v3` failures on py311 and py313 are from this bump.","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":165,"context_line":"# The default api version request is defined to be the"},{"line_number":166,"context_line":"# minimum version of the API supported."},{"line_number":167,"context_line":"_MIN_API_VERSION \u003d \"3.0\""},{"line_number":168,"context_line":"_MAX_API_VERSION \u003d \"3.72\""},{"line_number":169,"context_line":"UPDATED \u003d \"2023-08-31T00:00:00Z\""},{"line_number":170,"context_line":""},{"line_number":171,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"ba2ef2bd_0798c0d5","line":168,"in_reply_to":"876dce66_7d437eba","updated":"2026-10-26 19:06:48.000000000","message":"Still needs to be resolved","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":165,"context_line":"# The default api version request is defined to be the"},{"line_number":166,"context_line":"# minimum version of the API supported."},{"line_number":167,"context_line":"_MIN_API_VERSION \u003d \"3.0\""},{"line_number":168,"context_line":"_MAX_API_VERSION \u003d \"3.72\""},{"line_number":169,"context_line":"UPDATED \u003d \"2023-08-31T00:00:00Z\""},{"line_number":170,"context_line":""},{"line_number":171,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"5b0e015d_fe588d7c","line":168,"in_reply_to":"ba2ef2bd_0798c0d5","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"}],"cinder/api/schemas/volumes.py":[{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"7ec487ae8eed4d4212932518a1a6dbdc285f77a5","unresolved":true,"context_lines":[{"line_number":159,"context_line":"                \u0027source_volume_id\u0027: parameter_types.uuid,"},{"line_number":160,"context_line":"                \u0027group_id\u0027: parameter_types.uuid,"},{"line_number":161,"context_line":"                \u0027volume_type\u0027: parameter_types.name_allow_zero_min_length,"},{"line_number":162,"context_line":"                \u0027replication_metadata\u0027: {\u0027type\u0027: \u0027object\u0027},"},{"line_number":163,"context_line":"            },"},{"line_number":164,"context_line":"            \u0027required\u0027: [\u0027host\u0027, \u0027source_cloud_id\u0027,"},{"line_number":165,"context_line":"                         \u0027replication_metadata\u0027],"}],"source_content_type":"text/x-python","patch_set":7,"id":"5d4ad37a_08f8b7ab","line":162,"updated":"2026-10-14 18:31:25.000000000","message":"`replication_metadata` is an untyped object, so the only validation of its contents is `if not size or size \u003c 1` at api.py:2772; a string `\"1\"``raises TypeError and the API returns 500. Please define `volume_properties` in the schema (typed `size`, `volume_id`, `bootable`, `metadata`, `glance_metadata`) and `vendor_metadata` as an object.","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":159,"context_line":"                \u0027source_volume_id\u0027: parameter_types.uuid,"},{"line_number":160,"context_line":"                \u0027group_id\u0027: parameter_types.uuid,"},{"line_number":161,"context_line":"                \u0027volume_type\u0027: parameter_types.name_allow_zero_min_length,"},{"line_number":162,"context_line":"                \u0027replication_metadata\u0027: {\u0027type\u0027: \u0027object\u0027},"},{"line_number":163,"context_line":"            },"},{"line_number":164,"context_line":"            \u0027required\u0027: [\u0027host\u0027, \u0027source_cloud_id\u0027,"},{"line_number":165,"context_line":"                         \u0027replication_metadata\u0027],"}],"source_content_type":"text/x-python","patch_set":7,"id":"bb9ce1d0_c2357aeb","line":162,"in_reply_to":"10a97a93_6e4d9029","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":159,"context_line":"                \u0027source_volume_id\u0027: parameter_types.uuid,"},{"line_number":160,"context_line":"                \u0027group_id\u0027: parameter_types.uuid,"},{"line_number":161,"context_line":"                \u0027volume_type\u0027: parameter_types.name_allow_zero_min_length,"},{"line_number":162,"context_line":"                \u0027replication_metadata\u0027: {\u0027type\u0027: \u0027object\u0027},"},{"line_number":163,"context_line":"            },"},{"line_number":164,"context_line":"            \u0027required\u0027: [\u0027host\u0027, \u0027source_cloud_id\u0027,"},{"line_number":165,"context_line":"                         \u0027replication_metadata\u0027],"}],"source_content_type":"text/x-python","patch_set":7,"id":"10a97a93_6e4d9029","line":162,"in_reply_to":"5d4ad37a_08f8b7ab","updated":"2026-10-26 19:06:48.000000000","message":"Still open from PS7, and it now has a non-admin-reachable consequence: `v3/volumes.py:527` evaluates `replication_metadata.get(\u0027volume_properties\u0027, {}).get(\u0027volume_id\u0027)` before `volume_api.import_replica` runs the policy check, so a plain project member sending `\"volume_properties\": null` gets a 500 and a traceback in cinder-api. Typing `volume_properties` (size integer minimum 1, volume_id uuid, bootable boolean, metadata and glance_metadata objects with 255-char keys and values) and `vendor_metadata` as objects fixes both, and also removes the `vendor_metadata: null` path at `manager.py:5557` that strands a volume in managing.","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"}],"cinder/api/v3/router.py":[{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"7ec487ae8eed4d4212932518a1a6dbdc285f77a5","unresolved":true,"context_lines":[{"line_number":175,"context_line":"        mapper.resource(\"volume\", \"volumes\","},{"line_number":176,"context_line":"                        controller\u003dself.resources[\u0027volumes\u0027],"},{"line_number":177,"context_line":"                        collection\u003d{\u0027detail\u0027: \u0027GET\u0027, \u0027summary\u0027: \u0027GET\u0027,"},{"line_number":178,"context_line":"                                    \u0027import_replica\u0027: \u0027POST\u0027},"},{"line_number":179,"context_line":"                        member\u003d{\u0027action\u0027: \u0027POST\u0027})"},{"line_number":180,"context_line":""},{"line_number":181,"context_line":"        self.resources[\u0027messages\u0027] \u003d messages.create_resource(ext_mgr)"}],"source_content_type":"text/x-python","patch_set":7,"id":"eecd88f3_b5436440","line":178,"updated":"2026-10-14 18:31:25.000000000","message":"`import_replica` with an underscore here, but the action keys are `export-replica` and `import-replica`. Pick one spelling for all three (and match the spec).","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":175,"context_line":"        mapper.resource(\"volume\", \"volumes\","},{"line_number":176,"context_line":"                        controller\u003dself.resources[\u0027volumes\u0027],"},{"line_number":177,"context_line":"                        collection\u003d{\u0027detail\u0027: \u0027GET\u0027, \u0027summary\u0027: \u0027GET\u0027,"},{"line_number":178,"context_line":"                                    \u0027import_replica\u0027: \u0027POST\u0027},"},{"line_number":179,"context_line":"                        member\u003d{\u0027action\u0027: \u0027POST\u0027})"},{"line_number":180,"context_line":""},{"line_number":181,"context_line":"        self.resources[\u0027messages\u0027] \u003d messages.create_resource(ext_mgr)"}],"source_content_type":"text/x-python","patch_set":7,"id":"5778e352_07265549","line":178,"in_reply_to":"eecd88f3_b5436440","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"}],"cinder/api/v3/volumes.py":[{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"5899fa5a8a132e65d59110e771002e21068450f7","unresolved":false,"context_lines":[{"line_number":513,"context_line":"        return self._view_builder.detail(req, volume)"},{"line_number":514,"context_line":""},{"line_number":515,"context_line":""},{"line_number":516,"context_line":"    @wsgi.Controller.api_version(mv.EXPORT_IMPORT_REPLICA)"},{"line_number":517,"context_line":"    @wsgi.response(HTTPStatus.CREATED)"},{"line_number":518,"context_line":"    @validation.schema(schema.import_replica, mv.EXPORT_IMPORT_REPLICA)"},{"line_number":519,"context_line":"    def import_replica(self, req, body):"}],"source_content_type":"text/x-python","patch_set":1,"id":"584b848b_c49e0242","line":516,"updated":"2026-08-13 23:54:55.000000000","message":"pep8: E303 too many blank lines (2)","commit_id":"e09062093764509c9e76b53265801c588e274540"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"35370d49fc9a242dd43c6eab0fee9596c7e82776","unresolved":false,"context_lines":[{"line_number":513,"context_line":"        return self._view_builder.detail(req, volume)"},{"line_number":514,"context_line":""},{"line_number":515,"context_line":""},{"line_number":516,"context_line":"    @wsgi.Controller.api_version(mv.EXPORT_IMPORT_REPLICA)"},{"line_number":517,"context_line":"    @wsgi.response(HTTPStatus.CREATED)"},{"line_number":518,"context_line":"    @validation.schema(schema.import_replica, mv.EXPORT_IMPORT_REPLICA)"},{"line_number":519,"context_line":"    def import_replica(self, req, body):"}],"source_content_type":"text/x-python","patch_set":2,"id":"e5c08cef_d88ac158","line":516,"updated":"2026-08-18 20:03:21.000000000","message":"pep8: E303 too many blank lines (2)","commit_id":"5df57325110ed383d4141d222f4b564469b2bd6d"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"bde5a6571dcadc404fcfe444f8f022425a691c98","unresolved":false,"context_lines":[{"line_number":513,"context_line":"        return self._view_builder.detail(req, volume)"},{"line_number":514,"context_line":""},{"line_number":515,"context_line":""},{"line_number":516,"context_line":"    @wsgi.Controller.api_version(mv.EXPORT_IMPORT_REPLICA)"},{"line_number":517,"context_line":"    @wsgi.response(HTTPStatus.CREATED)"},{"line_number":518,"context_line":"    @validation.schema(schema.import_replica, mv.EXPORT_IMPORT_REPLICA)"},{"line_number":519,"context_line":"    def import_replica(self, req, body):"}],"source_content_type":"text/x-python","patch_set":3,"id":"025ecbf7_1129b10b","line":516,"updated":"2026-08-20 00:23:16.000000000","message":"pep8: E303 too many blank lines (2)","commit_id":"c12da181319252a913c230664bdc2fc5177d8cec"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"5f448ed0181b3e695362ddc18115676f8159eb58","unresolved":false,"context_lines":[{"line_number":513,"context_line":"        return self._view_builder.detail(req, volume)"},{"line_number":514,"context_line":""},{"line_number":515,"context_line":""},{"line_number":516,"context_line":"    @wsgi.Controller.api_version(mv.EXPORT_IMPORT_REPLICA)"},{"line_number":517,"context_line":"    @wsgi.response(HTTPStatus.CREATED)"},{"line_number":518,"context_line":"    @validation.schema(schema.import_replica, mv.EXPORT_IMPORT_REPLICA)"},{"line_number":519,"context_line":"    def import_replica(self, req, body):"}],"source_content_type":"text/x-python","patch_set":4,"id":"18aead5c_5ccfbf6d","line":516,"updated":"2026-08-21 16:01:25.000000000","message":"pep8: E303 too many blank lines (2)","commit_id":"70810156d10fcddf30b1f7c6a2d5809aee5e7068"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"d0d9ad1652290ec9575b3ef013501a9144dbc6ae","unresolved":false,"context_lines":[{"line_number":513,"context_line":"        return self._view_builder.detail(req, volume)"},{"line_number":514,"context_line":""},{"line_number":515,"context_line":""},{"line_number":516,"context_line":"    @wsgi.Controller.api_version(mv.EXPORT_IMPORT_REPLICA)"},{"line_number":517,"context_line":"    @wsgi.response(HTTPStatus.CREATED)"},{"line_number":518,"context_line":"    @validation.schema(schema.import_replica, mv.EXPORT_IMPORT_REPLICA)"},{"line_number":519,"context_line":"    def import_replica(self, req, body):"}],"source_content_type":"text/x-python","patch_set":5,"id":"be259698_fdb53c01","line":516,"updated":"2026-08-25 06:32:26.000000000","message":"pep8: E303 too many blank lines (2)","commit_id":"38845cf60edbcfb79f3871ea171c32324b24f3d9"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"003f1925daa5164410b5fc771ac1ef6775bd914f","unresolved":false,"context_lines":[{"line_number":513,"context_line":"        return self._view_builder.detail(req, volume)"},{"line_number":514,"context_line":""},{"line_number":515,"context_line":""},{"line_number":516,"context_line":"    @wsgi.Controller.api_version(mv.EXPORT_IMPORT_REPLICA)"},{"line_number":517,"context_line":"    @wsgi.response(HTTPStatus.CREATED)"},{"line_number":518,"context_line":"    @validation.schema(schema.import_replica, mv.EXPORT_IMPORT_REPLICA)"},{"line_number":519,"context_line":"    def import_replica(self, req, body):"}],"source_content_type":"text/x-python","patch_set":6,"id":"92b7de5b_5e58db84","line":516,"updated":"2026-09-15 11:52:42.000000000","message":"pep8: E303 too many blank lines (2)","commit_id":"a0fcff75930ce2ecb105d2e060762d5633c40539"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"7ec487ae8eed4d4212932518a1a6dbdc285f77a5","unresolved":true,"context_lines":[{"line_number":522,"context_line":"        host \u003d import_data[\u0027host\u0027]"},{"line_number":523,"context_line":"        source_cloud_id \u003d import_data[\u0027source_cloud_id\u0027]"},{"line_number":524,"context_line":"        replication_metadata \u003d import_data[\u0027replication_metadata\u0027]"},{"line_number":525,"context_line":"        source_volume_id \u003d import_data.get("},{"line_number":526,"context_line":"            \u0027source_volume_id\u0027,"},{"line_number":527,"context_line":"            replication_metadata.get(\u0027volume_properties\u0027, {}).get("},{"line_number":528,"context_line":"                \u0027volume_id\u0027))"}],"source_content_type":"text/x-python","patch_set":7,"id":"3669d7a0_8b0fe273","line":525,"updated":"2026-10-14 18:31:25.000000000","message":"If the request omits `source_volume_id` and the exported document has no `volume_properties.volume_id`, this is None and the default `get_import_replica_ref` builds `volume-None`. Please reject the request when both are missing.","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":522,"context_line":"        host \u003d import_data[\u0027host\u0027]"},{"line_number":523,"context_line":"        source_cloud_id \u003d import_data[\u0027source_cloud_id\u0027]"},{"line_number":524,"context_line":"        replication_metadata \u003d import_data[\u0027replication_metadata\u0027]"},{"line_number":525,"context_line":"        source_volume_id \u003d import_data.get("},{"line_number":526,"context_line":"            \u0027source_volume_id\u0027,"},{"line_number":527,"context_line":"            replication_metadata.get(\u0027volume_properties\u0027, {}).get("},{"line_number":528,"context_line":"                \u0027volume_id\u0027))"}],"source_content_type":"text/x-python","patch_set":7,"id":"c85bf8e4_a718df47","line":525,"in_reply_to":"3669d7a0_8b0fe273","updated":"2026-10-26 19:06:48.000000000","message":"Still open from PS7: a request with neither `source_volume_id` nor `volume_properties.volume_id` reaches the driver as `None` and the default ref becomes `volume-None`. `test_volumes.py:1275-1278` currently asserts that pass-through; it should assert a 400 instead.","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":522,"context_line":"        host \u003d import_data[\u0027host\u0027]"},{"line_number":523,"context_line":"        source_cloud_id \u003d import_data[\u0027source_cloud_id\u0027]"},{"line_number":524,"context_line":"        replication_metadata \u003d import_data[\u0027replication_metadata\u0027]"},{"line_number":525,"context_line":"        source_volume_id \u003d import_data.get("},{"line_number":526,"context_line":"            \u0027source_volume_id\u0027,"},{"line_number":527,"context_line":"            replication_metadata.get(\u0027volume_properties\u0027, {}).get("},{"line_number":528,"context_line":"                \u0027volume_id\u0027))"}],"source_content_type":"text/x-python","patch_set":7,"id":"52062828_f2f74db8","line":525,"in_reply_to":"c85bf8e4_a718df47","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":513,"context_line":"        return self._view_builder.detail(req, volume)"},{"line_number":514,"context_line":""},{"line_number":515,"context_line":"    @wsgi.Controller.api_version(mv.EXPORT_IMPORT_REPLICA)"},{"line_number":516,"context_line":"    @wsgi.response(HTTPStatus.CREATED)"},{"line_number":517,"context_line":"    @validation.schema(schema.import_replica, mv.EXPORT_IMPORT_REPLICA)"},{"line_number":518,"context_line":"    def import_replica(self, req, body):"},{"line_number":519,"context_line":"        \"\"\"Import a replicated volume from another OpenStack deployment.\"\"\""}],"source_content_type":"text/x-python","patch_set":9,"id":"b86692d0_2a9f8711","line":516,"updated":"2026-10-26 19:06:48.000000000","message":"This is an asynchronous cast that returns 201: the row is created in `managing` and the backend check runs later on cinder-volume, so a missing image lands in `error_managing` with no user message. Spec 985952 PS10 lines 340-344 say import validates the backend resource exists and returns 400 otherwise. One of the two has to change before the spec is approved: either validate synchronously with an RPC call before `volume.create()` and map `ManageExistingInvalidReference` to 400, or amend the spec to describe the asynchronous flow and error_managing. Either way `HTTPStatus.ACCEPTED` matches create and manage_existing; backup import is the only 201-with-cast precedent.","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":513,"context_line":"        return self._view_builder.detail(req, volume)"},{"line_number":514,"context_line":""},{"line_number":515,"context_line":"    @wsgi.Controller.api_version(mv.EXPORT_IMPORT_REPLICA)"},{"line_number":516,"context_line":"    @wsgi.response(HTTPStatus.CREATED)"},{"line_number":517,"context_line":"    @validation.schema(schema.import_replica, mv.EXPORT_IMPORT_REPLICA)"},{"line_number":518,"context_line":"    def import_replica(self, req, body):"},{"line_number":519,"context_line":"        \"\"\"Import a replicated volume from another OpenStack deployment.\"\"\""}],"source_content_type":"text/x-python","patch_set":9,"id":"8c210785_27a3b66f","line":516,"in_reply_to":"b86692d0_2a9f8711","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"b7253978b368dd2d50b37f309937178351358842"}],"cinder/policies/volume_actions.py":[{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":360,"context_line":"        ]),"},{"line_number":361,"context_line":"    policy.DocumentedRuleDefault("},{"line_number":362,"context_line":"        name\u003dEXPORT_REPLICA_POLICY,"},{"line_number":363,"context_line":"        check_str\u003dbase.RULE_ADMIN_API,"},{"line_number":364,"context_line":"        description\u003d\"Export volume replication metadata for cross-OpenStack \""},{"line_number":365,"context_line":"                    \"failover.\","},{"line_number":366,"context_line":"        operations\u003d["}],"source_content_type":"text/x-python","patch_set":9,"id":"ea99ddf6_dbe3afdd","line":363,"updated":"2026-10-26 19:06:48.000000000","message":"Both new rules default to `RULE_ADMIN_API` as the spec requires, but nothing under `cinder/tests/unit/policies` covers them, and the controller tests patch `authorize`. Please add `test_export_replica_policy` and `test_import_replica_policy` following `test_force_delete_policy`, including the secure-RBAC variants.","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":360,"context_line":"        ]),"},{"line_number":361,"context_line":"    policy.DocumentedRuleDefault("},{"line_number":362,"context_line":"        name\u003dEXPORT_REPLICA_POLICY,"},{"line_number":363,"context_line":"        check_str\u003dbase.RULE_ADMIN_API,"},{"line_number":364,"context_line":"        description\u003d\"Export volume replication metadata for cross-OpenStack \""},{"line_number":365,"context_line":"                    \"failover.\","},{"line_number":366,"context_line":"        operations\u003d["}],"source_content_type":"text/x-python","patch_set":9,"id":"97216f80_759f7f26","line":363,"in_reply_to":"ea99ddf6_dbe3afdd","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"b7253978b368dd2d50b37f309937178351358842"}],"cinder/volume/api.py":[{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"7ec487ae8eed4d4212932518a1a6dbdc285f77a5","unresolved":true,"context_lines":[{"line_number":2750,"context_line":"    def export_replica(self, context, volume, target_os, clear_existing):"},{"line_number":2751,"context_line":"        context.authorize(vol_action_policy.EXPORT_REPLICA_POLICY,"},{"line_number":2752,"context_line":"                          target_obj\u003dvolume)"},{"line_number":2753,"context_line":"        if volume.replication_status not in (\u0027failed-over\u0027,):"},{"line_number":2754,"context_line":"            msg \u003d (_(\"Volume %(vol_id)s replication_status must be \""},{"line_number":2755,"context_line":"                     \"\u0027failed-over\u0027, but current status is \""},{"line_number":2756,"context_line":"                     \"\u0027%(repl_status)s\u0027.\") %"}],"source_content_type":"text/x-python","patch_set":7,"id":"81404f6b_9b9bb02d","line":2753,"updated":"2026-10-14 18:31:25.000000000","message":"`(\u0027failed-over\u0027,)` should be `fields.ReplicationStatus.FAILED_OVER`.","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":2750,"context_line":"    def export_replica(self, context, volume, target_os, clear_existing):"},{"line_number":2751,"context_line":"        context.authorize(vol_action_policy.EXPORT_REPLICA_POLICY,"},{"line_number":2752,"context_line":"                          target_obj\u003dvolume)"},{"line_number":2753,"context_line":"        if volume.replication_status not in (\u0027failed-over\u0027,):"},{"line_number":2754,"context_line":"            msg \u003d (_(\"Volume %(vol_id)s replication_status must be \""},{"line_number":2755,"context_line":"                     \"\u0027failed-over\u0027, but current status is \""},{"line_number":2756,"context_line":"                     \"\u0027%(repl_status)s\u0027.\") %"}],"source_content_type":"text/x-python","patch_set":7,"id":"38621c3e_500f6a7e","line":2753,"in_reply_to":"031ce826_831c2a6a","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":2750,"context_line":"    def export_replica(self, context, volume, target_os, clear_existing):"},{"line_number":2751,"context_line":"        context.authorize(vol_action_policy.EXPORT_REPLICA_POLICY,"},{"line_number":2752,"context_line":"                          target_obj\u003dvolume)"},{"line_number":2753,"context_line":"        if volume.replication_status not in (\u0027failed-over\u0027,):"},{"line_number":2754,"context_line":"            msg \u003d (_(\"Volume %(vol_id)s replication_status must be \""},{"line_number":2755,"context_line":"                     \"\u0027failed-over\u0027, but current status is \""},{"line_number":2756,"context_line":"                     \"\u0027%(repl_status)s\u0027.\") %"}],"source_content_type":"text/x-python","patch_set":7,"id":"031ce826_831c2a6a","line":2753,"in_reply_to":"81404f6b_9b9bb02d","updated":"2026-10-26 19:06:48.000000000","message":"Still needs reolving","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"7ec487ae8eed4d4212932518a1a6dbdc285f77a5","unresolved":true,"context_lines":[{"line_number":2777,"context_line":"        display_description \u003d volume_properties.get("},{"line_number":2778,"context_line":"            \u0027display_description\u0027, \u0027\u0027)"},{"line_number":2779,"context_line":""},{"line_number":2780,"context_line":"        svc \u003d self._get_service_by_host_cluster(context, host, None)"},{"line_number":2781,"context_line":""},{"line_number":2782,"context_line":"        if volume_type:"},{"line_number":2783,"context_line":"            # An explicit target-cloud volume type was requested; it must"}],"source_content_type":"text/x-python","patch_set":7,"id":"e83f042a_461e7ea4","line":2780,"updated":"2026-10-14 18:31:25.000000000","message":"This resolves the service by host name and casts straight to the volume RPC. `manage_existing` deliberately goes through `scheduler_rpcapi.manage_existing` (flows/api/manage_existing.py:119) so the host is validated against the volume type\u0027s capabilities. Without that hop an admin can import a `replication_enabled`/`sync` type onto a backend that cannot serve it and end up with a volume marked `available` and `replication_status: enabled` that is neither. Please route through the scheduler like the manage flow does.","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":2777,"context_line":"        display_description \u003d volume_properties.get("},{"line_number":2778,"context_line":"            \u0027display_description\u0027, \u0027\u0027)"},{"line_number":2779,"context_line":""},{"line_number":2780,"context_line":"        svc \u003d self._get_service_by_host_cluster(context, host, None)"},{"line_number":2781,"context_line":""},{"line_number":2782,"context_line":"        if volume_type:"},{"line_number":2783,"context_line":"            # An explicit target-cloud volume type was requested; it must"}],"source_content_type":"text/x-python","patch_set":7,"id":"a7a04904_0f1e2f36","line":2780,"in_reply_to":"7a402ab8_e927029f","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":2777,"context_line":"        display_description \u003d volume_properties.get("},{"line_number":2778,"context_line":"            \u0027display_description\u0027, \u0027\u0027)"},{"line_number":2779,"context_line":""},{"line_number":2780,"context_line":"        svc \u003d self._get_service_by_host_cluster(context, host, None)"},{"line_number":2781,"context_line":""},{"line_number":2782,"context_line":"        if volume_type:"},{"line_number":2783,"context_line":"            # An explicit target-cloud volume type was requested; it must"}],"source_content_type":"text/x-python","patch_set":7,"id":"7a402ab8_e927029f","line":2780,"in_reply_to":"e83f042a_461e7ea4","updated":"2026-10-26 19:06:48.000000000","message":"Still needs resolving","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"7ec487ae8eed4d4212932518a1a6dbdc285f77a5","unresolved":true,"context_lines":[{"line_number":2841,"context_line":"        volume.size \u003d size"},{"line_number":2842,"context_line":"        volume.volume_type_id \u003d vol_type[\u0027id\u0027]"},{"line_number":2843,"context_line":"        volume.availability_zone \u003d availability_zone"},{"line_number":2844,"context_line":"        volume.replication_status \u003d fields.ReplicationStatus.DISABLED"},{"line_number":2845,"context_line":"        volume.metadata \u003d volume_properties.get(\u0027metadata\u0027, {})"},{"line_number":2846,"context_line":"        if group:"},{"line_number":2847,"context_line":"            volume.group_id \u003d group.id"}],"source_content_type":"text/x-python","patch_set":7,"id":"6489adc5_13d8b0c8","line":2844,"updated":"2026-10-14 18:31:25.000000000","message":"This is overwritten by the driver\u0027s model update for RBD, but a driver that returns no update leaves an imported replicated volume at `disabled`. Set it from the resolved volume type (`vol_type.is_replicated()`) so the default is right.","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":2841,"context_line":"        volume.size \u003d size"},{"line_number":2842,"context_line":"        volume.volume_type_id \u003d vol_type[\u0027id\u0027]"},{"line_number":2843,"context_line":"        volume.availability_zone \u003d availability_zone"},{"line_number":2844,"context_line":"        volume.replication_status \u003d fields.ReplicationStatus.DISABLED"},{"line_number":2845,"context_line":"        volume.metadata \u003d volume_properties.get(\u0027metadata\u0027, {})"},{"line_number":2846,"context_line":"        if group:"},{"line_number":2847,"context_line":"            volume.group_id \u003d group.id"}],"source_content_type":"text/x-python","patch_set":7,"id":"ccacf096_bd8f7c5e","line":2844,"in_reply_to":"6489adc5_13d8b0c8","updated":"2026-10-26 19:06:48.000000000","message":"Still needs resolving","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":2841,"context_line":"        volume.size \u003d size"},{"line_number":2842,"context_line":"        volume.volume_type_id \u003d vol_type[\u0027id\u0027]"},{"line_number":2843,"context_line":"        volume.availability_zone \u003d availability_zone"},{"line_number":2844,"context_line":"        volume.replication_status \u003d fields.ReplicationStatus.DISABLED"},{"line_number":2845,"context_line":"        volume.metadata \u003d volume_properties.get(\u0027metadata\u0027, {})"},{"line_number":2846,"context_line":"        if group:"},{"line_number":2847,"context_line":"            volume.group_id \u003d group.id"}],"source_content_type":"text/x-python","patch_set":7,"id":"969ed887_2a343c95","line":2844,"in_reply_to":"ccacf096_bd8f7c5e","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":2805,"context_line":"                        context, volume_type_name)"},{"line_number":2806,"context_line":"                except (exception.VolumeTypeNotFound,"},{"line_number":2807,"context_line":"                        exception.VolumeTypeNotFoundByName):"},{"line_number":2808,"context_line":"                    vol_type \u003d volume_types.get_default_volume_type(context)"},{"line_number":2809,"context_line":"            else:"},{"line_number":2810,"context_line":"                vol_type \u003d volume_types.get_default_volume_type(context)"},{"line_number":2811,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"2c6162e0_31baee05","line":2808,"updated":"2026-10-26 19:06:48.000000000","message":"When the request omits `volume_type` and the exported type name does not resolve, this silently substitutes the default type. The explicit-type branch at 2793-2799 raises `InvalidVolume` for the same condition, `manage_existing` rejects an unknown named type, and nothing in the spec, history entry or release note documents a fallback. The exported type carries the replication semantics, so an import that lands on `__DEFAULT__` with RBD forcing `replication_status` to enabled is wrong in two places at once. Please raise `InvalidVolume` naming the type and fall back to the default only when the document carries no type at all. Also map `VolumeTypeDefaultMisconfiguredError` as v3 create does, and add ddt cases for every type and group branch; none is tested today.","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":2805,"context_line":"                        context, volume_type_name)"},{"line_number":2806,"context_line":"                except (exception.VolumeTypeNotFound,"},{"line_number":2807,"context_line":"                        exception.VolumeTypeNotFoundByName):"},{"line_number":2808,"context_line":"                    vol_type \u003d volume_types.get_default_volume_type(context)"},{"line_number":2809,"context_line":"            else:"},{"line_number":2810,"context_line":"                vol_type \u003d volume_types.get_default_volume_type(context)"},{"line_number":2811,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"c045458d_ed168b6c","line":2808,"in_reply_to":"2c6162e0_31baee05","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":2819,"context_line":"        group \u003d None"},{"line_number":2820,"context_line":"        if group_id:"},{"line_number":2821,"context_line":"            try:"},{"line_number":2822,"context_line":"                group \u003d objects.Group.get_by_id(context, group_id)"},{"line_number":2823,"context_line":"            except exception.GroupNotFound:"},{"line_number":2824,"context_line":"                msg \u003d _(\"Group %s not found.\") % group_id"},{"line_number":2825,"context_line":"                raise exception.InvalidVolume(reason\u003dmsg)"}],"source_content_type":"text/x-python","patch_set":9,"id":"ca32be3a_9aedee15","line":2822,"updated":"2026-10-26 19:06:48.000000000","message":"The group check validates existence, backend and type membership but not `group.status`. The create flow refuses any group outside `GROUP_PROCEED_STATUS`. A group in `deleting`, `error` or `error_deleting` keeps its host and is accepted here, and since `group_destroy` never clears `Volume.group_id`, the imported volume becomes an undeletable member of a destroyed group. Please require `available` or `creating`, and give the host-less group case a group-specific message rather than the current \"volume is not assigned to a host\".","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":2819,"context_line":"        group \u003d None"},{"line_number":2820,"context_line":"        if group_id:"},{"line_number":2821,"context_line":"            try:"},{"line_number":2822,"context_line":"                group \u003d objects.Group.get_by_id(context, group_id)"},{"line_number":2823,"context_line":"            except exception.GroupNotFound:"},{"line_number":2824,"context_line":"                msg \u003d _(\"Group %s not found.\") % group_id"},{"line_number":2825,"context_line":"                raise exception.InvalidVolume(reason\u003dmsg)"}],"source_content_type":"text/x-python","patch_set":9,"id":"f3eb0efd_67b164e6","line":2822,"in_reply_to":"ca32be3a_9aedee15","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":2847,"context_line":"        volume.display_name \u003d display_name"},{"line_number":2848,"context_line":"        volume.display_description \u003d display_description"},{"line_number":2849,"context_line":"        volume.size \u003d size"},{"line_number":2850,"context_line":"        volume.volume_type_id \u003d vol_type[\u0027id\u0027]"},{"line_number":2851,"context_line":"        volume.availability_zone \u003d availability_zone"},{"line_number":2852,"context_line":"        volume.replication_status \u003d fields.ReplicationStatus.DISABLED"},{"line_number":2853,"context_line":"        volume.metadata \u003d volume_properties.get(\u0027metadata\u0027, {})"}],"source_content_type":"text/x-python","patch_set":9,"id":"faefdf42_5fbaebe5","line":2850,"updated":"2026-10-26 19:06:48.000000000","message":"Two checks that every other path performs are missing after the type is resolved.\n\n1. Encryption. Nothing rejects an encrypted `vol_type`, so the volume is created with an encrypted type and `encryption_key_id None`; reproduced with a LUKS type both explicitly and via the document\u0027s type name. Attach then runs in plaintext while `os-volume_encryption_metadata` reports a cipher, and a clone gets a fresh key and is LUKS-formatted on first attach, wiping it. Add `if volume_types.is_encrypted(context, vol_type[\u0027id\u0027]): raise InvalidVolume(...)` here, mirroring the export-side rejection. Note `API._is_encrypted` is dead code on master; use `volume_types.is_encrypted`.\n2. Multiattach. `EntryCreateTask` in the manage flow sets `multiattach` from the type\u0027s extra specs; this path never does, so an imported volume of a multiattach type refuses its second attachment at `_attachment_reserve`. Add `volume.multiattach \u003d self._is_multiattach(vol_type)`.","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":2847,"context_line":"        volume.display_name \u003d display_name"},{"line_number":2848,"context_line":"        volume.display_description \u003d display_description"},{"line_number":2849,"context_line":"        volume.size \u003d size"},{"line_number":2850,"context_line":"        volume.volume_type_id \u003d vol_type[\u0027id\u0027]"},{"line_number":2851,"context_line":"        volume.availability_zone \u003d availability_zone"},{"line_number":2852,"context_line":"        volume.replication_status \u003d fields.ReplicationStatus.DISABLED"},{"line_number":2853,"context_line":"        volume.metadata \u003d volume_properties.get(\u0027metadata\u0027, {})"}],"source_content_type":"text/x-python","patch_set":9,"id":"0f66cdc5_4056aa75","line":2850,"in_reply_to":"faefdf42_5fbaebe5","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":2850,"context_line":"        volume.volume_type_id \u003d vol_type[\u0027id\u0027]"},{"line_number":2851,"context_line":"        volume.availability_zone \u003d availability_zone"},{"line_number":2852,"context_line":"        volume.replication_status \u003d fields.ReplicationStatus.DISABLED"},{"line_number":2853,"context_line":"        volume.metadata \u003d volume_properties.get(\u0027metadata\u0027, {})"},{"line_number":2854,"context_line":"        if group:"},{"line_number":2855,"context_line":"            volume.group_id \u003d group.id"},{"line_number":2856,"context_line":"        volume.create()"}],"source_content_type":"text/x-python","patch_set":9,"id":"f29c31e6_016dde2e","line":2853,"updated":"2026-10-26 19:06:48.000000000","message":"`create()` runs `utils.check_metadata_properties` and caps name and description at 255; manage types metadata through `parameter_types.metadata_allows_null`. This path copies `display_name`, `display_description` and `metadata` from the document unchecked. A nested or list metadata value raises `ValueError` at this assignment and the controller only catches `ServiceNotFound` and `InvalidVolume`, so it is a 500; a 300-character name becomes a bare 400 from the DB layer. Please call `check_metadata_properties` here and type these fields in the schema.","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":2850,"context_line":"        volume.volume_type_id \u003d vol_type[\u0027id\u0027]"},{"line_number":2851,"context_line":"        volume.availability_zone \u003d availability_zone"},{"line_number":2852,"context_line":"        volume.replication_status \u003d fields.ReplicationStatus.DISABLED"},{"line_number":2853,"context_line":"        volume.metadata \u003d volume_properties.get(\u0027metadata\u0027, {})"},{"line_number":2854,"context_line":"        if group:"},{"line_number":2855,"context_line":"            volume.group_id \u003d group.id"},{"line_number":2856,"context_line":"        volume.create()"}],"source_content_type":"text/x-python","patch_set":9,"id":"f945a0f1_78266518","line":2853,"in_reply_to":"f29c31e6_016dde2e","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":2853,"context_line":"        volume.metadata \u003d volume_properties.get(\u0027metadata\u0027, {})"},{"line_number":2854,"context_line":"        if group:"},{"line_number":2855,"context_line":"            volume.group_id \u003d group.id"},{"line_number":2856,"context_line":"        volume.create()"},{"line_number":2857,"context_line":""},{"line_number":2858,"context_line":"        self.volume_rpcapi.import_replica("},{"line_number":2859,"context_line":"            context, volume, source_cloud_id, source_volume_id,"}],"source_content_type":"text/x-python","patch_set":9,"id":"10f66df5_6ccf2eca","line":2856,"updated":"2026-10-26 19:06:48.000000000","message":"No quota is reserved for the imported volume. The manage API flow reserves `volumes\u003d1` plus the per-type key before the manager adds gigabytes; this method has no QUOTAS call at all, and the manager flow\u0027s `update_size` option makes `QuotaReserveTask` skip the volume count. The imported volume keeps `use_quota\u003dTrue`, so a later delete releases `volumes\u003d-1`, and every import-delete cycle under-counts by one. Reproduced on the worktree. Reserve and commit `{\u0027volumes\u0027: 1}` with `add_volume_type_opts` before `volume.create()`, or reuse the API-side manage flow.","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":2853,"context_line":"        volume.metadata \u003d volume_properties.get(\u0027metadata\u0027, {})"},{"line_number":2854,"context_line":"        if group:"},{"line_number":2855,"context_line":"            volume.group_id \u003d group.id"},{"line_number":2856,"context_line":"        volume.create()"},{"line_number":2857,"context_line":""},{"line_number":2858,"context_line":"        self.volume_rpcapi.import_replica("},{"line_number":2859,"context_line":"            context, volume, source_cloud_id, source_volume_id,"}],"source_content_type":"text/x-python","patch_set":9,"id":"431b2945_012fa51e","line":2856,"in_reply_to":"10f66df5_6ccf2eca","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":2855,"context_line":"            volume.group_id \u003d group.id"},{"line_number":2856,"context_line":"        volume.create()"},{"line_number":2857,"context_line":""},{"line_number":2858,"context_line":"        self.volume_rpcapi.import_replica("},{"line_number":2859,"context_line":"            context, volume, source_cloud_id, source_volume_id,"},{"line_number":2860,"context_line":"            replication_metadata)"},{"line_number":2861,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"44caf978_e8da7ff0","line":2858,"updated":"2026-10-26 19:06:48.000000000","message":"The row is created at 2856 and the cast follows with no revert. `rpcapi.import_replica` carries `assert_min_rpc_version(\u00273.21\u0027)`, which raises `ServiceTooOld` before the cast whenever any cinder-volume service row is below 3.21, so in a mixed-version deployment the API returns a bare 400 and a `managing` volume is left behind that only force-delete removes. Wrap the cast in `save_and_reraise_exception` and destroy or error the row, or use the manage flow whose cast task has a revert.","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":2855,"context_line":"            volume.group_id \u003d group.id"},{"line_number":2856,"context_line":"        volume.create()"},{"line_number":2857,"context_line":""},{"line_number":2858,"context_line":"        self.volume_rpcapi.import_replica("},{"line_number":2859,"context_line":"            context, volume, source_cloud_id, source_volume_id,"},{"line_number":2860,"context_line":"            replication_metadata)"},{"line_number":2861,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"905e3d79_d6ad25cf","line":2858,"in_reply_to":"44caf978_e8da7ff0","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"62b58645c2b4297f774e6c861369ca581485f205","unresolved":false,"context_lines":[{"line_number":2884,"context_line":"            volume.create()"},{"line_number":2885,"context_line":"        except Exception:"},{"line_number":2886,"context_line":"            # Quota reservation was already made; clean it up on failure."},{"line_number":2887,"context_line":"            QUOTAS.rollback(context, reservations)"},{"line_number":2888,"context_line":"            raise"},{"line_number":2889,"context_line":""},{"line_number":2890,"context_line":"        self.volume_rpcapi.import_replica("}],"source_content_type":"text/x-python","patch_set":11,"id":"dd4b06a4_8449d00b","line":2887,"updated":"2026-10-29 19:52:24.000000000","message":"pep8: F821 undefined name \u0027reservations\u0027","commit_id":"5c0a9257a5879ee1f79730b8fd075e16563530e1"}],"cinder/volume/driver.py":[{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"7ec487ae8eed4d4212932518a1a6dbdc285f77a5","unresolved":true,"context_lines":[{"line_number":220,"context_line":"                      \"standard dict config form: replication_device \u003d \""},{"line_number":221,"context_line":"                      \"target_device_id:\u003crequired\u003e,\""},{"line_number":222,"context_line":"                      \"key1:value1,key2:value2...\"),"},{"line_number":223,"context_line":"    cfg.ListOpt(\u0027replication_encryption_keys\u0027,"},{"line_number":224,"context_line":"                default\u003d[],"},{"line_number":225,"context_line":"                secret\u003dTrue,"},{"line_number":226,"context_line":"                help\u003d\u0027List of cloud_id:barbican_key_id pairs for encrypting \u0027"}],"source_content_type":"text/x-python","patch_set":7,"id":"fd8757c2_94e3ac33","line":223,"updated":"2026-10-14 18:31:25.000000000","message":"`replication_encryption_keys` is registered in the per-backend `volume_opts`, marked `secret\u003dTrue`, documented as encrypting `admin_metadata`, and never referenced anywhere else in the patch; `admin_metadata` is exported in the clear at manager.py:5516. Please either implement it or drop it until the spec decides whether it is wanted. A secret-handling option that does nothing is worse than either. (Also: if it is kept, it is a cloud-level setting, not a per-backend one.)","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":220,"context_line":"                      \"standard dict config form: replication_device \u003d \""},{"line_number":221,"context_line":"                      \"target_device_id:\u003crequired\u003e,\""},{"line_number":222,"context_line":"                      \"key1:value1,key2:value2...\"),"},{"line_number":223,"context_line":"    cfg.ListOpt(\u0027replication_encryption_keys\u0027,"},{"line_number":224,"context_line":"                default\u003d[],"},{"line_number":225,"context_line":"                secret\u003dTrue,"},{"line_number":226,"context_line":"                help\u003d\u0027List of cloud_id:barbican_key_id pairs for encrypting \u0027"}],"source_content_type":"text/x-python","patch_set":7,"id":"ebc32139_dd74444d","line":223,"in_reply_to":"fd8757c2_94e3ac33","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"7ec487ae8eed4d4212932518a1a6dbdc285f77a5","unresolved":true,"context_lines":[{"line_number":1782,"context_line":"        \"\"\""},{"line_number":1783,"context_line":"        return {\u0027source-name\u0027: \u0027volume-%s\u0027 % source_volume_id}"},{"line_number":1784,"context_line":""},{"line_number":1785,"context_line":"    def import_replica(self, volume, manage_existing_ref):"},{"line_number":1786,"context_line":"        \"\"\"Import a replicated volume from another OpenStack deployment."},{"line_number":1787,"context_line":""},{"line_number":1788,"context_line":"        Similar to manage_existing but for replicated volumes:"}],"source_content_type":"text/x-python","patch_set":7,"id":"252f9888_d38e2cbe","line":1785,"updated":"2026-10-14 18:31:25.000000000","message":"Worth stating in the docstring that `manage_existing_get_size(volume, manage_existing_ref)` runs *before* `import_replica` (via `PrepareForQuotaReservationTask`). For drivers whose target-side object is still a snapshot that import must promote, which the spec explicitly allows, the ref has to be something `manage_existing_get_size` can measure. That constraint shapes how non-RBD drivers implement this.","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":1782,"context_line":"        \"\"\""},{"line_number":1783,"context_line":"        return {\u0027source-name\u0027: \u0027volume-%s\u0027 % source_volume_id}"},{"line_number":1784,"context_line":""},{"line_number":1785,"context_line":"    def import_replica(self, volume, manage_existing_ref):"},{"line_number":1786,"context_line":"        \"\"\"Import a replicated volume from another OpenStack deployment."},{"line_number":1787,"context_line":""},{"line_number":1788,"context_line":"        Similar to manage_existing but for replicated volumes:"}],"source_content_type":"text/x-python","patch_set":7,"id":"df347cc6_76f3e255","line":1785,"in_reply_to":"252f9888_d38e2cbe","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":1746,"context_line":"        \"\"\""},{"line_number":1747,"context_line":"        raise NotImplementedError()"},{"line_number":1748,"context_line":""},{"line_number":1749,"context_line":"    def export_replica(self, volume, clear_existing):"},{"line_number":1750,"context_line":"        \"\"\"Export vendor-specific metadata for cross-OpenStack import."},{"line_number":1751,"context_line":""},{"line_number":1752,"context_line":"        Returns a dict with backend-specific information needed to"}],"source_content_type":"text/x-python","patch_set":9,"id":"31bca286_b03be44c","line":1749,"updated":"2026-10-26 19:06:48.000000000","message":"Nothing under `doc/` or `api-ref/` changes. The admin replication guide has no procedure for exporting failed-over volumes to a surviving cloud, and the contributor replication reference does not mention the three new hooks. The spec\u0027s Documentation Impact lists both. Please add them in this change or state that they follow in the series. Also, every new `def` in the mypy-checked modules (`rbd.py`, `manager.py`, `volume/api.py`, `rpcapi.py`) is unannotated while its neighbours are typed; please add hints.","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":1746,"context_line":"        \"\"\""},{"line_number":1747,"context_line":"        raise NotImplementedError()"},{"line_number":1748,"context_line":""},{"line_number":1749,"context_line":"    def export_replica(self, volume, clear_existing):"},{"line_number":1750,"context_line":"        \"\"\"Export vendor-specific metadata for cross-OpenStack import."},{"line_number":1751,"context_line":""},{"line_number":1752,"context_line":"        Returns a dict with backend-specific information needed to"}],"source_content_type":"text/x-python","patch_set":9,"id":"df1c332a_7bcbf8b0","line":1749,"in_reply_to":"31bca286_b03be44c","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":1786,"context_line":"        :param source_volume_id: UUID of the volume on the source cloud"},{"line_number":1787,"context_line":"        :returns: manage_existing_ref dict, e.g. {\u0027source-name\u0027: \u0027...\u0027}"},{"line_number":1788,"context_line":"        \"\"\""},{"line_number":1789,"context_line":"        return {\u0027source-name\u0027: \u0027volume-%s\u0027 % source_volume_id}"},{"line_number":1790,"context_line":""},{"line_number":1791,"context_line":"    def import_replica(self, volume, manage_existing_ref, source_cloud_id):"},{"line_number":1792,"context_line":"        \"\"\"Import a replicated volume from another OpenStack deployment."}],"source_content_type":"text/x-python","patch_set":9,"id":"8f81f1ce_5516e961","line":1789,"updated":"2026-10-26 19:06:48.000000000","message":"`\u0027volume-%s\u0027 % source_volume_id` ignores `CONF.volume_name_template`, and the RBD override at `rbd.py:2312` has the same fallback. With a non-default template on both clouds and a document without `vendor_metadata`, which the schema allows, the ref names an image that does not exist and the volume lands in `error_managing`. Use `CONF.volume_name_template % source_volume_id` in both places and reword the docstring\u0027s \"standard name\".","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":1786,"context_line":"        :param source_volume_id: UUID of the volume on the source cloud"},{"line_number":1787,"context_line":"        :returns: manage_existing_ref dict, e.g. {\u0027source-name\u0027: \u0027...\u0027}"},{"line_number":1788,"context_line":"        \"\"\""},{"line_number":1789,"context_line":"        return {\u0027source-name\u0027: \u0027volume-%s\u0027 % source_volume_id}"},{"line_number":1790,"context_line":""},{"line_number":1791,"context_line":"    def import_replica(self, volume, manage_existing_ref, source_cloud_id):"},{"line_number":1792,"context_line":"        \"\"\"Import a replicated volume from another OpenStack deployment."}],"source_content_type":"text/x-python","patch_set":9,"id":"013d6fa6_21003779","line":1789,"in_reply_to":"8f81f1ce_5516e961","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":1793,"context_line":""},{"line_number":1794,"context_line":"        Similar to manage_existing but for replicated volumes:"},{"line_number":1795,"context_line":"        - Verifies the image/LUN exists on the backend"},{"line_number":1796,"context_line":"        - Does NOT rename (image already has correct name from replication)"},{"line_number":1797,"context_line":"        - Does NOT re-enable replication (already established by storage layer)"},{"line_number":1798,"context_line":""},{"line_number":1799,"context_line":"        source_cloud_id may be used for target-side bookkeeping or"}],"source_content_type":"text/x-python","patch_set":9,"id":"1093b1dd_393a35ed","line":1796,"updated":"2026-10-26 19:06:48.000000000","message":"\"Does NOT rename (image already has correct name from replication)\" tells an implementer the wrong thing: the new row has a fresh UUID and no `_name_id`, so `volume.name` points at nothing until the driver returns a model update that makes it resolve, as RBD does with `_name_id`. The change\u0027s own manager test models a driver returning `{}` and the volume still goes available. Please rewrite the bullet to say the driver must return `_name_id`, or `provider_location`/`provider_id` for drivers that resolve by those, with `_name_id` required to be a UUID. Fold in my PS7 note that `manage_existing_get_size` runs first through `PrepareForQuotaReservationTask`, that its size is what quota reserves and what gets saved, and that a driver promoting a snapshot must return a ref `manage_existing_get_size` can measure.","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":1793,"context_line":""},{"line_number":1794,"context_line":"        Similar to manage_existing but for replicated volumes:"},{"line_number":1795,"context_line":"        - Verifies the image/LUN exists on the backend"},{"line_number":1796,"context_line":"        - Does NOT rename (image already has correct name from replication)"},{"line_number":1797,"context_line":"        - Does NOT re-enable replication (already established by storage layer)"},{"line_number":1798,"context_line":""},{"line_number":1799,"context_line":"        source_cloud_id may be used for target-side bookkeeping or"}],"source_content_type":"text/x-python","patch_set":9,"id":"bbf1f665_a2d5175b","line":1796,"in_reply_to":"1093b1dd_393a35ed","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"b7253978b368dd2d50b37f309937178351358842"}],"cinder/volume/drivers/rbd.py":[{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":2308,"context_line":""},{"line_number":2309,"context_line":"    def get_import_replica_ref(self, vendor_metadata, source_cloud_id,"},{"line_number":2310,"context_line":"                               source_volume_id):"},{"line_number":2311,"context_line":"        rbd_image \u003d vendor_metadata.get(\u0027rbd_image\u0027)"},{"line_number":2312,"context_line":"        return {\u0027source-name\u0027: rbd_image or \u0027volume-%s\u0027 % source_volume_id}"},{"line_number":2313,"context_line":""},{"line_number":2314,"context_line":"    def import_replica(self, volume, manage_existing_ref, source_cloud_id):"}],"source_content_type":"text/x-python","patch_set":9,"id":"4d6c4544_fe20593e","line":2311,"updated":"2026-10-26 19:06:48.000000000","message":"`rbd_pool` is exported at 2305 but never read on import; `manage_existing_get_size` and `import_replica` always open the target\u0027s configured pool, so a pool misconfiguration surfaces as \"image does not exist\" in `error_managing`. Either compare it inside the flow and raise `ManageExistingInvalidReference` naming both pools, or drop it from the export so the document only carries what is consumed. Do not raise in `get_import_replica_ref`, which runs before the flow.","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":2308,"context_line":""},{"line_number":2309,"context_line":"    def get_import_replica_ref(self, vendor_metadata, source_cloud_id,"},{"line_number":2310,"context_line":"                               source_volume_id):"},{"line_number":2311,"context_line":"        rbd_image \u003d vendor_metadata.get(\u0027rbd_image\u0027)"},{"line_number":2312,"context_line":"        return {\u0027source-name\u0027: rbd_image or \u0027volume-%s\u0027 % source_volume_id}"},{"line_number":2313,"context_line":""},{"line_number":2314,"context_line":"    def import_replica(self, volume, manage_existing_ref, source_cloud_id):"}],"source_content_type":"text/x-python","patch_set":9,"id":"f825a162_e3fc9f3a","line":2311,"in_reply_to":"4d6c4544_fe20593e","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":2326,"context_line":"        # existing backend image name instead of the new volume UUID."},{"line_number":2327,"context_line":"        model_update \u003d {}"},{"line_number":2328,"context_line":"        source_uuid \u003d volume_utils.extract_id_from_volume_name(rbd_name)"},{"line_number":2329,"context_line":"        if source_uuid:"},{"line_number":2330,"context_line":"            model_update[\u0027_name_id\u0027] \u003d source_uuid"},{"line_number":2331,"context_line":"        model_update[\u0027replication_status\u0027] \u003d ("},{"line_number":2332,"context_line":"            fields.ReplicationStatus.ENABLED)"}],"source_content_type":"text/x-python","patch_set":9,"id":"f844bfff_02873778","line":2329,"updated":"2026-10-26 19:06:48.000000000","message":"`extract_id_from_volume_name` uses the target cloud\u0027s `volume_name_template`, but `rbd_image` was rendered with the source cloud\u0027s. When they differ, `source_uuid` is None, this branch is skipped, and the method still returns `ENABLED`; the flow then marks the volume available with a `volume.name` that points at a non-existent image. Attach, snapshot and extend fail with `ImageNotFound`, and `_delete_volume` swallows `ImageNotFound`, so delete succeeds and orphans the replica. Executed from the worktree with ref `cinder-\u003cuuid\u003e`. Raise `ManageExistingInvalidReference` when no UUID can be extracted, or have export put the `source name_id` into `vendor_metadata` explicitly. A test with a name like `vol-\u003cuuid\u003e` would exercise this; `volume-some-other-name` does not, since it yields `_name_id\u003d\u0027some-other-name\u0027`.","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":2326,"context_line":"        # existing backend image name instead of the new volume UUID."},{"line_number":2327,"context_line":"        model_update \u003d {}"},{"line_number":2328,"context_line":"        source_uuid \u003d volume_utils.extract_id_from_volume_name(rbd_name)"},{"line_number":2329,"context_line":"        if source_uuid:"},{"line_number":2330,"context_line":"            model_update[\u0027_name_id\u0027] \u003d source_uuid"},{"line_number":2331,"context_line":"        model_update[\u0027replication_status\u0027] \u003d ("},{"line_number":2332,"context_line":"            fields.ReplicationStatus.ENABLED)"}],"source_content_type":"text/x-python","patch_set":9,"id":"2bf860bd_654d1ec7","line":2329,"in_reply_to":"f844bfff_02873778","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":2327,"context_line":"        model_update \u003d {}"},{"line_number":2328,"context_line":"        source_uuid \u003d volume_utils.extract_id_from_volume_name(rbd_name)"},{"line_number":2329,"context_line":"        if source_uuid:"},{"line_number":2330,"context_line":"            model_update[\u0027_name_id\u0027] \u003d source_uuid"},{"line_number":2331,"context_line":"        model_update[\u0027replication_status\u0027] \u003d ("},{"line_number":2332,"context_line":"            fields.ReplicationStatus.ENABLED)"},{"line_number":2333,"context_line":"        return model_update"}],"source_content_type":"text/x-python","patch_set":9,"id":"cb00dd60_a74cb50d","line":2330,"updated":"2026-10-26 19:06:48.000000000","message":"Two knock-on effects of `_name_id` differing from `id`. `get_manageable_volumes` builds its known-ids set from `resource[\u0027id\u0027]` only, so every imported image is listed as safe to manage, and `manage_existing` on it renames the image out from under the imported volume; build the set from `id` and `name_id` and mark such images already managed. And the duplicate-import check above needs the same `_name_id` lookup. Both are the same two-line fix in `check_already_managed_volume`.","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":2327,"context_line":"        model_update \u003d {}"},{"line_number":2328,"context_line":"        source_uuid \u003d volume_utils.extract_id_from_volume_name(rbd_name)"},{"line_number":2329,"context_line":"        if source_uuid:"},{"line_number":2330,"context_line":"            model_update[\u0027_name_id\u0027] \u003d source_uuid"},{"line_number":2331,"context_line":"        model_update[\u0027replication_status\u0027] \u003d ("},{"line_number":2332,"context_line":"            fields.ReplicationStatus.ENABLED)"},{"line_number":2333,"context_line":"        return model_update"}],"source_content_type":"text/x-python","patch_set":9,"id":"2536c3c3_e0ab5dcd","line":2330,"in_reply_to":"cb00dd60_a74cb50d","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":2328,"context_line":"        source_uuid \u003d volume_utils.extract_id_from_volume_name(rbd_name)"},{"line_number":2329,"context_line":"        if source_uuid:"},{"line_number":2330,"context_line":"            model_update[\u0027_name_id\u0027] \u003d source_uuid"},{"line_number":2331,"context_line":"        model_update[\u0027replication_status\u0027] \u003d ("},{"line_number":2332,"context_line":"            fields.ReplicationStatus.ENABLED)"},{"line_number":2333,"context_line":"        return model_update"},{"line_number":2334,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"6c3f09e9_a116ebf3","line":2331,"updated":"2026-10-26 19:06:48.000000000","message":"Every other path that returns `ENABLED` goes through `_enable_replication`, which pairs it with `replication_driver_data` (`had_journaling`, `had_exclusive_lock`, `active_backend_id`). Here `ENABLED` comes back alone. `_disable_replication` at 1655-1656 calls `mirror_image_disable` and then `json.loads(volume.replication_driver_data)` with no guard, so retyping an imported volume off the replicated type, which is exactly what an operator does after a DR import to stop mirroring to the dead cloud, tears down mirroring and then raises; `retype` swallows that and fails later with a migration error, leaving `replication_status` enabled on an unmirrored image. Return `replication_driver_data` alongside `ENABLED`, and harden `_disable_replication` with `or \u0027{}\u0027` as the failover readers already do.","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":2328,"context_line":"        source_uuid \u003d volume_utils.extract_id_from_volume_name(rbd_name)"},{"line_number":2329,"context_line":"        if source_uuid:"},{"line_number":2330,"context_line":"            model_update[\u0027_name_id\u0027] \u003d source_uuid"},{"line_number":2331,"context_line":"        model_update[\u0027replication_status\u0027] \u003d ("},{"line_number":2332,"context_line":"            fields.ReplicationStatus.ENABLED)"},{"line_number":2333,"context_line":"        return model_update"},{"line_number":2334,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"eaba127d_e4e4bba9","line":2331,"in_reply_to":"6c3f09e9_a116ebf3","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":2330,"context_line":"            model_update[\u0027_name_id\u0027] \u003d source_uuid"},{"line_number":2331,"context_line":"        model_update[\u0027replication_status\u0027] \u003d ("},{"line_number":2332,"context_line":"            fields.ReplicationStatus.ENABLED)"},{"line_number":2333,"context_line":"        return model_update"},{"line_number":2334,"context_line":""},{"line_number":2335,"context_line":"    def _get_image_status(self, image_name):"},{"line_number":2336,"context_line":"        args \u003d [\u0027rbd\u0027, \u0027status\u0027,"}],"source_content_type":"text/x-python","patch_set":9,"id":"a669a667_da210dd2","line":2333,"updated":"2026-10-26 19:06:48.000000000","message":"`manage_existing` fails fast on a replication-plus-multiattach type via `_is_valid_type` and applies the type\u0027s back-end QoS through `_setup_volume`; `import_replica` does neither and asserts `ENABLED` without checking `mirror_image_get_info()`. An image imported onto a QoS type silently gets no QoS, and a document naming an unmirrored image yields a volume whose next `failover_host` errors it and its group. Reuse `_is_valid_type`, verify mirroring before returning `ENABLED`, and factor the QoS part of `_setup_volume` so it can be applied here.","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":2330,"context_line":"            model_update[\u0027_name_id\u0027] \u003d source_uuid"},{"line_number":2331,"context_line":"        model_update[\u0027replication_status\u0027] \u003d ("},{"line_number":2332,"context_line":"            fields.ReplicationStatus.ENABLED)"},{"line_number":2333,"context_line":"        return model_update"},{"line_number":2334,"context_line":""},{"line_number":2335,"context_line":"    def _get_image_status(self, image_name):"},{"line_number":2336,"context_line":"        args \u003d [\u0027rbd\u0027, \u0027status\u0027,"}],"source_content_type":"text/x-python","patch_set":9,"id":"a8898e3c_b2a7b09a","line":2333,"in_reply_to":"a669a667_da210dd2","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"b7253978b368dd2d50b37f309937178351358842"}],"cinder/volume/flows/manager/manage_existing.py":[{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":117,"context_line":"        self.db \u003d db"},{"line_number":118,"context_line":"        self.driver \u003d driver"},{"line_number":119,"context_line":""},{"line_number":120,"context_line":"    def execute(self, context, volume, manage_existing_ref, size,"},{"line_number":121,"context_line":"                source_cloud_id):"},{"line_number":122,"context_line":"        model_update \u003d self.driver.import_replica("},{"line_number":123,"context_line":"            volume, manage_existing_ref, source_cloud_id)"}],"source_content_type":"text/x-python","patch_set":9,"id":"1bdef936_e9960c37","line":120,"updated":"2026-10-26 19:06:48.000000000","message":"Now that `source_cloud_id` is only added to the store for the import variant (thanks, PS9 fixes `test_get_flow`), please add `test_get_flow_import_replica` asserting the flow name `volume_import_replica_manager`, that `ImportReplicaTask` is selected, and that the store carries the given `source_cloud_id`; and add `source_cloud_id` to `_verify_volume_flow_tasks.param_names`. Nothing tests the import variant of `get_flow` today.","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":117,"context_line":"        self.db \u003d db"},{"line_number":118,"context_line":"        self.driver \u003d driver"},{"line_number":119,"context_line":""},{"line_number":120,"context_line":"    def execute(self, context, volume, manage_existing_ref, size,"},{"line_number":121,"context_line":"                source_cloud_id):"},{"line_number":122,"context_line":"        model_update \u003d self.driver.import_replica("},{"line_number":123,"context_line":"            volume, manage_existing_ref, source_cloud_id)"}],"source_content_type":"text/x-python","patch_set":9,"id":"753d95db_f102398c","line":120,"in_reply_to":"1bdef936_e9960c37","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"b7253978b368dd2d50b37f309937178351358842"}],"cinder/volume/manager.py":[{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"35370d49fc9a242dd43c6eab0fee9596c7e82776","unresolved":false,"context_lines":[{"line_number":5557,"context_line":"                ctxt, vol_ref.id, glance_metadata)"},{"line_number":5558,"context_line":""},{"line_number":5559,"context_line":"        if strutils.bool_from_string(volume_properties.get(\u0027bootable\u0027,"},{"line_number":5560,"context_line":"                                                            False)):"},{"line_number":5561,"context_line":"            volume_utils.enable_bootable_flag(vol_ref)"},{"line_number":5562,"context_line":""},{"line_number":5563,"context_line":"        self._update_stats_for_managed(vol_ref)"}],"source_content_type":"text/x-python","patch_set":2,"id":"02ee11a8_ab168f8e","line":5560,"updated":"2026-08-18 20:03:21.000000000","message":"pep8: E127 continuation line over-indented for visual indent","commit_id":"5df57325110ed383d4141d222f4b564469b2bd6d"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"bde5a6571dcadc404fcfe444f8f022425a691c98","unresolved":false,"context_lines":[{"line_number":5556,"context_line":"                ctxt, vol_ref.id, glance_metadata)"},{"line_number":5557,"context_line":""},{"line_number":5558,"context_line":"        if strutils.bool_from_string(volume_properties.get(\u0027bootable\u0027,"},{"line_number":5559,"context_line":"                                                            False)):"},{"line_number":5560,"context_line":"            volume_utils.enable_bootable_flag(vol_ref)"},{"line_number":5561,"context_line":""},{"line_number":5562,"context_line":"        self._update_stats_for_managed(vol_ref)"}],"source_content_type":"text/x-python","patch_set":3,"id":"2179ed10_8f6cdb19","line":5559,"updated":"2026-08-20 00:23:16.000000000","message":"pep8: E127 continuation line over-indented for visual indent","commit_id":"c12da181319252a913c230664bdc2fc5177d8cec"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"5f448ed0181b3e695362ddc18115676f8159eb58","unresolved":false,"context_lines":[{"line_number":5556,"context_line":"                ctxt, vol_ref.id, glance_metadata)"},{"line_number":5557,"context_line":""},{"line_number":5558,"context_line":"        if strutils.bool_from_string(volume_properties.get(\u0027bootable\u0027,"},{"line_number":5559,"context_line":"                                                            False)):"},{"line_number":5560,"context_line":"            volume_utils.enable_bootable_flag(vol_ref)"},{"line_number":5561,"context_line":""},{"line_number":5562,"context_line":"        self._update_stats_for_managed(vol_ref)"}],"source_content_type":"text/x-python","patch_set":4,"id":"1886ca1e_f417ba04","line":5559,"updated":"2026-08-21 16:01:25.000000000","message":"pep8: E127 continuation line over-indented for visual indent","commit_id":"70810156d10fcddf30b1f7c6a2d5809aee5e7068"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"d0d9ad1652290ec9575b3ef013501a9144dbc6ae","unresolved":false,"context_lines":[{"line_number":5556,"context_line":"                ctxt, vol_ref.id, glance_metadata)"},{"line_number":5557,"context_line":""},{"line_number":5558,"context_line":"        if strutils.bool_from_string(volume_properties.get(\u0027bootable\u0027,"},{"line_number":5559,"context_line":"                                                            False)):"},{"line_number":5560,"context_line":"            volume_utils.enable_bootable_flag(vol_ref)"},{"line_number":5561,"context_line":""},{"line_number":5562,"context_line":"        self._update_stats_for_managed(vol_ref)"}],"source_content_type":"text/x-python","patch_set":5,"id":"63fd9d98_a6876c28","line":5559,"updated":"2026-08-25 06:32:26.000000000","message":"pep8: E127 continuation line over-indented for visual indent","commit_id":"38845cf60edbcfb79f3871ea171c32324b24f3d9"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"003f1925daa5164410b5fc771ac1ef6775bd914f","unresolved":false,"context_lines":[{"line_number":5558,"context_line":"                ctxt, vol_ref.id, glance_metadata)"},{"line_number":5559,"context_line":""},{"line_number":5560,"context_line":"        if strutils.bool_from_string(volume_properties.get(\u0027bootable\u0027,"},{"line_number":5561,"context_line":"                                                            False)):"},{"line_number":5562,"context_line":"            volume_utils.enable_bootable_flag(vol_ref)"},{"line_number":5563,"context_line":""},{"line_number":5564,"context_line":"        self._update_stats_for_managed(vol_ref)"}],"source_content_type":"text/x-python","patch_set":6,"id":"e93593be_3e3dfa5d","line":5561,"updated":"2026-09-15 11:52:42.000000000","message":"pep8: E127 continuation line over-indented for visual indent","commit_id":"a0fcff75930ce2ecb105d2e060762d5633c40539"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"7ec487ae8eed4d4212932518a1a6dbdc285f77a5","unresolved":true,"context_lines":[{"line_number":3303,"context_line":"                self.host,"},{"line_number":3304,"context_line":"                volume,"},{"line_number":3305,"context_line":"                ref,"},{"line_number":3306,"context_line":"                import_replica\u003dimport_replica,"},{"line_number":3307,"context_line":"            )"},{"line_number":3308,"context_line":"        except Exception:"},{"line_number":3309,"context_line":"            msg \u003d _(\"Failed to create manage_existing flow.\")"}],"source_content_type":"text/x-python","patch_set":7,"id":"cedbc575_4e6fd658","line":3306,"updated":"2026-10-14 18:31:25.000000000","message":"Adding `import_replica\u003dimport_replica` here changes the `get_flow` call signature that `test_manage_volume.test_run_manage_existing_flow_engine` and `..._exception` assert on (test_manage_volume.py:126, `assert_called_once_with` with the old positional args). Both fail on every Python in PS7; please update the assertions.","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":3303,"context_line":"                self.host,"},{"line_number":3304,"context_line":"                volume,"},{"line_number":3305,"context_line":"                ref,"},{"line_number":3306,"context_line":"                import_replica\u003dimport_replica,"},{"line_number":3307,"context_line":"            )"},{"line_number":3308,"context_line":"        except Exception:"},{"line_number":3309,"context_line":"            msg \u003d _(\"Failed to create manage_existing flow.\")"}],"source_content_type":"text/x-python","patch_set":7,"id":"1898dba7_286367eb","line":3306,"in_reply_to":"cedbc575_4e6fd658","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"7ec487ae8eed4d4212932518a1a6dbdc285f77a5","unresolved":true,"context_lines":[{"line_number":5500,"context_line":"        \"\"\"Export volume replica metadata for cross-OpenStack failover.\"\"\""},{"line_number":5501,"context_line":"        volume.refresh()"},{"line_number":5502,"context_line":"        volume_utils.require_driver_initialized(self.driver)"},{"line_number":5503,"context_line":""},{"line_number":5504,"context_line":"        vendor_metadata \u003d self.driver.export_replica(volume)"},{"line_number":5505,"context_line":""},{"line_number":5506,"context_line":"        admin_metadata \u003d {}"}],"source_content_type":"text/x-python","patch_set":7,"id":"f206128c_e15a9013","line":5503,"updated":"2026-10-14 18:31:25.000000000","message":"Every driver except RBD raises `NotImplementedError` here, and because this is an RPC `call` it surfaces as a 500 at the API. The manager already wraps `NotImplementedError` for the other optional driver features (eight places in this file). Please do the same and raise something the API can map to 400 or 501 with a \"driver does not support export_replica\" message.","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":5500,"context_line":"        \"\"\"Export volume replica metadata for cross-OpenStack failover.\"\"\""},{"line_number":5501,"context_line":"        volume.refresh()"},{"line_number":5502,"context_line":"        volume_utils.require_driver_initialized(self.driver)"},{"line_number":5503,"context_line":""},{"line_number":5504,"context_line":"        vendor_metadata \u003d self.driver.export_replica(volume)"},{"line_number":5505,"context_line":""},{"line_number":5506,"context_line":"        admin_metadata \u003d {}"}],"source_content_type":"text/x-python","patch_set":7,"id":"aed23693_74395721","line":5503,"in_reply_to":"b3401eed_992201b3","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":5500,"context_line":"        \"\"\"Export volume replica metadata for cross-OpenStack failover.\"\"\""},{"line_number":5501,"context_line":"        volume.refresh()"},{"line_number":5502,"context_line":"        volume_utils.require_driver_initialized(self.driver)"},{"line_number":5503,"context_line":""},{"line_number":5504,"context_line":"        vendor_metadata \u003d self.driver.export_replica(volume)"},{"line_number":5505,"context_line":""},{"line_number":5506,"context_line":"        admin_metadata \u003d {}"}],"source_content_type":"text/x-python","patch_set":7,"id":"b3401eed_992201b3","line":5503,"in_reply_to":"f206128c_e15a9013","updated":"2026-10-26 19:06:48.000000000","message":"Still needs to be reolved","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"7ec487ae8eed4d4212932518a1a6dbdc285f77a5","unresolved":true,"context_lines":[{"line_number":5531,"context_line":"        }"},{"line_number":5532,"context_line":""},{"line_number":5533,"context_line":"        if clear_existing:"},{"line_number":5534,"context_line":"            volume.destroy()"},{"line_number":5535,"context_line":""},{"line_number":5536,"context_line":"        return result"},{"line_number":5537,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"e43ccee4_1b2e44b4","line":5534,"updated":"2026-10-14 18:31:25.000000000","message":"`volume.destroy()` removes the row and nothing else. The delete path (manager.py:1053-1078) reserves negative `volumes`/`gigabytes` and commits; this does not, so the project\u0027s quota stays consumed for every exported volume. Nothing checks for snapshots (their rows will now reference a missing volume), attachments (the spec says operators must detach first, but the API does not enforce it), or `status` (only `replication_status` is checked, so an in-use, migrating or deleting volume passes).\n\nPlease either go through the real delete path, or refuse `clear_existing\u003dTrue` unless the volume is `available` with no snapshots and no attachments, and release quota explicitly. A unit test asserting quota is returned would be good.","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":5531,"context_line":"        }"},{"line_number":5532,"context_line":""},{"line_number":5533,"context_line":"        if clear_existing:"},{"line_number":5534,"context_line":"            volume.destroy()"},{"line_number":5535,"context_line":""},{"line_number":5536,"context_line":"        return result"},{"line_number":5537,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"7a7c64d8_9ce6bc7a","line":5534,"in_reply_to":"e43ccee4_1b2e44b4","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"7ec487ae8eed4d4212932518a1a6dbdc285f77a5","unresolved":true,"context_lines":[{"line_number":5549,"context_line":""},{"line_number":5550,"context_line":"        admin_metadata \u003d volume_properties.get(\u0027admin_metadata\u0027, {})"},{"line_number":5551,"context_line":"        if admin_metadata:"},{"line_number":5552,"context_line":"            self.db.volume_admin_metadata_update("},{"line_number":5553,"context_line":"                ctxt, vol_ref.id, admin_metadata, delete\u003dFalse)"},{"line_number":5554,"context_line":""},{"line_number":5555,"context_line":"        glance_metadata \u003d volume_properties.get(\u0027glance_metadata\u0027, {})"}],"source_content_type":"text/x-python","patch_set":7,"id":"76d73b41_e43fa1e7","line":5552,"updated":"2026-10-14 18:31:25.000000000","message":"Replaying the whole `admin_metadata` dict is risky: it carries `attached_mode` and `format`, so a detached import inherits the source\u0027s `attached_mode: rw`, and anything a driver stashed there is backend-specific. Suggest whitelisting `readonly` (the only operator-meaningful key; see `api_utils._visible_admin_metadata_keys`) or leaving admin metadata to the driver\u0027s `vendor_metadata`.","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":5549,"context_line":""},{"line_number":5550,"context_line":"        admin_metadata \u003d volume_properties.get(\u0027admin_metadata\u0027, {})"},{"line_number":5551,"context_line":"        if admin_metadata:"},{"line_number":5552,"context_line":"            self.db.volume_admin_metadata_update("},{"line_number":5553,"context_line":"                ctxt, vol_ref.id, admin_metadata, delete\u003dFalse)"},{"line_number":5554,"context_line":""},{"line_number":5555,"context_line":"        glance_metadata \u003d volume_properties.get(\u0027glance_metadata\u0027, {})"}],"source_content_type":"text/x-python","patch_set":7,"id":"ab823247_f1012e12","line":5552,"in_reply_to":"76d73b41_e43fa1e7","updated":"2026-10-26 19:06:48.000000000","message":"Three problems share this line, all beyond what my PS7 comment covered.\n\n1. **Order**. `export_replica is a synchronous `cctxt.call` with the default 60 second `rpc_response_timeout`. The document is built in memory, the row is destroyed, and only then is the document returned; nothing persists it. oslo.messaging does not cancel the handler on a client timeout (checked on the fake transport), so a driver that spends more than 60 seconds on best-effort teardown against a dead source array, which the docstring and spec invite, produces a 500 with no document, a destroyed row, and a 404 on retry. Do the destroy in `API.export_replica` after the call returns, through the real delete path with unmanage semantics, never `driver.delete_volume`. Separately, map `MessagingTimeout`, `DriverNotInitialized` and `VolumeBackendAPIException` in `_export_replica` to something other than a bare 500.\n2. **Cascade**. `volume.destroy()` soft-deletes every dependent row: snapshots, attachments, transfers, metadata. The API checks only `replication_status` and `encryption_key_id`, so a volume with live snapshots, an active attachment or a pending transfer passes. Snapshot quota is never released, no `snapshot.delete` notification is emitted, and the backend snapshots are left with no record on either cloud. Claim the volume with a `conditional_update` requiring `available` or `error`, not attached, no snapshots, and no active migration, raising `InvalidVolume` on zero rows; omit `group_id` from the expectation since the spec wants per-member export.\nBookkeeping. delete_volume\u0027s unmanage branch also emits unmanage.start/unmanage.end, decrements allocated_capacity_gb, publishes capabilities and cleans the volume lock files. None of that happens here, so the source backend over-reports allocation until restart and telemetry never sees the removal.\nAll three are the same restructuring my PS7 quota comment needs, so one rework covers C14 and this.","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":5549,"context_line":""},{"line_number":5550,"context_line":"        admin_metadata \u003d volume_properties.get(\u0027admin_metadata\u0027, {})"},{"line_number":5551,"context_line":"        if admin_metadata:"},{"line_number":5552,"context_line":"            self.db.volume_admin_metadata_update("},{"line_number":5553,"context_line":"                ctxt, vol_ref.id, admin_metadata, delete\u003dFalse)"},{"line_number":5554,"context_line":""},{"line_number":5555,"context_line":"        glance_metadata \u003d volume_properties.get(\u0027glance_metadata\u0027, {})"}],"source_content_type":"text/x-python","patch_set":7,"id":"0b80081b_1185e4aa","line":5552,"in_reply_to":"ab823247_f1012e12","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"7ec487ae8eed4d4212932518a1a6dbdc285f77a5","unresolved":true,"context_lines":[{"line_number":5554,"context_line":""},{"line_number":5555,"context_line":"        glance_metadata \u003d volume_properties.get(\u0027glance_metadata\u0027, {})"},{"line_number":5556,"context_line":"        if glance_metadata:"},{"line_number":5557,"context_line":"            self.db.volume_glance_metadata_bulk_create("},{"line_number":5558,"context_line":"                ctxt, vol_ref.id, glance_metadata)"},{"line_number":5559,"context_line":""},{"line_number":5560,"context_line":"        if strutils.bool_from_string("}],"source_content_type":"text/x-python","patch_set":7,"id":"6eddb0aa_288debb7","line":5557,"updated":"2026-10-14 18:31:25.000000000","message":"`glance_metadata` from the source cloud carries that cloud\u0027s `image_id`; replaying it unchanged and then setting bootable means the target cloud has a bootable volume pointing at an image it does not have. Either strip the id-bearing keys, or document that the operator must reconcile them.","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":5554,"context_line":""},{"line_number":5555,"context_line":"        glance_metadata \u003d volume_properties.get(\u0027glance_metadata\u0027, {})"},{"line_number":5556,"context_line":"        if glance_metadata:"},{"line_number":5557,"context_line":"            self.db.volume_glance_metadata_bulk_create("},{"line_number":5558,"context_line":"                ctxt, vol_ref.id, glance_metadata)"},{"line_number":5559,"context_line":""},{"line_number":5560,"context_line":"        if strutils.bool_from_string("}],"source_content_type":"text/x-python","patch_set":7,"id":"e2b9dafa_ebd60f0f","line":5557,"in_reply_to":"05b26b87_f917b344","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":5554,"context_line":""},{"line_number":5555,"context_line":"        glance_metadata \u003d volume_properties.get(\u0027glance_metadata\u0027, {})"},{"line_number":5556,"context_line":"        if glance_metadata:"},{"line_number":5557,"context_line":"            self.db.volume_glance_metadata_bulk_create("},{"line_number":5558,"context_line":"                ctxt, vol_ref.id, glance_metadata)"},{"line_number":5559,"context_line":""},{"line_number":5560,"context_line":"        if strutils.bool_from_string("}],"source_content_type":"text/x-python","patch_set":7,"id":"05b26b87_f917b344","line":5557,"in_reply_to":"6eddb0aa_288debb7","updated":"2026-10-26 19:06:48.000000000","message":"Still needs resolving","commit_id":"635574d9c5a29703e8b8c13e2521a5877b2f0657"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":5508,"context_line":"                        detail\u003d"},{"line_number":5509,"context_line":"                        message_field.Detail.IMAGE_FORMAT_UNACCEPTABLE)"},{"line_number":5510,"context_line":""},{"line_number":5511,"context_line":"    def export_replica(self, ctxt, volume, clear_existing):"},{"line_number":5512,"context_line":"        \"\"\"Export volume replica metadata for cross-OpenStack failover.\"\"\""},{"line_number":5513,"context_line":"        volume.refresh()"},{"line_number":5514,"context_line":"        volume_utils.require_driver_initialized(self.driver)"}],"source_content_type":"text/x-python","patch_set":9,"id":"56c20f69_19c9eaa7","line":5511,"updated":"2026-10-26 19:06:48.000000000","message":"Please add a test that calls `_export_replica` below 3.72 (the import side has one, the export side does not), and at `test_volume_actions.py:153` the second `mock_export.assert_not_called()` is a copy-paste duplicate of line 152.","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":5508,"context_line":"                        detail\u003d"},{"line_number":5509,"context_line":"                        message_field.Detail.IMAGE_FORMAT_UNACCEPTABLE)"},{"line_number":5510,"context_line":""},{"line_number":5511,"context_line":"    def export_replica(self, ctxt, volume, clear_existing):"},{"line_number":5512,"context_line":"        \"\"\"Export volume replica metadata for cross-OpenStack failover.\"\"\""},{"line_number":5513,"context_line":"        volume.refresh()"},{"line_number":5514,"context_line":"        volume_utils.require_driver_initialized(self.driver)"}],"source_content_type":"text/x-python","patch_set":9,"id":"daac9c75_94c427eb","line":5511,"in_reply_to":"56c20f69_19c9eaa7","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":5554,"context_line":"            \u0027volume_properties\u0027, {})"},{"line_number":5555,"context_line":""},{"line_number":5556,"context_line":"        vendor_metadata \u003d replication_metadata.get(\u0027vendor_metadata\u0027, {})"},{"line_number":5557,"context_line":"        ref \u003d self.driver.get_import_replica_ref("},{"line_number":5558,"context_line":"            vendor_metadata, source_cloud_id, source_volume_id)"},{"line_number":5559,"context_line":"        vol_ref \u003d self._run_manage_existing_flow_engine("},{"line_number":5560,"context_line":"            ctxt, volume, ref, import_replica\u003dTrue,"}],"source_content_type":"text/x-python","patch_set":9,"id":"9daee70e_a65abdae","line":5557,"updated":"2026-10-26 19:06:48.000000000","message":"`import_replica` has no `require_driver_initialized` (export has one at 5514), no try/except, and runs `get_import_replica_ref` before the flow, so the flow\u0027s `error_managing` revert does not cover it. The API has already returned 201 with the row in managing, and a cast drops the exception, so a failure here leaves a volume that nothing recovers short of reset-state or force-delete. It is reachable today: `\"vendor_metadata\": null` is schema-valid, `.get(\u0027vendor_metadata\u0027, {})` returns None for it, and RBD\u0027s `vendor_metadata.get(...)` raises `AttributeError`. Move the ref computation into the flow or wrap these pre-flow steps with `flow_common.error_out(volume, status\u003d\u0027error_managing\u0027)`.","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":5554,"context_line":"            \u0027volume_properties\u0027, {})"},{"line_number":5555,"context_line":""},{"line_number":5556,"context_line":"        vendor_metadata \u003d replication_metadata.get(\u0027vendor_metadata\u0027, {})"},{"line_number":5557,"context_line":"        ref \u003d self.driver.get_import_replica_ref("},{"line_number":5558,"context_line":"            vendor_metadata, source_cloud_id, source_volume_id)"},{"line_number":5559,"context_line":"        vol_ref \u003d self._run_manage_existing_flow_engine("},{"line_number":5560,"context_line":"            ctxt, volume, ref, import_replica\u003dTrue,"}],"source_content_type":"text/x-python","patch_set":9,"id":"448ff029_e23a2ab2","line":5557,"in_reply_to":"9daee70e_a65abdae","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":5556,"context_line":"        vendor_metadata \u003d replication_metadata.get(\u0027vendor_metadata\u0027, {})"},{"line_number":5557,"context_line":"        ref \u003d self.driver.get_import_replica_ref("},{"line_number":5558,"context_line":"            vendor_metadata, source_cloud_id, source_volume_id)"},{"line_number":5559,"context_line":"        vol_ref \u003d self._run_manage_existing_flow_engine("},{"line_number":5560,"context_line":"            ctxt, volume, ref, import_replica\u003dTrue,"},{"line_number":5561,"context_line":"            source_cloud_id\u003dsource_cloud_id)"},{"line_number":5562,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"3a0a15be_83b2f305","line":5559,"updated":"2026-10-26 19:06:48.000000000","message":"**Blocker.** Nothing refuses importing the same backend resource twice. `manage_existing` rejects a source-name whose UUID is already a volume via `check_already_managed_volume`, and RBD\u0027s rename makes a repeat manage fail. Import has neither guard: the API never looks up `source_volume_id`, this call runs the flow straight away, and RBD\u0027s `import_replica` deliberately does not rename and sets `_name_id` to the UUID in the image name on every call. `_name_id` has no uniqueness constraint and `Volume.name` is `volume_name_template % name_id`, so N imports of one document give N available volumes resolving to one image; RBD `delete_volume` removes `volume.name`. Three verifiers reproduced it: two imports of the same document, both available, same `_name_id`, and deleting one removes the image under the other. A load-balancer timeout and retry, a second operator, or the spec\u0027s failback re-import onto the cloud that still holds the original record all trigger it.\n\nFix in two places: in `API.import_replica`, before `volume.create()`, raise `InvalidVolume` when `check_already_managed_volume(source_volume_id)` is true or any non-deleted volume has `_name_id \u003d\u003d source_volume_id`; and in the manager, after `get_import_replica_ref`, check the UUID embedded in the ref against live volumes on this host by both id and `_name_id`, erroring to `error_managing` on a hit. Document in `BaseVD.import_replica` that drivers whose names do not derive from `source_volume_id` must do their own duplicate check.","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":5556,"context_line":"        vendor_metadata \u003d replication_metadata.get(\u0027vendor_metadata\u0027, {})"},{"line_number":5557,"context_line":"        ref \u003d self.driver.get_import_replica_ref("},{"line_number":5558,"context_line":"            vendor_metadata, source_cloud_id, source_volume_id)"},{"line_number":5559,"context_line":"        vol_ref \u003d self._run_manage_existing_flow_engine("},{"line_number":5560,"context_line":"            ctxt, volume, ref, import_replica\u003dTrue,"},{"line_number":5561,"context_line":"            source_cloud_id\u003dsource_cloud_id)"},{"line_number":5562,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"d67651a4_f5d28442","line":5559,"in_reply_to":"3a0a15be_83b2f305","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":5560,"context_line":"            ctxt, volume, ref, import_replica\u003dTrue,"},{"line_number":5561,"context_line":"            source_cloud_id\u003dsource_cloud_id)"},{"line_number":5562,"context_line":""},{"line_number":5563,"context_line":"        admin_metadata \u003d volume_properties.get(\u0027admin_metadata\u0027, {})"},{"line_number":5564,"context_line":"        if admin_metadata:"},{"line_number":5565,"context_line":"            self.db.volume_admin_metadata_update("},{"line_number":5566,"context_line":"                ctxt, vol_ref.id, admin_metadata, delete\u003dFalse)"}],"source_content_type":"text/x-python","patch_set":9,"id":"4fe1ab33_3591e7e5","line":5563,"updated":"2026-10-26 19:06:48.000000000","message":"The flow ends with `CreateVolumeOnFinishTask` setting `available` and emitting `import_replica.end`, and only then are admin metadata, glance metadata and bootable applied, unguarded, under the request context. A failure in any of them, for example a 300-character admin metadata value on MySQL or `enable_bootable_flag` re-raising `MetadataUpdateFailure`, leaves an available volume that is partially populated with only a cinder-volume traceback to show for it. Set bootable at creation in the API as `EntryCreateTask` does, and apply the metadata inside the flow before the finish task so a failure reverts to `error_managing`. Pass `ctxt.elevated()` to `volume_admin_metadata_update`.","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":5560,"context_line":"            ctxt, volume, ref, import_replica\u003dTrue,"},{"line_number":5561,"context_line":"            source_cloud_id\u003dsource_cloud_id)"},{"line_number":5562,"context_line":""},{"line_number":5563,"context_line":"        admin_metadata \u003d volume_properties.get(\u0027admin_metadata\u0027, {})"},{"line_number":5564,"context_line":"        if admin_metadata:"},{"line_number":5565,"context_line":"            self.db.volume_admin_metadata_update("},{"line_number":5566,"context_line":"                ctxt, vol_ref.id, admin_metadata, delete\u003dFalse)"}],"source_content_type":"text/x-python","patch_set":9,"id":"f695e81d_c49ee623","line":5563,"in_reply_to":"4fe1ab33_3591e7e5","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"62b58645c2b4297f774e6c861369ca581485f205","unresolved":false,"context_lines":[{"line_number":5583,"context_line":"                        existing_vol.name_id \u003d\u003d extracted_uuid):"},{"line_number":5584,"context_line":"                    reason \u003d (_(\"Backend resource %s is already managed as \""},{"line_number":5585,"context_line":"                                \"volume %s.\") %"},{"line_number":5586,"context_line":"                             (extracted_uuid, existing_vol.id))"},{"line_number":5587,"context_line":"                    flow_common.error_out(volume, reason\u003dreason,"},{"line_number":5588,"context_line":"                                          status\u003d\u0027error_managing\u0027)"},{"line_number":5589,"context_line":"                    msg \u003d _(\"Duplicate import: backend resource already \""}],"source_content_type":"text/x-python","patch_set":11,"id":"b1ec2b40_f060e06e","line":5586,"updated":"2026-10-29 19:52:24.000000000","message":"pep8: E128 continuation line under-indented for visual indent","commit_id":"5c0a9257a5879ee1f79730b8fd075e16563530e1"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"62b58645c2b4297f774e6c861369ca581485f205","unresolved":false,"context_lines":[{"line_number":5616,"context_line":"            except Exception:"},{"line_number":5617,"context_line":"                with excutils.save_and_reraise_exception():"},{"line_number":5618,"context_line":"                    reason \u003d (_(\"Failed to set admin metadata for imported \""},{"line_number":5619,"context_line":"                               \"volume %s.\") % vol_ref.id)"},{"line_number":5620,"context_line":"                    flow_common.error_out(vol_ref, reason\u003dreason,"},{"line_number":5621,"context_line":"                                          status\u003d\u0027error_managing\u0027)"},{"line_number":5622,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"3d512103_0f0567ff","line":5619,"updated":"2026-10-29 19:52:24.000000000","message":"pep8: E128 continuation line under-indented for visual indent","commit_id":"5c0a9257a5879ee1f79730b8fd075e16563530e1"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"62b58645c2b4297f774e6c861369ca581485f205","unresolved":false,"context_lines":[{"line_number":5634,"context_line":"            except Exception:"},{"line_number":5635,"context_line":"                with excutils.save_and_reraise_exception():"},{"line_number":5636,"context_line":"                    reason \u003d (_(\"Failed to set glance metadata for imported \""},{"line_number":5637,"context_line":"                               \"volume %s.\") % vol_ref.id)"},{"line_number":5638,"context_line":"                    flow_common.error_out(vol_ref, reason\u003dreason,"},{"line_number":5639,"context_line":"                                          status\u003d\u0027error_managing\u0027)"},{"line_number":5640,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"ea18d448_b305d294","line":5637,"updated":"2026-10-29 19:52:24.000000000","message":"pep8: E128 continuation line under-indented for visual indent","commit_id":"5c0a9257a5879ee1f79730b8fd075e16563530e1"}],"releasenotes/notes/cross-cloud-replication-export-import-ef39cca491954691.yaml":[{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"878cae5a69ed73cdbb9a7c12a0fd89e126fa9811","unresolved":true,"context_lines":[{"line_number":1,"context_line":"---"},{"line_number":2,"context_line":"features:"},{"line_number":3,"context_line":"  - |"},{"line_number":4,"context_line":"    Added microversion 3.72, which adds the ``export_replica`` volume"},{"line_number":5,"context_line":"    action and the ``import_replica`` volume API for moving a"},{"line_number":6,"context_line":"    failed-over replicated volume\u0027s data and metadata to a volume in a"},{"line_number":7,"context_line":"    different OpenStack deployment. Both actions require driver"}],"source_content_type":"text/x-yaml","patch_set":9,"id":"8090beda_2c738c32","line":4,"updated":"2026-10-26 19:06:48.000000000","message":"The note never mentions `clear_existing`, the one destructive option this change adds, and it is also the only operator-facing text since there is no api-ref yet. One or two sentences: it deletes the source Cinder record once the document has been obtained, volumes should be detached first or Nova block device mappings reconciled afterwards, per the spec.","commit_id":"b7253978b368dd2d50b37f309937178351358842"},{"author":{"_account_id":27615,"name":"Rajat Dhasmana","email":"rajatdhasmana@gmail.com","username":"whoami-rajat"},"change_message_id":"b6325b242ea3e6f08df1ce8363749fac77cad391","unresolved":false,"context_lines":[{"line_number":1,"context_line":"---"},{"line_number":2,"context_line":"features:"},{"line_number":3,"context_line":"  - |"},{"line_number":4,"context_line":"    Added microversion 3.72, which adds the ``export_replica`` volume"},{"line_number":5,"context_line":"    action and the ``import_replica`` volume API for moving a"},{"line_number":6,"context_line":"    failed-over replicated volume\u0027s data and metadata to a volume in a"},{"line_number":7,"context_line":"    different OpenStack deployment. Both actions require driver"}],"source_content_type":"text/x-yaml","patch_set":9,"id":"c13fd934_132fdd68","line":4,"in_reply_to":"8090beda_2c738c32","updated":"2026-10-29 21:15:04.000000000","message":"Done","commit_id":"b7253978b368dd2d50b37f309937178351358842"}]}
