)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"e48f7ea430e810264e00d5bf6613a76718ff3602","unresolved":true,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Add Glance preferred stores support"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Cinder can now send the configured ordered Glance store preferences"},{"line_number":10,"context_line":"to Glance when downloading an image. This helps deployments choose"},{"line_number":11,"context_line":"a local or co-located image copy."},{"line_number":12,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"6fa946ce_e40f2c8a","line":9,"updated":"2026-10-20 19:20:16.000000000","message":"Nit: worth one line noting the `python-glanceclient\u003e\u003d4.12.0` bump and why (first release whose `images.data()` accepts `prefer`), so the requirements change is explained in the log rather than only in the review.","commit_id":"8a32be5c38d841f2f4fd1bb36993483ab44bd486"},{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"3d058bf09132b2e49adf1356f585a35992b8b258","unresolved":false,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Add Glance preferred stores support"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Cinder can now send the configured ordered Glance store preferences"},{"line_number":10,"context_line":"to Glance when downloading an image. This helps deployments choose"},{"line_number":11,"context_line":"a local or co-located image copy."},{"line_number":12,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"61ec1597_f0df0020","line":9,"in_reply_to":"6fa946ce_e40f2c8a","updated":"2026-11-06 16:43:40.000000000","message":"Acknowledged","commit_id":"8a32be5c38d841f2f4fd1bb36993483ab44bd486"}],"/PATCHSET_LEVEL":[{"author":{"_account_id":4523,"name":"Eric Harney","email":"eharney@redhat.com","username":"eharney"},"change_message_id":"aec7cb39c7ac2a0077330717dd8d82ec4612a9fb","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"5e4fc8cb_48160bce","updated":"2026-10-20 15:31:08.000000000","message":"Needs to bump glanceclient version in requirements.txt to 4.12.0+","commit_id":"ea6c6ec98feba08d3276b8a9d31f3d98a61f8df2"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"e00c7ba97fcbe46ab347216a598bc1a28fdfafef","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"7e2efa4e_442e8347","updated":"2026-10-20 16:13:48.000000000","message":"Two more things inline: the new \"functional\" test is a unit test in the wrong directory and duplicates the unit case, and the help text / reno should spell out the version dependency and what a misconfigured store name does to every image download. -1 only for the requirements bump; +1 once that and the test relocation are in.","commit_id":"ea6c6ec98feba08d3276b8a9d31f3d98a61f8df2"},{"author":{"_account_id":5314,"name":"Brian Rosmaita","email":"rosmaita.fossdev@gmail.com","username":"brian-rosmaita"},"change_message_id":"36b8c76f81e0642e1bf03c931df9a5994c1a423b","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":2,"id":"684452ba_8469a95b","updated":"2026-11-06 16:10:42.000000000","message":"Code and tests look fine; see inline for comments about the help text and release note.","commit_id":"8a32be5c38d841f2f4fd1bb36993483ab44bd486"},{"author":{"_account_id":35075,"name":"Alexander Deiter","email":"adeiter@infinidat.com","username":"adeiter"},"change_message_id":"869e1841679e609c04a9bfc9fb67b2effab2c7af","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"7feccbd5_1e8852f5","updated":"2026-11-06 14:35:38.000000000","message":"Looks good to me - thank you!","commit_id":"8a32be5c38d841f2f4fd1bb36993483ab44bd486"},{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"4cb1b37b8652686e2254b713b6824d038e8331b2","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"d2a5b9d0_d397b4ae","updated":"2026-10-20 18:04:08.000000000","message":"Thank you Eric and Simon, made changes as per your suggestion!!","commit_id":"8a32be5c38d841f2f4fd1bb36993483ab44bd486"},{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"3d058bf09132b2e49adf1356f585a35992b8b258","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"3d0761cc_9d1cf0c0","updated":"2026-11-06 16:43:40.000000000","message":"Thank you all for reviews, Brian and Simon made changes as per your suggestions.","commit_id":"8a32be5c38d841f2f4fd1bb36993483ab44bd486"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"e48f7ea430e810264e00d5bf6613a76718ff3602","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"79593462_4059bfb9","updated":"2026-10-20 19:20:16.000000000","message":"Two wording nits inline that can ride along if there is a PS3 for any other reason.","commit_id":"8a32be5c38d841f2f4fd1bb36993483ab44bd486"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"fa175ea3a6a413ccb796a5215bf4e90506a95b19","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"11bbc5e3_ca2793d7","updated":"2026-11-06 17:24:42.000000000","message":"Everything done, so +1 for this - one comment inline though.","commit_id":"8a67dc43c59fae96c0dcdc88d6c405065a8dd616"},{"author":{"_account_id":5314,"name":"Brian Rosmaita","email":"rosmaita.fossdev@gmail.com","username":"brian-rosmaita"},"change_message_id":"b4b6d5646cd03802ffc78f310177ed991b472147","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"5b442bee_93865f11","updated":"2026-11-06 20:46:45.000000000","message":"Revisions LGTM.","commit_id":"8a67dc43c59fae96c0dcdc88d6c405065a8dd616"}],"cinder/common/config.py":[{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"e00c7ba97fcbe46ab347216a598bc1a28fdfafef","unresolved":true,"context_lines":[{"line_number":202,"context_line":"                     \u0027downloading an image. The stores are tried in the \u0027"},{"line_number":203,"context_line":"                     \u0027order they are listed. If none of the preferred \u0027"},{"line_number":204,"context_line":"                     \u0027stores has the image, Glance selects a store using \u0027"},{"line_number":205,"context_line":"                     \u0027its own configuration. This option requires Glance \u0027"},{"line_number":206,"context_line":"                     \u0027API support for the ``prefer`` image data query \u0027"},{"line_number":207,"context_line":"                     \u0027parameter and configured multi-store backends.\u0027),"},{"line_number":208,"context_line":"]"}],"source_content_type":"text/x-python","patch_set":1,"id":"04296d03_83c9c799","line":205,"updated":"2026-10-20 16:13:48.000000000","message":"Two things worth saying here that operators will otherwise learn the hard way:\n\n 1. Version dependency, concretely: Glance 2026.2 (Hibiscus) or later and python-glanceclient 4.12.0 or later. On an older Glance the query parameter is silently ignored and the option does nothing, which is fine but should be stated rather than \"requires Glance API support\".\n  2. Failure mode: Glance returns 400 when multi-store is not enabled or when any listed store is not in its `enabled_backends`. Cinder maps that to `Invalid`, so one typo in this list breaks every create-volume-from-image and every image-cache seed, per request, with no startup check. Please say so.\n\nOptionally, note that Glance does not apply `prefer` when its image cache middleware serves the download, and that Cinder\u0027s `allowed_direct_url_schemes` file path bypasses the client call entirely.","commit_id":"ea6c6ec98feba08d3276b8a9d31f3d98a61f8df2"},{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"4cb1b37b8652686e2254b713b6824d038e8331b2","unresolved":false,"context_lines":[{"line_number":202,"context_line":"                     \u0027downloading an image. The stores are tried in the \u0027"},{"line_number":203,"context_line":"                     \u0027order they are listed. If none of the preferred \u0027"},{"line_number":204,"context_line":"                     \u0027stores has the image, Glance selects a store using \u0027"},{"line_number":205,"context_line":"                     \u0027its own configuration. This option requires Glance \u0027"},{"line_number":206,"context_line":"                     \u0027API support for the ``prefer`` image data query \u0027"},{"line_number":207,"context_line":"                     \u0027parameter and configured multi-store backends.\u0027),"},{"line_number":208,"context_line":"]"}],"source_content_type":"text/x-python","patch_set":1,"id":"7f7f4f78_8377ada6","line":205,"in_reply_to":"04296d03_83c9c799","updated":"2026-10-20 18:04:08.000000000","message":"Done","commit_id":"ea6c6ec98feba08d3276b8a9d31f3d98a61f8df2"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"e48f7ea430e810264e00d5bf6613a76718ff3602","unresolved":true,"context_lines":[{"line_number":209,"context_line":"                     \u0027silently ignored and this option has no effect. \u0027"},{"line_number":210,"context_line":"                     \u0027Glance returns HTTP 400 if multi-store is not enabled \u0027"},{"line_number":211,"context_line":"                     \u0027or if a listed store is not in its \u0027"},{"line_number":212,"context_line":"                     \u0027``enabled_backends``; Cinder translates that response \u0027"},{"line_number":213,"context_line":"                     \u0027to ``Invalid``. There is no startup validation, so a \u0027"},{"line_number":214,"context_line":"                     \u0027typo in this list fails each image download request. \u0027"},{"line_number":215,"context_line":"                     \u0027Glance does not apply ``prefer`` when its image cache \u0027"}],"source_content_type":"text/x-python","patch_set":2,"id":"533c0959_e7d3d09e","line":212,"updated":"2026-10-20 19:20:16.000000000","message":"Nit: \"Cinder translates that response to `Invalid`\" names an internal exception class that an operator never sees. Suggest \"the image download fails with a 400 error\" here and the matching sentence in the reno.","commit_id":"8a32be5c38d841f2f4fd1bb36993483ab44bd486"},{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"3d058bf09132b2e49adf1356f585a35992b8b258","unresolved":false,"context_lines":[{"line_number":209,"context_line":"                     \u0027silently ignored and this option has no effect. \u0027"},{"line_number":210,"context_line":"                     \u0027Glance returns HTTP 400 if multi-store is not enabled \u0027"},{"line_number":211,"context_line":"                     \u0027or if a listed store is not in its \u0027"},{"line_number":212,"context_line":"                     \u0027``enabled_backends``; Cinder translates that response \u0027"},{"line_number":213,"context_line":"                     \u0027to ``Invalid``. There is no startup validation, so a \u0027"},{"line_number":214,"context_line":"                     \u0027typo in this list fails each image download request. \u0027"},{"line_number":215,"context_line":"                     \u0027Glance does not apply ``prefer`` when its image cache \u0027"}],"source_content_type":"text/x-python","patch_set":2,"id":"b8d81664_a655a651","line":212,"in_reply_to":"4ce7d628_c7c482a8","updated":"2026-11-06 16:43:40.000000000","message":"Acknowledged","commit_id":"8a32be5c38d841f2f4fd1bb36993483ab44bd486"},{"author":{"_account_id":5314,"name":"Brian Rosmaita","email":"rosmaita.fossdev@gmail.com","username":"brian-rosmaita"},"change_message_id":"36b8c76f81e0642e1bf03c931df9a5994c1a423b","unresolved":true,"context_lines":[{"line_number":209,"context_line":"                     \u0027silently ignored and this option has no effect. \u0027"},{"line_number":210,"context_line":"                     \u0027Glance returns HTTP 400 if multi-store is not enabled \u0027"},{"line_number":211,"context_line":"                     \u0027or if a listed store is not in its \u0027"},{"line_number":212,"context_line":"                     \u0027``enabled_backends``; Cinder translates that response \u0027"},{"line_number":213,"context_line":"                     \u0027to ``Invalid``. There is no startup validation, so a \u0027"},{"line_number":214,"context_line":"                     \u0027typo in this list fails each image download request. \u0027"},{"line_number":215,"context_line":"                     \u0027Glance does not apply ``prefer`` when its image cache \u0027"}],"source_content_type":"text/x-python","patch_set":2,"id":"4ce7d628_c7c482a8","line":212,"in_reply_to":"533c0959_e7d3d09e","updated":"2026-11-06 16:10:42.000000000","message":"I agree with Simon; the operator should see the 400 from glance in the logs, so it would be better to focus on that.  (From the end user perspective, by the time this happens, I believe that the volume-create has returned a 202 and what\u0027s going to happen is that the volume will go to error.)","commit_id":"8a32be5c38d841f2f4fd1bb36993483ab44bd486"},{"author":{"_account_id":5314,"name":"Brian Rosmaita","email":"rosmaita.fossdev@gmail.com","username":"brian-rosmaita"},"change_message_id":"36b8c76f81e0642e1bf03c931df9a5994c1a423b","unresolved":true,"context_lines":[{"line_number":210,"context_line":"                     \u0027Glance returns HTTP 400 if multi-store is not enabled \u0027"},{"line_number":211,"context_line":"                     \u0027or if a listed store is not in its \u0027"},{"line_number":212,"context_line":"                     \u0027``enabled_backends``; Cinder translates that response \u0027"},{"line_number":213,"context_line":"                     \u0027to ``Invalid``. There is no startup validation, so a \u0027"},{"line_number":214,"context_line":"                     \u0027typo in this list fails each image download request. \u0027"},{"line_number":215,"context_line":"                     \u0027Glance does not apply ``prefer`` when its image cache \u0027"},{"line_number":216,"context_line":"                     \u0027middleware serves the download. If \u0027"},{"line_number":217,"context_line":"                     \u0027``allowed_direct_url_schemes`` causes Cinder to use a \u0027"}],"source_content_type":"text/x-python","patch_set":2,"id":"71ab041e_1e4f1ff7","line":214,"range":{"start_line":213,"start_character":38,"end_line":214,"end_character":75},"updated":"2026-11-06 16:10:42.000000000","message":"This is a really important point; I think it should be the second sentence in the help text.","commit_id":"8a32be5c38d841f2f4fd1bb36993483ab44bd486"},{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"3d058bf09132b2e49adf1356f585a35992b8b258","unresolved":false,"context_lines":[{"line_number":210,"context_line":"                     \u0027Glance returns HTTP 400 if multi-store is not enabled \u0027"},{"line_number":211,"context_line":"                     \u0027or if a listed store is not in its \u0027"},{"line_number":212,"context_line":"                     \u0027``enabled_backends``; Cinder translates that response \u0027"},{"line_number":213,"context_line":"                     \u0027to ``Invalid``. There is no startup validation, so a \u0027"},{"line_number":214,"context_line":"                     \u0027typo in this list fails each image download request. \u0027"},{"line_number":215,"context_line":"                     \u0027Glance does not apply ``prefer`` when its image cache \u0027"},{"line_number":216,"context_line":"                     \u0027middleware serves the download. If \u0027"},{"line_number":217,"context_line":"                     \u0027``allowed_direct_url_schemes`` causes Cinder to use a \u0027"}],"source_content_type":"text/x-python","patch_set":2,"id":"46210b96_a4371ab0","line":214,"range":{"start_line":213,"start_character":38,"end_line":214,"end_character":75},"in_reply_to":"71ab041e_1e4f1ff7","updated":"2026-11-06 16:43:40.000000000","message":"Acknowledged","commit_id":"8a32be5c38d841f2f4fd1bb36993483ab44bd486"}],"cinder/image/glance.py":[{"author":{"_account_id":4523,"name":"Eric Harney","email":"eharney@redhat.com","username":"eharney"},"change_message_id":"aec7cb39c7ac2a0077330717dd8d82ec4612a9fb","unresolved":true,"context_lines":[{"line_number":506,"context_line":"                    return"},{"line_number":507,"context_line":""},{"line_number":508,"context_line":"        try:"},{"line_number":509,"context_line":"            if CONF.glance_preferred_stores:"},{"line_number":510,"context_line":"                image_chunks \u003d self._client.call("},{"line_number":511,"context_line":"                    context, \u0027data\u0027, image_id,"},{"line_number":512,"context_line":"                    prefer\u003dCONF.glance_preferred_stores)"}],"source_content_type":"text/x-python","patch_set":1,"id":"72e58002_75cb4043","line":509,"range":{"start_line":509,"start_character":12,"end_line":509,"end_character":44},"updated":"2026-10-20 15:31:08.000000000","message":"I think you can just unconditionally pass prefer\u003dCONF.glance_perferred_stores since the client does an \"if prefer:\" check for this field anyway.  No need for if/else here.","commit_id":"ea6c6ec98feba08d3276b8a9d31f3d98a61f8df2"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"e00c7ba97fcbe46ab347216a598bc1a28fdfafef","unresolved":true,"context_lines":[{"line_number":506,"context_line":"                    return"},{"line_number":507,"context_line":""},{"line_number":508,"context_line":"        try:"},{"line_number":509,"context_line":"            if CONF.glance_preferred_stores:"},{"line_number":510,"context_line":"                image_chunks \u003d self._client.call("},{"line_number":511,"context_line":"                    context, \u0027data\u0027, image_id,"},{"line_number":512,"context_line":"                    prefer\u003dCONF.glance_preferred_stores)"}],"source_content_type":"text/x-python","patch_set":1,"id":"d65b59a3_0bd474ed","line":509,"range":{"start_line":509,"start_character":12,"end_line":509,"end_character":44},"in_reply_to":"72e58002_75cb4043","updated":"2026-10-20 16:13:48.000000000","message":"I agree with Eric here","commit_id":"ea6c6ec98feba08d3276b8a9d31f3d98a61f8df2"},{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"760e162d891b6c416c9da9cc7b42155ae15010c2","unresolved":false,"context_lines":[{"line_number":506,"context_line":"                    return"},{"line_number":507,"context_line":""},{"line_number":508,"context_line":"        try:"},{"line_number":509,"context_line":"            if CONF.glance_preferred_stores:"},{"line_number":510,"context_line":"                image_chunks \u003d self._client.call("},{"line_number":511,"context_line":"                    context, \u0027data\u0027, image_id,"},{"line_number":512,"context_line":"                    prefer\u003dCONF.glance_preferred_stores)"}],"source_content_type":"text/x-python","patch_set":1,"id":"af1d30cf_374d281d","line":509,"range":{"start_line":509,"start_character":12,"end_line":509,"end_character":44},"in_reply_to":"72e58002_75cb4043","updated":"2026-10-20 17:25:56.000000000","message":"I have done this to keep existing unit test changes minimal, but if you guys are insisting then I will make the change.","commit_id":"ea6c6ec98feba08d3276b8a9d31f3d98a61f8df2"},{"author":{"_account_id":36171,"name":"jayaanand borra","display_name":"jayaanand borra","email":"jayaanand.borra@netapp.com","username":"jayaanan","status":"netapp"},"change_message_id":"5eb308bc66c6e906515970cefb972c6d60015bfa","unresolved":true,"context_lines":[{"line_number":506,"context_line":"                    return"},{"line_number":507,"context_line":""},{"line_number":508,"context_line":"        try:"},{"line_number":509,"context_line":"            image_chunks \u003d self._client.call("},{"line_number":510,"context_line":"                context, \u0027data\u0027, image_id,"},{"line_number":511,"context_line":"                prefer\u003dCONF.glance_preferred_stores)"},{"line_number":512,"context_line":"        except Exception:"}],"source_content_type":"text/x-python","patch_set":2,"id":"5e93edba_b5d27e40","line":509,"updated":"2026-11-06 14:34:08.000000000","message":"With these changes... This section may become right choke point with clone_image, cinder:// clone,\nimage-volume cache hits.","commit_id":"8a32be5c38d841f2f4fd1bb36993483ab44bd486"},{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"3d058bf09132b2e49adf1356f585a35992b8b258","unresolved":false,"context_lines":[{"line_number":506,"context_line":"                    return"},{"line_number":507,"context_line":""},{"line_number":508,"context_line":"        try:"},{"line_number":509,"context_line":"            image_chunks \u003d self._client.call("},{"line_number":510,"context_line":"                context, \u0027data\u0027, image_id,"},{"line_number":511,"context_line":"                prefer\u003dCONF.glance_preferred_stores)"},{"line_number":512,"context_line":"        except Exception:"}],"source_content_type":"text/x-python","patch_set":2,"id":"60faead0_5cf4124f","line":509,"in_reply_to":"5e93edba_b5d27e40","updated":"2026-11-06 16:43:40.000000000","message":"Acknowledged","commit_id":"8a32be5c38d841f2f4fd1bb36993483ab44bd486"},{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"fa175ea3a6a413ccb796a5215bf4e90506a95b19","unresolved":false,"context_lines":[{"line_number":506,"context_line":"                    return"},{"line_number":507,"context_line":""},{"line_number":508,"context_line":"        try:"},{"line_number":509,"context_line":"            image_chunks \u003d self._client.call("},{"line_number":510,"context_line":"                context, \u0027data\u0027, image_id,"},{"line_number":511,"context_line":"                prefer\u003dCONF.glance_preferred_stores)"},{"line_number":512,"context_line":"        except Exception:"}],"source_content_type":"text/x-python","patch_set":3,"id":"7eef030f_20e0b777","line":509,"updated":"2026-11-06 17:24:42.000000000","message":"This call is only reached when Cinder actually streams image data from Glance. `clone_image()`, a `cinder://` location and an image-volume cache hit all return before `download()` is called, and a `file://` direct URL returns at the `shutil.copyfileobj` branch above, so none of those paths pass through here and the preference adds no work to them. Marking resolved unless you had a different path in mind.","commit_id":"8a67dc43c59fae96c0dcdc88d6c405065a8dd616"}],"cinder/tests/functional/test_glance.py":[{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"e00c7ba97fcbe46ab347216a598bc1a28fdfafef","unresolved":true,"context_lines":[{"line_number":22,"context_line":"from cinder.tests.unit import test"},{"line_number":23,"context_line":""},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"class GlancePreferredStoresTest(test.TestCase):"},{"line_number":26,"context_line":"    def setUp(self):"},{"line_number":27,"context_line":"        super(GlancePreferredStoresTest, self).setUp()"},{"line_number":28,"context_line":"        self.context \u003d context.RequestContext(\u0027fake\u0027, \u0027fake\u0027)"}],"source_content_type":"text/x-python","patch_set":1,"id":"a0134bee_358f07c0","line":25,"updated":"2026-10-20 16:13:48.000000000","message":"This is a unit test, not a functional test: it inherits `cinder.tests.unit.test.TestCase`, mocks `_create_glance_client` at line 35, and uses none of `functional_helpers._FunctionalTestBase`. `test_download_with_preferred_stores` at line 45 also duplicates the case added to `cinder/tests/unit/image/test_glance.py:947`. Please move `test_download_without_preferred_stores` into the unit module next to the existing one and drop this file. (Both pass locally and flake8 is clean, so this is placement only.)","commit_id":"ea6c6ec98feba08d3276b8a9d31f3d98a61f8df2"},{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"760e162d891b6c416c9da9cc7b42155ae15010c2","unresolved":false,"context_lines":[{"line_number":22,"context_line":"from cinder.tests.unit import test"},{"line_number":23,"context_line":""},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"class GlancePreferredStoresTest(test.TestCase):"},{"line_number":26,"context_line":"    def setUp(self):"},{"line_number":27,"context_line":"        super(GlancePreferredStoresTest, self).setUp()"},{"line_number":28,"context_line":"        self.context \u003d context.RequestContext(\u0027fake\u0027, \u0027fake\u0027)"}],"source_content_type":"text/x-python","patch_set":1,"id":"6a06f430_0e0361ce","line":25,"in_reply_to":"a0134bee_358f07c0","updated":"2026-10-20 17:25:56.000000000","message":"Acknowledged","commit_id":"ea6c6ec98feba08d3276b8a9d31f3d98a61f8df2"}],"cinder/tests/unit/image/test_glance.py":[{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"e00c7ba97fcbe46ab347216a598bc1a28fdfafef","unresolved":true,"context_lines":[{"line_number":954,"context_line":""},{"line_number":955,"context_line":"        service.download(self.context, image_id, writer)"},{"line_number":956,"context_line":""},{"line_number":957,"context_line":"        client.call.assert_called_once_with("},{"line_number":958,"context_line":"            self.context, \u0027data\u0027, image_id,"},{"line_number":959,"context_line":"            prefer\u003d[\u0027local-store\u0027, \u0027regional-store\u0027])"},{"line_number":960,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"b83f2a91_cc6e8535","line":957,"updated":"2026-10-20 16:13:48.000000000","message":"Once `prefer\u003d` is passed unconditionally, add the companion case asserting `prefer\u003d[]` when the option is unset, replacing the \"without\" case from the functional file.","commit_id":"ea6c6ec98feba08d3276b8a9d31f3d98a61f8df2"},{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"760e162d891b6c416c9da9cc7b42155ae15010c2","unresolved":false,"context_lines":[{"line_number":954,"context_line":""},{"line_number":955,"context_line":"        service.download(self.context, image_id, writer)"},{"line_number":956,"context_line":""},{"line_number":957,"context_line":"        client.call.assert_called_once_with("},{"line_number":958,"context_line":"            self.context, \u0027data\u0027, image_id,"},{"line_number":959,"context_line":"            prefer\u003d[\u0027local-store\u0027, \u0027regional-store\u0027])"},{"line_number":960,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"8f6127ca_3394152d","line":957,"in_reply_to":"b83f2a91_cc6e8535","updated":"2026-10-20 17:25:56.000000000","message":"Acknowledged","commit_id":"ea6c6ec98feba08d3276b8a9d31f3d98a61f8df2"}],"releasenotes/notes/glance-preferred-stores-0b7d24d1a8c94e6f.yaml":[{"author":{"_account_id":13425,"name":"Simon Dodsley","email":"simon@everpuredata.com","username":"sdodsley"},"change_message_id":"e00c7ba97fcbe46ab347216a598bc1a28fdfafef","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":"    Adds a new ``glance_preferred_stores`` configuration option. The option"},{"line_number":5,"context_line":"    is an ordered list of Glance store identifiers that Cinder passes to"},{"line_number":6,"context_line":"    Glance when downloading an image, allowing deployments with replicated"},{"line_number":7,"context_line":"    images to prefer a local or co-located store."}],"source_content_type":"text/x-yaml","patch_set":1,"id":"73ad7816_3ac938e7","line":4,"updated":"2026-10-20 16:13:48.000000000","message":"Please add the dependency in the reno as well: requires Glance 2026.2 or later with multi-store enabled and python-glanceclient 4.12.0 or later; on older Glance the option has no effect. Deployers read renos, not option help, when planning an upgrade.","commit_id":"ea6c6ec98feba08d3276b8a9d31f3d98a61f8df2"},{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"760e162d891b6c416c9da9cc7b42155ae15010c2","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":"    Adds a new ``glance_preferred_stores`` configuration option. The option"},{"line_number":5,"context_line":"    is an ordered list of Glance store identifiers that Cinder passes to"},{"line_number":6,"context_line":"    Glance when downloading an image, allowing deployments with replicated"},{"line_number":7,"context_line":"    images to prefer a local or co-located store."}],"source_content_type":"text/x-yaml","patch_set":1,"id":"2efe96a9_1f46d101","line":4,"in_reply_to":"73ad7816_3ac938e7","updated":"2026-10-20 17:25:56.000000000","message":"Acknowledged","commit_id":"ea6c6ec98feba08d3276b8a9d31f3d98a61f8df2"},{"author":{"_account_id":5314,"name":"Brian Rosmaita","email":"rosmaita.fossdev@gmail.com","username":"brian-rosmaita"},"change_message_id":"36b8c76f81e0642e1bf03c931df9a5994c1a423b","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":2,"id":"e9c65ac2_ced5f38c","line":16,"updated":"2026-11-06 16:10:42.000000000","message":"I suggest rewriting the note like this:\n\n```\n  - |\n    Adds a new ``glance_preferred_stores`` configuration option. The option\n    is an ordered list of Glance store identifiers that Cinder passes to\n    Glance when downloading an image, allowing deployments with replicated\n    images to prefer a local or co-located store.\n    \n    This feature requires Glance 2026.2 (Hibiscus) or later with multi-store\n    enabled and python-glanceclient 4.12.0 or later. On an older Glance\n    deployment, the ``prefer`` query parameter is silently ignored and the\n    option has no effect.\n\n    Troubleshooting:\n\n    * Glance rejects the request with HTTP 400 if multi-store is not enabled\n      or if a configured store is not in its ``enabled_backends``.  So note\n      that a typo in this list will cause all volume creation from an image\n      requests to fail.\n\n    * Glance does not apply the preference when its image cache middleware\n      serves the download, so if your cloud is so configured, this option\n      will have no effect.\n\n    * Direct file downloads, when the ``allowed_direct_url_schemes`` option\n      has been configured, completely bypass the Glance client, and hence\n      the ``glance_preferred_stores`` option will have no effect on their\n      download source.\n```","commit_id":"8a32be5c38d841f2f4fd1bb36993483ab44bd486"},{"author":{"_account_id":9303,"name":"Abhishek Kekane","email":"akekane@redhat.com","username":"abhishekkekane"},"change_message_id":"3d058bf09132b2e49adf1356f585a35992b8b258","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"752f7cd6_765bcc29","line":16,"in_reply_to":"e9c65ac2_ced5f38c","updated":"2026-11-06 16:43:40.000000000","message":"Acknowledged","commit_id":"8a32be5c38d841f2f4fd1bb36993483ab44bd486"}]}
