)]}'
{"id":"openstack%2Foslo.messaging~993312","triplet_id":"openstack%2Foslo.messaging~master~I6b2c89ee3f33d4be601b7ef001bdc7b7e39cdb9d","project":"openstack/oslo.messaging","branch":"master","topic":"bp/oslo-http-driver","attention_set":{"9816":{"account":{"_account_id":9816,"name":"Takashi Kajinami","email":"kajinamit@oss.nttdata.com","username":"kajinamit"},"last_update":"2026-06-15 15:56:31.000000000","reason":"\u003cGERRIT_ACCOUNT_10273\u003e replied on the change","reason_account":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"}},"33451":{"account":{"_account_id":33451,"name":"Yushiro Furukawa","display_name":"Yushiro Furukawa","email":"yushiro.furukawa@lycorp.co.jp","username":"yushiro2"},"last_update":"2026-07-10 02:41:01.000000000","reason":"\u003cGERRIT_ACCOUNT_10273\u003e replied on the change","reason_account":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"}}},"removed_from_attention_set":{"10273":{"account":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"last_update":"2026-07-10 02:41:01.000000000","reason":"\u003cGERRIT_ACCOUNT_10273\u003e replied on the change","reason_account":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"}}},"hashtags":[],"change_id":"I6b2c89ee3f33d4be601b7ef001bdc7b7e39cdb9d","subject":"HTTP-RPC driver: various fixes","status":"NEW","created":"2026-06-15 08:47:49.000000000","updated":"2026-07-17 07:26:52.000000000","submit_type":"MERGE_IF_NECESSARY","mergeable":false,"submittable":false,"total_comment_count":35,"unresolved_comment_count":3,"has_review_started":true,"meta_rev_id":"23efd10c3dddd4cb907a0c255a6322e1fc9f3aa6","_number":993312,"virtual_id_number":993312,"owner":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"actions":{},"labels":{"Verified":{"recommended":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"all":[{"_account_id":33451,"name":"Yushiro Furukawa","display_name":"Yushiro Furukawa","email":"yushiro.furukawa@lycorp.co.jp","username":"yushiro2"},{"tag":"autogenerated:zuul:check","value":1,"date":"2026-07-17 07:26:52.000000000","permitted_voting_range":{"min":-2,"max":2},"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]}],"values":{"-2":"Fails","-1":"Doesn\u0027t seem to work"," 0":"No score","+1":"Works for me","+2":"Verified"},"description":"","value":1,"default_value":0,"optional":true},"Code-Review":{"all":[{"value":0,"permitted_voting_range":{"min":-1,"max":1},"_account_id":33451,"name":"Yushiro Furukawa","display_name":"Yushiro Furukawa","email":"yushiro.furukawa@lycorp.co.jp","username":"yushiro2"},{"value":0,"permitted_voting_range":{"min":-1,"max":1},"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]}],"values":{"-2":"Do not merge","-1":"This patch needs further work before it can be merged"," 0":"No score","+1":"Looks good to me, but someone else must approve","+2":"Looks good to me (core reviewer)"},"description":"","default_value":0,"optional":true},"Workflow":{"all":[{"_account_id":33451,"name":"Yushiro Furukawa","display_name":"Yushiro Furukawa","email":"yushiro.furukawa@lycorp.co.jp","username":"yushiro2"},{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]}],"values":{"-1":"Work in progress"," 0":"Ready for reviews","+1":"Approved"},"description":"","default_value":0,"optional":true},"Backport-Candidate":{"all":[{"value":0,"permitted_voting_range":{"min":-1,"max":1},"_account_id":33451,"name":"Yushiro Furukawa","display_name":"Yushiro Furukawa","email":"yushiro.furukawa@lycorp.co.jp","username":"yushiro2"},{"value":0,"permitted_voting_range":{"min":-1,"max":1},"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]}],"values":{"-2":"Do Not Backport","-1":"Not A Backport Candidate"," 0":"Backport Review Needed","+1":"Proposed Backport","+2":"Should Backport"},"description":"","default_value":0,"optional":true}},"removable_reviewers":[],"reviewers":{"REVIEWER":[{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},{"_account_id":33451,"name":"Yushiro Furukawa","display_name":"Yushiro Furukawa","email":"yushiro.furukawa@lycorp.co.jp","username":"yushiro2"}],"CC":[{"_account_id":9816,"name":"Takashi Kajinami","email":"kajinamit@oss.nttdata.com","username":"kajinamit"}]},"pending_reviewers":{},"reviewer_updates":[{"updated":"2026-06-15 10:51:29.000000000","updated_by":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"reviewer":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"state":"REVIEWER"},{"updated":"2026-06-15 10:55:55.000000000","updated_by":{"_account_id":9816,"name":"Takashi Kajinami","email":"kajinamit@oss.nttdata.com","username":"kajinamit"},"reviewer":{"_account_id":9816,"name":"Takashi Kajinami","email":"kajinamit@oss.nttdata.com","username":"kajinamit"},"state":"CC"},{"updated":"2026-06-17 01:43:38.000000000","updated_by":{"_account_id":33451,"name":"Yushiro Furukawa","display_name":"Yushiro Furukawa","email":"yushiro.furukawa@lycorp.co.jp","username":"yushiro2"},"reviewer":{"_account_id":33451,"name":"Yushiro Furukawa","display_name":"Yushiro Furukawa","email":"yushiro.furukawa@lycorp.co.jp","username":"yushiro2"},"state":"CC"},{"updated":"2026-06-17 05:58:04.000000000","updated_by":{"_account_id":33451,"name":"Yushiro Furukawa","display_name":"Yushiro Furukawa","email":"yushiro.furukawa@lycorp.co.jp","username":"yushiro2"},"reviewer":{"_account_id":33451,"name":"Yushiro Furukawa","display_name":"Yushiro Furukawa","email":"yushiro.furukawa@lycorp.co.jp","username":"yushiro2"},"state":"REVIEWER"}],"messages":[{"id":"659395159db4d6ba72f99936224773bd3830398f","tag":"autogenerated:gerrit:newPatchSet","author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"date":"2026-06-15 08:47:49.000000000","message":"Uploaded patch set 1.","accounts_in_message":[],"_revision_number":1},{"id":"96d348bd9e2c8a8b57eb44de7a7859bfcaf9955f","tag":"autogenerated:zuul:check","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2026-06-15 10:51:29.000000000","message":"Patch Set 1: Verified-1\n\nBuild failed (check pipeline).  For information on how to proceed, see\nhttps://docs.opendev.org/opendev/infra-manual/latest/developers.html#automated-testing\nand https://docs.openstack.org/project-team-guide/testing.html#how-to-handle-test-failures\n\nhttps://zuul.opendev.org/t/openstack/buildset/cd96843472474aad8abc78629c6d1128\n\n- tempest-full-py3 https://zuul.opendev.org/t/openstack/build/8688ae04817f47f28ac70887aff81e6d : POST_FAILURE in 1h 06m 15s\n- openstack-tox-cover https://zuul.opendev.org/t/openstack/build/5bd2e6df205949068ef3a65f64e1f41d : SUCCESS in 3m 03s\n- openstack-tox-pep8 https://zuul.opendev.org/t/openstack/build/1884b88c6c7344d38fbe3a6859d95853 : FAILURE in 2m 22s\n- openstack-tox-py311 https://zuul.opendev.org/t/openstack/build/5822b329ec694dcf9551c1f401aee5b1 : SUCCESS in 3m 34s\n- openstack-tox-py313 https://zuul.opendev.org/t/openstack/build/558a858e49984fc6a92b3053f44b18ca : SUCCESS in 4m 08s\n- openstack-tox-py314 https://zuul.opendev.org/t/openstack/build/cfe00b4c9b834858b936a61420c949be : SUCCESS in 5m 49s (non-voting)\n- openstack-tox-docs https://zuul.opendev.org/t/openstack/build/1d4196b51c5d49c4a807c7977aaf1fa2 : SUCCESS in 3m 46s\n- build-openstack-releasenotes https://zuul.opendev.org/t/openstack/build/dc9a9c19ccb246469820d4b90112babc : SUCCESS in 5m 59s\n- oslo.messaging-tox-py311-func-scenario01 https://zuul.opendev.org/t/openstack/build/84bf9b0a0dec45d5bd1b8ad8686d3cfa : SUCCESS in 4m 45s\n- oslo.messaging-tox-py311-func-scenario02 https://zuul.opendev.org/t/openstack/build/cdd7f33e327e4401be16452ef85a042c : FAILURE in 16m 02s (non-voting)\n- oslo.messaging-tox-py310-func-http https://zuul.opendev.org/t/openstack/build/3a4da84da95a45a19fbfb92af0b6699f : FAILURE in 1m 50s (non-voting)\n- oslo.messaging-src-dsvm-full-rabbit https://zuul.opendev.org/t/openstack/build/79b541d05aa544f29768cacd29c63b90 : SUCCESS in 1h 57m 39s\n- oslo.messaging-src-dsvm-full-kafka-hybrid https://zuul.opendev.org/t/openstack/build/07158e094d594d51b0b695dc64023a05 : SUCCESS in 1h 53m 07s (non-voting)\n- oslo.messaging-grenade https://zuul.opendev.org/t/openstack/build/7c9a25d4393e4ebd98c47ec8ad69d2b4 : SUCCESS in 29m 22s (non-voting)\n- oslo.messaging-grenade-multinode https://zuul.opendev.org/t/openstack/build/bb5854ee21f240b2b3dcfdedae7950f2 : SUCCESS in 54m 40s (non-voting)","accounts_in_message":[],"_revision_number":1},{"id":"b99cc4456ac302910613a2aef77b7fa60b07d2cb","author":{"_account_id":9816,"name":"Takashi Kajinami","email":"kajinamit@oss.nttdata.com","username":"kajinamit"},"date":"2026-06-15 10:55:55.000000000","message":"Patch Set 1:\n\n(1 comment)","accounts_in_message":[],"_revision_number":1},{"id":"6417311ce1c7170e1097de8e64ffce069e081787","author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"date":"2026-06-15 15:56:31.000000000","message":"Patch Set 1:\n\n(1 comment)","accounts_in_message":[],"_revision_number":1},{"id":"595b15279d3fd3b0bfe023662be3502be8d57162","author":{"_account_id":33451,"name":"Yushiro Furukawa","display_name":"Yushiro Furukawa","email":"yushiro.furukawa@lycorp.co.jp","username":"yushiro2"},"date":"2026-06-17 01:43:38.000000000","message":"Patch Set 1:\n\n(1 comment)","accounts_in_message":[],"_revision_number":1},{"id":"1e189aa4f00db7bab01623d722d70ad311f94562","author":{"_account_id":33451,"name":"Yushiro Furukawa","display_name":"Yushiro Furukawa","email":"yushiro.furukawa@lycorp.co.jp","username":"yushiro2"},"date":"2026-06-17 05:58:04.000000000","message":"Patch Set 1: Code-Review-1\n\n(7 comments)","accounts_in_message":[],"_revision_number":1},{"id":"a08b52fa96b59857bf44d9520bcaf2025d2a4edc","author":{"_account_id":33451,"name":"Yushiro Furukawa","display_name":"Yushiro Furukawa","email":"yushiro.furukawa@lycorp.co.jp","username":"yushiro2"},"date":"2026-06-17 06:01:36.000000000","message":"Patch Set 1:\n\n(2 comments)","accounts_in_message":[],"_revision_number":1},{"id":"c09d44a4225627e4d204a2782f5add756eff7a00","author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"date":"2026-06-17 09:17:58.000000000","message":"Patch Set 1:\n\n(8 comments)","accounts_in_message":[],"_revision_number":1},{"id":"92048d41b354a791c4c3b9e59ec2badced386f9a","tag":"autogenerated:gerrit:newPatchSet","author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"date":"2026-06-17 13:29:16.000000000","message":"Uploaded patch set 2.\n\nOutdated Votes:\n* Code-Review-1 (copy condition: \"changekind:TRIVIAL_REBASE OR is:MIN\")\n* Verified-1 (copy condition: \"NEVER\")\n","accounts_in_message":[],"_revision_number":2},{"id":"b27ca6340bae85f3035a948a7e184d2c6e904ed4","tag":"autogenerated:zuul:check","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2026-06-17 15:21:05.000000000","message":"Patch Set 2: Verified+1\n\nBuild succeeded (check pipeline).\nhttps://zuul.opendev.org/t/openstack/buildset/470812fcdad94f768b9510ee5c18e21c\n\n- tempest-full-py3 https://zuul.opendev.org/t/openstack/build/d0a16f316b0e4c8ca2860e0163a29fb6 : SUCCESS in 1h 12m 59s\n- openstack-tox-cover https://zuul.opendev.org/t/openstack/build/c4500e5201c645889024269ed2998c7b : SUCCESS in 8m 20s\n- openstack-tox-pep8 https://zuul.opendev.org/t/openstack/build/546a5e02caaf4ddc8f5c526d188593ac : SUCCESS in 3m 29s\n- openstack-tox-py311 https://zuul.opendev.org/t/openstack/build/de438d7e524a46f6a7ed36ec596054d6 : SUCCESS in 4m 21s\n- openstack-tox-py313 https://zuul.opendev.org/t/openstack/build/57e446519bcd4415b006ba81b288acc5 : SUCCESS in 4m 35s\n- openstack-tox-py314 https://zuul.opendev.org/t/openstack/build/679e1a9753964e6198b92ace84965857 : SUCCESS in 6m 34s (non-voting)\n- openstack-tox-docs https://zuul.opendev.org/t/openstack/build/42faa496e75b4b18afa02bedcf558920 : SUCCESS in 3m 45s\n- build-openstack-releasenotes https://zuul.opendev.org/t/openstack/build/fa039c1030b04ceca33025aedacfebcd : SUCCESS in 4m 58s\n- oslo.messaging-tox-py311-func-scenario01 https://zuul.opendev.org/t/openstack/build/88ef2291d07d4af6a9a211344a6fc3ed : SUCCESS in 5m 01s\n- oslo.messaging-tox-py311-func-scenario02 https://zuul.opendev.org/t/openstack/build/9e7b8ed49f534256949c07c730b0c821 : FAILURE in 7m 19s (non-voting)\n- oslo.messaging-tox-py310-func-http https://zuul.opendev.org/t/openstack/build/02180b9ff918444489c86f56db34bda0 : FAILURE in 2m 40s (non-voting)\n- oslo.messaging-src-dsvm-full-rabbit https://zuul.opendev.org/t/openstack/build/8c36a281ea8f4f91a8e2669b3970caca : SUCCESS in 1h 41m 19s\n- oslo.messaging-src-dsvm-full-kafka-hybrid https://zuul.opendev.org/t/openstack/build/bf12bccf9eb24e1fbcbb68a5b62952cd : SUCCESS in 1h 18m 52s (non-voting)\n- oslo.messaging-grenade https://zuul.opendev.org/t/openstack/build/f16f43bbd634412f93e64f654bfbf657 : SUCCESS in 1h 05m 41s (non-voting)\n- oslo.messaging-grenade-multinode https://zuul.opendev.org/t/openstack/build/dcc4e9107a95477d91ed6d7d05ab1cf1 : SUCCESS in 1h 21m 29s (non-voting)","accounts_in_message":[],"_revision_number":2},{"id":"6bf595c5ef2c5e02d121e96e82cae44377584e80","author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"date":"2026-06-18 11:11:54.000000000","message":"Patch Set 2:\n\n(1 comment)","accounts_in_message":[],"_revision_number":2},{"id":"4c93efe6c1307acdbd2400ef3770516cab71cd14","tag":"autogenerated:gerrit:newPatchSet","author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"date":"2026-06-23 02:12:14.000000000","message":"Uploaded patch set 3.\n\nOutdated Votes:\n* Verified+1 (copy condition: \"NEVER\")\n","accounts_in_message":[],"_revision_number":3},{"id":"8349c59469bbb5fe2a398bdd06fbf5119210cf49","author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"date":"2026-06-23 03:39:31.000000000","message":"Patch Set 3:\n\n(3 comments)","accounts_in_message":[],"_revision_number":3},{"id":"871979c6715dd24a631df3a76d8827e4c48ca049","tag":"autogenerated:zuul:check","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2026-06-23 04:13:23.000000000","message":"Patch Set 3: Verified+1\n\nBuild succeeded (check pipeline).\nhttps://zuul.opendev.org/t/openstack/buildset/92d47bf13d2e47258b3fec924bebd1a0\n\n- tempest-full-py3 https://zuul.opendev.org/t/openstack/build/4e6e288a4a8c4bf3ad5b4f9e767c3f59 : SUCCESS in 57m 39s\n- openstack-tox-cover https://zuul.opendev.org/t/openstack/build/b39500502bb04fc481cda07b723e2a90 : SUCCESS in 6m 48s\n- openstack-tox-pep8 https://zuul.opendev.org/t/openstack/build/62b38e12f16b49f08fbe1151fef58ab3 : SUCCESS in 3m 06s\n- openstack-tox-py311 https://zuul.opendev.org/t/openstack/build/392bd7ba35714d76b2218ea81dfb6f63 : SUCCESS in 5m 02s\n- openstack-tox-py313 https://zuul.opendev.org/t/openstack/build/8f91f6e3a08643cdbbe6498db3fe2609 : SUCCESS in 4m 42s\n- openstack-tox-py314 https://zuul.opendev.org/t/openstack/build/a827ca00b9d748cabe04aa4bd528a4ae : SUCCESS in 4m 26s (non-voting)\n- openstack-tox-docs https://zuul.opendev.org/t/openstack/build/dd1726bec57d41ada0e0b57385eb6f7a : SUCCESS in 4m 14s\n- build-openstack-releasenotes https://zuul.opendev.org/t/openstack/build/5ddbeeb1266a4374903124d401bf209f : SUCCESS in 4m 09s\n- oslo.messaging-tox-py311-func-scenario01 https://zuul.opendev.org/t/openstack/build/92ddcce89c734f21b567e7b2018e350b : SUCCESS in 5m 45s\n- oslo.messaging-tox-py311-func-scenario02 https://zuul.opendev.org/t/openstack/build/f1ca4c649f124526b4b005a1224c549f : FAILURE in 5m 26s (non-voting)\n- oslo.messaging-tox-py310-func-http https://zuul.opendev.org/t/openstack/build/8ac1fe6301024f8d98d4da3a8202f454 : FAILURE in 3m 57s (non-voting)\n- oslo.messaging-src-dsvm-full-rabbit https://zuul.opendev.org/t/openstack/build/284ca0a0fcde4adab8e8148b914643c3 : SUCCESS in 1h 01m 49s\n- oslo.messaging-src-dsvm-full-kafka-hybrid https://zuul.opendev.org/t/openstack/build/d3df0e6c538f444ab1cdcd1fcb63e456 : SUCCESS in 1h 19m 40s (non-voting)\n- oslo.messaging-grenade https://zuul.opendev.org/t/openstack/build/c9f35a55a7d94e3880fd3f64c0906040 : SUCCESS in 1h 05m 58s (non-voting)\n- oslo.messaging-grenade-multinode https://zuul.opendev.org/t/openstack/build/c4367a13d6d54df08381ea4ca87fe500 : SUCCESS in 44m 21s (non-voting)","accounts_in_message":[],"_revision_number":3},{"id":"3fa09d850fe35aba7b30422ddb89d12e1da411a4","author":{"_account_id":33451,"name":"Yushiro Furukawa","display_name":"Yushiro Furukawa","email":"yushiro.furukawa@lycorp.co.jp","username":"yushiro2"},"date":"2026-06-30 08:42:44.000000000","message":"Patch Set 3:\n\n(8 comments)","accounts_in_message":[],"_revision_number":3},{"id":"d4ae41fe2d2b80af43897d51e112783c4e4b687f","tag":"autogenerated:gerrit:newPatchSet","author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"real_author":{"_account_id":33451,"name":"Yushiro Furukawa","display_name":"Yushiro Furukawa","email":"yushiro.furukawa@lycorp.co.jp","username":"yushiro2"},"date":"2026-06-30 08:45:06.000000000","message":"Patch Set 4: Patch Set 3 was rebased on behalf of \u003cGERRIT_ACCOUNT_10273\u003e\n\nOutdated Votes:\n* Verified+1 (copy condition: \"NEVER\")\n","accounts_in_message":[{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"}],"_revision_number":4},{"id":"e3db0f4a634126607d27aca3f3cdce4c934384a5","tag":"autogenerated:zuul:check","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2026-06-30 10:35:32.000000000","message":"Patch Set 4: Verified-1\n\nBuild failed (check pipeline).  For information on how to proceed, see\nhttps://docs.opendev.org/opendev/infra-manual/latest/developers.html#automated-testing\nand https://docs.openstack.org/project-team-guide/testing.html#how-to-handle-test-failures\n\nhttps://zuul.opendev.org/t/openstack/buildset/61b2695b8a4a4e8b859b2e6b5ac38826\n\n- tempest-full-py3 https://zuul.opendev.org/t/openstack/build/a2709107fa014d7ab1067dc486603830 : SUCCESS in 1h 34m 14s\n- openstack-tox-cover https://zuul.opendev.org/t/openstack/build/fa79b6cc7b404d86a9e0f0bf4d48f29c : SUCCESS in 4m 06s\n- openstack-tox-pep8 https://zuul.opendev.org/t/openstack/build/bf037490550a4833a81c4bc8ae23d53c : FAILURE in 2m 56s\n- openstack-tox-py311 https://zuul.opendev.org/t/openstack/build/1fdc2c240d444f1ab0124ff113d90ca0 : SUCCESS in 3m 32s\n- openstack-tox-py313 https://zuul.opendev.org/t/openstack/build/4133cc4b7fd54507b76ed6b826c21556 : SUCCESS in 3m 56s\n- openstack-tox-py314 https://zuul.opendev.org/t/openstack/build/8278508485204e9299554a0e14d5acf1 : SUCCESS in 7m 16s\n- openstack-tox-py315 https://zuul.opendev.org/t/openstack/build/fa2f112676a24997b87cf7ea196403cc : FAILURE in 5m 24s (non-voting)\n- openstack-tox-docs https://zuul.opendev.org/t/openstack/build/45263d142dd5481487abb8694e5bdcf0 : SUCCESS in 3m 37s\n- build-openstack-releasenotes https://zuul.opendev.org/t/openstack/build/b9271ac75a4a46a98a14e6a1b64eb9ab : SUCCESS in 4m 06s\n- oslo.messaging-tox-py311-func-scenario01 https://zuul.opendev.org/t/openstack/build/70590f023f904a85a2d8886ca5b6745c : SUCCESS in 6m 16s\n- oslo.messaging-tox-py311-func-scenario02 https://zuul.opendev.org/t/openstack/build/60d11b969cf44e9783ca12c25efdcd05 : FAILURE in 15m 16s (non-voting)\n- oslo.messaging-tox-py310-func-http https://zuul.opendev.org/t/openstack/build/9d2da0a1756e4af1bc76f1fde396a898 : FAILURE in 1m 59s (non-voting)\n- oslo.messaging-src-dsvm-full-rabbit https://zuul.opendev.org/t/openstack/build/a4d5bfe167b04a1a83f85e98bcf280dd : SUCCESS in 1h 20m 29s\n- oslo.messaging-src-dsvm-full-kafka-hybrid https://zuul.opendev.org/t/openstack/build/09ef65705ad94c53ad11b46a405cd3ac : SUCCESS in 1h 47m 35s (non-voting)\n- oslo.messaging-grenade https://zuul.opendev.org/t/openstack/build/e0b3be64af11418c86a2d1fa5e148803 : SUCCESS in 31m 17s (non-voting)\n- oslo.messaging-grenade-multinode https://zuul.opendev.org/t/openstack/build/b829d5c081464522a1234f695525386f : SUCCESS in 1h 17m 06s (non-voting)","accounts_in_message":[],"_revision_number":4},{"id":"732ed8bed713ce53488e6d690e714102ceebbe3d","author":{"_account_id":33451,"name":"Yushiro Furukawa","display_name":"Yushiro Furukawa","email":"yushiro.furukawa@lycorp.co.jp","username":"yushiro2"},"date":"2026-06-30 15:38:27.000000000","message":"Patch Set 4:\n\n(1 comment)","accounts_in_message":[],"_revision_number":4},{"id":"3f4790cf8ff1966a8c98d826065a915c336cfdde","tag":"autogenerated:gerrit:newPatchSet","author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"real_author":{"_account_id":33451,"name":"Yushiro Furukawa","display_name":"Yushiro Furukawa","email":"yushiro.furukawa@lycorp.co.jp","username":"yushiro2"},"date":"2026-06-30 15:40:15.000000000","message":"Patch Set 5: Patch Set 4 was rebased on behalf of \u003cGERRIT_ACCOUNT_10273\u003e\n\nOutdated Votes:\n* Verified-1 (copy condition: \"NEVER\")\n","accounts_in_message":[{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"}],"_revision_number":5},{"id":"f958e93ddb21645c6f696886630c08e4e70e581b","tag":"autogenerated:zuul:check","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2026-06-30 17:20:13.000000000","message":"Patch Set 5: Verified+1\n\nBuild succeeded (check pipeline).\nhttps://zuul.opendev.org/t/openstack/buildset/df37788527de4d54ab384f08415d6d82\n\n- tempest-full-py3 https://zuul.opendev.org/t/openstack/build/6f0c5a4b5c5942b9a51c6f6f39139efb : SUCCESS in 1h 33m 34s\n- openstack-tox-cover https://zuul.opendev.org/t/openstack/build/c70ec74a3463415a831cd6b32a8153f9 : SUCCESS in 5m 45s\n- openstack-tox-pep8 https://zuul.opendev.org/t/openstack/build/72a060bb518b4e95a8de6b55af774d5e : SUCCESS in 3m 30s\n- openstack-tox-py311 https://zuul.opendev.org/t/openstack/build/222245887d644260bef317d57b87af49 : SUCCESS in 4m 17s\n- openstack-tox-py313 https://zuul.opendev.org/t/openstack/build/9cc4ffd2f3514d0ebcc1445279ab4253 : SUCCESS in 2m 56s\n- openstack-tox-py314 https://zuul.opendev.org/t/openstack/build/ce2f76427a024403bde63d1193fddf1f : SUCCESS in 9m 50s\n- openstack-tox-py315 https://zuul.opendev.org/t/openstack/build/bce5f4ca945a43d5bd192ba7aa9dab96 : FAILURE in 5m 22s (non-voting)\n- openstack-tox-docs https://zuul.opendev.org/t/openstack/build/6407909f1e6349508f4c6b3712915eec : SUCCESS in 6m 33s\n- build-openstack-releasenotes https://zuul.opendev.org/t/openstack/build/172966d317274bb2a7b33a5abc425e56 : SUCCESS in 6m 03s\n- oslo.messaging-tox-py311-func-scenario01 https://zuul.opendev.org/t/openstack/build/6bd5cc20b2ea48de92ab2b9bb36aced7 : SUCCESS in 5m 41s\n- oslo.messaging-tox-py311-func-scenario02 https://zuul.opendev.org/t/openstack/build/3e474e9421ff40aa9619800fa398127e : FAILURE in 4m 43s (non-voting)\n- oslo.messaging-tox-py310-func-http https://zuul.opendev.org/t/openstack/build/9ec585abe0c040c4a2d586a143cfa891 : FAILURE in 2m 04s (non-voting)\n- oslo.messaging-src-dsvm-full-rabbit https://zuul.opendev.org/t/openstack/build/77020776b40947fd9ab7a9e3357becad : SUCCESS in 1h 07m 22s\n- oslo.messaging-src-dsvm-full-kafka-hybrid https://zuul.opendev.org/t/openstack/build/3d7ca02cf04b4ab79ee05e1e72a5fcee : SUCCESS in 1h 08m 16s (non-voting)\n- oslo.messaging-grenade https://zuul.opendev.org/t/openstack/build/6fcf2a8c867f44bc85eb3db91a0f3902 : SUCCESS in 1h 08m 40s (non-voting)\n- oslo.messaging-grenade-multinode https://zuul.opendev.org/t/openstack/build/d67214edd66d4c359f975516ca9b2c15 : SUCCESS in 1h 18m 55s (non-voting)","accounts_in_message":[],"_revision_number":5},{"id":"f7cc603819f1856d84691ece25de0096d96e688a","tag":"autogenerated:gerrit:newPatchSet","author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"date":"2026-07-08 05:36:24.000000000","message":"Uploaded patch set 6.\n\nOutdated Votes:\n* Verified+1 (copy condition: \"NEVER\")\n","accounts_in_message":[],"_revision_number":6},{"id":"c6148822faa3c634e674a8e72217ed12e9cb1986","tag":"autogenerated:zuul:check","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2026-07-08 07:24:38.000000000","message":"Patch Set 6: Verified+1\n\nBuild succeeded (check pipeline).\nhttps://zuul.opendev.org/t/openstack/buildset/0d8f7c8a96bb406184bb99cc49f8c85b\n\n- tempest-full-py3 https://zuul.opendev.org/t/openstack/build/405328de7a744a1aa83d6c97f1963eb8 : SUCCESS in 1h 43m 00s\n- openstack-tox-cover https://zuul.opendev.org/t/openstack/build/b723b0a2dc8f416ea6103a5ff17562c6 : SUCCESS in 4m 56s\n- openstack-tox-pep8 https://zuul.opendev.org/t/openstack/build/23660d9241b94b308f6e99c82c0172d5 : SUCCESS in 2m 35s\n- openstack-tox-py311 https://zuul.opendev.org/t/openstack/build/9a649fe375314126b9a4e438f71dd070 : SUCCESS in 3m 55s\n- openstack-tox-py313 https://zuul.opendev.org/t/openstack/build/c5a52eb78ff54fa79d202be8ba5a37a5 : SUCCESS in 2m 53s\n- openstack-tox-py314 https://zuul.opendev.org/t/openstack/build/2377096232884aac8c309a028b83871a : SUCCESS in 4m 01s\n- openstack-tox-py315 https://zuul.opendev.org/t/openstack/build/889c5f877b8f43f59fba0a2887a36030 : FAILURE in 3m 36s (non-voting)\n- openstack-tox-docs https://zuul.opendev.org/t/openstack/build/915ec41fbac14db99d6794026c98f9ee : SUCCESS in 2m 19s\n- build-openstack-releasenotes https://zuul.opendev.org/t/openstack/build/36b82d4b7d1d4d64af7bd4904a3074be : SUCCESS in 5m 06s\n- oslo.messaging-tox-py311-func-scenario01 https://zuul.opendev.org/t/openstack/build/e4482bdfab4541c2be35b18d380e0a0c : SUCCESS in 10m 56s\n- oslo.messaging-tox-py311-func-scenario02 https://zuul.opendev.org/t/openstack/build/b76436c3b75f4e8db75961a2a0a6dd36 : FAILURE in 4m 16s (non-voting)\n- oslo.messaging-tox-py310-func-http https://zuul.opendev.org/t/openstack/build/d6236ab5897949a38ca6ae1f5d7afd59 : FAILURE in 4m 03s (non-voting)\n- oslo.messaging-src-dsvm-full-rabbit https://zuul.opendev.org/t/openstack/build/d79538dd68d943e4b3698f7a02c6c94b : SUCCESS in 1h 27m 27s\n- oslo.messaging-src-dsvm-full-kafka-hybrid https://zuul.opendev.org/t/openstack/build/95b426c7c4034eb9aaea4901426fc53a : SUCCESS in 1h 27m 05s (non-voting)\n- oslo.messaging-grenade https://zuul.opendev.org/t/openstack/build/1f08fef1d05244af805ace0b6c4c0c54 : SUCCESS in 44m 53s (non-voting)\n- oslo.messaging-grenade-multinode https://zuul.opendev.org/t/openstack/build/624e085d3a2841668831283ef768df95 : SUCCESS in 37m 21s (non-voting)","accounts_in_message":[],"_revision_number":6},{"id":"7a26e9cc5555faa4dbb6a6a7a6ac56654aca8a0d","tag":"autogenerated:gerrit:newPatchSet","author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"date":"2026-07-08 09:17:22.000000000","message":"Uploaded patch set 7.\n\nOutdated Votes:\n* Verified+1 (copy condition: \"NEVER\")\n","accounts_in_message":[],"_revision_number":7},{"id":"87239a98fedade9f94bf93adec65ca62e1b12f2b","tag":"autogenerated:zuul:check","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2026-07-08 11:10:22.000000000","message":"Patch Set 7: Verified-1\n\nBuild failed (check pipeline).  For information on how to proceed, see\nhttps://docs.opendev.org/opendev/infra-manual/latest/developers.html#automated-testing\nand https://docs.openstack.org/project-team-guide/testing.html#how-to-handle-test-failures\n\nhttps://zuul.opendev.org/t/openstack/buildset/43ea5dc88cc54ea1b0c987ed7729889e\n\n- tempest-full-py3 https://zuul.opendev.org/t/openstack/build/ef8c2e86018e48338badbbb661b2624a : SUCCESS in 1h 32m 38s\n- openstack-tox-cover https://zuul.opendev.org/t/openstack/build/99125e68fa1748848cb4eb24581c320c : FAILURE in 3m 29s\n- openstack-tox-pep8 https://zuul.opendev.org/t/openstack/build/8d6eecbd9d8848768b326e29515b9033 : SUCCESS in 3m 47s\n- openstack-tox-py311 https://zuul.opendev.org/t/openstack/build/42e19bec47d148f0ae364151548d9714 : FAILURE in 3m 52s\n- openstack-tox-py313 https://zuul.opendev.org/t/openstack/build/3bfe7b3fdd034eb3bdbe7cb515407149 : FAILURE in 4m 20s\n- openstack-tox-py314 https://zuul.opendev.org/t/openstack/build/107d0736fb3d4c22bb52f03e3da22360 : FAILURE in 6m 05s\n- openstack-tox-py315 https://zuul.opendev.org/t/openstack/build/1fe78f7abd974bef8d14655b91abb82e : FAILURE in 6m 06s (non-voting)\n- openstack-tox-docs https://zuul.opendev.org/t/openstack/build/cd0dd2917ba3457eb1dfb25096fb451b : FAILURE in 3m 49s\n- build-openstack-releasenotes https://zuul.opendev.org/t/openstack/build/b78d92cdfda14776a3f1c198e287cc15 : SUCCESS in 4m 43s\n- oslo.messaging-tox-py311-func-scenario01 https://zuul.opendev.org/t/openstack/build/d8d44b9275cd432da106e7c99c1caaa6 : FAILURE in 4m 34s\n- oslo.messaging-tox-py311-func-scenario02 https://zuul.opendev.org/t/openstack/build/a650dc53c0d4411f9642520a1594f77d : FAILURE in 10m 25s (non-voting)\n- oslo.messaging-tox-py310-func-http https://zuul.opendev.org/t/openstack/build/87ffdd2cbcce427abdfa419fc0f2c519 : FAILURE in 3m 29s (non-voting)\n- oslo.messaging-src-dsvm-full-rabbit https://zuul.opendev.org/t/openstack/build/58af72eb728c4bc69b45a6c201d8d6b8 : SUCCESS in 1h 43m 14s\n- oslo.messaging-src-dsvm-full-kafka-hybrid https://zuul.opendev.org/t/openstack/build/9eb9ea94f1f349418f9693e49b6fafb7 : SUCCESS in 1h 44m 44s (non-voting)\n- oslo.messaging-grenade https://zuul.opendev.org/t/openstack/build/ae8cf3a5c5fb478ca2f27ba128e9d64a : SUCCESS in 1h 05m 25s (non-voting)\n- oslo.messaging-grenade-multinode https://zuul.opendev.org/t/openstack/build/4111377b20e34a9bb67317b8646b92c4 : SUCCESS in 1h 12m 24s (non-voting)","accounts_in_message":[],"_revision_number":7},{"id":"12817bbff8802993015f212d56f91982b15ff346","tag":"autogenerated:gerrit:newPatchSet","author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"date":"2026-07-08 18:29:33.000000000","message":"Uploaded patch set 8.\n\nOutdated Votes:\n* Verified-1 (copy condition: \"NEVER\")\n","accounts_in_message":[],"_revision_number":8},{"id":"d6a4e6d323f11edcdabe306fda3f430877e8d026","tag":"autogenerated:gerrit:newPatchSet","author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"date":"2026-07-08 18:52:42.000000000","message":"Uploaded patch set 9.","accounts_in_message":[],"_revision_number":9},{"id":"a653bce6c3d9115241dd7e6495551e2b060efec2","tag":"autogenerated:zuul:check","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2026-07-08 20:42:03.000000000","message":"Patch Set 9: Verified+1\n\nBuild succeeded (check pipeline).\nhttps://zuul.opendev.org/t/openstack/buildset/3e35c5ee3dea4c51b63728fd2a856af8\n\n- tempest-full-py3 https://zuul.opendev.org/t/openstack/build/6bbd590b3e484574b126c37a7d5c8aae : SUCCESS in 1h 37m 48s\n- openstack-tox-cover https://zuul.opendev.org/t/openstack/build/7bac20420e1142db95712febd6a27f49 : SUCCESS in 4m 15s\n- openstack-tox-pep8 https://zuul.opendev.org/t/openstack/build/471e8bddcc5245dcb311d19050181491 : SUCCESS in 3m 20s\n- openstack-tox-py311 https://zuul.opendev.org/t/openstack/build/7c9c4ddade59433eb3b40c247376fc87 : SUCCESS in 3m 43s\n- openstack-tox-py313 https://zuul.opendev.org/t/openstack/build/7dec797488a8487da765846ee82550ed : SUCCESS in 3m 50s\n- openstack-tox-py314 https://zuul.opendev.org/t/openstack/build/a4a0b4e16313472c978459dd3e1dd029 : SUCCESS in 7m 28s\n- openstack-tox-py315 https://zuul.opendev.org/t/openstack/build/8ef12d1aa39c424f80c0fedd80fd83d9 : FAILURE in 5m 38s (non-voting)\n- openstack-tox-docs https://zuul.opendev.org/t/openstack/build/f2967fbf331f485d9cc89e7e915a904a : SUCCESS in 5m 21s\n- build-openstack-releasenotes https://zuul.opendev.org/t/openstack/build/65aa1c2f21b04503959f075d1b4efedc : SUCCESS in 2m 57s\n- oslo.messaging-tox-py311-func-scenario01 https://zuul.opendev.org/t/openstack/build/e34095d20e454084b643f3c351b4add7 : SUCCESS in 5m 38s\n- oslo.messaging-tox-py311-func-scenario02 https://zuul.opendev.org/t/openstack/build/cce52a0eb9ad41e886d3823b3524779c : FAILURE in 5m 02s (non-voting)\n- oslo.messaging-tox-py310-func-http https://zuul.opendev.org/t/openstack/build/086a309f9a404723abe779d783c81043 : FAILURE in 1m 49s (non-voting)\n- oslo.messaging-src-dsvm-full-rabbit https://zuul.opendev.org/t/openstack/build/e17ee06abfb54ecd82459a6ffa1778fc : SUCCESS in 1h 39m 38s\n- oslo.messaging-src-dsvm-full-kafka-hybrid https://zuul.opendev.org/t/openstack/build/73c874e6b98545de941a35609464bbca : SUCCESS in 1h 08m 11s (non-voting)\n- oslo.messaging-grenade https://zuul.opendev.org/t/openstack/build/ea3895ebfda54c2a91eb911abcba237a : SUCCESS in 1h 05m 07s (non-voting)\n- oslo.messaging-grenade-multinode https://zuul.opendev.org/t/openstack/build/a9df8f805ffa496b9905171ca3c18e31 : SUCCESS in 1h 22m 48s (non-voting)","accounts_in_message":[],"_revision_number":9},{"id":"ff2057202539cebfe4aaa1a3c722c2083bbd9da5","tag":"autogenerated:gerrit:newPatchSet","author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"date":"2026-07-09 05:21:59.000000000","message":"Uploaded patch set 10.\n\nOutdated Votes:\n* Verified+1 (copy condition: \"NEVER\")\n","accounts_in_message":[],"_revision_number":10},{"id":"7f900d137391aaa8e009643fa9be8c898ef2ce79","tag":"autogenerated:zuul:check","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2026-07-09 07:03:57.000000000","message":"Patch Set 10: Verified+1\n\nBuild succeeded (check pipeline).\nhttps://zuul.opendev.org/t/openstack/buildset/139571b377564e89962fab2f9ff9df77\n\n- tempest-full-py3 https://zuul.opendev.org/t/openstack/build/5704a5ae1a964055ac38d6b73299e555 : SUCCESS in 1h 11m 49s\n- openstack-tox-cover https://zuul.opendev.org/t/openstack/build/c753b31d600c4525bd6daa1a2139202b : SUCCESS in 3m 45s\n- openstack-tox-pep8 https://zuul.opendev.org/t/openstack/build/e4857fb9c577438680c32c7ef9f0e7c5 : SUCCESS in 3m 32s\n- openstack-tox-py311 https://zuul.opendev.org/t/openstack/build/a918f1822b7440d3ab289d1bb9b6bc81 : SUCCESS in 6m 47s\n- openstack-tox-py313 https://zuul.opendev.org/t/openstack/build/294f60c871ef4dc18046469beb30b852 : SUCCESS in 5m 54s\n- openstack-tox-py314 https://zuul.opendev.org/t/openstack/build/93c65c16f7144d18a433d0c5cf3f436d : SUCCESS in 5m 33s\n- openstack-tox-py315 https://zuul.opendev.org/t/openstack/build/19691cd3b69d44db80d967e7d42df97b : FAILURE in 4m 12s (non-voting)\n- openstack-tox-docs https://zuul.opendev.org/t/openstack/build/c19465fc71c94a87944d8bd2500daaac : SUCCESS in 2m 15s\n- build-openstack-releasenotes https://zuul.opendev.org/t/openstack/build/68ee3d6b9eb749fbb40ee289faa33f45 : SUCCESS in 2m 55s\n- oslo.messaging-tox-py311-func-scenario01 https://zuul.opendev.org/t/openstack/build/2ee0c86c9d4e4a9fa7cfe17545f490af : SUCCESS in 4m 10s\n- oslo.messaging-tox-py311-func-scenario02 https://zuul.opendev.org/t/openstack/build/91f8658b06564211afd3498a9f8c226c : FAILURE in 5m 15s (non-voting)\n- oslo.messaging-tox-py310-func-http https://zuul.opendev.org/t/openstack/build/86d35887e98c44b194911d71198e52ca : FAILURE in 1m 57s (non-voting)\n- oslo.messaging-src-dsvm-full-rabbit https://zuul.opendev.org/t/openstack/build/ba533f5f995040e5b01ff4f69fe19fbc : SUCCESS in 1h 38m 33s\n- oslo.messaging-src-dsvm-full-kafka-hybrid https://zuul.opendev.org/t/openstack/build/88dab2363bd241fcae1f6be81a617576 : SUCCESS in 1h 32m 45s (non-voting)\n- oslo.messaging-grenade https://zuul.opendev.org/t/openstack/build/b51ca388ce1c4836aab597e35c640bc2 : SUCCESS in 29m 42s (non-voting)\n- oslo.messaging-grenade-multinode https://zuul.opendev.org/t/openstack/build/b9689d11dee94d52a1fbbe23908aa45e : SUCCESS in 1h 15m 11s (non-voting)","accounts_in_message":[],"_revision_number":10},{"id":"3cb1cf2fdadff14b8fbe691e3ae7ef60aee4b794","tag":"autogenerated:gerrit:newPatchSet","author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"date":"2026-07-09 10:17:59.000000000","message":"Uploaded patch set 11.\n\nOutdated Votes:\n* Verified+1 (copy condition: \"NEVER\")\n","accounts_in_message":[],"_revision_number":11},{"id":"9adb771b98462c29ba68ea757e8599486a15d863","tag":"autogenerated:gerrit:newPatchSet","author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"date":"2026-07-09 10:47:30.000000000","message":"Uploaded patch set 12.","accounts_in_message":[],"_revision_number":12},{"id":"435440a73391677f3ea30ccd193c14a6c5ffb6a2","tag":"autogenerated:zuul:check","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2026-07-09 12:48:34.000000000","message":"Patch Set 12: Verified+1\n\nBuild succeeded (check pipeline).\nhttps://zuul.opendev.org/t/openstack/buildset/552ea42c86df4943b7acb30f4e23f602\n\n- tempest-full-py3 https://zuul.opendev.org/t/openstack/build/6309f6bf5c9d4062a1b28296bd278ca3 : SUCCESS in 1h 09m 34s\n- openstack-tox-cover https://zuul.opendev.org/t/openstack/build/4506de11f33f43c0b7600da4d72ffef9 : SUCCESS in 7m 33s\n- openstack-tox-pep8 https://zuul.opendev.org/t/openstack/build/395f37ba2a444ed794904fcd0293f67c : SUCCESS in 4m 39s\n- openstack-tox-py311 https://zuul.opendev.org/t/openstack/build/9fb3e9752a634648bd1f29ddaa700248 : SUCCESS in 3m 52s\n- openstack-tox-py313 https://zuul.opendev.org/t/openstack/build/8b5581a90a7042f3ad5010318915d3dd : SUCCESS in 3m 24s\n- openstack-tox-py314 https://zuul.opendev.org/t/openstack/build/2007c02194cc49d7bf0c0c7ce7126979 : SUCCESS in 6m 38s\n- openstack-tox-py315 https://zuul.opendev.org/t/openstack/build/73b93ea5a95e4f9e807098100a5a45d0 : FAILURE in 7m 40s (non-voting)\n- openstack-tox-docs https://zuul.opendev.org/t/openstack/build/30cdcee57a6d450b8998e480d9fa1bb1 : SUCCESS in 5m 59s\n- build-openstack-releasenotes https://zuul.opendev.org/t/openstack/build/753dbee0d63c4e0aaf92c9069cd8a1ee : SUCCESS in 4m 43s\n- oslo.messaging-tox-py311-func-scenario01 https://zuul.opendev.org/t/openstack/build/3c5b408fcf804e01bf6a77d751ea6a0f : SUCCESS in 5m 22s\n- oslo.messaging-tox-py311-func-scenario02 https://zuul.opendev.org/t/openstack/build/9b0da566cfa74846b7702fa79796c138 : FAILURE in 5m 14s (non-voting)\n- oslo.messaging-tox-py310-func-http https://zuul.opendev.org/t/openstack/build/c4f9e7e67e4341bd91a3765b1e1cff22 : FAILURE in 3m 27s (non-voting)\n- oslo.messaging-src-dsvm-full-rabbit https://zuul.opendev.org/t/openstack/build/49fbe7c25a97464e83a5bed748c71849 : SUCCESS in 1h 44m 38s\n- oslo.messaging-src-dsvm-full-kafka-hybrid https://zuul.opendev.org/t/openstack/build/6900765c07954a2bb29aaba8ae47a414 : SUCCESS in 1h 52m 29s (non-voting)\n- oslo.messaging-grenade https://zuul.opendev.org/t/openstack/build/3350b2f8047c41db8c8756d47556f4e1 : SUCCESS in 1h 11m 03s (non-voting)\n- oslo.messaging-grenade-multinode https://zuul.opendev.org/t/openstack/build/779784a4d72c4096a408497d17977837 : SUCCESS in 55m 33s (non-voting)","accounts_in_message":[],"_revision_number":12},{"id":"5ba67e6c98dd7f08aee5da1aafeabdba656a0918","tag":"autogenerated:gerrit:newPatchSet","author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"date":"2026-07-09 23:23:37.000000000","message":"Uploaded patch set 13.\n\nOutdated Votes:\n* Verified+1 (copy condition: \"NEVER\")\n","accounts_in_message":[],"_revision_number":13},{"id":"0c7c2a487a86e0b50d96310e7b702a79d3df4931","tag":"autogenerated:zuul:check","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2026-07-10 01:09:52.000000000","message":"Patch Set 13: Verified+1\n\nBuild succeeded (check pipeline).\nhttps://zuul.opendev.org/t/openstack/buildset/e99e65e8771d49fbaf8c69b7dc3e51d4\n\n- tempest-full-py3 https://zuul.opendev.org/t/openstack/build/03cc48eba5b54a30ab4feed65ec056a0 : SUCCESS in 41m 35s\n- openstack-tox-cover https://zuul.opendev.org/t/openstack/build/8d7d0824e09b476c85b8252b9612c442 : SUCCESS in 2m 45s\n- openstack-tox-pep8 https://zuul.opendev.org/t/openstack/build/a5811ac5014d4b3f83744daeaf4b160a : SUCCESS in 3m 04s\n- openstack-tox-py311 https://zuul.opendev.org/t/openstack/build/23d978ef25eb487da9b4e7a1082feb3e : SUCCESS in 2m 34s\n- openstack-tox-py313 https://zuul.opendev.org/t/openstack/build/6ba5cdb7f6e542278c5227a63dc0a4a8 : SUCCESS in 4m 01s\n- openstack-tox-py314 https://zuul.opendev.org/t/openstack/build/41af392ca5ea478fa3f0c28f9621b256 : SUCCESS in 3m 54s\n- openstack-tox-py315 https://zuul.opendev.org/t/openstack/build/adcbb3bb7fbb4591a8da0709699ab3e3 : FAILURE in 5m 37s (non-voting)\n- openstack-tox-docs https://zuul.opendev.org/t/openstack/build/9e3962537ac54dca91a2ba61dfdede29 : SUCCESS in 3m 54s\n- build-openstack-releasenotes https://zuul.opendev.org/t/openstack/build/226f206bf95243e5b2656e4c24f2831e : SUCCESS in 4m 15s\n- oslo.messaging-tox-py311-func-scenario01 https://zuul.opendev.org/t/openstack/build/1d934dd58bb649f9878477d5965d1ec4 : SUCCESS in 5m 16s\n- oslo.messaging-tox-py311-func-scenario02 https://zuul.opendev.org/t/openstack/build/3772e71ad8954bce93ea6e0919db60cb : FAILURE in 7m 38s (non-voting)\n- oslo.messaging-tox-py310-func-http https://zuul.opendev.org/t/openstack/build/d5e9db60f5f8412187c6e55133235b52 : FAILURE in 3m 06s (non-voting)\n- oslo.messaging-src-dsvm-full-rabbit https://zuul.opendev.org/t/openstack/build/e374e7c5676d4fde8ab8be6eb7ea3036 : SUCCESS in 1h 30m 24s\n- oslo.messaging-src-dsvm-full-kafka-hybrid https://zuul.opendev.org/t/openstack/build/6ae1e774936444b2952c3a6467cecc1a : SUCCESS in 1h 39m 39s (non-voting)\n- oslo.messaging-grenade https://zuul.opendev.org/t/openstack/build/5ceb2afc94d34cd5990ffc4d34cc6876 : SUCCESS in 1h 05m 06s (non-voting)\n- oslo.messaging-grenade-multinode https://zuul.opendev.org/t/openstack/build/4eb974c0e81f41e98a7d6f6d2a5a5a4c : SUCCESS in 1h 16m 36s (non-voting)","accounts_in_message":[],"_revision_number":13},{"id":"591a9dafa38ba33f9ae8f84f5ab7bc16a89d321a","tag":"autogenerated:gerrit:newPatchSet","author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"date":"2026-07-10 02:30:32.000000000","message":"Uploaded patch set 14.\n\nOutdated Votes:\n* Verified+1 (copy condition: \"NEVER\")\n","accounts_in_message":[],"_revision_number":14},{"id":"33be550b9fa6f810c62795bf6baeb00be1b00bfb","author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"date":"2026-07-10 02:41:01.000000000","message":"Patch Set 14:\n\n(2 comments)","accounts_in_message":[],"_revision_number":14},{"id":"41ae72023a49d7f9f6f8f464568003effc8b16d3","tag":"autogenerated:zuul:check","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2026-07-10 04:48:46.000000000","message":"Patch Set 14: Verified+1\n\nBuild succeeded (check pipeline).\nhttps://zuul.opendev.org/t/openstack/buildset/1e3aea49eedd492884a80d231148b4e2\n\n- tempest-full-py3 https://zuul.opendev.org/t/openstack/build/8e95e8b71d4346c9bcfc6f61f24dc112 : SUCCESS in 1h 37m 50s\n- openstack-tox-cover https://zuul.opendev.org/t/openstack/build/704a619a634c4301aa7173303afa1393 : SUCCESS in 6m 47s\n- openstack-tox-pep8 https://zuul.opendev.org/t/openstack/build/2ec3098fa585453e980dc8c4104e119d : SUCCESS in 4m 29s\n- openstack-tox-py311 https://zuul.opendev.org/t/openstack/build/54b47c48119e4a5e8223c4034cf8793d : SUCCESS in 6m 25s\n- openstack-tox-py313 https://zuul.opendev.org/t/openstack/build/c4ec5443f280421591ee1465e832a561 : SUCCESS in 5m 28s\n- openstack-tox-py314 https://zuul.opendev.org/t/openstack/build/b8c255dcbc0b4f04b0381c77f48d5fe0 : SUCCESS in 9m 05s\n- openstack-tox-py315 https://zuul.opendev.org/t/openstack/build/d3edc797e39f465c842ba83c3883e269 : FAILURE in 8m 27s (non-voting)\n- openstack-tox-docs https://zuul.opendev.org/t/openstack/build/d7fe816adba8425db83bdc2149a7724e : SUCCESS in 4m 23s\n- build-openstack-releasenotes https://zuul.opendev.org/t/openstack/build/cadea311efe440f8aca88fb43d5c9942 : SUCCESS in 4m 51s\n- oslo.messaging-tox-py311-func-scenario01 https://zuul.opendev.org/t/openstack/build/6094d264c1e54af5a118689278f566fd : SUCCESS in 5m 47s\n- oslo.messaging-tox-py311-func-scenario02 https://zuul.opendev.org/t/openstack/build/8fa55307f87b4d349cab8b08841973b4 : FAILURE in 6m 28s (non-voting)\n- oslo.messaging-tox-py310-func-http https://zuul.opendev.org/t/openstack/build/21b22814099e48fc877b35a4e5ce96c7 : FAILURE in 5m 23s (non-voting)\n- oslo.messaging-src-dsvm-full-rabbit https://zuul.opendev.org/t/openstack/build/4df94f13329c4ea0873a47f2be6ed002 : SUCCESS in 1h 28m 45s\n- oslo.messaging-src-dsvm-full-kafka-hybrid https://zuul.opendev.org/t/openstack/build/1a831e05a4c945a081d3e5b0526febda : SUCCESS in 1h 40m 52s (non-voting)\n- oslo.messaging-grenade https://zuul.opendev.org/t/openstack/build/36c8f2171e114eba84683ae03b322641 : SUCCESS in 1h 03m 55s (non-voting)\n- oslo.messaging-grenade-multinode https://zuul.opendev.org/t/openstack/build/eed972007b764d7b9b91178171c86e14 : SUCCESS in 1h 02m 48s (non-voting)","accounts_in_message":[],"_revision_number":14},{"id":"2003e3effd13d1b048888bbe95dcd6d2b3e95681","tag":"autogenerated:gerrit:newPatchSet","author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"date":"2026-07-11 21:36:37.000000000","message":"Patch Set 15: Patch Set 14 was rebased\n\nOutdated Votes:\n* Verified+1 (copy condition: \"NEVER\")\n","accounts_in_message":[],"_revision_number":15},{"id":"9b9fac315ea01091a6c5f512780b101c747ad4fd","tag":"autogenerated:zuul:check","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2026-07-11 23:26:17.000000000","message":"Patch Set 15: Verified+1\n\nBuild succeeded (check pipeline).\nhttps://zuul.opendev.org/t/openstack/buildset/0d57396c277b4ee9813edd563bbb2e70\n\n- tempest-full-py3 https://zuul.opendev.org/t/openstack/build/34cea310018c448582de627cc1c8630a : SUCCESS in 1h 36m 05s\n- openstack-tox-cover https://zuul.opendev.org/t/openstack/build/38724438042548fbb72fb9abc4f666ea : SUCCESS in 4m 39s\n- openstack-tox-pep8 https://zuul.opendev.org/t/openstack/build/b89cce2f963c44f98165ad37554c4976 : SUCCESS in 3m 12s\n- openstack-tox-py311 https://zuul.opendev.org/t/openstack/build/7f678c0a85134153bfdfa9e813ecf7ac : SUCCESS in 3m 44s\n- openstack-tox-py313 https://zuul.opendev.org/t/openstack/build/7920769b33914ac998cd4c98aae8a9e1 : SUCCESS in 3m 59s\n- openstack-tox-py314 https://zuul.opendev.org/t/openstack/build/96a8d96223bd4ff48ad14b924f24662f : SUCCESS in 5m 08s\n- openstack-tox-py315 https://zuul.opendev.org/t/openstack/build/b8bb26c24d2f4223a1cfbd8ceadef692 : FAILURE in 3m 51s (non-voting)\n- openstack-tox-docs https://zuul.opendev.org/t/openstack/build/fde771131177416cb47efbff96612e9f : SUCCESS in 3m 59s\n- build-openstack-releasenotes https://zuul.opendev.org/t/openstack/build/13a40b670de243cda21b0d298a596386 : SUCCESS in 3m 29s\n- oslo.messaging-tox-py311-func-scenario01 https://zuul.opendev.org/t/openstack/build/e10fc099573d4eac995e2fd428a62c92 : SUCCESS in 5m 08s\n- oslo.messaging-tox-py311-func-scenario02 https://zuul.opendev.org/t/openstack/build/71fa491fdb4c4ee3acdd12d8bf18d3e6 : FAILURE in 3m 05s (non-voting)\n- oslo.messaging-tox-py310-func-http https://zuul.opendev.org/t/openstack/build/b25bd40701604e4a9c0eacb45066247e : FAILURE in 2m 32s (non-voting)\n- oslo.messaging-src-dsvm-full-rabbit https://zuul.opendev.org/t/openstack/build/140dc3895a8340ad90e11c25d8bd5f63 : SUCCESS in 1h 39m 25s\n- oslo.messaging-src-dsvm-full-kafka-hybrid https://zuul.opendev.org/t/openstack/build/f0154471b37546edb00f963206b0595d : SUCCESS in 1h 42m 39s (non-voting)\n- oslo.messaging-grenade https://zuul.opendev.org/t/openstack/build/72def19a9d7c43c5a28beb28f606e0f2 : SUCCESS in 1h 09m 13s (non-voting)\n- oslo.messaging-grenade-multinode https://zuul.opendev.org/t/openstack/build/66e67bb4cfee4ceebb51c1d0197a4572 : SUCCESS in 1h 17m 39s (non-voting)","accounts_in_message":[],"_revision_number":15},{"id":"9cffad09b6fff75fdafa35aa3766f3b5659791a0","tag":"autogenerated:gerrit:newPatchSet","author":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"date":"2026-07-17 05:37:37.000000000","message":"Patch Set 16: Patch Set 15 was rebased\n\nOutdated Votes:\n* Verified+1 (copy condition: \"NEVER\")\n","accounts_in_message":[],"_revision_number":16},{"id":"23efd10c3dddd4cb907a0c255a6322e1fc9f3aa6","tag":"autogenerated:zuul:check","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2026-07-17 07:26:52.000000000","message":"Patch Set 16: Verified+1\n\nBuild succeeded (check pipeline).\nhttps://zuul.opendev.org/t/openstack/buildset/fbdfea13a2b64a5294ca8cecf4f74c83\n\n- tempest-full-py3 https://zuul.opendev.org/t/openstack/build/b096cd8347064179adfb7c6704feb5cf : SUCCESS in 1h 39m 29s\n- openstack-tox-cover https://zuul.opendev.org/t/openstack/build/5b4c51d99b1642139f4f2c6029fc1d98 : SUCCESS in 4m 15s\n- openstack-tox-pep8 https://zuul.opendev.org/t/openstack/build/42e4804f566548d1b7e8318473d8601f : SUCCESS in 3m 38s\n- openstack-tox-py311 https://zuul.opendev.org/t/openstack/build/0dab24c3b16a44cab880da99d1ecaa93 : SUCCESS in 4m 44s\n- openstack-tox-py313 https://zuul.opendev.org/t/openstack/build/ca94ece0848044c1a45fc743fc599b6f : SUCCESS in 4m 08s\n- openstack-tox-py314 https://zuul.opendev.org/t/openstack/build/a5755da3c48942319f2b728895b02580 : SUCCESS in 6m 19s\n- openstack-tox-py315 https://zuul.opendev.org/t/openstack/build/23e6850a7e934181aeb5c3bc1aead165 : FAILURE in 7m 39s (non-voting)\n- openstack-tox-docs https://zuul.opendev.org/t/openstack/build/eeb0abef23204599b0a16d8ca95158f8 : SUCCESS in 3m 20s\n- build-openstack-releasenotes https://zuul.opendev.org/t/openstack/build/4b26b7aeb9c343c4a4852b157f8c04c3 : SUCCESS in 2m 28s\n- oslo.messaging-tox-py311-func-scenario01 https://zuul.opendev.org/t/openstack/build/2b3947867fa04448a45e159b3d3590a2 : SUCCESS in 4m 52s\n- oslo.messaging-tox-py311-func-scenario02 https://zuul.opendev.org/t/openstack/build/7976846346b747b5927510a8d119e453 : FAILURE in 4m 31s (non-voting)\n- oslo.messaging-tox-py310-func-http https://zuul.opendev.org/t/openstack/build/ff357a0e34404d7699ba1cde35b25ec4 : FAILURE in 1m 49s (non-voting)\n- oslo.messaging-src-dsvm-full-rabbit https://zuul.opendev.org/t/openstack/build/08c57e8962e147fd887202f391b1d685 : SUCCESS in 1h 02m 36s\n- oslo.messaging-src-dsvm-full-kafka-hybrid https://zuul.opendev.org/t/openstack/build/5ae80184e09948dfad8bb344ec790218 : SUCCESS in 1h 02m 25s (non-voting)\n- oslo.messaging-grenade https://zuul.opendev.org/t/openstack/build/d26329025c4f4c019ee0e87865e507ce : SUCCESS in 1h 07m 18s (non-voting)\n- oslo.messaging-grenade-multinode https://zuul.opendev.org/t/openstack/build/103bdc5096254fa9bb2ab4cb79a329f8 : SUCCESS in 1h 16m 27s (non-voting)","accounts_in_message":[],"_revision_number":16}],"current_revision_number":16,"current_revision":"3f05700d7b9f2c9fb19ee5469521d8046f67cab8","revisions":{"c3a386396638447ae07b190ee5adad512b8c5f09":{"kind":"REWORK","_number":1,"created":"2026-06-15 08:47:49.000000000","uploader":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"ref":"refs/changes/12/993312/1","fetch":{"anonymous http":{"url":"https://review.opendev.org/openstack/oslo.messaging","ref":"refs/changes/12/993312/1","commands":{"Checkout":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/1 \u0026\u0026 git checkout FETCH_HEAD","Cherry Pick":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/1 \u0026\u0026 git cherry-pick FETCH_HEAD","Format Patch":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/1 \u0026\u0026 git format-patch -1 --stdout FETCH_HEAD","Pull":"git pull https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/1"}}},"commit":{"parents":[{"commit":"a67ca72efb18834776493a57823de58f0ab5cb90","subject":"Add HTTP Driver documentation","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/a67ca72efb18834776493a57823de58f0ab5cb90"}]}],"author":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-06-15 08:47:43.000000000","tz":-240},"committer":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-06-15 08:47:43.000000000","tz":-240},"subject":"HTTP-RPC driver fixes (various)","message":"HTTP-RPC driver fixes (various)\n\nAddress some bugs and quality issues in the HTTP transport driver:\n\nSecurity:\n- Fix auth bypass when api_auth_token is not configured: require_auth\n  decorator now rejects requests when the expected token is None/empty\n  instead of allowing all requests through.\n- Use hmac.compare_digest for constant-time token comparison to prevent\n  timing side-channel attacks.\n\nBug fixes:\n- Thread caller-specified retry count through send() to _send() instead\n  of always using the config default. The retry parameter was accepted\n  but silently ignored.\n- Move _pack_context_with_message() call from _select_target_service()\n  to _send(), before the retry loop. Previously, context was packed on\n  every retry attempt, double-nesting the context dict on retries.\n- Protect the final retry attempt in retry_decorator with the same\n  exception handler as earlier attempts. Previously the last call ran\n  outside try/except, causing unhandled crashes on final-attempt failure.\n- Add exponential backoff with jitter between retry attempts to prevent\n  thundering herd under transient failures (0.5s base, 30s cap).\n- Replace broken custom JSON serializer (__json_serialize) with oslo\u0027s\n  jsonutils.dumps. The custom serializer converted strings to character\n  lists via hasattr(obj, \u0027__iter__\u0027) and duplicated datetime handling\n  that jsonutils already provides correctly.\n- Fix double exchange prefix in service name construction (e.g. Ironic\n  sets exchange\u003d\"ironic\" and topic\u003d\"ironic.conductor_manager\",\n  producing \"ironic.ironic.conductor_manager\"). _service_name() now\n  checks for existing prefix before prepending.\n- Add directed RPC topic-splitting fallback for services that embed the\n  server name in the topic (e.g. topic\u003d\"conductor_manager.hostname\"\n  with target.server\u003dNone). Walks dot-separated segments to find valid\n  base topic + server combinations.\n- Implement HTTPDriver.cleanup() to close HTTPClient session and release\n  connection pool resources. Previously was a no-op (pass).\n- Create FanoutHandler once at app creation time instead of per-request\n  to avoid repeated resource allocation.\n\nQuality:\n- Downgrade per-request log messages from LOG.info to LOG.debug to\n  reduce log noise under production RPC load.\n- Replace Consul-hardcoded log messages in FanoutHandler with generic\n  \"service broker\" language for broker-agnostic operation.\n- Use bare raise instead of raise err to preserve original traceback.\n- Use oslo_serialization.jsonutils throughout for JSON serialization\n  and deserialization per OpenStack conventions (needed for Cinder).\n- Fix assertIsNot(0, len(...)) identity test to assertGreater for\n  correct value comparison in unit tests.\n- Use requests.Session for connection pooling instead of per-call\n  requests.post.\n\nGenerated-By: claude-opus-4-6 (OpenCode)\nChange-Id: I6b2c89ee3f33d4be601b7ef001bdc7b7e39cdb9d\nSigned-off-by: flux.adam@gmail.com\n","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/c3a386396638447ae07b190ee5adad512b8c5f09"}],"resolve_conflicts_web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/c3a386396638447ae07b190ee5adad512b8c5f09"}]},"branch":"refs/heads/master"},"439084f1da55646801cc6df065edf533cc99f954":{"kind":"REWORK","_number":2,"created":"2026-06-17 13:29:16.000000000","uploader":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"ref":"refs/changes/12/993312/2","fetch":{"anonymous http":{"url":"https://review.opendev.org/openstack/oslo.messaging","ref":"refs/changes/12/993312/2","commands":{"Checkout":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/2 \u0026\u0026 git checkout FETCH_HEAD","Cherry Pick":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/2 \u0026\u0026 git cherry-pick FETCH_HEAD","Format Patch":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/2 \u0026\u0026 git format-patch -1 --stdout FETCH_HEAD","Pull":"git pull https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/2"}}},"commit":{"parents":[{"commit":"a67ca72efb18834776493a57823de58f0ab5cb90","subject":"Add HTTP Driver documentation","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/a67ca72efb18834776493a57823de58f0ab5cb90"}]}],"author":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-06-15 08:47:43.000000000","tz":-240},"committer":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-06-17 13:24:43.000000000","tz":-240},"subject":"HTTP-RPC driver: various fixes","message":"HTTP-RPC driver: various fixes\n\nAddress a number of bugs and quality issues in the HTTP transport\ndriver.\n\nSecurity:\n- Fix auth bypass when api_auth_token is not configured: the auth check\n  now rejects requests when the expected token is None/empty instead of\n  allowing all requests through.\n- Use hmac.compare_digest for constant-time token comparison to prevent\n  timing side-channel attacks.\n- Require api_auth_token at startup on the server: HTTPListenerBase\n  raises ConfigurationError when the token is empty (the Broadcaster is\n  covered transitively). A server with auth enabled fails closed (401)\n  without a token, so an empty token there is always a misconfiguration;\n  failing at startup surfaces it immediately instead of on the first\n  request. The driver itself does not require a token, so processes that\n  construct the transport without ever sending RPC are not forced to\n  configure one.\n\nBug fixes:\n- Thread the caller-specified retry count through send() to _send()\n  instead of always using the config default; the retry parameter was\n  accepted but silently ignored.\n- Honor the RPCClient contract where retry \u003c 0 (and the None default)\n  means retry forever. Previously range(times + 1) with times\u003d-1\n  produced range(0) -\u003e zero attempts, silently dropping the call.\n  Negative/None now iterates indefinitely (itertools.count) with the\n  backoff exponent capped to avoid overflow.\n- Move the _pack_context_with_message() call from\n  _select_target_service() to _send(), before the retry loop.\n  Previously context was packed on every retry attempt, double-nesting\n  the context dict on retries.\n- Protect the final retry attempt in retry_decorator with the same\n  exception handler as earlier attempts. Previously the last call ran\n  outside try/except, crashing on a final-attempt failure.\n- Add exponential backoff with jitter between retry attempts to avoid a\n  thundering herd under transient failures (0.5s base, 30s cap). The\n  jitter uses random.uniform (non-crypto, marked \u0027# nosec B311\u0027).\n- Replace the broken custom JSON serializer (__json_serialize) with\n  oslo_serialization.jsonutils, used consistently for serialization and\n  deserialization. The custom serializer converted strings to character\n  lists via hasattr(obj, \u0027__iter__\u0027) and duplicated datetime handling\n  that jsonutils already provides correctly.\n- Fix the double exchange prefix in service-name construction (e.g.\n  Ironic sets exchange\u003d\"ironic\" and topic\u003d\"ironic.conductor_manager\",\n  producing \"ironic.ironic.conductor_manager\"); _service_name() now\n  checks for an existing prefix before prepending.\n- Add a directed-RPC topic-splitting fallback for services that embed\n  the server name in the topic (e.g. topic\u003d\"conductor_manager.hostname\"\n  with target.server\u003dNone). Walk the dot-separated segments\n  (right-to-left) to find a valid base topic + server combination.\n- factory.create_app(): wire the fanout handler explicitly via\n  enable_fanout_handler\u003dFalse rather than implicitly probing the\n  optional [oslo_messaging_http_broadcaster] group, which raised\n  NoSuchOptError on the normal RPC-server path (only the broadcaster\n  registers that group). Create the handler once at app-creation time\n  instead of per request.\n- FanoutHandler: require an explicit \u0027service_name\u0027 field in the fanout\n  message and raise ValueError if it is missing, instead of silently\n  reconstructing exchange + \u0027.\u0027 + topic (which produced wrong targets\n  for topics that already embed the exchange).\n- RPCCastFanout: log the full traceback via LOG.exception and return a\n  generic \u0027Internal server error\u0027 (500) instead of echoing the raw\n  exception string to the client; stop logging request bodies in the\n  call/cast timeout paths to avoid leaking message payloads.\n- Import oslo_serialization.jsonutils in api.py (used by jsonutils.loads\n  but never imported).\n- Implement HTTPDriver.cleanup() to close the HTTPClient session and\n  release connection-pool resources; previously a no-op.\n\nQuality:\n- Downgrade per-request log messages from info to debug to reduce log\n  noise under production RPC load.\n- Replace Consul-hardcoded log messages in FanoutHandler with generic\n  \"service broker\" language for broker-agnostic operation.\n- Use a bare raise instead of raise err to preserve the original\n  traceback.\n- Use requests.Session for connection pooling instead of a per-call\n  requests.post.\n- Fix an assertIsNot(0, len(...)) identity check to assertGreater for a\n  correct value comparison in the unit tests.\n\nGenerated-By: claude-opus-4-6 (OpenCode)\nChange-Id: I6b2c89ee3f33d4be601b7ef001bdc7b7e39cdb9d\nSigned-off-by: flux.adam@gmail.com\n","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/439084f1da55646801cc6df065edf533cc99f954"}],"resolve_conflicts_web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/439084f1da55646801cc6df065edf533cc99f954"}]},"branch":"refs/heads/master"},"cd8fff240c5965bb8c1cb1ced5f44b4bea661845":{"kind":"REWORK","_number":3,"created":"2026-06-23 02:12:14.000000000","uploader":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"ref":"refs/changes/12/993312/3","fetch":{"anonymous http":{"url":"https://review.opendev.org/openstack/oslo.messaging","ref":"refs/changes/12/993312/3","commands":{"Checkout":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/3 \u0026\u0026 git checkout FETCH_HEAD","Cherry Pick":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/3 \u0026\u0026 git cherry-pick FETCH_HEAD","Format Patch":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/3 \u0026\u0026 git format-patch -1 --stdout FETCH_HEAD","Pull":"git pull https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/3"}}},"commit":{"parents":[{"commit":"a67ca72efb18834776493a57823de58f0ab5cb90","subject":"Add HTTP Driver documentation","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/a67ca72efb18834776493a57823de58f0ab5cb90"}]}],"author":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-06-15 08:47:43.000000000","tz":-240},"committer":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-06-23 00:41:31.000000000","tz":-240},"subject":"HTTP-RPC driver: various fixes","message":"HTTP-RPC driver: various fixes\n\nAddress a number of bugs and quality issues in the HTTP transport\ndriver.\n\nSecurity:\n- Fix auth bypass when api_auth_token is not configured: the auth check\n  now rejects requests when the expected token is None/empty instead of\n  allowing all requests through.\n- Use hmac.compare_digest for constant-time token comparison to prevent\n  timing side-channel attacks.\n- Require api_auth_token at startup on the server: HTTPListenerBase\n  raises ConfigurationError when the token is empty (the Broadcaster is\n  covered transitively). A server with auth enabled fails closed (401)\n  without a token, so an empty token there is always a misconfiguration;\n  failing at startup surfaces it immediately instead of on the first\n  request. The driver itself does not require a token, so processes that\n  construct the transport without ever sending RPC are not forced to\n  configure one.\n\nBug fixes:\n- Thread the caller-specified retry count through send() to _send()\n  instead of always using the config default; the retry parameter was\n  accepted but silently ignored.\n- Honor the RPCClient contract where retry \u003c 0 (and the None default)\n  means retry forever. Previously range(times + 1) with times\u003d-1\n  produced range(0) -\u003e zero attempts, silently dropping the call.\n  Negative/None now iterates indefinitely (itertools.count) with the\n  backoff exponent capped to avoid overflow.\n- Move the _pack_context_with_message() call from\n  _select_target_service() to _send(), before the retry loop.\n  Previously context was packed on every retry attempt, double-nesting\n  the context dict on retries.\n- Protect the final retry attempt in retry_decorator with the same\n  exception handler as earlier attempts. Previously the last call ran\n  outside try/except, crashing on a final-attempt failure.\n- Add exponential backoff with jitter between retry attempts to avoid a\n  thundering herd under transient failures (0.5s base, 30s cap). The\n  jitter uses random.uniform (non-crypto, marked \u0027# nosec B311\u0027).\n- Replace the broken custom JSON serializer (__json_serialize) with\n  oslo_serialization.jsonutils, used consistently for serialization and\n  deserialization. The custom serializer converted strings to character\n  lists via hasattr(obj, \u0027__iter__\u0027) and duplicated datetime handling\n  that jsonutils already provides correctly.\n- Fix the double exchange prefix in service-name construction (e.g.\n  Ironic sets exchange\u003d\"ironic\" and topic\u003d\"ironic.conductor_manager\",\n  producing \"ironic.ironic.conductor_manager\"); _service_name() now\n  checks for an existing prefix before prepending.\n- Add a directed-RPC topic-splitting fallback for services that embed\n  the server name in the topic (e.g. topic\u003d\"conductor_manager.hostname\"\n  with target.server\u003dNone). Walk the dot-separated segments\n  (right-to-left) to find a valid base topic + server combination.\n- Classify an unavailable fanout relay as a transient delivery failure:\n  when no live broadcaster (\u0027fanout\u0027) Lease is found, _select_target_service\n  raises MessageDeliveryFailure instead of InvalidTarget, honoring the\n  caller\u0027s retry setting exactly as the rabbit driver does for an\n  unreachable broker. A fanout cast to a momentarily-unreachable relay\n  is a transient condition, not a permanent invalid target; InvalidTarget\n  (a ValueError subtype) caused callers such as neutron\u0027s ovo_rpc push to\n  treat a brief relay gap as fatal and abort event dispatch.\n- factory.create_app(): wire the fanout handler explicitly via\n  enable_fanout_handler\u003dFalse rather than implicitly probing the\n  optional [oslo_messaging_http_broadcaster] group, which raised\n  NoSuchOptError on the normal RPC-server path (only the broadcaster\n  registers that group). Create the handler once at app-creation time\n  instead of per request.\n- FanoutHandler: require an explicit \u0027service_name\u0027 field in the fanout\n  message and raise ValueError if it is missing, instead of silently\n  reconstructing exchange + \u0027.\u0027 + topic (which produced wrong targets\n  for topics that already embed the exchange).\n- RPCCastFanout: log the full traceback via LOG.exception and return a\n  generic \u0027Internal server error\u0027 (500) instead of echoing the raw\n  exception string to the client; stop logging request bodies in the\n  call/cast timeout paths to avoid leaking message payloads.\n- Import oslo_serialization.jsonutils in api.py (used by jsonutils.loads\n  but never imported).\n- Implement HTTPDriver.cleanup() to close the HTTPClient session and\n  release connection-pool resources; previously a no-op.\n\n- Align the ServiceBroker.get_services() abstract signature with its\n  implementations: ConsulOperator has accepted force_revalidate since\n  it was introduced and the Broadcaster passes fetch_all, but the\n  abstract method declared neither, and its docstring described\n  `service` as a Service object when callers pass a service-name\n  string. Declare both keyword parameters and correct the docstring so\n  the interface matches reality.\n\nQuality:\n- Downgrade per-request log messages from info to debug to reduce log\n  noise under production RPC load.\n- Replace Consul-hardcoded log messages in FanoutHandler with generic\n  \"service broker\" language for broker-agnostic operation.\n- Use a bare raise instead of raise err to preserve the original\n  traceback.\n- Use requests.Session for connection pooling instead of a per-call\n  requests.post.\n- Fix an assertIsNot(0, len(...)) identity check to assertGreater for a\n  correct value comparison in the unit tests.\n\nGenerated-By: claude-opus-4-6 (OpenCode)\nChange-Id: I6b2c89ee3f33d4be601b7ef001bdc7b7e39cdb9d\nSigned-off-by: flux.adam@gmail.com\n","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/cd8fff240c5965bb8c1cb1ced5f44b4bea661845"}],"resolve_conflicts_web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/cd8fff240c5965bb8c1cb1ced5f44b4bea661845"}]},"branch":"refs/heads/master"},"a18bc278c850e38c611ed5e069b2f07a56a47923":{"kind":"TRIVIAL_REBASE","_number":4,"created":"2026-06-30 08:45:06.000000000","uploader":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"real_uploader":{"_account_id":33451,"name":"Yushiro Furukawa","display_name":"Yushiro Furukawa","email":"yushiro.furukawa@lycorp.co.jp","username":"yushiro2"},"ref":"refs/changes/12/993312/4","fetch":{"anonymous http":{"url":"https://review.opendev.org/openstack/oslo.messaging","ref":"refs/changes/12/993312/4","commands":{"Checkout":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/4 \u0026\u0026 git checkout FETCH_HEAD","Cherry Pick":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/4 \u0026\u0026 git cherry-pick FETCH_HEAD","Format Patch":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/4 \u0026\u0026 git format-patch -1 --stdout FETCH_HEAD","Pull":"git pull https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/4"}}},"commit":{"parents":[{"commit":"a4ca301ea588dd58a3e64ea0d84b0a3f1c180714","subject":"Add DevStack plugin for HTTP driver","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/a4ca301ea588dd58a3e64ea0d84b0a3f1c180714"}]}],"author":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-06-15 08:47:43.000000000","tz":-240},"committer":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-06-30 08:45:06.000000000","tz":0},"subject":"HTTP-RPC driver: various fixes","message":"HTTP-RPC driver: various fixes\n\nAddress a number of bugs and quality issues in the HTTP transport\ndriver.\n\nSecurity:\n- Fix auth bypass when api_auth_token is not configured: the auth check\n  now rejects requests when the expected token is None/empty instead of\n  allowing all requests through.\n- Use hmac.compare_digest for constant-time token comparison to prevent\n  timing side-channel attacks.\n- Require api_auth_token at startup on the server: HTTPListenerBase\n  raises ConfigurationError when the token is empty (the Broadcaster is\n  covered transitively). A server with auth enabled fails closed (401)\n  without a token, so an empty token there is always a misconfiguration;\n  failing at startup surfaces it immediately instead of on the first\n  request. The driver itself does not require a token, so processes that\n  construct the transport without ever sending RPC are not forced to\n  configure one.\n\nBug fixes:\n- Thread the caller-specified retry count through send() to _send()\n  instead of always using the config default; the retry parameter was\n  accepted but silently ignored.\n- Honor the RPCClient contract where retry \u003c 0 (and the None default)\n  means retry forever. Previously range(times + 1) with times\u003d-1\n  produced range(0) -\u003e zero attempts, silently dropping the call.\n  Negative/None now iterates indefinitely (itertools.count) with the\n  backoff exponent capped to avoid overflow.\n- Move the _pack_context_with_message() call from\n  _select_target_service() to _send(), before the retry loop.\n  Previously context was packed on every retry attempt, double-nesting\n  the context dict on retries.\n- Protect the final retry attempt in retry_decorator with the same\n  exception handler as earlier attempts. Previously the last call ran\n  outside try/except, crashing on a final-attempt failure.\n- Add exponential backoff with jitter between retry attempts to avoid a\n  thundering herd under transient failures (0.5s base, 30s cap). The\n  jitter uses random.uniform (non-crypto, marked \u0027# nosec B311\u0027).\n- Replace the broken custom JSON serializer (__json_serialize) with\n  oslo_serialization.jsonutils, used consistently for serialization and\n  deserialization. The custom serializer converted strings to character\n  lists via hasattr(obj, \u0027__iter__\u0027) and duplicated datetime handling\n  that jsonutils already provides correctly.\n- Fix the double exchange prefix in service-name construction (e.g.\n  Ironic sets exchange\u003d\"ironic\" and topic\u003d\"ironic.conductor_manager\",\n  producing \"ironic.ironic.conductor_manager\"); _service_name() now\n  checks for an existing prefix before prepending.\n- Add a directed-RPC topic-splitting fallback for services that embed\n  the server name in the topic (e.g. topic\u003d\"conductor_manager.hostname\"\n  with target.server\u003dNone). Walk the dot-separated segments\n  (right-to-left) to find a valid base topic + server combination.\n- Classify an unavailable fanout relay as a transient delivery failure:\n  when no live broadcaster (\u0027fanout\u0027) Lease is found, _select_target_service\n  raises MessageDeliveryFailure instead of InvalidTarget, honoring the\n  caller\u0027s retry setting exactly as the rabbit driver does for an\n  unreachable broker. A fanout cast to a momentarily-unreachable relay\n  is a transient condition, not a permanent invalid target; InvalidTarget\n  (a ValueError subtype) caused callers such as neutron\u0027s ovo_rpc push to\n  treat a brief relay gap as fatal and abort event dispatch.\n- factory.create_app(): wire the fanout handler explicitly via\n  enable_fanout_handler\u003dFalse rather than implicitly probing the\n  optional [oslo_messaging_http_broadcaster] group, which raised\n  NoSuchOptError on the normal RPC-server path (only the broadcaster\n  registers that group). Create the handler once at app-creation time\n  instead of per request.\n- FanoutHandler: require an explicit \u0027service_name\u0027 field in the fanout\n  message and raise ValueError if it is missing, instead of silently\n  reconstructing exchange + \u0027.\u0027 + topic (which produced wrong targets\n  for topics that already embed the exchange).\n- RPCCastFanout: log the full traceback via LOG.exception and return a\n  generic \u0027Internal server error\u0027 (500) instead of echoing the raw\n  exception string to the client; stop logging request bodies in the\n  call/cast timeout paths to avoid leaking message payloads.\n- Import oslo_serialization.jsonutils in api.py (used by jsonutils.loads\n  but never imported).\n- Implement HTTPDriver.cleanup() to close the HTTPClient session and\n  release connection-pool resources; previously a no-op.\n\n- Align the ServiceBroker.get_services() abstract signature with its\n  implementations: ConsulOperator has accepted force_revalidate since\n  it was introduced and the Broadcaster passes fetch_all, but the\n  abstract method declared neither, and its docstring described\n  `service` as a Service object when callers pass a service-name\n  string. Declare both keyword parameters and correct the docstring so\n  the interface matches reality.\n\nQuality:\n- Downgrade per-request log messages from info to debug to reduce log\n  noise under production RPC load.\n- Replace Consul-hardcoded log messages in FanoutHandler with generic\n  \"service broker\" language for broker-agnostic operation.\n- Use a bare raise instead of raise err to preserve the original\n  traceback.\n- Use requests.Session for connection pooling instead of a per-call\n  requests.post.\n- Fix an assertIsNot(0, len(...)) identity check to assertGreater for a\n  correct value comparison in the unit tests.\n\nGenerated-By: claude-opus-4-6 (OpenCode)\nChange-Id: I6b2c89ee3f33d4be601b7ef001bdc7b7e39cdb9d\nSigned-off-by: flux.adam@gmail.com\n","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/a18bc278c850e38c611ed5e069b2f07a56a47923"}],"resolve_conflicts_web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/a18bc278c850e38c611ed5e069b2f07a56a47923"}]},"branch":"refs/heads/master","description":"Rebase","conflicts":{"base":"a67ca72efb18834776493a57823de58f0ab5cb90","ours":"cd8fff240c5965bb8c1cb1ced5f44b4bea661845","theirs":"a4ca301ea588dd58a3e64ea0d84b0a3f1c180714","merge_strategy":"recursive","contains_conflicts":false}},"c1dea48e678e06c309903aaa8bf280e18a04cb3f":{"kind":"TRIVIAL_REBASE","_number":5,"created":"2026-06-30 15:40:15.000000000","uploader":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"real_uploader":{"_account_id":33451,"name":"Yushiro Furukawa","display_name":"Yushiro Furukawa","email":"yushiro.furukawa@lycorp.co.jp","username":"yushiro2"},"ref":"refs/changes/12/993312/5","fetch":{"anonymous http":{"url":"https://review.opendev.org/openstack/oslo.messaging","ref":"refs/changes/12/993312/5","commands":{"Checkout":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/5 \u0026\u0026 git checkout FETCH_HEAD","Cherry Pick":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/5 \u0026\u0026 git cherry-pick FETCH_HEAD","Format Patch":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/5 \u0026\u0026 git format-patch -1 --stdout FETCH_HEAD","Pull":"git pull https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/5"}}},"commit":{"parents":[{"commit":"6f36cdb647aa9beeefee60c16c43ed7e215e3e70","subject":"Add DevStack plugin for HTTP driver","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/6f36cdb647aa9beeefee60c16c43ed7e215e3e70"}]}],"author":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-06-15 08:47:43.000000000","tz":-240},"committer":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-06-30 15:40:15.000000000","tz":0},"subject":"HTTP-RPC driver: various fixes","message":"HTTP-RPC driver: various fixes\n\nAddress a number of bugs and quality issues in the HTTP transport\ndriver.\n\nSecurity:\n- Fix auth bypass when api_auth_token is not configured: the auth check\n  now rejects requests when the expected token is None/empty instead of\n  allowing all requests through.\n- Use hmac.compare_digest for constant-time token comparison to prevent\n  timing side-channel attacks.\n- Require api_auth_token at startup on the server: HTTPListenerBase\n  raises ConfigurationError when the token is empty (the Broadcaster is\n  covered transitively). A server with auth enabled fails closed (401)\n  without a token, so an empty token there is always a misconfiguration;\n  failing at startup surfaces it immediately instead of on the first\n  request. The driver itself does not require a token, so processes that\n  construct the transport without ever sending RPC are not forced to\n  configure one.\n\nBug fixes:\n- Thread the caller-specified retry count through send() to _send()\n  instead of always using the config default; the retry parameter was\n  accepted but silently ignored.\n- Honor the RPCClient contract where retry \u003c 0 (and the None default)\n  means retry forever. Previously range(times + 1) with times\u003d-1\n  produced range(0) -\u003e zero attempts, silently dropping the call.\n  Negative/None now iterates indefinitely (itertools.count) with the\n  backoff exponent capped to avoid overflow.\n- Move the _pack_context_with_message() call from\n  _select_target_service() to _send(), before the retry loop.\n  Previously context was packed on every retry attempt, double-nesting\n  the context dict on retries.\n- Protect the final retry attempt in retry_decorator with the same\n  exception handler as earlier attempts. Previously the last call ran\n  outside try/except, crashing on a final-attempt failure.\n- Add exponential backoff with jitter between retry attempts to avoid a\n  thundering herd under transient failures (0.5s base, 30s cap). The\n  jitter uses random.uniform (non-crypto, marked \u0027# nosec B311\u0027).\n- Replace the broken custom JSON serializer (__json_serialize) with\n  oslo_serialization.jsonutils, used consistently for serialization and\n  deserialization. The custom serializer converted strings to character\n  lists via hasattr(obj, \u0027__iter__\u0027) and duplicated datetime handling\n  that jsonutils already provides correctly.\n- Fix the double exchange prefix in service-name construction (e.g.\n  Ironic sets exchange\u003d\"ironic\" and topic\u003d\"ironic.conductor_manager\",\n  producing \"ironic.ironic.conductor_manager\"); _service_name() now\n  checks for an existing prefix before prepending.\n- Add a directed-RPC topic-splitting fallback for services that embed\n  the server name in the topic (e.g. topic\u003d\"conductor_manager.hostname\"\n  with target.server\u003dNone). Walk the dot-separated segments\n  (right-to-left) to find a valid base topic + server combination.\n- Classify an unavailable fanout relay as a transient delivery failure:\n  when no live broadcaster (\u0027fanout\u0027) Lease is found, _select_target_service\n  raises MessageDeliveryFailure instead of InvalidTarget, honoring the\n  caller\u0027s retry setting exactly as the rabbit driver does for an\n  unreachable broker. A fanout cast to a momentarily-unreachable relay\n  is a transient condition, not a permanent invalid target; InvalidTarget\n  (a ValueError subtype) caused callers such as neutron\u0027s ovo_rpc push to\n  treat a brief relay gap as fatal and abort event dispatch.\n- factory.create_app(): wire the fanout handler explicitly via\n  enable_fanout_handler\u003dFalse rather than implicitly probing the\n  optional [oslo_messaging_http_broadcaster] group, which raised\n  NoSuchOptError on the normal RPC-server path (only the broadcaster\n  registers that group). Create the handler once at app-creation time\n  instead of per request.\n- FanoutHandler: require an explicit \u0027service_name\u0027 field in the fanout\n  message and raise ValueError if it is missing, instead of silently\n  reconstructing exchange + \u0027.\u0027 + topic (which produced wrong targets\n  for topics that already embed the exchange).\n- RPCCastFanout: log the full traceback via LOG.exception and return a\n  generic \u0027Internal server error\u0027 (500) instead of echoing the raw\n  exception string to the client; stop logging request bodies in the\n  call/cast timeout paths to avoid leaking message payloads.\n- Import oslo_serialization.jsonutils in api.py (used by jsonutils.loads\n  but never imported).\n- Implement HTTPDriver.cleanup() to close the HTTPClient session and\n  release connection-pool resources; previously a no-op.\n\n- Align the ServiceBroker.get_services() abstract signature with its\n  implementations: ConsulOperator has accepted force_revalidate since\n  it was introduced and the Broadcaster passes fetch_all, but the\n  abstract method declared neither, and its docstring described\n  `service` as a Service object when callers pass a service-name\n  string. Declare both keyword parameters and correct the docstring so\n  the interface matches reality.\n\nQuality:\n- Downgrade per-request log messages from info to debug to reduce log\n  noise under production RPC load.\n- Replace Consul-hardcoded log messages in FanoutHandler with generic\n  \"service broker\" language for broker-agnostic operation.\n- Use a bare raise instead of raise err to preserve the original\n  traceback.\n- Use requests.Session for connection pooling instead of a per-call\n  requests.post.\n- Fix an assertIsNot(0, len(...)) identity check to assertGreater for a\n  correct value comparison in the unit tests.\n\nGenerated-By: claude-opus-4-6 (OpenCode)\nChange-Id: I6b2c89ee3f33d4be601b7ef001bdc7b7e39cdb9d\nSigned-off-by: flux.adam@gmail.com\n","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/c1dea48e678e06c309903aaa8bf280e18a04cb3f"}],"resolve_conflicts_web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/c1dea48e678e06c309903aaa8bf280e18a04cb3f"}]},"branch":"refs/heads/master","description":"Rebase","conflicts":{"base":"a4ca301ea588dd58a3e64ea0d84b0a3f1c180714","ours":"a18bc278c850e38c611ed5e069b2f07a56a47923","theirs":"6f36cdb647aa9beeefee60c16c43ed7e215e3e70","merge_strategy":"recursive","contains_conflicts":false}},"a1a3631674fdef9de478fc6b42e08a5d5376150f":{"kind":"REWORK","_number":6,"created":"2026-07-08 05:36:24.000000000","uploader":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"ref":"refs/changes/12/993312/6","fetch":{"anonymous http":{"url":"https://review.opendev.org/openstack/oslo.messaging","ref":"refs/changes/12/993312/6","commands":{"Checkout":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/6 \u0026\u0026 git checkout FETCH_HEAD","Cherry Pick":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/6 \u0026\u0026 git cherry-pick FETCH_HEAD","Format Patch":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/6 \u0026\u0026 git format-patch -1 --stdout FETCH_HEAD","Pull":"git pull https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/6"}}},"commit":{"parents":[{"commit":"6f36cdb647aa9beeefee60c16c43ed7e215e3e70","subject":"Add DevStack plugin for HTTP driver","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/6f36cdb647aa9beeefee60c16c43ed7e215e3e70"}]}],"author":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-06-15 08:47:43.000000000","tz":-240},"committer":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-07-08 05:36:09.000000000","tz":-240},"subject":"HTTP-RPC driver: various fixes","message":"HTTP-RPC driver: various fixes\n\nAddress a number of bugs and quality issues in the HTTP transport\ndriver.\n\nSecurity:\n- Fix auth bypass when api_auth_token is not configured: the auth check\n  now rejects requests when the expected token is None/empty instead of\n  allowing all requests through.\n- Use hmac.compare_digest for constant-time token comparison to prevent\n  timing side-channel attacks.\n- Require api_auth_token at startup on the server: HTTPListenerBase\n  raises ConfigurationError when the token is empty (the Broadcaster is\n  covered transitively). A server with auth enabled fails closed (401)\n  without a token, so an empty token there is always a misconfiguration;\n  failing at startup surfaces it immediately instead of on the first\n  request. The driver itself does not require a token, so processes that\n  construct the transport without ever sending RPC are not forced to\n  configure one.\n\nBug fixes:\n- Thread the caller-specified retry count through send() to _send()\n  instead of always using the config default; the retry parameter was\n  accepted but silently ignored.\n- Honor the RPCClient contract where retry \u003c 0 (and the None default)\n  means retry forever. Previously range(times + 1) with times\u003d-1\n  produced range(0) -\u003e zero attempts, silently dropping the call.\n  Negative/None now iterates indefinitely (itertools.count) with the\n  backoff exponent capped to avoid overflow.\n- Move the _pack_context_with_message() call from\n  _select_target_service() to _send(), before the retry loop.\n  Previously context was packed on every retry attempt, double-nesting\n  the context dict on retries.\n- Protect the final retry attempt in retry_decorator with the same\n  exception handler as earlier attempts. Previously the last call ran\n  outside try/except, crashing on a final-attempt failure.\n- Add exponential backoff with jitter between retry attempts to avoid a\n  thundering herd under transient failures (0.5s base, 30s cap). The\n  jitter uses random.uniform (non-crypto, marked \u0027# nosec B311\u0027).\n- Replace the broken custom JSON serializer (__json_serialize) with\n  oslo_serialization.jsonutils, used consistently for serialization and\n  deserialization. The custom serializer converted strings to character\n  lists via hasattr(obj, \u0027__iter__\u0027) and duplicated datetime handling\n  that jsonutils already provides correctly.\n- Fix the double exchange prefix in service-name construction (e.g.\n  Ironic sets exchange\u003d\"ironic\" and topic\u003d\"ironic.conductor_manager\",\n  producing \"ironic.ironic.conductor_manager\"); _service_name() now\n  checks for an existing prefix before prepending.\n- Add a directed-RPC topic-splitting fallback for services that embed\n  the server name in the topic (e.g. topic\u003d\"conductor_manager.hostname\"\n  with target.server\u003dNone). Walk the dot-separated segments\n  (right-to-left) to find a valid base topic + server combination.\n- Classify an unavailable fanout relay as a transient delivery failure:\n  when no live broadcaster (\u0027fanout\u0027) Lease is found, _select_target_service\n  raises MessageDeliveryFailure instead of InvalidTarget, honoring the\n  caller\u0027s retry setting exactly as the rabbit driver does for an\n  unreachable broker. A fanout cast to a momentarily-unreachable relay\n  is a transient condition, not a permanent invalid target; InvalidTarget\n  (a ValueError subtype) caused callers such as neutron\u0027s ovo_rpc push to\n  treat a brief relay gap as fatal and abort event dispatch.\n- factory.create_app(): wire the fanout handler explicitly via\n  enable_fanout_handler\u003dFalse rather than implicitly probing the\n  optional [oslo_messaging_http_broadcaster] group, which raised\n  NoSuchOptError on the normal RPC-server path (only the broadcaster\n  registers that group). Create the handler once at app-creation time\n  instead of per request.\n- FanoutHandler: require an explicit \u0027service_name\u0027 field in the fanout\n  message and raise ValueError if it is missing, instead of silently\n  reconstructing exchange + \u0027.\u0027 + topic (which produced wrong targets\n  for topics that already embed the exchange).\n- RPCCastFanout: log the full traceback via LOG.exception and return a\n  generic \u0027Internal server error\u0027 (500) instead of echoing the raw\n  exception string to the client; stop logging request bodies in the\n  call/cast timeout paths to avoid leaking message payloads.\n- Import oslo_serialization.jsonutils in api.py (used by jsonutils.loads\n  but never imported).\n- Implement HTTPDriver.cleanup() to close the HTTPClient session and\n  release connection-pool resources; previously a no-op.\n\n- Align the ServiceBroker.get_services() abstract signature with its\n  implementations: ConsulOperator has accepted force_revalidate since\n  it was introduced and the Broadcaster passes fetch_all, but the\n  abstract method declared neither, and its docstring described\n  `service` as a Service object when callers pass a service-name\n  string. Declare both keyword parameters and correct the docstring so\n  the interface matches reality.\n\nQuality:\n- Downgrade per-request log messages from info to debug to reduce log\n  noise under production RPC load.\n- Replace Consul-hardcoded log messages in FanoutHandler with generic\n  \"service broker\" language for broker-agnostic operation.\n- Use a bare raise instead of raise err to preserve the original\n  traceback.\n- Use requests.Session for connection pooling instead of a per-call\n  requests.post.\n- Fix an assertIsNot(0, len(...)) identity check to assertGreater for a\n  correct value comparison in the unit tests.\n\nGenerated-By: claude-opus-4-6 (OpenCode)\nChange-Id: I6b2c89ee3f33d4be601b7ef001bdc7b7e39cdb9d\nSigned-off-by: flux.adam@gmail.com\n","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/a1a3631674fdef9de478fc6b42e08a5d5376150f"}],"resolve_conflicts_web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/a1a3631674fdef9de478fc6b42e08a5d5376150f"}]},"branch":"refs/heads/master"},"9dd590684cffc1c6a6ec252b672f4d2ee29335fc":{"kind":"REWORK","_number":7,"created":"2026-07-08 09:17:22.000000000","uploader":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"ref":"refs/changes/12/993312/7","fetch":{"anonymous http":{"url":"https://review.opendev.org/openstack/oslo.messaging","ref":"refs/changes/12/993312/7","commands":{"Checkout":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/7 \u0026\u0026 git checkout FETCH_HEAD","Cherry Pick":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/7 \u0026\u0026 git cherry-pick FETCH_HEAD","Format Patch":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/7 \u0026\u0026 git format-patch -1 --stdout FETCH_HEAD","Pull":"git pull https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/7"}}},"commit":{"parents":[{"commit":"6f36cdb647aa9beeefee60c16c43ed7e215e3e70","subject":"Add DevStack plugin for HTTP driver","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/6f36cdb647aa9beeefee60c16c43ed7e215e3e70"}]}],"author":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-06-15 08:47:43.000000000","tz":-240},"committer":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-07-08 08:35:45.000000000","tz":-240},"subject":"HTTP-RPC driver: various fixes","message":"HTTP-RPC driver: various fixes\n\nAddress a number of bugs and quality issues in the HTTP transport\ndriver.\n\nSecurity:\n- Fix auth bypass when api_auth_token is not configured: the auth check\n  now rejects requests when the expected token is None/empty instead of\n  allowing all requests through.\n- Use hmac.compare_digest for constant-time token comparison to prevent\n  timing side-channel attacks.\n- Require api_auth_token at startup on the server: HTTPListenerBase\n  raises ConfigurationError when the token is empty (the Broadcaster is\n  covered transitively). A server with auth enabled fails closed (401)\n  without a token, so an empty token there is always a misconfiguration;\n  failing at startup surfaces it immediately instead of on the first\n  request. The driver itself does not require a token, so processes that\n  construct the transport without ever sending RPC are not forced to\n  configure one.\n\nBug fixes:\n- Thread the caller-specified retry count through send() to _send()\n  instead of always using the config default; the retry parameter was\n  accepted but silently ignored.\n- Honor the RPCClient contract where retry \u003c 0 (and the None default)\n  means retry forever. Previously range(times + 1) with times\u003d-1\n  produced range(0) -\u003e zero attempts, silently dropping the call.\n  Negative/None now iterates indefinitely (itertools.count) with the\n  backoff exponent capped to avoid overflow.\n- Move the _pack_context_with_message() call from\n  _select_target_service() to _send(), before the retry loop.\n  Previously context was packed on every retry attempt, double-nesting\n  the context dict on retries.\n- Protect the final retry attempt in retry_decorator with the same\n  exception handler as earlier attempts. Previously the last call ran\n  outside try/except, crashing on a final-attempt failure.\n- Add exponential backoff with jitter between retry attempts to avoid a\n  thundering herd under transient failures (0.5s base, 30s cap). The\n  jitter uses random.uniform (non-crypto, marked \u0027# nosec B311\u0027).\n- Replace the broken custom JSON serializer (__json_serialize) with\n  oslo_serialization.jsonutils, used consistently for serialization and\n  deserialization. The custom serializer converted strings to character\n  lists via hasattr(obj, \u0027__iter__\u0027) and duplicated datetime handling\n  that jsonutils already provides correctly.\n- Fix the double exchange prefix in service-name construction (e.g.\n  Ironic sets exchange\u003d\"ironic\" and topic\u003d\"ironic.conductor_manager\",\n  producing \"ironic.ironic.conductor_manager\"); _service_name() now\n  checks for an existing prefix before prepending.\n- Add a directed-RPC topic-splitting fallback for services that embed\n  the server name in the topic (e.g. topic\u003d\"conductor_manager.hostname\"\n  with target.server\u003dNone). Walk the dot-separated segments\n  (right-to-left) to find a valid base topic + server combination.\n- Classify an unavailable fanout relay as a transient delivery failure:\n  when no live broadcaster (\u0027fanout\u0027) Lease is found, _select_target_service\n  raises MessageDeliveryFailure instead of InvalidTarget, honoring the\n  caller\u0027s retry setting exactly as the rabbit driver does for an\n  unreachable broker. A fanout cast to a momentarily-unreachable relay\n  is a transient condition, not a permanent invalid target; InvalidTarget\n  (a ValueError subtype) caused callers such as neutron\u0027s ovo_rpc push to\n  treat a brief relay gap as fatal and abort event dispatch.\n- factory.create_app(): wire the fanout handler explicitly via\n  enable_fanout_handler\u003dFalse rather than implicitly probing the\n  optional [oslo_messaging_http_broadcaster] group, which raised\n  NoSuchOptError on the normal RPC-server path (only the broadcaster\n  registers that group). Create the handler once at app-creation time\n  instead of per request.\n- FanoutHandler: require an explicit \u0027service_name\u0027 field in the fanout\n  message and raise ValueError if it is missing, instead of silently\n  reconstructing exchange + \u0027.\u0027 + topic (which produced wrong targets\n  for topics that already embed the exchange).\n- RPCCastFanout: log the full traceback via LOG.exception and return a\n  generic \u0027Internal server error\u0027 (500) instead of echoing the raw\n  exception string to the client; stop logging request bodies in the\n  call/cast timeout paths to avoid leaking message payloads.\n- Import oslo_serialization.jsonutils in api.py (used by jsonutils.loads\n  but never imported).\n- Implement HTTPDriver.cleanup() to close the HTTPClient session and\n  release connection-pool resources; previously a no-op.\n\n- Align the ServiceBroker.get_services() abstract signature with its\n  implementations: ConsulOperator has accepted force_revalidate since\n  it was introduced and the Broadcaster passes fetch_all, but the\n  abstract method declared neither, and its docstring described\n  `service` as a Service object when callers pass a service-name\n  string. Declare both keyword parameters and correct the docstring so\n  the interface matches reality.\n\nQuality:\n- Downgrade per-request log messages from info to debug to reduce log\n  noise under production RPC load.\n- Replace Consul-hardcoded log messages in FanoutHandler with generic\n  \"service broker\" language for broker-agnostic operation.\n- Use a bare raise instead of raise err to preserve the original\n  traceback.\n- Use requests.Session for connection pooling instead of a per-call\n  requests.post.\n- Fix an assertIsNot(0, len(...)) identity check to assertGreater for a\n  correct value comparison in the unit tests.\n\nGenerated-By: claude-opus-4-6 (OpenCode)\nChange-Id: I6b2c89ee3f33d4be601b7ef001bdc7b7e39cdb9d\nSigned-off-by: flux.adam@gmail.com\n","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/9dd590684cffc1c6a6ec252b672f4d2ee29335fc"}],"resolve_conflicts_web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/9dd590684cffc1c6a6ec252b672f4d2ee29335fc"}]},"branch":"refs/heads/master"},"03578246912d2752bb7c35f9074a29fd078349ee":{"kind":"REWORK","_number":8,"created":"2026-07-08 18:29:33.000000000","uploader":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"ref":"refs/changes/12/993312/8","fetch":{"anonymous http":{"url":"https://review.opendev.org/openstack/oslo.messaging","ref":"refs/changes/12/993312/8","commands":{"Checkout":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/8 \u0026\u0026 git checkout FETCH_HEAD","Cherry Pick":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/8 \u0026\u0026 git cherry-pick FETCH_HEAD","Format Patch":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/8 \u0026\u0026 git format-patch -1 --stdout FETCH_HEAD","Pull":"git pull https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/8"}}},"commit":{"parents":[{"commit":"6f36cdb647aa9beeefee60c16c43ed7e215e3e70","subject":"Add DevStack plugin for HTTP driver","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/6f36cdb647aa9beeefee60c16c43ed7e215e3e70"}]}],"author":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-06-15 08:47:43.000000000","tz":-240},"committer":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-07-08 18:26:19.000000000","tz":-240},"subject":"HTTP-RPC driver: various fixes","message":"HTTP-RPC driver: various fixes\n\nAddress a number of bugs and quality issues in the HTTP transport\ndriver.\n\nSecurity:\n- Fix auth bypass when api_auth_token is not configured: the auth check\n  now rejects requests when the expected token is None/empty instead of\n  allowing all requests through.\n- Use hmac.compare_digest for constant-time token comparison to prevent\n  timing side-channel attacks.\n- Require api_auth_token at startup on the server: HTTPListenerBase\n  raises ConfigurationError when the token is empty (the Broadcaster is\n  covered transitively). A server with auth enabled fails closed (401)\n  without a token, so an empty token there is always a misconfiguration;\n  failing at startup surfaces it immediately instead of on the first\n  request. The driver itself does not require a token, so processes that\n  construct the transport without ever sending RPC are not forced to\n  configure one.\n\nBug fixes:\n- Thread the caller-specified retry count through send() to _send()\n  instead of always using the config default; the retry parameter was\n  accepted but silently ignored.\n- Honor the RPCClient contract where retry \u003c 0 (and the None default)\n  means retry forever. Previously range(times + 1) with times\u003d-1\n  produced range(0) -\u003e zero attempts, silently dropping the call.\n  Negative/None now iterates indefinitely (itertools.count) with the\n  backoff exponent capped to avoid overflow.\n- Move the _pack_context_with_message() call from\n  _select_target_service() to _send(), before the retry loop.\n  Previously context was packed on every retry attempt, double-nesting\n  the context dict on retries.\n- Protect the final retry attempt in retry_decorator with the same\n  exception handler as earlier attempts. Previously the last call ran\n  outside try/except, crashing on a final-attempt failure.\n- Add exponential backoff with jitter between retry attempts to avoid a\n  thundering herd under transient failures (0.5s base, 30s cap). The\n  jitter uses random.uniform (non-crypto, marked \u0027# nosec B311\u0027).\n- Replace the broken custom JSON serializer (__json_serialize) with\n  oslo_serialization.jsonutils, used consistently for serialization and\n  deserialization. The custom serializer converted strings to character\n  lists via hasattr(obj, \u0027__iter__\u0027) and duplicated datetime handling\n  that jsonutils already provides correctly.\n- Fix the double exchange prefix in service-name construction (e.g.\n  Ironic sets exchange\u003d\"ironic\" and topic\u003d\"ironic.conductor_manager\",\n  producing \"ironic.ironic.conductor_manager\"); _service_name() now\n  checks for an existing prefix before prepending.\n- Add a directed-RPC topic-splitting fallback for services that embed\n  the server name in the topic (e.g. topic\u003d\"conductor_manager.hostname\"\n  with target.server\u003dNone). Walk the dot-separated segments\n  (right-to-left) to find a valid base topic + server combination.\n- Classify an unavailable fanout relay as a transient delivery failure:\n  when no live broadcaster (\u0027fanout\u0027) Lease is found, _select_target_service\n  raises MessageDeliveryFailure instead of InvalidTarget, honoring the\n  caller\u0027s retry setting exactly as the rabbit driver does for an\n  unreachable broker. A fanout cast to a momentarily-unreachable relay\n  is a transient condition, not a permanent invalid target; InvalidTarget\n  (a ValueError subtype) caused callers such as neutron\u0027s ovo_rpc push to\n  treat a brief relay gap as fatal and abort event dispatch.\n- factory.create_app(): wire the fanout handler explicitly via\n  enable_fanout_handler\u003dFalse rather than implicitly probing the\n  optional [oslo_messaging_http_broadcaster] group, which raised\n  NoSuchOptError on the normal RPC-server path (only the broadcaster\n  registers that group). Create the handler once at app-creation time\n  instead of per request.\n- FanoutHandler: require an explicit \u0027service_name\u0027 field in the fanout\n  message and raise ValueError if it is missing, instead of silently\n  reconstructing exchange + \u0027.\u0027 + topic (which produced wrong targets\n  for topics that already embed the exchange).\n- RPCCastFanout: log the full traceback via LOG.exception and return a\n  generic \u0027Internal server error\u0027 (500) instead of echoing the raw\n  exception string to the client; stop logging request bodies in the\n  call/cast timeout paths to avoid leaking message payloads.\n- Import oslo_serialization.jsonutils in api.py (used by jsonutils.loads\n  but never imported).\n- Implement HTTPDriver.cleanup() to close the HTTPClient session and\n  release connection-pool resources; previously a no-op.\n\n- Align the ServiceBroker.get_services() abstract signature with its\n  implementations: ConsulOperator has accepted force_revalidate since\n  it was introduced and the Broadcaster passes fetch_all, but the\n  abstract method declared neither, and its docstring described\n  `service` as a Service object when callers pass a service-name\n  string. Declare both keyword parameters and correct the docstring so\n  the interface matches reality.\n\nQuality:\n- Downgrade per-request log messages from info to debug to reduce log\n  noise under production RPC load.\n- Replace Consul-hardcoded log messages in FanoutHandler with generic\n  \"service broker\" language for broker-agnostic operation.\n- Use a bare raise instead of raise err to preserve the original\n  traceback.\n- Use requests.Session for connection pooling instead of a per-call\n  requests.post.\n- Fix an assertIsNot(0, len(...)) identity check to assertGreater for a\n  correct value comparison in the unit tests.\n\nGenerated-By: claude-opus-4-6 (OpenCode)\nChange-Id: I6b2c89ee3f33d4be601b7ef001bdc7b7e39cdb9d\nSigned-off-by: flux.adam@gmail.com\nSigned-off-by: Adam Harwell \u003cflux.adam@gmail.com\u003e\n","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/03578246912d2752bb7c35f9074a29fd078349ee"}],"resolve_conflicts_web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/03578246912d2752bb7c35f9074a29fd078349ee"}]},"branch":"refs/heads/master"},"7b7e96a3e8f0c93bc04ee947863adaa05f107393":{"kind":"REWORK","_number":9,"created":"2026-07-08 18:52:42.000000000","uploader":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"ref":"refs/changes/12/993312/9","fetch":{"anonymous http":{"url":"https://review.opendev.org/openstack/oslo.messaging","ref":"refs/changes/12/993312/9","commands":{"Checkout":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/9 \u0026\u0026 git checkout FETCH_HEAD","Cherry Pick":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/9 \u0026\u0026 git cherry-pick FETCH_HEAD","Format Patch":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/9 \u0026\u0026 git format-patch -1 --stdout FETCH_HEAD","Pull":"git pull https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/9"}}},"commit":{"parents":[{"commit":"6f36cdb647aa9beeefee60c16c43ed7e215e3e70","subject":"Add DevStack plugin for HTTP driver","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/6f36cdb647aa9beeefee60c16c43ed7e215e3e70"}]}],"author":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-06-15 08:47:43.000000000","tz":-240},"committer":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-07-08 18:47:35.000000000","tz":-240},"subject":"HTTP-RPC driver: various fixes","message":"HTTP-RPC driver: various fixes\n\nAddress a number of bugs and quality issues in the HTTP transport\ndriver.\n\nSecurity:\n- Fix auth bypass when api_auth_token is not configured: the auth check\n  now rejects requests when the expected token is None/empty instead of\n  allowing all requests through.\n- Use hmac.compare_digest for constant-time token comparison to prevent\n  timing side-channel attacks.\n- Require api_auth_token at startup on the server: HTTPListenerBase\n  raises ConfigurationError when the token is empty (the Broadcaster is\n  covered transitively). A server with auth enabled fails closed (401)\n  without a token, so an empty token there is always a misconfiguration;\n  failing at startup surfaces it immediately instead of on the first\n  request. The driver itself does not require a token, so processes that\n  construct the transport without ever sending RPC are not forced to\n  configure one.\n\nBug fixes:\n- Thread the caller-specified retry count through send() to _send()\n  instead of always using the config default; the retry parameter was\n  accepted but silently ignored.\n- Honor the RPCClient contract where retry \u003c 0 (and the None default)\n  means retry forever. Previously range(times + 1) with times\u003d-1\n  produced range(0) -\u003e zero attempts, silently dropping the call.\n  Negative/None now iterates indefinitely (itertools.count) with the\n  backoff exponent capped to avoid overflow.\n- Move the _pack_context_with_message() call from\n  _select_target_service() to _send(), before the retry loop.\n  Previously context was packed on every retry attempt, double-nesting\n  the context dict on retries.\n- Protect the final retry attempt in retry_decorator with the same\n  exception handler as earlier attempts. Previously the last call ran\n  outside try/except, crashing on a final-attempt failure.\n- Add exponential backoff with jitter between retry attempts to avoid a\n  thundering herd under transient failures (0.5s base, 30s cap). The\n  jitter uses random.uniform (non-crypto, marked \u0027# nosec B311\u0027).\n- Replace the broken custom JSON serializer (__json_serialize) with\n  oslo_serialization.jsonutils, used consistently for serialization and\n  deserialization. The custom serializer converted strings to character\n  lists via hasattr(obj, \u0027__iter__\u0027) and duplicated datetime handling\n  that jsonutils already provides correctly.\n- Fix the double exchange prefix in service-name construction (e.g.\n  Ironic sets exchange\u003d\"ironic\" and topic\u003d\"ironic.conductor_manager\",\n  producing \"ironic.ironic.conductor_manager\"); _service_name() now\n  checks for an existing prefix before prepending.\n- Add a directed-RPC topic-splitting fallback for services that embed\n  the server name in the topic (e.g. topic\u003d\"conductor_manager.hostname\"\n  with target.server\u003dNone). Walk the dot-separated segments\n  (right-to-left) to find a valid base topic + server combination.\n- Classify an unavailable fanout relay as a transient delivery failure:\n  when no live broadcaster (\u0027fanout\u0027) Lease is found, _select_target_service\n  raises MessageDeliveryFailure instead of InvalidTarget, honoring the\n  caller\u0027s retry setting exactly as the rabbit driver does for an\n  unreachable broker. A fanout cast to a momentarily-unreachable relay\n  is a transient condition, not a permanent invalid target; InvalidTarget\n  (a ValueError subtype) caused callers such as neutron\u0027s ovo_rpc push to\n  treat a brief relay gap as fatal and abort event dispatch.\n- factory.create_app(): wire the fanout handler explicitly via\n  enable_fanout_handler\u003dFalse rather than implicitly probing the\n  optional [oslo_messaging_http_broadcaster] group, which raised\n  NoSuchOptError on the normal RPC-server path (only the broadcaster\n  registers that group). Create the handler once at app-creation time\n  instead of per request.\n- FanoutHandler: require an explicit \u0027service_name\u0027 field in the fanout\n  message and raise ValueError if it is missing, instead of silently\n  reconstructing exchange + \u0027.\u0027 + topic (which produced wrong targets\n  for topics that already embed the exchange).\n- RPCCastFanout: log the full traceback via LOG.exception and return a\n  generic \u0027Internal server error\u0027 (500) instead of echoing the raw\n  exception string to the client; stop logging request bodies in the\n  call/cast timeout paths to avoid leaking message payloads.\n- Import oslo_serialization.jsonutils in api.py (used by jsonutils.loads\n  but never imported).\n- Implement HTTPDriver.cleanup() to close the HTTPClient session and\n  release connection-pool resources; previously a no-op.\n\n- Align the ServiceBroker.get_services() abstract signature with its\n  implementations: ConsulOperator has accepted force_revalidate since\n  it was introduced and the Broadcaster passes fetch_all, but the\n  abstract method declared neither, and its docstring described\n  `service` as a Service object when callers pass a service-name\n  string. Declare both keyword parameters and correct the docstring so\n  the interface matches reality.\n\nQuality:\n- Downgrade per-request log messages from info to debug to reduce log\n  noise under production RPC load.\n- Replace Consul-hardcoded log messages in FanoutHandler with generic\n  \"service broker\" language for broker-agnostic operation.\n- Use a bare raise instead of raise err to preserve the original\n  traceback.\n- Use requests.Session for connection pooling instead of a per-call\n  requests.post.\n- Fix an assertIsNot(0, len(...)) identity check to assertGreater for a\n  correct value comparison in the unit tests.\n\nGenerated-By: claude-opus-4-6 (OpenCode)\nChange-Id: I6b2c89ee3f33d4be601b7ef001bdc7b7e39cdb9d\nSigned-off-by: flux.adam@gmail.com\nSigned-off-by: Adam Harwell \u003cflux.adam@gmail.com\u003e\n","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/7b7e96a3e8f0c93bc04ee947863adaa05f107393"}],"resolve_conflicts_web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/7b7e96a3e8f0c93bc04ee947863adaa05f107393"}]},"branch":"refs/heads/master"},"2d79a928986a8505810321d525c332b69aad1094":{"kind":"REWORK","_number":10,"created":"2026-07-09 05:21:59.000000000","uploader":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"ref":"refs/changes/12/993312/10","fetch":{"anonymous http":{"url":"https://review.opendev.org/openstack/oslo.messaging","ref":"refs/changes/12/993312/10","commands":{"Checkout":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/10 \u0026\u0026 git checkout FETCH_HEAD","Cherry Pick":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/10 \u0026\u0026 git cherry-pick FETCH_HEAD","Format Patch":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/10 \u0026\u0026 git format-patch -1 --stdout FETCH_HEAD","Pull":"git pull https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/10"}}},"commit":{"parents":[{"commit":"6f36cdb647aa9beeefee60c16c43ed7e215e3e70","subject":"Add DevStack plugin for HTTP driver","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/6f36cdb647aa9beeefee60c16c43ed7e215e3e70"}]}],"author":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-06-15 08:47:43.000000000","tz":-240},"committer":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-07-09 05:00:35.000000000","tz":-240},"subject":"HTTP-RPC driver: various fixes","message":"HTTP-RPC driver: various fixes\n\nAddress a number of bugs and quality issues in the HTTP transport\ndriver.\n\nSecurity:\n- Fix auth bypass when api_auth_token is not configured: the auth check\n  now rejects requests when the expected token is None/empty instead of\n  allowing all requests through.\n- Use hmac.compare_digest for constant-time token comparison to prevent\n  timing side-channel attacks.\n- Require api_auth_token at startup on the server: HTTPListenerBase\n  raises ConfigurationError when the token is empty (the Broadcaster is\n  covered transitively). A server with auth enabled fails closed (401)\n  without a token, so an empty token there is always a misconfiguration;\n  failing at startup surfaces it immediately instead of on the first\n  request. The driver itself does not require a token, so processes that\n  construct the transport without ever sending RPC are not forced to\n  configure one.\n\nBug fixes:\n- Thread the caller-specified retry count through send() to _send()\n  instead of always using the config default; the retry parameter was\n  accepted but silently ignored.\n- Honor the RPCClient contract where retry \u003c 0 (and the None default)\n  means retry forever. Previously range(times + 1) with times\u003d-1\n  produced range(0) -\u003e zero attempts, silently dropping the call.\n  Negative/None now iterates indefinitely (itertools.count) with the\n  backoff exponent capped to avoid overflow.\n- Move the _pack_context_with_message() call from\n  _select_target_service() to _send(), before the retry loop.\n  Previously context was packed on every retry attempt, double-nesting\n  the context dict on retries.\n- Protect the final retry attempt in retry_decorator with the same\n  exception handler as earlier attempts. Previously the last call ran\n  outside try/except, crashing on a final-attempt failure.\n- Add exponential backoff with jitter between retry attempts to avoid a\n  thundering herd under transient failures (0.5s base, 30s cap). The\n  jitter uses random.uniform (non-crypto, marked \u0027# nosec B311\u0027).\n- Replace the broken custom JSON serializer (__json_serialize) with\n  oslo_serialization.jsonutils, used consistently for serialization and\n  deserialization. The custom serializer converted strings to character\n  lists via hasattr(obj, \u0027__iter__\u0027) and duplicated datetime handling\n  that jsonutils already provides correctly.\n- Fix the double exchange prefix in service-name construction (e.g.\n  Ironic sets exchange\u003d\"ironic\" and topic\u003d\"ironic.conductor_manager\",\n  producing \"ironic.ironic.conductor_manager\"); _service_name() now\n  checks for an existing prefix before prepending.\n- Add a directed-RPC topic-splitting fallback for services that embed\n  the server name in the topic (e.g. topic\u003d\"conductor_manager.hostname\"\n  with target.server\u003dNone). Walk the dot-separated segments\n  (right-to-left) to find a valid base topic + server combination.\n- Classify an unavailable fanout relay as a transient delivery failure:\n  when no live broadcaster (\u0027fanout\u0027) Lease is found, _select_target_service\n  raises MessageDeliveryFailure instead of InvalidTarget, honoring the\n  caller\u0027s retry setting exactly as the rabbit driver does for an\n  unreachable broker. A fanout cast to a momentarily-unreachable relay\n  is a transient condition, not a permanent invalid target; InvalidTarget\n  (a ValueError subtype) caused callers such as neutron\u0027s ovo_rpc push to\n  treat a brief relay gap as fatal and abort event dispatch.\n- factory.create_app(): wire the fanout handler explicitly via\n  enable_fanout_handler\u003dFalse rather than implicitly probing the\n  optional [oslo_messaging_http_broadcaster] group, which raised\n  NoSuchOptError on the normal RPC-server path (only the broadcaster\n  registers that group). Create the handler once at app-creation time\n  instead of per request.\n- FanoutHandler: require an explicit \u0027service_name\u0027 field in the fanout\n  message and raise ValueError if it is missing, instead of silently\n  reconstructing exchange + \u0027.\u0027 + topic (which produced wrong targets\n  for topics that already embed the exchange).\n- RPCCastFanout: log the full traceback via LOG.exception and return a\n  generic \u0027Internal server error\u0027 (500) instead of echoing the raw\n  exception string to the client; stop logging request bodies in the\n  call/cast timeout paths to avoid leaking message payloads.\n- Import oslo_serialization.jsonutils in api.py (used by jsonutils.loads\n  but never imported).\n- Implement HTTPDriver.cleanup() to close the HTTPClient session and\n  release connection-pool resources; previously a no-op.\n\n- Align the ServiceBroker.get_services() abstract signature with its\n  implementations: ConsulOperator has accepted force_revalidate since\n  it was introduced and the Broadcaster passes fetch_all, but the\n  abstract method declared neither, and its docstring described\n  `service` as a Service object when callers pass a service-name\n  string. Declare both keyword parameters and correct the docstring so\n  the interface matches reality.\n\nQuality:\n- Downgrade per-request log messages from info to debug to reduce log\n  noise under production RPC load.\n- Replace Consul-hardcoded log messages in FanoutHandler with generic\n  \"service broker\" language for broker-agnostic operation.\n- Use a bare raise instead of raise err to preserve the original\n  traceback.\n- Use requests.Session for connection pooling instead of a per-call\n  requests.post.\n- Fix an assertIsNot(0, len(...)) identity check to assertGreater for a\n  correct value comparison in the unit tests.\n\nGenerated-By: claude-opus-4-6 (OpenCode)\nChange-Id: I6b2c89ee3f33d4be601b7ef001bdc7b7e39cdb9d\nSigned-off-by: flux.adam@gmail.com\nSigned-off-by: Adam Harwell \u003cflux.adam@gmail.com\u003e\n","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/2d79a928986a8505810321d525c332b69aad1094"}],"resolve_conflicts_web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/2d79a928986a8505810321d525c332b69aad1094"}]},"branch":"refs/heads/master"},"02aafab04cc26ab40dcc00f6dda37b73051f79d3":{"kind":"REWORK","_number":11,"created":"2026-07-09 10:17:59.000000000","uploader":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"ref":"refs/changes/12/993312/11","fetch":{"anonymous http":{"url":"https://review.opendev.org/openstack/oslo.messaging","ref":"refs/changes/12/993312/11","commands":{"Checkout":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/11 \u0026\u0026 git checkout FETCH_HEAD","Cherry Pick":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/11 \u0026\u0026 git cherry-pick FETCH_HEAD","Format Patch":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/11 \u0026\u0026 git format-patch -1 --stdout FETCH_HEAD","Pull":"git pull https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/11"}}},"commit":{"parents":[{"commit":"6f36cdb647aa9beeefee60c16c43ed7e215e3e70","subject":"Add DevStack plugin for HTTP driver","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/6f36cdb647aa9beeefee60c16c43ed7e215e3e70"}]}],"author":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-06-15 08:47:43.000000000","tz":-240},"committer":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-07-09 09:44:40.000000000","tz":-240},"subject":"HTTP-RPC driver: various fixes","message":"HTTP-RPC driver: various fixes\n\nAddress a number of bugs and quality issues in the HTTP transport\ndriver.\n\nSecurity:\n- Fix auth bypass when api_auth_token is not configured: the auth check\n  now rejects requests when the expected token is None/empty instead of\n  allowing all requests through.\n- Use hmac.compare_digest for constant-time token comparison to prevent\n  timing side-channel attacks.\n- Require api_auth_token at startup on the server: HTTPListenerBase\n  raises ConfigurationError when the token is empty (the Broadcaster is\n  covered transitively). A server with auth enabled fails closed (401)\n  without a token, so an empty token there is always a misconfiguration;\n  failing at startup surfaces it immediately instead of on the first\n  request. The driver itself does not require a token, so processes that\n  construct the transport without ever sending RPC are not forced to\n  configure one.\n\nBug fixes:\n- Thread the caller-specified retry count through send() to _send()\n  instead of always using the config default; the retry parameter was\n  accepted but silently ignored.\n- Honor the RPCClient contract where retry \u003c 0 (and the None default)\n  means retry forever. Previously range(times + 1) with times\u003d-1\n  produced range(0) -\u003e zero attempts, silently dropping the call.\n  Negative/None now iterates indefinitely (itertools.count) with the\n  backoff exponent capped to avoid overflow.\n- Move the _pack_context_with_message() call from\n  _select_target_service() to _send(), before the retry loop.\n  Previously context was packed on every retry attempt, double-nesting\n  the context dict on retries.\n- Protect the final retry attempt in retry_decorator with the same\n  exception handler as earlier attempts. Previously the last call ran\n  outside try/except, crashing on a final-attempt failure.\n- Add exponential backoff with jitter between retry attempts to avoid a\n  thundering herd under transient failures (0.5s base, 30s cap). The\n  jitter uses random.uniform (non-crypto, marked \u0027# nosec B311\u0027).\n- Replace the broken custom JSON serializer (__json_serialize) with\n  oslo_serialization.jsonutils, used consistently for serialization and\n  deserialization. The custom serializer converted strings to character\n  lists via hasattr(obj, \u0027__iter__\u0027) and duplicated datetime handling\n  that jsonutils already provides correctly.\n- Fix the double exchange prefix in service-name construction (e.g.\n  Ironic sets exchange\u003d\"ironic\" and topic\u003d\"ironic.conductor_manager\",\n  producing \"ironic.ironic.conductor_manager\"); _service_name() now\n  checks for an existing prefix before prepending.\n- Add a directed-RPC topic-splitting fallback for services that embed\n  the server name in the topic (e.g. topic\u003d\"conductor_manager.hostname\"\n  with target.server\u003dNone). Walk the dot-separated segments\n  (right-to-left) to find a valid base topic + server combination.\n- Classify an unavailable fanout relay as a transient delivery failure:\n  when no live broadcaster (\u0027fanout\u0027) Lease is found, _select_target_service\n  raises MessageDeliveryFailure instead of InvalidTarget, honoring the\n  caller\u0027s retry setting exactly as the rabbit driver does for an\n  unreachable broker. A fanout cast to a momentarily-unreachable relay\n  is a transient condition, not a permanent invalid target; InvalidTarget\n  (a ValueError subtype) caused callers such as neutron\u0027s ovo_rpc push to\n  treat a brief relay gap as fatal and abort event dispatch.\n- factory.create_app(): wire the fanout handler explicitly via\n  enable_fanout_handler\u003dFalse rather than implicitly probing the\n  optional [oslo_messaging_http_broadcaster] group, which raised\n  NoSuchOptError on the normal RPC-server path (only the broadcaster\n  registers that group). Create the handler once at app-creation time\n  instead of per request.\n- FanoutHandler: require an explicit \u0027service_name\u0027 field in the fanout\n  message and raise ValueError if it is missing, instead of silently\n  reconstructing exchange + \u0027.\u0027 + topic (which produced wrong targets\n  for topics that already embed the exchange).\n- RPCCastFanout: log the full traceback via LOG.exception and return a\n  generic \u0027Internal server error\u0027 (500) instead of echoing the raw\n  exception string to the client; stop logging request bodies in the\n  call/cast timeout paths to avoid leaking message payloads.\n- Import oslo_serialization.jsonutils in api.py (used by jsonutils.loads\n  but never imported).\n- Implement HTTPDriver.cleanup() to close the HTTPClient session and\n  release connection-pool resources; previously a no-op.\n\n- Align the ServiceBroker.get_services() abstract signature with its\n  implementations: ConsulOperator has accepted force_revalidate since\n  it was introduced and the Broadcaster passes fetch_all, but the\n  abstract method declared neither, and its docstring described\n  `service` as a Service object when callers pass a service-name\n  string. Declare both keyword parameters and correct the docstring so\n  the interface matches reality.\n\nQuality:\n- Downgrade per-request log messages from info to debug to reduce log\n  noise under production RPC load.\n- Replace Consul-hardcoded log messages in FanoutHandler with generic\n  \"service broker\" language for broker-agnostic operation.\n- Use a bare raise instead of raise err to preserve the original\n  traceback.\n- Use requests.Session for connection pooling instead of a per-call\n  requests.post.\n- Fix an assertIsNot(0, len(...)) identity check to assertGreater for a\n  correct value comparison in the unit tests.\n\nGenerated-By: claude-opus-4-6 (OpenCode)\nChange-Id: I6b2c89ee3f33d4be601b7ef001bdc7b7e39cdb9d\nSigned-off-by: flux.adam@gmail.com\nSigned-off-by: Adam Harwell \u003cflux.adam@gmail.com\u003e\n","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/02aafab04cc26ab40dcc00f6dda37b73051f79d3"}],"resolve_conflicts_web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/02aafab04cc26ab40dcc00f6dda37b73051f79d3"}]},"branch":"refs/heads/master"},"af08014e5d34149f650d479b8904956a3795e7ca":{"kind":"REWORK","_number":12,"created":"2026-07-09 10:47:30.000000000","uploader":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"ref":"refs/changes/12/993312/12","fetch":{"anonymous http":{"url":"https://review.opendev.org/openstack/oslo.messaging","ref":"refs/changes/12/993312/12","commands":{"Checkout":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/12 \u0026\u0026 git checkout FETCH_HEAD","Cherry Pick":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/12 \u0026\u0026 git cherry-pick FETCH_HEAD","Format Patch":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/12 \u0026\u0026 git format-patch -1 --stdout FETCH_HEAD","Pull":"git pull https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/12"}}},"commit":{"parents":[{"commit":"6f36cdb647aa9beeefee60c16c43ed7e215e3e70","subject":"Add DevStack plugin for HTTP driver","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/6f36cdb647aa9beeefee60c16c43ed7e215e3e70"}]}],"author":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-06-15 08:47:43.000000000","tz":-240},"committer":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-07-09 10:45:58.000000000","tz":-240},"subject":"HTTP-RPC driver: various fixes","message":"HTTP-RPC driver: various fixes\n\nAddress a number of bugs and quality issues in the HTTP transport\ndriver.\n\nSecurity:\n- Fix auth bypass when api_auth_token is not configured: the auth check\n  now rejects requests when the expected token is None/empty instead of\n  allowing all requests through.\n- Use hmac.compare_digest for constant-time token comparison to prevent\n  timing side-channel attacks.\n- Require api_auth_token at startup on the server: HTTPListenerBase\n  raises ConfigurationError when the token is empty (the Broadcaster is\n  covered transitively). A server with auth enabled fails closed (401)\n  without a token, so an empty token there is always a misconfiguration;\n  failing at startup surfaces it immediately instead of on the first\n  request. The driver itself does not require a token, so processes that\n  construct the transport without ever sending RPC are not forced to\n  configure one.\n\nBug fixes:\n- Thread the caller-specified retry count through send() to _send()\n  instead of always using the config default; the retry parameter was\n  accepted but silently ignored.\n- Honor the RPCClient contract where retry \u003c 0 (and the None default)\n  means retry forever. Previously range(times + 1) with times\u003d-1\n  produced range(0) -\u003e zero attempts, silently dropping the call.\n  Negative/None now iterates indefinitely (itertools.count) with the\n  backoff exponent capped to avoid overflow.\n- Move the _pack_context_with_message() call from\n  _select_target_service() to _send(), before the retry loop.\n  Previously context was packed on every retry attempt, double-nesting\n  the context dict on retries.\n- Protect the final retry attempt in retry_decorator with the same\n  exception handler as earlier attempts. Previously the last call ran\n  outside try/except, crashing on a final-attempt failure.\n- Add exponential backoff with jitter between retry attempts to avoid a\n  thundering herd under transient failures (0.5s base, 30s cap). The\n  jitter uses random.uniform (non-crypto, marked \u0027# nosec B311\u0027).\n- Replace the broken custom JSON serializer (__json_serialize) with\n  oslo_serialization.jsonutils, used consistently for serialization and\n  deserialization. The custom serializer converted strings to character\n  lists via hasattr(obj, \u0027__iter__\u0027) and duplicated datetime handling\n  that jsonutils already provides correctly.\n- Fix the double exchange prefix in service-name construction (e.g.\n  Ironic sets exchange\u003d\"ironic\" and topic\u003d\"ironic.conductor_manager\",\n  producing \"ironic.ironic.conductor_manager\"); _service_name() now\n  checks for an existing prefix before prepending.\n- Add a directed-RPC topic-splitting fallback for services that embed\n  the server name in the topic (e.g. topic\u003d\"conductor_manager.hostname\"\n  with target.server\u003dNone). Walk the dot-separated segments\n  (right-to-left) to find a valid base topic + server combination.\n- Classify an unavailable fanout relay as a transient delivery failure:\n  when no live broadcaster (\u0027fanout\u0027) Lease is found, _select_target_service\n  raises MessageDeliveryFailure instead of InvalidTarget, honoring the\n  caller\u0027s retry setting exactly as the rabbit driver does for an\n  unreachable broker. A fanout cast to a momentarily-unreachable relay\n  is a transient condition, not a permanent invalid target; InvalidTarget\n  (a ValueError subtype) caused callers such as neutron\u0027s ovo_rpc push to\n  treat a brief relay gap as fatal and abort event dispatch.\n- factory.create_app(): wire the fanout handler explicitly via\n  enable_fanout_handler\u003dFalse rather than implicitly probing the\n  optional [oslo_messaging_http_broadcaster] group, which raised\n  NoSuchOptError on the normal RPC-server path (only the broadcaster\n  registers that group). Create the handler once at app-creation time\n  instead of per request.\n- FanoutHandler: require an explicit \u0027service_name\u0027 field in the fanout\n  message and raise ValueError if it is missing, instead of silently\n  reconstructing exchange + \u0027.\u0027 + topic (which produced wrong targets\n  for topics that already embed the exchange).\n- RPCCastFanout: log the full traceback via LOG.exception and return a\n  generic \u0027Internal server error\u0027 (500) instead of echoing the raw\n  exception string to the client; stop logging request bodies in the\n  call/cast timeout paths to avoid leaking message payloads.\n- Import oslo_serialization.jsonutils in api.py (used by jsonutils.loads\n  but never imported).\n- Implement HTTPDriver.cleanup() to close the HTTPClient session and\n  release connection-pool resources; previously a no-op.\n\n- Align the ServiceBroker.get_services() abstract signature with its\n  implementations: ConsulOperator has accepted force_revalidate since\n  it was introduced and the Broadcaster passes fetch_all, but the\n  abstract method declared neither, and its docstring described\n  `service` as a Service object when callers pass a service-name\n  string. Declare both keyword parameters and correct the docstring so\n  the interface matches reality.\n\nQuality:\n- Downgrade per-request log messages from info to debug to reduce log\n  noise under production RPC load.\n- Replace Consul-hardcoded log messages in FanoutHandler with generic\n  \"service broker\" language for broker-agnostic operation.\n- Use a bare raise instead of raise err to preserve the original\n  traceback.\n- Use requests.Session for connection pooling instead of a per-call\n  requests.post.\n- Fix an assertIsNot(0, len(...)) identity check to assertGreater for a\n  correct value comparison in the unit tests.\n\nGenerated-By: claude-opus-4-6 (OpenCode)\nChange-Id: I6b2c89ee3f33d4be601b7ef001bdc7b7e39cdb9d\nSigned-off-by: flux.adam@gmail.com\nSigned-off-by: Adam Harwell \u003cflux.adam@gmail.com\u003e\n","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/af08014e5d34149f650d479b8904956a3795e7ca"}],"resolve_conflicts_web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/af08014e5d34149f650d479b8904956a3795e7ca"}]},"branch":"refs/heads/master"},"dd45bf492c249a36cb20bb3585b7ec8990ab64ab":{"kind":"REWORK","_number":13,"created":"2026-07-09 23:23:37.000000000","uploader":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"ref":"refs/changes/12/993312/13","fetch":{"anonymous http":{"url":"https://review.opendev.org/openstack/oslo.messaging","ref":"refs/changes/12/993312/13","commands":{"Checkout":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/13 \u0026\u0026 git checkout FETCH_HEAD","Cherry Pick":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/13 \u0026\u0026 git cherry-pick FETCH_HEAD","Format Patch":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/13 \u0026\u0026 git format-patch -1 --stdout FETCH_HEAD","Pull":"git pull https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/13"}}},"commit":{"parents":[{"commit":"6f36cdb647aa9beeefee60c16c43ed7e215e3e70","subject":"Add DevStack plugin for HTTP driver","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/6f36cdb647aa9beeefee60c16c43ed7e215e3e70"}]}],"author":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-06-15 08:47:43.000000000","tz":-240},"committer":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-07-09 23:17:11.000000000","tz":-240},"subject":"HTTP-RPC driver: various fixes","message":"HTTP-RPC driver: various fixes\n\nAddress a number of bugs and quality issues in the HTTP transport\ndriver.\n\nSecurity:\n- Fix auth bypass when api_auth_token is not configured: the auth check\n  now rejects requests when the expected token is None/empty instead of\n  allowing all requests through.\n- Use hmac.compare_digest for constant-time token comparison to prevent\n  timing side-channel attacks.\n- Require api_auth_token at startup on the server: HTTPListenerBase\n  raises ConfigurationError when the token is empty (the Broadcaster is\n  covered transitively). A server with auth enabled fails closed (401)\n  without a token, so an empty token there is always a misconfiguration;\n  failing at startup surfaces it immediately instead of on the first\n  request. The driver itself does not require a token, so processes that\n  construct the transport without ever sending RPC are not forced to\n  configure one.\n\nBug fixes:\n- Thread the caller-specified retry count through send() to _send()\n  instead of always using the config default; the retry parameter was\n  accepted but silently ignored.\n- Honor the RPCClient contract where retry \u003c 0 (and the None default)\n  means retry forever. Previously range(times + 1) with times\u003d-1\n  produced range(0) -\u003e zero attempts, silently dropping the call.\n  Negative/None now iterates indefinitely (itertools.count) with the\n  backoff exponent capped to avoid overflow.\n- Move the _pack_context_with_message() call from\n  _select_target_service() to _send(), before the retry loop.\n  Previously context was packed on every retry attempt, double-nesting\n  the context dict on retries.\n- Protect the final retry attempt in retry_decorator with the same\n  exception handler as earlier attempts. Previously the last call ran\n  outside try/except, crashing on a final-attempt failure.\n- Add exponential backoff with jitter between retry attempts to avoid a\n  thundering herd under transient failures (0.5s base, 30s cap). The\n  jitter uses random.uniform (non-crypto, marked \u0027# nosec B311\u0027).\n- Replace the broken custom JSON serializer (__json_serialize) with\n  oslo_serialization.jsonutils, used consistently for serialization and\n  deserialization. The custom serializer converted strings to character\n  lists via hasattr(obj, \u0027__iter__\u0027) and duplicated datetime handling\n  that jsonutils already provides correctly.\n- Fix the double exchange prefix in service-name construction (e.g.\n  Ironic sets exchange\u003d\"ironic\" and topic\u003d\"ironic.conductor_manager\",\n  producing \"ironic.ironic.conductor_manager\"); _service_name() now\n  checks for an existing prefix before prepending.\n- Add a directed-RPC topic-splitting fallback for services that embed\n  the server name in the topic (e.g. topic\u003d\"conductor_manager.hostname\"\n  with target.server\u003dNone). Walk the dot-separated segments\n  (right-to-left) to find a valid base topic + server combination.\n- Classify an unavailable fanout relay as a transient delivery failure:\n  when no live broadcaster (\u0027fanout\u0027) Lease is found, _select_target_service\n  raises MessageDeliveryFailure instead of InvalidTarget, honoring the\n  caller\u0027s retry setting exactly as the rabbit driver does for an\n  unreachable broker. A fanout cast to a momentarily-unreachable relay\n  is a transient condition, not a permanent invalid target; InvalidTarget\n  (a ValueError subtype) caused callers such as neutron\u0027s ovo_rpc push to\n  treat a brief relay gap as fatal and abort event dispatch.\n- factory.create_app(): wire the fanout handler explicitly via\n  enable_fanout_handler\u003dFalse rather than implicitly probing the\n  optional [oslo_messaging_http_broadcaster] group, which raised\n  NoSuchOptError on the normal RPC-server path (only the broadcaster\n  registers that group). Create the handler once at app-creation time\n  instead of per request.\n- FanoutHandler: require an explicit \u0027service_name\u0027 field in the fanout\n  message and raise ValueError if it is missing, instead of silently\n  reconstructing exchange + \u0027.\u0027 + topic (which produced wrong targets\n  for topics that already embed the exchange).\n- RPCCastFanout: log the full traceback via LOG.exception and return a\n  generic \u0027Internal server error\u0027 (500) instead of echoing the raw\n  exception string to the client; stop logging request bodies in the\n  call/cast timeout paths to avoid leaking message payloads.\n- Import oslo_serialization.jsonutils in api.py (used by jsonutils.loads\n  but never imported).\n- Implement HTTPDriver.cleanup() to close the HTTPClient session and\n  release connection-pool resources; previously a no-op.\n\n- Align the ServiceBroker.get_services() abstract signature with its\n  implementations: ConsulOperator has accepted force_revalidate since\n  it was introduced and the Broadcaster passes fetch_all, but the\n  abstract method declared neither, and its docstring described\n  `service` as a Service object when callers pass a service-name\n  string. Declare both keyword parameters and correct the docstring so\n  the interface matches reality.\n\nQuality:\n- Downgrade per-request log messages from info to debug to reduce log\n  noise under production RPC load.\n- Replace Consul-hardcoded log messages in FanoutHandler with generic\n  \"service broker\" language for broker-agnostic operation.\n- Use a bare raise instead of raise err to preserve the original\n  traceback.\n- Use requests.Session for connection pooling instead of a per-call\n  requests.post.\n- Fix an assertIsNot(0, len(...)) identity check to assertGreater for a\n  correct value comparison in the unit tests.\n\nGenerated-By: claude-opus-4-6 (OpenCode)\nChange-Id: I6b2c89ee3f33d4be601b7ef001bdc7b7e39cdb9d\nSigned-off-by: flux.adam@gmail.com\nSigned-off-by: Adam Harwell \u003cflux.adam@gmail.com\u003e\n","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/dd45bf492c249a36cb20bb3585b7ec8990ab64ab"}],"resolve_conflicts_web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/dd45bf492c249a36cb20bb3585b7ec8990ab64ab"}]},"branch":"refs/heads/master"},"036ffd0bcf9d79420f2b545cbc8d644840c35ec6":{"kind":"REWORK","_number":14,"created":"2026-07-10 02:30:32.000000000","uploader":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"ref":"refs/changes/12/993312/14","fetch":{"anonymous http":{"url":"https://review.opendev.org/openstack/oslo.messaging","ref":"refs/changes/12/993312/14","commands":{"Checkout":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/14 \u0026\u0026 git checkout FETCH_HEAD","Cherry Pick":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/14 \u0026\u0026 git cherry-pick FETCH_HEAD","Format Patch":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/14 \u0026\u0026 git format-patch -1 --stdout FETCH_HEAD","Pull":"git pull https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/14"}}},"commit":{"parents":[{"commit":"6f36cdb647aa9beeefee60c16c43ed7e215e3e70","subject":"Add DevStack plugin for HTTP driver","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/6f36cdb647aa9beeefee60c16c43ed7e215e3e70"}]}],"author":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-06-15 08:47:43.000000000","tz":-240},"committer":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-07-10 02:26:12.000000000","tz":-240},"subject":"HTTP-RPC driver: various fixes","message":"HTTP-RPC driver: various fixes\n\nAddress a number of bugs and quality issues in the HTTP transport\ndriver.\n\nSecurity:\n- Fix auth bypass when api_auth_token is not configured: the auth check\n  now rejects requests when the expected token is None/empty instead of\n  allowing all requests through.\n- Use hmac.compare_digest for constant-time token comparison to prevent\n  timing side-channel attacks.\n- Require api_auth_token at startup on the server: HTTPListenerBase\n  raises ConfigurationError when the token is empty (the Broadcaster is\n  covered transitively). A server with auth enabled fails closed (401)\n  without a token, so an empty token there is always a misconfiguration;\n  failing at startup surfaces it immediately instead of on the first\n  request. The driver itself does not require a token, so processes that\n  construct the transport without ever sending RPC are not forced to\n  configure one.\n\nBug fixes:\n- Thread the caller-specified retry count through send() to _send()\n  instead of always using the config default; the retry parameter was\n  accepted but silently ignored.\n- Honor the RPCClient contract where retry \u003c 0 (and the None default)\n  means retry forever. Previously range(times + 1) with times\u003d-1\n  produced range(0) -\u003e zero attempts, silently dropping the call.\n  Negative/None now iterates indefinitely (itertools.count) with the\n  backoff exponent capped to avoid overflow.\n- Move the _pack_context_with_message() call from\n  _select_target_service() to _send(), before the retry loop.\n  Previously context was packed on every retry attempt, double-nesting\n  the context dict on retries.\n- Protect the final retry attempt in retry_decorator with the same\n  exception handler as earlier attempts. Previously the last call ran\n  outside try/except, crashing on a final-attempt failure.\n- Add exponential backoff with jitter between retry attempts to avoid a\n  thundering herd under transient failures (0.5s base, 30s cap). The\n  jitter uses random.uniform (non-crypto, marked \u0027# nosec B311\u0027).\n- Replace the broken custom JSON serializer (__json_serialize) with\n  oslo_serialization.jsonutils, used consistently for serialization and\n  deserialization. The custom serializer converted strings to character\n  lists via hasattr(obj, \u0027__iter__\u0027) and duplicated datetime handling\n  that jsonutils already provides correctly.\n- Fix the double exchange prefix in service-name construction (e.g.\n  Ironic sets exchange\u003d\"ironic\" and topic\u003d\"ironic.conductor_manager\",\n  producing \"ironic.ironic.conductor_manager\"); _service_name() now\n  checks for an existing prefix before prepending.\n- Add a directed-RPC topic-splitting fallback for services that embed\n  the server name in the topic (e.g. topic\u003d\"conductor_manager.hostname\"\n  with target.server\u003dNone). Walk the dot-separated segments\n  (right-to-left) to find a valid base topic + server combination.\n- Classify an unavailable fanout relay as a transient delivery failure:\n  when no live broadcaster (\u0027fanout\u0027) Lease is found, _select_target_service\n  raises MessageDeliveryFailure instead of InvalidTarget, honoring the\n  caller\u0027s retry setting exactly as the rabbit driver does for an\n  unreachable broker. A fanout cast to a momentarily-unreachable relay\n  is a transient condition, not a permanent invalid target; InvalidTarget\n  (a ValueError subtype) caused callers such as neutron\u0027s ovo_rpc push to\n  treat a brief relay gap as fatal and abort event dispatch.\n- factory.create_app(): wire the fanout handler explicitly via\n  enable_fanout_handler\u003dFalse rather than implicitly probing the\n  optional [oslo_messaging_http_broadcaster] group, which raised\n  NoSuchOptError on the normal RPC-server path (only the broadcaster\n  registers that group). Create the handler once at app-creation time\n  instead of per request.\n- FanoutHandler: require an explicit \u0027service_name\u0027 field in the fanout\n  message and raise ValueError if it is missing, instead of silently\n  reconstructing exchange + \u0027.\u0027 + topic (which produced wrong targets\n  for topics that already embed the exchange).\n- RPCCastFanout: log the full traceback via LOG.exception and return a\n  generic \u0027Internal server error\u0027 (500) instead of echoing the raw\n  exception string to the client; stop logging request bodies in the\n  call/cast timeout paths to avoid leaking message payloads.\n- Import oslo_serialization.jsonutils in api.py (used by jsonutils.loads\n  but never imported).\n- Implement HTTPDriver.cleanup() to close the HTTPClient session and\n  release connection-pool resources; previously a no-op.\n\n- Align the ServiceBroker.get_services() abstract signature with its\n  implementations: ConsulOperator has accepted force_revalidate since\n  it was introduced and the Broadcaster passes fetch_all, but the\n  abstract method declared neither, and its docstring described\n  `service` as a Service object when callers pass a service-name\n  string. Declare both keyword parameters and correct the docstring so\n  the interface matches reality.\n\nQuality:\n- Downgrade per-request log messages from info to debug to reduce log\n  noise under production RPC load.\n- Replace Consul-hardcoded log messages in FanoutHandler with generic\n  \"service broker\" language for broker-agnostic operation.\n- Use a bare raise instead of raise err to preserve the original\n  traceback.\n- Use requests.Session for connection pooling instead of a per-call\n  requests.post.\n- Fix an assertIsNot(0, len(...)) identity check to assertGreater for a\n  correct value comparison in the unit tests.\n\nGenerated-By: claude-opus-4-6 (OpenCode)\nChange-Id: I6b2c89ee3f33d4be601b7ef001bdc7b7e39cdb9d\nSigned-off-by: flux.adam@gmail.com\nSigned-off-by: Adam Harwell \u003cflux.adam@gmail.com\u003e\n","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/036ffd0bcf9d79420f2b545cbc8d644840c35ec6"}],"resolve_conflicts_web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/036ffd0bcf9d79420f2b545cbc8d644840c35ec6"}]},"branch":"refs/heads/master"},"4fadf355c46d2568aa169b6bb259b6947551d0f8":{"kind":"TRIVIAL_REBASE","_number":15,"created":"2026-07-11 21:36:37.000000000","uploader":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"ref":"refs/changes/12/993312/15","fetch":{"anonymous http":{"url":"https://review.opendev.org/openstack/oslo.messaging","ref":"refs/changes/12/993312/15","commands":{"Checkout":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/15 \u0026\u0026 git checkout FETCH_HEAD","Cherry Pick":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/15 \u0026\u0026 git cherry-pick FETCH_HEAD","Format Patch":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/15 \u0026\u0026 git format-patch -1 --stdout FETCH_HEAD","Pull":"git pull https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/15"}}},"commit":{"parents":[{"commit":"745ff26152012716cd45a58efbadf0e32318b233","subject":"Add DevStack plugin for HTTP driver","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/745ff26152012716cd45a58efbadf0e32318b233"}]}],"author":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-06-15 08:47:43.000000000","tz":-240},"committer":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-07-11 21:36:37.000000000","tz":0},"subject":"HTTP-RPC driver: various fixes","message":"HTTP-RPC driver: various fixes\n\nAddress a number of bugs and quality issues in the HTTP transport\ndriver.\n\nSecurity:\n- Fix auth bypass when api_auth_token is not configured: the auth check\n  now rejects requests when the expected token is None/empty instead of\n  allowing all requests through.\n- Use hmac.compare_digest for constant-time token comparison to prevent\n  timing side-channel attacks.\n- Require api_auth_token at startup on the server: HTTPListenerBase\n  raises ConfigurationError when the token is empty (the Broadcaster is\n  covered transitively). A server with auth enabled fails closed (401)\n  without a token, so an empty token there is always a misconfiguration;\n  failing at startup surfaces it immediately instead of on the first\n  request. The driver itself does not require a token, so processes that\n  construct the transport without ever sending RPC are not forced to\n  configure one.\n\nBug fixes:\n- Thread the caller-specified retry count through send() to _send()\n  instead of always using the config default; the retry parameter was\n  accepted but silently ignored.\n- Honor the RPCClient contract where retry \u003c 0 (and the None default)\n  means retry forever. Previously range(times + 1) with times\u003d-1\n  produced range(0) -\u003e zero attempts, silently dropping the call.\n  Negative/None now iterates indefinitely (itertools.count) with the\n  backoff exponent capped to avoid overflow.\n- Move the _pack_context_with_message() call from\n  _select_target_service() to _send(), before the retry loop.\n  Previously context was packed on every retry attempt, double-nesting\n  the context dict on retries.\n- Protect the final retry attempt in retry_decorator with the same\n  exception handler as earlier attempts. Previously the last call ran\n  outside try/except, crashing on a final-attempt failure.\n- Add exponential backoff with jitter between retry attempts to avoid a\n  thundering herd under transient failures (0.5s base, 30s cap). The\n  jitter uses random.uniform (non-crypto, marked \u0027# nosec B311\u0027).\n- Replace the broken custom JSON serializer (__json_serialize) with\n  oslo_serialization.jsonutils, used consistently for serialization and\n  deserialization. The custom serializer converted strings to character\n  lists via hasattr(obj, \u0027__iter__\u0027) and duplicated datetime handling\n  that jsonutils already provides correctly.\n- Fix the double exchange prefix in service-name construction (e.g.\n  Ironic sets exchange\u003d\"ironic\" and topic\u003d\"ironic.conductor_manager\",\n  producing \"ironic.ironic.conductor_manager\"); _service_name() now\n  checks for an existing prefix before prepending.\n- Add a directed-RPC topic-splitting fallback for services that embed\n  the server name in the topic (e.g. topic\u003d\"conductor_manager.hostname\"\n  with target.server\u003dNone). Walk the dot-separated segments\n  (right-to-left) to find a valid base topic + server combination.\n- Classify an unavailable fanout relay as a transient delivery failure:\n  when no live broadcaster (\u0027fanout\u0027) Lease is found, _select_target_service\n  raises MessageDeliveryFailure instead of InvalidTarget, honoring the\n  caller\u0027s retry setting exactly as the rabbit driver does for an\n  unreachable broker. A fanout cast to a momentarily-unreachable relay\n  is a transient condition, not a permanent invalid target; InvalidTarget\n  (a ValueError subtype) caused callers such as neutron\u0027s ovo_rpc push to\n  treat a brief relay gap as fatal and abort event dispatch.\n- factory.create_app(): wire the fanout handler explicitly via\n  enable_fanout_handler\u003dFalse rather than implicitly probing the\n  optional [oslo_messaging_http_broadcaster] group, which raised\n  NoSuchOptError on the normal RPC-server path (only the broadcaster\n  registers that group). Create the handler once at app-creation time\n  instead of per request.\n- FanoutHandler: require an explicit \u0027service_name\u0027 field in the fanout\n  message and raise ValueError if it is missing, instead of silently\n  reconstructing exchange + \u0027.\u0027 + topic (which produced wrong targets\n  for topics that already embed the exchange).\n- RPCCastFanout: log the full traceback via LOG.exception and return a\n  generic \u0027Internal server error\u0027 (500) instead of echoing the raw\n  exception string to the client; stop logging request bodies in the\n  call/cast timeout paths to avoid leaking message payloads.\n- Import oslo_serialization.jsonutils in api.py (used by jsonutils.loads\n  but never imported).\n- Implement HTTPDriver.cleanup() to close the HTTPClient session and\n  release connection-pool resources; previously a no-op.\n\n- Align the ServiceBroker.get_services() abstract signature with its\n  implementations: ConsulOperator has accepted force_revalidate since\n  it was introduced and the Broadcaster passes fetch_all, but the\n  abstract method declared neither, and its docstring described\n  `service` as a Service object when callers pass a service-name\n  string. Declare both keyword parameters and correct the docstring so\n  the interface matches reality.\n\nQuality:\n- Downgrade per-request log messages from info to debug to reduce log\n  noise under production RPC load.\n- Replace Consul-hardcoded log messages in FanoutHandler with generic\n  \"service broker\" language for broker-agnostic operation.\n- Use a bare raise instead of raise err to preserve the original\n  traceback.\n- Use requests.Session for connection pooling instead of a per-call\n  requests.post.\n- Fix an assertIsNot(0, len(...)) identity check to assertGreater for a\n  correct value comparison in the unit tests.\n\nGenerated-By: claude-opus-4-6 (OpenCode)\nChange-Id: I6b2c89ee3f33d4be601b7ef001bdc7b7e39cdb9d\nSigned-off-by: flux.adam@gmail.com\nSigned-off-by: Adam Harwell \u003cflux.adam@gmail.com\u003e\n","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/4fadf355c46d2568aa169b6bb259b6947551d0f8"}],"resolve_conflicts_web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/4fadf355c46d2568aa169b6bb259b6947551d0f8"}]},"branch":"refs/heads/master","description":"Rebase","conflicts":{"base":"6f36cdb647aa9beeefee60c16c43ed7e215e3e70","ours":"036ffd0bcf9d79420f2b545cbc8d644840c35ec6","theirs":"745ff26152012716cd45a58efbadf0e32318b233","merge_strategy":"recursive","contains_conflicts":false}},"3f05700d7b9f2c9fb19ee5469521d8046f67cab8":{"kind":"TRIVIAL_REBASE","_number":16,"created":"2026-07-17 05:37:37.000000000","uploader":{"_account_id":10273,"name":"Adam Harwell","email":"flux.adam@gmail.com","username":"rm_you"},"ref":"refs/changes/12/993312/16","fetch":{"anonymous http":{"url":"https://review.opendev.org/openstack/oslo.messaging","ref":"refs/changes/12/993312/16","commands":{"Checkout":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/16 \u0026\u0026 git checkout FETCH_HEAD","Cherry Pick":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/16 \u0026\u0026 git cherry-pick FETCH_HEAD","Format Patch":"git fetch https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/16 \u0026\u0026 git format-patch -1 --stdout FETCH_HEAD","Pull":"git pull https://review.opendev.org/openstack/oslo.messaging refs/changes/12/993312/16"}}},"commit":{"parents":[{"commit":"7be9311eea5c9eacca575e94b4d701e041650524","subject":"Add DevStack plugin for HTTP driver","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/7be9311eea5c9eacca575e94b4d701e041650524"}]}],"author":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-06-15 08:47:43.000000000","tz":-240},"committer":{"name":"Adam Harwell","email":"flux.adam@gmail.com","date":"2026-07-17 05:37:37.000000000","tz":0},"subject":"HTTP-RPC driver: various fixes","message":"HTTP-RPC driver: various fixes\n\nAddress a number of bugs and quality issues in the HTTP transport\ndriver.\n\nSecurity:\n- Fix auth bypass when api_auth_token is not configured: the auth check\n  now rejects requests when the expected token is None/empty instead of\n  allowing all requests through.\n- Use hmac.compare_digest for constant-time token comparison to prevent\n  timing side-channel attacks.\n- Require api_auth_token at startup on the server: HTTPListenerBase\n  raises ConfigurationError when the token is empty (the Broadcaster is\n  covered transitively). A server with auth enabled fails closed (401)\n  without a token, so an empty token there is always a misconfiguration;\n  failing at startup surfaces it immediately instead of on the first\n  request. The driver itself does not require a token, so processes that\n  construct the transport without ever sending RPC are not forced to\n  configure one.\n\nBug fixes:\n- Thread the caller-specified retry count through send() to _send()\n  instead of always using the config default; the retry parameter was\n  accepted but silently ignored.\n- Honor the RPCClient contract where retry \u003c 0 (and the None default)\n  means retry forever. Previously range(times + 1) with times\u003d-1\n  produced range(0) -\u003e zero attempts, silently dropping the call.\n  Negative/None now iterates indefinitely (itertools.count) with the\n  backoff exponent capped to avoid overflow.\n- Move the _pack_context_with_message() call from\n  _select_target_service() to _send(), before the retry loop.\n  Previously context was packed on every retry attempt, double-nesting\n  the context dict on retries.\n- Protect the final retry attempt in retry_decorator with the same\n  exception handler as earlier attempts. Previously the last call ran\n  outside try/except, crashing on a final-attempt failure.\n- Add exponential backoff with jitter between retry attempts to avoid a\n  thundering herd under transient failures (0.5s base, 30s cap). The\n  jitter uses random.uniform (non-crypto, marked \u0027# nosec B311\u0027).\n- Replace the broken custom JSON serializer (__json_serialize) with\n  oslo_serialization.jsonutils, used consistently for serialization and\n  deserialization. The custom serializer converted strings to character\n  lists via hasattr(obj, \u0027__iter__\u0027) and duplicated datetime handling\n  that jsonutils already provides correctly.\n- Fix the double exchange prefix in service-name construction (e.g.\n  Ironic sets exchange\u003d\"ironic\" and topic\u003d\"ironic.conductor_manager\",\n  producing \"ironic.ironic.conductor_manager\"); _service_name() now\n  checks for an existing prefix before prepending.\n- Add a directed-RPC topic-splitting fallback for services that embed\n  the server name in the topic (e.g. topic\u003d\"conductor_manager.hostname\"\n  with target.server\u003dNone). Walk the dot-separated segments\n  (right-to-left) to find a valid base topic + server combination.\n- Classify an unavailable fanout relay as a transient delivery failure:\n  when no live broadcaster (\u0027fanout\u0027) Lease is found, _select_target_service\n  raises MessageDeliveryFailure instead of InvalidTarget, honoring the\n  caller\u0027s retry setting exactly as the rabbit driver does for an\n  unreachable broker. A fanout cast to a momentarily-unreachable relay\n  is a transient condition, not a permanent invalid target; InvalidTarget\n  (a ValueError subtype) caused callers such as neutron\u0027s ovo_rpc push to\n  treat a brief relay gap as fatal and abort event dispatch.\n- factory.create_app(): wire the fanout handler explicitly via\n  enable_fanout_handler\u003dFalse rather than implicitly probing the\n  optional [oslo_messaging_http_broadcaster] group, which raised\n  NoSuchOptError on the normal RPC-server path (only the broadcaster\n  registers that group). Create the handler once at app-creation time\n  instead of per request.\n- FanoutHandler: require an explicit \u0027service_name\u0027 field in the fanout\n  message and raise ValueError if it is missing, instead of silently\n  reconstructing exchange + \u0027.\u0027 + topic (which produced wrong targets\n  for topics that already embed the exchange).\n- RPCCastFanout: log the full traceback via LOG.exception and return a\n  generic \u0027Internal server error\u0027 (500) instead of echoing the raw\n  exception string to the client; stop logging request bodies in the\n  call/cast timeout paths to avoid leaking message payloads.\n- Import oslo_serialization.jsonutils in api.py (used by jsonutils.loads\n  but never imported).\n- Implement HTTPDriver.cleanup() to close the HTTPClient session and\n  release connection-pool resources; previously a no-op.\n\n- Align the ServiceBroker.get_services() abstract signature with its\n  implementations: ConsulOperator has accepted force_revalidate since\n  it was introduced and the Broadcaster passes fetch_all, but the\n  abstract method declared neither, and its docstring described\n  `service` as a Service object when callers pass a service-name\n  string. Declare both keyword parameters and correct the docstring so\n  the interface matches reality.\n\nQuality:\n- Downgrade per-request log messages from info to debug to reduce log\n  noise under production RPC load.\n- Replace Consul-hardcoded log messages in FanoutHandler with generic\n  \"service broker\" language for broker-agnostic operation.\n- Use a bare raise instead of raise err to preserve the original\n  traceback.\n- Use requests.Session for connection pooling instead of a per-call\n  requests.post.\n- Fix an assertIsNot(0, len(...)) identity check to assertGreater for a\n  correct value comparison in the unit tests.\n\nGenerated-By: claude-opus-4-6 (OpenCode)\nChange-Id: I6b2c89ee3f33d4be601b7ef001bdc7b7e39cdb9d\nSigned-off-by: flux.adam@gmail.com\nSigned-off-by: Adam Harwell \u003cflux.adam@gmail.com\u003e\n","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/3f05700d7b9f2c9fb19ee5469521d8046f67cab8"}],"resolve_conflicts_web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/oslo.messaging/commit/3f05700d7b9f2c9fb19ee5469521d8046f67cab8"}]},"branch":"refs/heads/master","description":"Rebase","conflicts":{"base":"745ff26152012716cd45a58efbadf0e32318b233","ours":"4fadf355c46d2568aa169b6bb259b6947551d0f8","theirs":"7be9311eea5c9eacca575e94b4d701e041650524","merge_strategy":"recursive","contains_conflicts":false}}},"requirements":[],"submit_records":[{"rule_name":"gerrit~DefaultSubmitRule","status":"OK","labels":[{"label":"Verified","status":"MAY","applied_by":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]}},{"label":"Code-Review","status":"MAY"},{"label":"Workflow","status":"MAY"},{"label":"Backport-Candidate","status":"MAY"}]}],"submit_requirements":[{"name":"Verified","description":"Verified in gate by CI","status":"UNSATISFIED","is_legacy":false,"submittability_expression_result":{"expression":"label:Verified\u003dMAX AND -label:Verified\u003dMIN","fulfilled":false,"status":"FAIL","passing_atoms":[],"failing_atoms":["label:Verified\u003dMAX","label:Verified\u003dMIN"],"atom_explanations":{"label:Verified\u003dMAX":"","label:Verified\u003dMIN":""}}},{"name":"Backport-Candidate","description":"Backport candidate status","status":"NOT_APPLICABLE","is_legacy":false,"applicability_expression_result":{"fulfilled":false,"status":"FAIL"},"submittability_expression_result":{"expression":"is:true","fulfilled":true,"status":"NOT_EVALUATED","passing_atoms":[],"failing_atoms":[],"atom_explanations":{}}},{"name":"Code-Review","description":"Code reviewed by core reviewer","status":"UNSATISFIED","is_legacy":false,"submittability_expression_result":{"expression":"label:Code-Review\u003dMAX AND -label:Code-Review\u003dMIN","fulfilled":false,"status":"FAIL","passing_atoms":[],"failing_atoms":["label:Code-Review\u003dMAX","label:Code-Review\u003dMIN"],"atom_explanations":{"label:Code-Review\u003dMAX":"","label:Code-Review\u003dMIN":""}}},{"name":"Workflow","description":"Approved for gate by core reviewer","status":"UNSATISFIED","is_legacy":false,"submittability_expression_result":{"expression":"label:Workflow\u003dMAX AND -label:Workflow\u003dMIN","fulfilled":false,"status":"FAIL","passing_atoms":[],"failing_atoms":["label:Workflow\u003dMAX","label:Workflow\u003dMIN"],"atom_explanations":{"label:Workflow\u003dMAX":"","label:Workflow\u003dMIN":""}}}]}
