)]}'
{"id":"openstack%2Fkeystone~755736","triplet_id":"openstack%2Fkeystone~stable%2Ftrain~Ia45a45ff852d0d4e3a713dae07a46d4ff8d370f3","project":"openstack/keystone","branch":"stable/train","hashtags":[],"change_id":"Ia45a45ff852d0d4e3a713dae07a46d4ff8d370f3","subject":"Implement more robust connection handling for asynchronous LDAP calls","status":"MERGED","created":"2020-10-02 09:22:22.000000000","updated":"2020-11-17 01:55:43.000000000","submitted":"2020-11-17 01:53:56.000000000","submitter":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"total_comment_count":0,"unresolved_comment_count":0,"has_review_started":true,"submission_id":"755736-1605578036764-044f1fb9","meta_rev_id":"a1c69c8eea799bbb61cd3ca0e7c90c9ab5a65417","_number":755736,"virtual_id_number":755736,"owner":{"_account_id":27954,"name":"Moisés Guimarães de Medeiros","email":"guimaraes@pm.me","username":"moguimar"},"actions":{},"labels":{"Verified":{"approved":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"all":[{"value":0,"_account_id":16465,"name":"Kristi Nikolla","email":"knikolla@bu.edu","username":"knikolla"},{"value":0,"_account_id":9954,"name":"Lance Bragstad","username":"lbragstad","inactive":true},{"value":0,"_account_id":27954,"name":"Moisés Guimarães de Medeiros","email":"guimaraes@pm.me","username":"moguimar"},{"value":0,"_account_id":8866,"name":"Raildo Mascena de Sousa Filho","email":"rmascena@redhat.com","username":"raildo"},{"value":0,"_account_id":8482,"name":"Colleen Murphy","email":"colleen@gazlene.net","username":"krinkle"},{"value":0,"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},{"tag":"autogenerated:zuul:gate","value":2,"date":"2020-11-17 01:53:56.000000000","post_submit":true,"permitted_voting_range":{"min":2,"max":2},"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},{"value":0,"_account_id":21420,"name":"Gage Hugo","email":"gagehugo@gmail.com","username":"ghugo"}],"values":{"-2":"Fails","-1":"Doesn\u0027t seem to work"," 0":"No score","+1":"Works for me","+2":"Verified"},"description":"","default_value":0,"optional":true},"Code-Review":{"approved":{"_account_id":8482,"name":"Colleen Murphy","email":"colleen@gazlene.net","username":"krinkle"},"recommended":{"_account_id":8866,"name":"Raildo Mascena de Sousa Filho","email":"rmascena@redhat.com","username":"raildo"},"all":[{"value":0,"_account_id":16465,"name":"Kristi Nikolla","email":"knikolla@bu.edu","username":"knikolla"},{"value":0,"_account_id":9954,"name":"Lance Bragstad","username":"lbragstad","inactive":true},{"value":0,"_account_id":27954,"name":"Moisés Guimarães de Medeiros","email":"guimaraes@pm.me","username":"moguimar"},{"value":1,"date":"2020-11-03 14:09:48.000000000","permitted_voting_range":{"min":1,"max":1},"_account_id":8866,"name":"Raildo Mascena de Sousa Filho","email":"rmascena@redhat.com","username":"raildo"},{"value":2,"date":"2020-11-16 23:01:32.000000000","_account_id":8482,"name":"Colleen Murphy","email":"colleen@gazlene.net","username":"krinkle"},{"value":2,"date":"2020-11-03 14:57:56.000000000","permitted_voting_range":{"min":2,"max":2},"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},{"value":0,"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},{"value":0,"_account_id":21420,"name":"Gage Hugo","email":"gagehugo@gmail.com","username":"ghugo"}],"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":"","value":1,"default_value":0,"optional":true},"Workflow":{"approved":{"_account_id":8482,"name":"Colleen Murphy","email":"colleen@gazlene.net","username":"krinkle"},"all":[{"value":0,"_account_id":16465,"name":"Kristi Nikolla","email":"knikolla@bu.edu","username":"knikolla"},{"value":0,"_account_id":9954,"name":"Lance Bragstad","username":"lbragstad","inactive":true},{"value":0,"_account_id":27954,"name":"Moisés Guimarães de Medeiros","email":"guimaraes@pm.me","username":"moguimar"},{"value":0,"_account_id":8866,"name":"Raildo Mascena de Sousa Filho","email":"rmascena@redhat.com","username":"raildo"},{"value":1,"date":"2020-11-16 23:01:32.000000000","_account_id":8482,"name":"Colleen Murphy","email":"colleen@gazlene.net","username":"krinkle"},{"value":0,"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},{"value":0,"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},{"value":0,"_account_id":21420,"name":"Gage Hugo","email":"gagehugo@gmail.com","username":"ghugo"}],"values":{"-1":"Work in progress"," 0":"Ready for reviews","+1":"Approved"},"description":"","default_value":0,"optional":true}},"removable_reviewers":[],"reviewers":{"REVIEWER":[{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},{"_account_id":8482,"name":"Colleen Murphy","email":"colleen@gazlene.net","username":"krinkle"},{"_account_id":8866,"name":"Raildo Mascena de Sousa Filho","email":"rmascena@redhat.com","username":"raildo"},{"_account_id":9954,"name":"Lance Bragstad","username":"lbragstad","inactive":true},{"_account_id":16465,"name":"Kristi Nikolla","email":"knikolla@bu.edu","username":"knikolla"},{"_account_id":21420,"name":"Gage Hugo","email":"gagehugo@gmail.com","username":"ghugo"},{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},{"_account_id":27954,"name":"Moisés Guimarães de Medeiros","email":"guimaraes@pm.me","username":"moguimar"}]},"pending_reviewers":{},"reviewer_updates":[{"updated":"2020-10-02 09:22:22.000000000","updated_by":{"_account_id":9954,"name":"Lance Bragstad","username":"lbragstad","inactive":true},"reviewer":{"_account_id":9954,"name":"Lance Bragstad","username":"lbragstad","inactive":true},"state":"REVIEWER"},{"updated":"2020-10-18 14:49:25.000000000","updated_by":{"_account_id":21420,"name":"Gage Hugo","email":"gagehugo@gmail.com","username":"ghugo"},"reviewer":{"_account_id":21420,"name":"Gage Hugo","email":"gagehugo@gmail.com","username":"ghugo"},"state":"REVIEWER"},{"updated":"2020-10-18 14:49:31.000000000","updated_by":{"_account_id":16465,"name":"Kristi Nikolla","email":"knikolla@bu.edu","username":"knikolla"},"reviewer":{"_account_id":16465,"name":"Kristi Nikolla","email":"knikolla@bu.edu","username":"knikolla"},"state":"REVIEWER"},{"updated":"2020-11-03 14:09:48.000000000","updated_by":{"_account_id":8866,"name":"Raildo Mascena de Sousa Filho","email":"rmascena@redhat.com","username":"raildo"},"reviewer":{"_account_id":8866,"name":"Raildo Mascena de Sousa Filho","email":"rmascena@redhat.com","username":"raildo"},"state":"REVIEWER"},{"updated":"2020-11-03 14:57:56.000000000","updated_by":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"reviewer":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"state":"REVIEWER"},{"updated":"2020-11-16 23:01:32.000000000","updated_by":{"_account_id":8482,"name":"Colleen Murphy","email":"colleen@gazlene.net","username":"krinkle"},"reviewer":{"_account_id":8482,"name":"Colleen Murphy","email":"colleen@gazlene.net","username":"krinkle"},"state":"REVIEWER"},{"updated":"2020-11-17 01:53:56.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"}],"messages":[{"id":"f244bb8fbdd3ed9597833dc157e09c9c5f107c0b","author":{"_account_id":27954,"name":"Moisés Guimarães de Medeiros","email":"guimaraes@pm.me","username":"moguimar"},"date":"2020-10-02 09:22:22.000000000","message":"Patch Set 1: Cherry Picked from branch stable/ussuri.","accounts_in_message":[],"_revision_number":1},{"id":"42a76a4d51cfd79843e4d9b89135a1093073e7aa","tag":"autogenerated:zuul:check","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2020-10-02 16:20:23.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\n\n\n- openstack-tox-cover https://zuul.opendev.org/t/openstack/build/2be78a6c7b89481ea45a0401e161d03f : SUCCESS in 15m 46s\n- openstack-tox-lower-constraints https://zuul.opendev.org/t/openstack/build/9434f2eb43894b1485ef0b2ecd368593 : FAILURE in 13m 35s\n- openstack-tox-pep8 https://zuul.opendev.org/t/openstack/build/e48aa285e803462ba6cd2fe41d1a2a46 : SUCCESS in 6m 37s\n- openstack-tox-py27 https://zuul.opendev.org/t/openstack/build/3f947587eb804b64aa4a757a7457652c : SUCCESS in 14m 19s\n- openstack-tox-py36 https://zuul.opendev.org/t/openstack/build/8ca693744f28445bb163b63f8d7be94f : SUCCESS in 14m 34s\n- openstack-tox-py37 https://zuul.opendev.org/t/openstack/build/5d119a7656784ac18c6acc1430e7bf85 : SUCCESS in 14m 11s\n- openstack-tox-docs https://zuul.opendev.org/t/openstack/build/67f85e62c1ad4bd599914f18238f1c45 : SUCCESS in 12m 25s\n- tempest-full https://zuul.opendev.org/t/openstack/build/bd6f6f3d76d24296bcb16f920c9d4f5e : SUCCESS in 1h 26m 26s\n- neutron-grenade https://zuul.opendev.org/t/openstack/build/13c7754f608b4cc090985585e30153f6 : SUCCESS in 1h 28m 27s\n- grenade https://zuul.opendev.org/t/openstack/build/4032a4ca2f874457b6e5652a0376f236 : SUCCESS in 1h 00m 49s\n- tempest-full-py3 https://zuul.opendev.org/t/openstack/build/28637d058cfa4583a6ea2f239ff8d8d7 : SUCCESS in 1h 23m 07s\n- build-openstack-releasenotes https://zuul.opendev.org/t/openstack/build/779d94447116435bbacc7ddb3b588e32 : SUCCESS in 9m 09s\n- keystone-dsvm-functional https://zuul.opendev.org/t/openstack/build/a2686fbc191b4855908b5ce808848582 : SUCCESS in 28m 51s\n- keystone-dsvm-py3-functional https://zuul.opendev.org/t/openstack/build/d6795796ab824e2fa32ef07c9eaaaf3e : SUCCESS in 31m 13s\n- keystone-dsvm-functional-federation-opensuse15 https://zuul.opendev.org/t/openstack/build/fb5efd7f2afc41f2b0b4c04ede8a0fa3 : FAILURE in 6m 46s (non-voting)\n- keystone-dsvm-py3-functional-federation-opensuse15 https://zuul.opendev.org/t/openstack/build/623141d0c659447ea17a40d1ec06532a : FAILURE in 7m 02s (non-voting)\n- keystone-dsvm-py3-functional-federation-opensuse15-k2k https://zuul.opendev.org/t/openstack/build/5b1cc50acb664662b0387f4cc690c9b1 : FAILURE in 7m 11s\n- keystoneclient-devstack-functional https://zuul.opendev.org/t/openstack/build/cc90873fe3b141f9ac5967977f6a1cca : SUCCESS in 27m 09s (non-voting)\n- keystone-dsvm-ldap-domain-specific-driver https://zuul.opendev.org/t/openstack/build/24f63c10fe674ea395a49367d21da93b : SUCCESS in 43m 18s (non-voting)\n- grenade-py3 https://zuul.opendev.org/t/openstack/build/3d7b9450ab594d30a7b1b82c39252d21 : SUCCESS in 1h 04m 16s\n- tempest-ipv6-only https://zuul.opendev.org/t/openstack/build/efa02bef058b49e0933fcfe008d0c455 : SUCCESS in 58m 12s\n- keystone-tox-protection https://zuul.opendev.org/t/openstack/build/e07c8e6b55704843853555f860702d2b : SUCCESS in 37m 17s","accounts_in_message":[],"_revision_number":1},{"id":"9796768829f0406f7e7e4266a73f34197dad30d2","author":{"_account_id":27954,"name":"Moisés Guimarães de Medeiros","email":"guimaraes@pm.me","username":"moguimar"},"date":"2020-10-18 14:55:46.000000000","message":"Patch Set 1:\n\nrecheck","accounts_in_message":[],"_revision_number":1},{"id":"688c75a3a2671ddd54d6a71ff7456091225c985a","tag":"autogenerated:zuul:check","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2020-10-18 16:35:23.000000000","message":"Patch Set 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\n\n\n- openstack-tox-cover https://zuul.opendev.org/t/openstack/build/3957225bb4ea4fa09cd49ee7f850c37d : SUCCESS in 18m 05s\n- openstack-tox-lower-constraints https://zuul.opendev.org/t/openstack/build/cc87db37d14e41cb8c001da2ac9238d9 : FAILURE in 25m 58s\n- openstack-tox-pep8 https://zuul.opendev.org/t/openstack/build/78ba61df64ba4b39bb20914841689c39 : SUCCESS in 9m 08s\n- openstack-tox-py27 https://zuul.opendev.org/t/openstack/build/f29bc7d2bb7d42a5a455091dbd15d0f6 : SUCCESS in 26m 31s\n- openstack-tox-py36 https://zuul.opendev.org/t/openstack/build/32015eb1eb704f7dbd22f429fa4c74db : SUCCESS in 24m 33s\n- openstack-tox-py37 https://zuul.opendev.org/t/openstack/build/3655081e278f4a16a8737322cf545601 : SUCCESS in 24m 33s\n- openstack-tox-docs https://zuul.opendev.org/t/openstack/build/828eb4e41c1d406aaee422eca93448b9 : SUCCESS in 13m 05s\n- tempest-full https://zuul.opendev.org/t/openstack/build/c3ceea7006524fd595b67e566e99e352 : SUCCESS in 1h 33m 11s\n- neutron-grenade https://zuul.opendev.org/t/openstack/build/77052424304e4166980191a3fba431f9 : SUCCESS in 57m 36s\n- grenade https://zuul.opendev.org/t/openstack/build/029dbfc2b9b64c04bc3af6f2b57f0ed2 : SUCCESS in 57m 08s\n- tempest-full-py3 https://zuul.opendev.org/t/openstack/build/263a339af90b408b91a5091580d346aa : SUCCESS in 1h 13m 50s\n- build-openstack-releasenotes https://zuul.opendev.org/t/openstack/build/d38d650611724d8bbbd0dd635ab02930 : SUCCESS in 10m 00s\n- keystone-dsvm-functional https://zuul.opendev.org/t/openstack/build/f155c938fe254fcb8c1e4c504aa03637 : SUCCESS in 35m 06s\n- keystone-dsvm-py3-functional https://zuul.opendev.org/t/openstack/build/ccaa682132804ce5bbe91bafaaca0e96 : SUCCESS in 30m 30s\n- keystone-dsvm-functional-federation-opensuse15 https://zuul.opendev.org/t/openstack/build/049f7117c5034b668d60534d9d100aef : FAILURE in 7m 50s (non-voting)\n- keystone-dsvm-py3-functional-federation-opensuse15 https://zuul.opendev.org/t/openstack/build/ff638c1064b942828fbc60f376972854 : FAILURE in 7m 49s (non-voting)\n- keystone-dsvm-py3-functional-federation-opensuse15-k2k https://zuul.opendev.org/t/openstack/build/9a212429f3194c248d8bd6c0c3b308e9 : FAILURE in 7m 46s\n- keystoneclient-devstack-functional https://zuul.opendev.org/t/openstack/build/1b918f4112aa47fd8460f95c628245df : FAILURE in 15m 25s (non-voting)\n- keystone-dsvm-ldap-domain-specific-driver https://zuul.opendev.org/t/openstack/build/6a6be28f367e4b0ba1bc09f06be3d66a : SUCCESS in 37m 17s (non-voting)\n- grenade-py3 https://zuul.opendev.org/t/openstack/build/4fb26b87c689427699e302a2aac20523 : SUCCESS in 1h 04m 17s\n- tempest-ipv6-only https://zuul.opendev.org/t/openstack/build/e005e826ed084fad80ee320c951a0695 : SUCCESS in 58m 45s\n- keystone-tox-protection https://zuul.opendev.org/t/openstack/build/1b19eec5a5a1476596124b6050de0bb9 : SUCCESS in 48m 33s","accounts_in_message":[],"_revision_number":1},{"id":"b67be6fbd8cdaa94258275135b8acf2afd5a0f2b","author":{"_account_id":27954,"name":"Moisés Guimarães de Medeiros","email":"guimaraes@pm.me","username":"moguimar"},"date":"2020-10-19 07:43:51.000000000","message":"Patch Set 1:\n\nrecheck","accounts_in_message":[],"_revision_number":1},{"id":"d639c5d9637bfb637b7e5a095de94f02e13d34c6","tag":"autogenerated:zuul:check","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2020-10-19 09:27:13.000000000","message":"Patch Set 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\n\n\n- openstack-tox-cover https://zuul.opendev.org/t/openstack/build/58ba49991db343099d9c336b320a001a : SUCCESS in 17m 15s\n- openstack-tox-lower-constraints https://zuul.opendev.org/t/openstack/build/59c69efcd91e4d0d9c82e99b1cceb246 : FAILURE in 16m 21s\n- openstack-tox-pep8 https://zuul.opendev.org/t/openstack/build/596cbdc9c6604092ab304cdab7e46034 : SUCCESS in 9m 54s\n- openstack-tox-py27 https://zuul.opendev.org/t/openstack/build/4e5557761ef846899e2ac3549667c1ab : SUCCESS in 15m 34s\n- openstack-tox-py36 https://zuul.opendev.org/t/openstack/build/3e0866eff3e64eb287c13d774b489315 : SUCCESS in 13m 57s\n- openstack-tox-py37 https://zuul.opendev.org/t/openstack/build/b3f20282306c4b69a7def17af97e0103 : SUCCESS in 15m 17s\n- openstack-tox-docs https://zuul.opendev.org/t/openstack/build/bd218f010ce7413ab8c0f30e378e7d98 : SUCCESS in 14m 18s\n- tempest-full https://zuul.opendev.org/t/openstack/build/761135e764e6445482f1cc4c039a0458 : SUCCESS in 1h 37m 21s\n- neutron-grenade https://zuul.opendev.org/t/openstack/build/9ca6eab1ea3346bbaff7d292ef76ac7e : SUCCESS in 1h 05m 39s\n- grenade https://zuul.opendev.org/t/openstack/build/8910c5f569fc40269d20e172b808c629 : SUCCESS in 1h 06m 15s\n- tempest-full-py3 https://zuul.opendev.org/t/openstack/build/380be669745a46a896d5f4c18365d05c : SUCCESS in 1h 22m 26s\n- build-openstack-releasenotes https://zuul.opendev.org/t/openstack/build/87bde8f440a64b2f8e34e62f439e8415 : SUCCESS in 8m 57s\n- keystone-dsvm-functional https://zuul.opendev.org/t/openstack/build/7e28908f51e8439ca5cc386e72dc7493 : SUCCESS in 35m 55s\n- keystone-dsvm-py3-functional https://zuul.opendev.org/t/openstack/build/73817d53d9c44be788717617f9cfd527 : SUCCESS in 37m 28s\n- keystone-dsvm-functional-federation-opensuse15 https://zuul.opendev.org/t/openstack/build/478b153625b242d7b677955337f8dc3f : FAILURE in 12m 19s (non-voting)\n- keystone-dsvm-py3-functional-federation-opensuse15 https://zuul.opendev.org/t/openstack/build/0291bbce782546bf9b3baf35efbd696b : FAILURE in 13m 40s (non-voting)\n- keystone-dsvm-py3-functional-federation-opensuse15-k2k https://zuul.opendev.org/t/openstack/build/c9a668a383474ad4a28724c964db990f : FAILURE in 11m 56s\n- keystoneclient-devstack-functional https://zuul.opendev.org/t/openstack/build/5955c74a05f2426a8ee07cc1180f9084 : SUCCESS in 21m 28s (non-voting)\n- keystone-dsvm-ldap-domain-specific-driver https://zuul.opendev.org/t/openstack/build/e47a5164b47849be860216f14d9d331d : SUCCESS in 48m 53s (non-voting)\n- grenade-py3 https://zuul.opendev.org/t/openstack/build/f9cba325019d4f569f3c4eeef6eea40b : SUCCESS in 59m 38s\n- tempest-ipv6-only https://zuul.opendev.org/t/openstack/build/96f48305140946f990c2ed20311c2325 : SUCCESS in 56m 37s\n- keystone-tox-protection https://zuul.opendev.org/t/openstack/build/c47975166ebf446094d21743875060ba : SUCCESS in 39m 30s","accounts_in_message":[],"_revision_number":1},{"id":"1087da18bda3ed9a0a0c21a49e480b94be7b2f25","author":{"_account_id":27954,"name":"Moisés Guimarães de Medeiros","email":"guimaraes@pm.me","username":"moguimar"},"date":"2020-10-19 14:43:15.000000000","message":"Patch Set 2: Patch Set 1 was rebased","accounts_in_message":[],"_revision_number":2},{"id":"03208fee7a2853f64292116e45c96469ebd6cc38","tag":"autogenerated:zuul:check","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2020-10-19 17:47:22.000000000","message":"Patch Set 2: 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\n\n\n- openstack-tox-cover https://zuul.opendev.org/t/openstack/build/0064de23346c4eac9404157ca88993ad : SUCCESS in 16m 48s\n- openstack-tox-lower-constraints https://zuul.opendev.org/t/openstack/build/c4c66b2c7a364338ab7d3d4412a54eb0 : SUCCESS in 15m 27s\n- openstack-tox-pep8 https://zuul.opendev.org/t/openstack/build/26eb8e1244154c61922146c9522b96a6 : SUCCESS in 10m 09s\n- openstack-tox-py27 https://zuul.opendev.org/t/openstack/build/eba0a9d728be4603b1afeef05e5d3a60 : SUCCESS in 16m 42s\n- openstack-tox-py36 https://zuul.opendev.org/t/openstack/build/94f446930c334807ad5d35a321591611 : SUCCESS in 16m 28s\n- openstack-tox-py37 https://zuul.opendev.org/t/openstack/build/3275c37da8cd4cfba67dc28525edf59f : SUCCESS in 16m 15s\n- openstack-tox-docs https://zuul.opendev.org/t/openstack/build/8a7f6b2999ca4a7a8d02f0e921e88c7c : SUCCESS in 14m 49s\n- tempest-full https://zuul.opendev.org/t/openstack/build/0189cfcf580e439cbf19de1474ae586c : SUCCESS in 1h 33m 35s\n- neutron-grenade https://zuul.opendev.org/t/openstack/build/fe41abb8727946ea8220934c3a80afff : SUCCESS in 57m 28s\n- grenade https://zuul.opendev.org/t/openstack/build/8f9c3ce019f04a1daafd7881f9e4d46b : SUCCESS in 55m 42s\n- tempest-full-py3 https://zuul.opendev.org/t/openstack/build/1e3a7dafe51b47fa8c40e31bf1ba7f2a : SUCCESS in 1h 27m 28s\n- build-openstack-releasenotes https://zuul.opendev.org/t/openstack/build/b99d575348b9449ebab19f2dc0bb4c45 : SUCCESS in 9m 11s\n- keystone-dsvm-functional https://zuul.opendev.org/t/openstack/build/2609ef9c333a43b79d82ac725307d519 : SUCCESS in 33m 09s\n- keystone-dsvm-py3-functional https://zuul.opendev.org/t/openstack/build/1c23abec0bf64ff486db97e893fe0f1d : SUCCESS in 35m 33s\n- keystone-dsvm-functional-federation-opensuse15 https://zuul.opendev.org/t/openstack/build/28e7e9b1355a4f12ae9eacc8f4b6ef3d : FAILURE in 8m 49s (non-voting)\n- keystone-dsvm-py3-functional-federation-opensuse15 https://zuul.opendev.org/t/openstack/build/4ba8ae68962e42f893f3cc8e204e9432 : FAILURE in 8m 21s (non-voting)\n- keystone-dsvm-py3-functional-federation-opensuse15-k2k https://zuul.opendev.org/t/openstack/build/1a85104ed4e64b93bbf5e8a59e251eaa : FAILURE in 8m 42s\n- keystoneclient-devstack-functional https://zuul.opendev.org/t/openstack/build/41db660db7a3466680b25066203971e2 : SUCCESS in 18m 01s (non-voting)\n- keystone-dsvm-ldap-domain-specific-driver https://zuul.opendev.org/t/openstack/build/3be510115a0b41c387bda1ac34d6abce : SUCCESS in 48m 22s (non-voting)\n- grenade-py3 https://zuul.opendev.org/t/openstack/build/0eee415ec1c944298a918d52a31fced7 : SUCCESS in 1h 03m 57s\n- tempest-ipv6-only https://zuul.opendev.org/t/openstack/build/64107916b94442178b5685b8ab7accdf : SUCCESS in 56m 12s\n- keystone-tox-protection https://zuul.opendev.org/t/openstack/build/cdf5dceffce84e1ca5e5d7f2f007be33 : SUCCESS in 48m 26s","accounts_in_message":[],"_revision_number":2},{"id":"510dd97e63e49a5ba54d168eb6dadacd85edf415","author":{"_account_id":27954,"name":"Moisés Guimarães de Medeiros","email":"guimaraes@pm.me","username":"moguimar"},"date":"2020-10-23 20:38:36.000000000","message":"Patch Set 3: Patch Set 2 was rebased","accounts_in_message":[],"_revision_number":3},{"id":"2099cc62dc0b70c08625cbf0ea375737cdd45652","tag":"autogenerated:zuul:check","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2020-10-23 23:01:23.000000000","message":"Patch Set 3:\n\nBuild failed (check pipeline).  For information on how to proceed, see\nhttps://docs.opendev.org/opendev/infra-manual/latest/developers.html#automated-testing\n\n\n- openstack-tox-cover https://zuul.opendev.org/t/openstack/build/1f3138f4ff4c4750b1ae91706a7a113b : SUCCESS in 18m 25s\n- openstack-tox-lower-constraints https://zuul.opendev.org/t/openstack/build/e653e2a8328547bfbcadba61183de64a : SUCCESS in 14m 54s\n- openstack-tox-pep8 https://zuul.opendev.org/t/openstack/build/2ef2e9dab45448569851ca10791d8366 : SUCCESS in 29m 13s\n- openstack-tox-py27 https://zuul.opendev.org/t/openstack/build/4e13650f63c940bd952da43637287e0d : SUCCESS in 15m 46s\n- openstack-tox-py36 https://zuul.opendev.org/t/openstack/build/b4bb6e3c8c904108bafa8d9719d04b57 : SUCCESS in 35m 34s\n- openstack-tox-py37 https://zuul.opendev.org/t/openstack/build/26b17564a819441d96df51a66e4db598 : SUCCESS in 18m 16s\n- openstack-tox-docs https://zuul.opendev.org/t/openstack/build/0303caa275c54fb4a2fb4d9ee91d4ae7 : SUCCESS in 13m 09s\n- tempest-full https://zuul.opendev.org/t/openstack/build/2f1555ee2b124ffaa929e03c520789f2 : SUCCESS in 1h 24m 38s\n- neutron-grenade https://zuul.opendev.org/t/openstack/build/b78f59a5ce734679b3b423dacaf53c32 : SUCCESS in 2h 00m 10s\n- grenade https://zuul.opendev.org/t/openstack/build/5431cafb2a2d4d6ca486b091f96509c9 : SUCCESS in 2h 05m 50s\n- tempest-full-py3 https://zuul.opendev.org/t/openstack/build/8e52a59f9d974ba98939d5f193413caf : TIMED_OUT in 2h 05m 52s\n- build-openstack-releasenotes https://zuul.opendev.org/t/openstack/build/a4fbd82f136c4edcba4c7e55c01a0fd9 : SUCCESS in 28m 47s\n- keystone-dsvm-functional https://zuul.opendev.org/t/openstack/build/d2165d26e6ae45daab00ac9067851a31 : TIMED_OUT in 1h 14m 32s\n- keystone-dsvm-py3-functional https://zuul.opendev.org/t/openstack/build/3f070bc7adeb4fecb44b64821e80a576 : SUCCESS in 35m 04s\n- keystone-dsvm-functional-federation-opensuse15 https://zuul.opendev.org/t/openstack/build/6b77e50b0f9a4239bde89097ea36ef9c : FAILURE in 47m 56s (non-voting)\n- keystone-dsvm-py3-functional-federation-opensuse15 https://zuul.opendev.org/t/openstack/build/e1aed1ae89d34655ac8bc4846a360684 : FAILURE in 16m 44s (non-voting)\n- keystone-dsvm-py3-functional-federation-opensuse15-k2k https://zuul.opendev.org/t/openstack/build/778651f05ff54628999efc639c44741a : FAILURE in 16m 37s\n- keystoneclient-devstack-functional https://zuul.opendev.org/t/openstack/build/b4f0d2a7a1574954aedc3c9b71628173 : SUCCESS in 22m 27s (non-voting)\n- keystone-dsvm-ldap-domain-specific-driver https://zuul.opendev.org/t/openstack/build/9683735465564ad781865654b58066eb : SUCCESS in 45m 21s (non-voting)\n- grenade-py3 https://zuul.opendev.org/t/openstack/build/adb2723eb44e421780f0928092cd20d9 : SUCCESS in 2h 05m 41s\n- tempest-ipv6-only https://zuul.opendev.org/t/openstack/build/7d6f18317f1d417ab8bf6584e1931b62 : SUCCESS in 47m 31s\n- keystone-tox-protection https://zuul.opendev.org/t/openstack/build/d9ffada551bc409395c9a637994aca6a : SUCCESS in 50m 20s","accounts_in_message":[],"_revision_number":3},{"id":"6296840672b9176f56f3feef05abb187c35fe643","author":{"_account_id":27954,"name":"Moisés Guimarães de Medeiros","email":"guimaraes@pm.me","username":"moguimar"},"date":"2020-11-03 00:15:43.000000000","message":"Patch Set 4: Patch Set 3 was rebased","accounts_in_message":[],"_revision_number":4},{"id":"0b4c8a2741473be366e323651bd99eadb0b82bbd","tag":"autogenerated:zuul:check","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2020-11-03 06:48:27.000000000","message":"Patch Set 4: Verified+1\n\nBuild succeeded (check pipeline).\n\n- openstack-tox-cover https://zuul.opendev.org/t/openstack/build/cd8460199ccf41e29435ac82dc3d69ba : SUCCESS in 15m 25s\n- openstack-tox-lower-constraints https://zuul.opendev.org/t/openstack/build/724bcaa01a2b41d4be23e3edd7210190 : SUCCESS in 13m 37s\n- openstack-tox-pep8 https://zuul.opendev.org/t/openstack/build/2fac047301884913a9e182e56c49b41d : SUCCESS in 5m 45s\n- openstack-tox-py27 https://zuul.opendev.org/t/openstack/build/d5a81236c5b44490b6a8c132cdc95473 : SUCCESS in 12m 29s\n- openstack-tox-py36 https://zuul.opendev.org/t/openstack/build/31a80ad5e219455e85e0a0b6765d6a25 : SUCCESS in 11m 13s\n- openstack-tox-py37 https://zuul.opendev.org/t/openstack/build/7a0448d75de04d77ab65710b28aaa755 : SUCCESS in 12m 30s\n- openstack-tox-docs https://zuul.opendev.org/t/openstack/build/9071b5dbf67c4409b9c9459fdc6c2ebe : SUCCESS in 15m 03s\n- tempest-full https://zuul.opendev.org/t/openstack/build/4fc15434a1e84cafa0be40974ff714ff : SUCCESS in 1h 51m 00s\n- neutron-grenade https://zuul.opendev.org/t/openstack/build/cffa48fb5bc941d5ad93edb88a3862a8 : SUCCESS in 57m 33s\n- grenade https://zuul.opendev.org/t/openstack/build/cf9a0cb19dbc40a3ad3f8025842667a5 : SUCCESS in 1h 18m 30s\n- tempest-full-py3 https://zuul.opendev.org/t/openstack/build/896a6f137b364fb5ab5868da4e36b4bb : SUCCESS in 1h 34m 08s\n- build-openstack-releasenotes https://zuul.opendev.org/t/openstack/build/a714ef62758b4247aff9c08cbd17eeeb : SUCCESS in 7m 27s\n- keystone-dsvm-functional https://zuul.opendev.org/t/openstack/build/57f08334caec432b9a191b233e2dfd7a : SUCCESS in 51m 40s\n- keystone-dsvm-py3-functional https://zuul.opendev.org/t/openstack/build/349d4538efa74489ab6530be580c6430 : SUCCESS in 33m 37s\n- keystone-dsvm-functional-federation-opensuse15 https://zuul.opendev.org/t/openstack/build/9ad8161300a44362b3bca94278b7d914 : FAILURE in 12m 08s (non-voting)\n- keystone-dsvm-py3-functional-federation-opensuse15 https://zuul.opendev.org/t/openstack/build/53f9fcbdaab1442dae59bea5daefaaf2 : FAILURE in 11m 45s (non-voting)\n- keystone-dsvm-py3-functional-federation-opensuse15-k2k https://zuul.opendev.org/t/openstack/build/585c7c03514a4248b366e1c3d637ead5 : FAILURE in 5m 00s (non-voting)\n- keystoneclient-devstack-functional https://zuul.opendev.org/t/openstack/build/0afb532897614a818f6b8557b983aaed : SUCCESS in 13m 24s (non-voting)\n- keystone-dsvm-ldap-domain-specific-driver https://zuul.opendev.org/t/openstack/build/124f42e5ebf4426f84ceb4dda654c7d9 : SUCCESS in 35m 58s (non-voting)\n- grenade-py3 https://zuul.opendev.org/t/openstack/build/e18b0b76a19841709baf64038171bad0 : SUCCESS in 57m 01s\n- tempest-ipv6-only https://zuul.opendev.org/t/openstack/build/9de5e88549e6404095a4a36a8ad4de25 : SUCCESS in 55m 18s\n- keystone-tox-protection https://zuul.opendev.org/t/openstack/build/c8ba7a08aa98440f814aba9b2f30794f : SUCCESS in 38m 37s","accounts_in_message":[],"_revision_number":4},{"id":"7ea8f6881f268b1d36bea3c73962595fabdb619b","author":{"_account_id":8866,"name":"Raildo Mascena de Sousa Filho","email":"rmascena@redhat.com","username":"raildo"},"date":"2020-11-03 14:09:48.000000000","message":"Patch Set 4: Code-Review+1","accounts_in_message":[],"_revision_number":4},{"id":"6c3bb19df28901203ad8660f79bed635c24e4429","author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"date":"2020-11-03 14:57:56.000000000","message":"Patch Set 4: Code-Review+2","accounts_in_message":[],"_revision_number":4},{"id":"a962ecbdd83f8a17e32a61fcc3cab3b4279072c5","author":{"_account_id":8482,"name":"Colleen Murphy","email":"colleen@gazlene.net","username":"krinkle"},"date":"2020-11-16 23:01:32.000000000","message":"Patch Set 4: Code-Review+2 Workflow+1","accounts_in_message":[],"_revision_number":4},{"id":"8d5e9ccf2cac418714907e543e5845ed3cf6d355","tag":"autogenerated:zuul:gate","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2020-11-16 23:01:56.000000000","message":"Patch Set 4: -Verified\n\nStarting gate jobs.","accounts_in_message":[],"_revision_number":4},{"id":"8ac2c4c5da967b51c4391d8e58d82be7acd5dd34","tag":"autogenerated:zuul:gate","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2020-11-17 01:53:56.000000000","message":"Patch Set 4: Verified+2\n\nBuild succeeded (gate pipeline).\n\n- openstack-tox-lower-constraints https://zuul.opendev.org/t/openstack/build/75c4d3eb80b442c69f23fc928de65fe7 : SUCCESS in 21m 45s\n- openstack-tox-pep8 https://zuul.opendev.org/t/openstack/build/f059a327f8e1450cbccb9e41ac7d2649 : SUCCESS in 5m 59s\n- openstack-tox-py27 https://zuul.opendev.org/t/openstack/build/b59244d9138348d987408843a1aacdbe : SUCCESS in 12m 47s\n- openstack-tox-py36 https://zuul.opendev.org/t/openstack/build/9416aa63bf604ace85d8e93689502c8f : SUCCESS in 12m 42s\n- openstack-tox-py37 https://zuul.opendev.org/t/openstack/build/be5bb634bb3a4d14888ef5c7a0031646 : SUCCESS in 13m 08s\n- openstack-tox-docs https://zuul.opendev.org/t/openstack/build/3a3fbddff7c240a9a32b2ffb5107bad8 : SUCCESS in 12m 20s\n- tempest-full https://zuul.opendev.org/t/openstack/build/69150bc6ae5d4817b27a64380975bef9 : SUCCESS in 1h 30m 46s\n- neutron-grenade https://zuul.opendev.org/t/openstack/build/604c23fa4e464d8f9aa2d4e2f33c8135 : SUCCESS in 1h 05m 52s\n- grenade https://zuul.opendev.org/t/openstack/build/b7da93b8d2464b6aad0c45664269f3fb : SUCCESS in 1h 01m 57s\n- tempest-full-py3 https://zuul.opendev.org/t/openstack/build/e428fce0150447b78f0611fd46327697 : SUCCESS in 1h 25m 32s\n- build-openstack-releasenotes https://zuul.opendev.org/t/openstack/build/18722058f8b34754861b1249f3d2930d : SUCCESS in 7m 39s\n- keystone-dsvm-functional https://zuul.opendev.org/t/openstack/build/3c94853bc5c0451eb13f5652746f6b4a : SUCCESS in 34m 46s\n- keystone-dsvm-py3-functional https://zuul.opendev.org/t/openstack/build/36070bca78424ffbbba4555c90360134 : SUCCESS in 35m 22s\n- grenade-py3 https://zuul.opendev.org/t/openstack/build/b532acb14af64319826ada70c66f7ff5 : SUCCESS in 1h 06m 33s\n- tempest-ipv6-only https://zuul.opendev.org/t/openstack/build/4205241f4aef4858810ae7a6fe0f3f69 : SUCCESS in 1h 01m 17s\n- keystone-tox-protection https://zuul.opendev.org/t/openstack/build/88b6759d0e0b4a19b1589c0498b2a4a9 : SUCCESS in 37m 35s","accounts_in_message":[],"_revision_number":4},{"id":"c4f120a8794f512d1ab56cbca8c694e1dc3d2693","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2020-11-17 01:53:56.000000000","message":"Change has been successfully merged by Zuul","accounts_in_message":[],"_revision_number":4},{"id":"a1c69c8eea799bbb61cd3ca0e7c90c9ab5a65417","tag":"autogenerated:zuul:promote","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2020-11-17 01:55:43.000000000","message":"Patch Set 4:\n\nBuild succeeded (promote pipeline).\n\n- promote-openstack-tox-docs https://zuul.opendev.org/t/openstack/build/8f8621a96a1e46fcbb5d34f5e7b0fc99 : SUCCESS in 1m 22s\n- promote-openstack-releasenotes https://zuul.opendev.org/t/openstack/build/a14d46907fbb45bda6811d1041cd977f : SUCCESS in 47s","accounts_in_message":[],"_revision_number":4}],"current_revision_number":4,"current_revision":"105f95795f661f8106b3f33b87662024e5bf6dcb","revisions":{"36b49fb4f1a0c69efffe6425701c5a942833be40":{"kind":"REWORK","_number":1,"created":"2020-10-02 09:22:22.000000000","uploader":{"_account_id":27954,"name":"Moisés Guimarães de Medeiros","email":"guimaraes@pm.me","username":"moguimar"},"ref":"refs/changes/36/755736/1","fetch":{"anonymous http":{"url":"https://review.opendev.org/openstack/keystone","ref":"refs/changes/36/755736/1","commands":{"Checkout":"git fetch https://review.opendev.org/openstack/keystone refs/changes/36/755736/1 \u0026\u0026 git checkout FETCH_HEAD","Cherry Pick":"git fetch https://review.opendev.org/openstack/keystone refs/changes/36/755736/1 \u0026\u0026 git cherry-pick FETCH_HEAD","Format Patch":"git fetch https://review.opendev.org/openstack/keystone refs/changes/36/755736/1 \u0026\u0026 git format-patch -1 --stdout FETCH_HEAD","Pull":"git pull https://review.opendev.org/openstack/keystone refs/changes/36/755736/1"}}},"commit":{"parents":[{"commit":"fb7d54543fd69e046a5136ca4028f4e128b947c2","subject":"Fix lower-constraint for PyMySQL","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/keystone/commit/fb7d54543fd69e046a5136ca4028f4e128b947c2"}]}],"author":{"name":"Lance Bragstad","email":"lbragstad@gmail.com","date":"2020-09-29 15:20:13.000000000","tz":-300},"committer":{"name":"Moisés Guimarães","email":"moguimar@redhat.com","date":"2020-10-02 09:22:22.000000000","tz":0},"subject":"Implement more robust connection handling for asynchronous LDAP calls","message":"Implement more robust connection handling for asynchronous LDAP calls\n\nKeystone\u0027s paging implementation contains a memory leak. The issue is\nnoticeable if you integrate keystone with an LDAP server that supports\npaging and set `keystone.conf [ldap] page_size` to a low integer\n(e.g., 5).\n\nKeystone\u0027s LDAP backend uses `python-ldap` to interact with LDAP\nservers. For paged requests, it uses `search_ext()`, which is an\nasynchronous API [0]. The server responds with a message ID, which the\nclient uses to retrieve all data for the request. In keystone\u0027s case,\nthe `search_ext()` method is invoked with a page control that tells\nthe server to deliver responses in increments according to the page\nsize configured with `keystone.conf [ldap] page_size`. So long as the\nclient has the original connection used to fetch the message ID, it\ncan request the rest of the information associated to the request.\n\nKeystone\u0027s paging implementation loops continuously for paged\nrequests. It takes the message ID it gets from `search_ext()` and\ncalls `result3()`, asking the server for the data associated with that\nspecific message. Keystone continues to do this until the server sends\nan indicator that it has no more data relevant to the query (via a\ncookie). The `search_ext()` and `result3()` methods must use the same\nLDAP connection.\n\nGiven the above information, keystone uses context managers to provide\nconnections. This is relevant when deploying connection pools, where\ncertain connections are re-used from a pool. Keystone relies on Python\ncontext managers to handle connections, which is pretty typical\nuse-case for context managers. Connection managers allow us to do the\nfollowing (assuming pseudocode):\n\n  with self.get_connection as conn:\n      response \u003d conn.search_s()\n      return format(response)\n\nThe above snippet assumes the `get_connection` method provides a\nconnection object and a callable that implements `search_s`. Upon\nexiting the `with` statement, the connection is disconnected, or put\nback into the pool, or whatever the implementation of the context\nmanager decides to do. Most connections in the LDAP backend are\nhandled in this fashion.\n\nUnfortunately, the LDAP driver is somewhat oblivious to paging, it\u0027s\ncontrol implementation, or the fact that it uses an asynchronous API.\nInstead, the driver leaves it up to the handler objects it uses for\nconnections to determine if the request should be controlled via\npaging. This is an anti-pattern since the backend establishes the\nconnection for the request but doesn\u0027t ensure that connection is\nsafely handled for asynchronous APIs.\n\nThis forces the `search_ext()` and `result3()` implementations in the\nPooledLDAPHandler to know how to handle connections and context\nmanagers, since it needs to ensure the same connection is used for\npaged requests. The current code tried to clean up the context\nmanager responsible for connections after the results are collected\nfrom the server using the message ID. I believe it does this because\nit needs to get a new connection for each message in the paged\nresults, even though it already operates from within a connection\nestablished via a context manager and the PooledLDAPHandler almost\nalways returns the same connection object from the pool. The code\ntries to use a weak reference to create a callback that tears down the\ncontext manager when nothing else references it. At a high-level, the\nidea is similar to the following pseudocode:\n\n  with self.get_connection as conn:\n      while True:\n\tldap_data \u003d []\n\tcontext_manager \u003d self.get_connection()\n\tconnection \u003d context_manager.__enter__()\n\tmessage_id \u003d connection.search_ext()\n\tresults \u003d connection.result3(message_id)\n\tldap_data.append(results)\n\tcontext_manager.__exit__()\n\nI wasn\u0027t able to see the callback get invoked or work as described in\ncomments, resulting in memory bloat, especially with low page sizes\nwhich results in more requests. A weak reference invokes the callback\nwhen the weak reference is called, but there are no other references\nto the original object [1]. In our case, I don\u0027t think we invoke that\npath because we don\u0027t actually do anything with the weak reference. We\nassume it\u0027s going to run the callback when the object is garbage\ncollected.\n\nThis commit attempts to address this issue by using the concept of a\nfinalizer [2], which was designed for similar cases. It also attempts\nto hide the cleanup implementation in the AsynchronousMessage object,\nso that callers don\u0027t have to worry about making sure they invoke the\nfinalizer.\n\nAn alternative approach would be to push more of the paging logic and\nimplementation up into the LDAP driver. This would make it easier to\nput the entire asynchronous API flow for paging into a `with`\nstatement and relying on the normal behavior of context managers to\nclean up accordingly. This approach would remove the manual cleanup\ninvocation, regardless of using weak references or finalizer objects.\nHowever, this approach would likely require a non-trivial amount of\ndesign work to refactor the entire LDAP backend. The LDAP backend has\nother issues that would complicate the re-design process:\n\n  - Handlers and connection are generalized to mean the same thing\n  - Method names don\u0027t follow a convention\n  - Domain-specific language from python-ldap bleeds into keystone\u0027s\n    implementation (e.g., get_all, _ldap_get_all, add_member) at\n    different points in the backend (e.g., UserApi (BaseLdap), GroupApi\n    (BaseLdap), KeystoneLDAPHandler, PooledLDAPHandler,\n    PythonLDAPHandler)\n  - Backend contains dead code from when keystone supported writeable\n    LDAP backends\n  - Responsibility for connections and connection handling is spread\n    across objects (BaseLdap, LDAPHandler)\n  - Handlers will invoke methods differently based on configuration at\n    runtime, which is a sign that the relationship between the driver,\n    handlers, and connection objects isn\u0027t truely polymorphic\n\nWhile keeping the logic for properly handling context managers and\nconnections in the Handlers might not be ideal, it is a relatively\nminimal fix in comparison to a re-design or backend refactor. These\nissues can be considered during a refactor of the LDAP backend if or\nwhen the community decides to re-design the LDAP backend.\n\n[0] https://www.python-ldap.org/en/python-ldap-3.3.0/reference/ldap.html#ldap.LDAPObject.search_ext\n[1] https://docs.python.org/3/library/weakref.html#weakref.ref\n[2] https://docs.python.org/3/library/weakref.html#finalizer-objects\n\nCloses-Bug: 1896125\nChange-Id: Ia45a45ff852d0d4e3a713dae07a46d4ff8d370f3\n","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/keystone/commit/36b49fb4f1a0c69efffe6425701c5a942833be40"}],"resolve_conflicts_web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/keystone/commit/36b49fb4f1a0c69efffe6425701c5a942833be40"}]},"branch":"refs/heads/stable/train"},"789ff6eb643c13749f71cd6c972ff496042e73a2":{"kind":"TRIVIAL_REBASE","_number":2,"created":"2020-10-19 14:43:15.000000000","uploader":{"_account_id":27954,"name":"Moisés Guimarães de Medeiros","email":"guimaraes@pm.me","username":"moguimar"},"ref":"refs/changes/36/755736/2","fetch":{"anonymous http":{"url":"https://review.opendev.org/openstack/keystone","ref":"refs/changes/36/755736/2","commands":{"Checkout":"git fetch https://review.opendev.org/openstack/keystone refs/changes/36/755736/2 \u0026\u0026 git checkout FETCH_HEAD","Cherry Pick":"git fetch https://review.opendev.org/openstack/keystone refs/changes/36/755736/2 \u0026\u0026 git cherry-pick FETCH_HEAD","Format Patch":"git fetch https://review.opendev.org/openstack/keystone refs/changes/36/755736/2 \u0026\u0026 git format-patch -1 --stdout FETCH_HEAD","Pull":"git pull https://review.opendev.org/openstack/keystone refs/changes/36/755736/2"}}},"commit":{"parents":[{"commit":"b7c3458b6f11ade0ce54889ae5f782fbac4a9a2e","subject":"Update amqp lower constraint","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/keystone/commit/b7c3458b6f11ade0ce54889ae5f782fbac4a9a2e"}]}],"author":{"name":"Lance Bragstad","email":"lbragstad@gmail.com","date":"2020-09-29 15:20:13.000000000","tz":-300},"committer":{"name":"Moisés Guimarães","email":"moguimar@redhat.com","date":"2020-10-19 14:43:15.000000000","tz":0},"subject":"Implement more robust connection handling for asynchronous LDAP calls","message":"Implement more robust connection handling for asynchronous LDAP calls\n\nKeystone\u0027s paging implementation contains a memory leak. The issue is\nnoticeable if you integrate keystone with an LDAP server that supports\npaging and set `keystone.conf [ldap] page_size` to a low integer\n(e.g., 5).\n\nKeystone\u0027s LDAP backend uses `python-ldap` to interact with LDAP\nservers. For paged requests, it uses `search_ext()`, which is an\nasynchronous API [0]. The server responds with a message ID, which the\nclient uses to retrieve all data for the request. In keystone\u0027s case,\nthe `search_ext()` method is invoked with a page control that tells\nthe server to deliver responses in increments according to the page\nsize configured with `keystone.conf [ldap] page_size`. So long as the\nclient has the original connection used to fetch the message ID, it\ncan request the rest of the information associated to the request.\n\nKeystone\u0027s paging implementation loops continuously for paged\nrequests. It takes the message ID it gets from `search_ext()` and\ncalls `result3()`, asking the server for the data associated with that\nspecific message. Keystone continues to do this until the server sends\nan indicator that it has no more data relevant to the query (via a\ncookie). The `search_ext()` and `result3()` methods must use the same\nLDAP connection.\n\nGiven the above information, keystone uses context managers to provide\nconnections. This is relevant when deploying connection pools, where\ncertain connections are re-used from a pool. Keystone relies on Python\ncontext managers to handle connections, which is pretty typical\nuse-case for context managers. Connection managers allow us to do the\nfollowing (assuming pseudocode):\n\n  with self.get_connection as conn:\n      response \u003d conn.search_s()\n      return format(response)\n\nThe above snippet assumes the `get_connection` method provides a\nconnection object and a callable that implements `search_s`. Upon\nexiting the `with` statement, the connection is disconnected, or put\nback into the pool, or whatever the implementation of the context\nmanager decides to do. Most connections in the LDAP backend are\nhandled in this fashion.\n\nUnfortunately, the LDAP driver is somewhat oblivious to paging, it\u0027s\ncontrol implementation, or the fact that it uses an asynchronous API.\nInstead, the driver leaves it up to the handler objects it uses for\nconnections to determine if the request should be controlled via\npaging. This is an anti-pattern since the backend establishes the\nconnection for the request but doesn\u0027t ensure that connection is\nsafely handled for asynchronous APIs.\n\nThis forces the `search_ext()` and `result3()` implementations in the\nPooledLDAPHandler to know how to handle connections and context\nmanagers, since it needs to ensure the same connection is used for\npaged requests. The current code tried to clean up the context\nmanager responsible for connections after the results are collected\nfrom the server using the message ID. I believe it does this because\nit needs to get a new connection for each message in the paged\nresults, even though it already operates from within a connection\nestablished via a context manager and the PooledLDAPHandler almost\nalways returns the same connection object from the pool. The code\ntries to use a weak reference to create a callback that tears down the\ncontext manager when nothing else references it. At a high-level, the\nidea is similar to the following pseudocode:\n\n  with self.get_connection as conn:\n      while True:\n\tldap_data \u003d []\n\tcontext_manager \u003d self.get_connection()\n\tconnection \u003d context_manager.__enter__()\n\tmessage_id \u003d connection.search_ext()\n\tresults \u003d connection.result3(message_id)\n\tldap_data.append(results)\n\tcontext_manager.__exit__()\n\nI wasn\u0027t able to see the callback get invoked or work as described in\ncomments, resulting in memory bloat, especially with low page sizes\nwhich results in more requests. A weak reference invokes the callback\nwhen the weak reference is called, but there are no other references\nto the original object [1]. In our case, I don\u0027t think we invoke that\npath because we don\u0027t actually do anything with the weak reference. We\nassume it\u0027s going to run the callback when the object is garbage\ncollected.\n\nThis commit attempts to address this issue by using the concept of a\nfinalizer [2], which was designed for similar cases. It also attempts\nto hide the cleanup implementation in the AsynchronousMessage object,\nso that callers don\u0027t have to worry about making sure they invoke the\nfinalizer.\n\nAn alternative approach would be to push more of the paging logic and\nimplementation up into the LDAP driver. This would make it easier to\nput the entire asynchronous API flow for paging into a `with`\nstatement and relying on the normal behavior of context managers to\nclean up accordingly. This approach would remove the manual cleanup\ninvocation, regardless of using weak references or finalizer objects.\nHowever, this approach would likely require a non-trivial amount of\ndesign work to refactor the entire LDAP backend. The LDAP backend has\nother issues that would complicate the re-design process:\n\n  - Handlers and connection are generalized to mean the same thing\n  - Method names don\u0027t follow a convention\n  - Domain-specific language from python-ldap bleeds into keystone\u0027s\n    implementation (e.g., get_all, _ldap_get_all, add_member) at\n    different points in the backend (e.g., UserApi (BaseLdap), GroupApi\n    (BaseLdap), KeystoneLDAPHandler, PooledLDAPHandler,\n    PythonLDAPHandler)\n  - Backend contains dead code from when keystone supported writeable\n    LDAP backends\n  - Responsibility for connections and connection handling is spread\n    across objects (BaseLdap, LDAPHandler)\n  - Handlers will invoke methods differently based on configuration at\n    runtime, which is a sign that the relationship between the driver,\n    handlers, and connection objects isn\u0027t truely polymorphic\n\nWhile keeping the logic for properly handling context managers and\nconnections in the Handlers might not be ideal, it is a relatively\nminimal fix in comparison to a re-design or backend refactor. These\nissues can be considered during a refactor of the LDAP backend if or\nwhen the community decides to re-design the LDAP backend.\n\n[0] https://www.python-ldap.org/en/python-ldap-3.3.0/reference/ldap.html#ldap.LDAPObject.search_ext\n[1] https://docs.python.org/3/library/weakref.html#weakref.ref\n[2] https://docs.python.org/3/library/weakref.html#finalizer-objects\n\nCloses-Bug: 1896125\nChange-Id: Ia45a45ff852d0d4e3a713dae07a46d4ff8d370f3\n","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/keystone/commit/789ff6eb643c13749f71cd6c972ff496042e73a2"}],"resolve_conflicts_web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/keystone/commit/789ff6eb643c13749f71cd6c972ff496042e73a2"}]},"branch":"refs/heads/stable/train"},"f6df6d1ec496bce7e977d04b4f040790f2ad52aa":{"kind":"NO_CHANGE","_number":3,"created":"2020-10-23 20:38:36.000000000","uploader":{"_account_id":27954,"name":"Moisés Guimarães de Medeiros","email":"guimaraes@pm.me","username":"moguimar"},"ref":"refs/changes/36/755736/3","fetch":{"anonymous http":{"url":"https://review.opendev.org/openstack/keystone","ref":"refs/changes/36/755736/3","commands":{"Checkout":"git fetch https://review.opendev.org/openstack/keystone refs/changes/36/755736/3 \u0026\u0026 git checkout FETCH_HEAD","Cherry Pick":"git fetch https://review.opendev.org/openstack/keystone refs/changes/36/755736/3 \u0026\u0026 git cherry-pick FETCH_HEAD","Format Patch":"git fetch https://review.opendev.org/openstack/keystone refs/changes/36/755736/3 \u0026\u0026 git format-patch -1 --stdout FETCH_HEAD","Pull":"git pull https://review.opendev.org/openstack/keystone refs/changes/36/755736/3"}}},"commit":{"parents":[{"commit":"d435a915160a9876b58f2a04696d9430790e5cdc","subject":"Update amqp lower constraint","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/keystone/commit/d435a915160a9876b58f2a04696d9430790e5cdc"}]}],"author":{"name":"Lance Bragstad","email":"lbragstad@gmail.com","date":"2020-09-29 15:20:13.000000000","tz":-300},"committer":{"name":"Moisés Guimarães","email":"moguimar@redhat.com","date":"2020-10-23 20:38:36.000000000","tz":0},"subject":"Implement more robust connection handling for asynchronous LDAP calls","message":"Implement more robust connection handling for asynchronous LDAP calls\n\nKeystone\u0027s paging implementation contains a memory leak. The issue is\nnoticeable if you integrate keystone with an LDAP server that supports\npaging and set `keystone.conf [ldap] page_size` to a low integer\n(e.g., 5).\n\nKeystone\u0027s LDAP backend uses `python-ldap` to interact with LDAP\nservers. For paged requests, it uses `search_ext()`, which is an\nasynchronous API [0]. The server responds with a message ID, which the\nclient uses to retrieve all data for the request. In keystone\u0027s case,\nthe `search_ext()` method is invoked with a page control that tells\nthe server to deliver responses in increments according to the page\nsize configured with `keystone.conf [ldap] page_size`. So long as the\nclient has the original connection used to fetch the message ID, it\ncan request the rest of the information associated to the request.\n\nKeystone\u0027s paging implementation loops continuously for paged\nrequests. It takes the message ID it gets from `search_ext()` and\ncalls `result3()`, asking the server for the data associated with that\nspecific message. Keystone continues to do this until the server sends\nan indicator that it has no more data relevant to the query (via a\ncookie). The `search_ext()` and `result3()` methods must use the same\nLDAP connection.\n\nGiven the above information, keystone uses context managers to provide\nconnections. This is relevant when deploying connection pools, where\ncertain connections are re-used from a pool. Keystone relies on Python\ncontext managers to handle connections, which is pretty typical\nuse-case for context managers. Connection managers allow us to do the\nfollowing (assuming pseudocode):\n\n  with self.get_connection as conn:\n      response \u003d conn.search_s()\n      return format(response)\n\nThe above snippet assumes the `get_connection` method provides a\nconnection object and a callable that implements `search_s`. Upon\nexiting the `with` statement, the connection is disconnected, or put\nback into the pool, or whatever the implementation of the context\nmanager decides to do. Most connections in the LDAP backend are\nhandled in this fashion.\n\nUnfortunately, the LDAP driver is somewhat oblivious to paging, it\u0027s\ncontrol implementation, or the fact that it uses an asynchronous API.\nInstead, the driver leaves it up to the handler objects it uses for\nconnections to determine if the request should be controlled via\npaging. This is an anti-pattern since the backend establishes the\nconnection for the request but doesn\u0027t ensure that connection is\nsafely handled for asynchronous APIs.\n\nThis forces the `search_ext()` and `result3()` implementations in the\nPooledLDAPHandler to know how to handle connections and context\nmanagers, since it needs to ensure the same connection is used for\npaged requests. The current code tried to clean up the context\nmanager responsible for connections after the results are collected\nfrom the server using the message ID. I believe it does this because\nit needs to get a new connection for each message in the paged\nresults, even though it already operates from within a connection\nestablished via a context manager and the PooledLDAPHandler almost\nalways returns the same connection object from the pool. The code\ntries to use a weak reference to create a callback that tears down the\ncontext manager when nothing else references it. At a high-level, the\nidea is similar to the following pseudocode:\n\n  with self.get_connection as conn:\n      while True:\n\tldap_data \u003d []\n\tcontext_manager \u003d self.get_connection()\n\tconnection \u003d context_manager.__enter__()\n\tmessage_id \u003d connection.search_ext()\n\tresults \u003d connection.result3(message_id)\n\tldap_data.append(results)\n\tcontext_manager.__exit__()\n\nI wasn\u0027t able to see the callback get invoked or work as described in\ncomments, resulting in memory bloat, especially with low page sizes\nwhich results in more requests. A weak reference invokes the callback\nwhen the weak reference is called, but there are no other references\nto the original object [1]. In our case, I don\u0027t think we invoke that\npath because we don\u0027t actually do anything with the weak reference. We\nassume it\u0027s going to run the callback when the object is garbage\ncollected.\n\nThis commit attempts to address this issue by using the concept of a\nfinalizer [2], which was designed for similar cases. It also attempts\nto hide the cleanup implementation in the AsynchronousMessage object,\nso that callers don\u0027t have to worry about making sure they invoke the\nfinalizer.\n\nAn alternative approach would be to push more of the paging logic and\nimplementation up into the LDAP driver. This would make it easier to\nput the entire asynchronous API flow for paging into a `with`\nstatement and relying on the normal behavior of context managers to\nclean up accordingly. This approach would remove the manual cleanup\ninvocation, regardless of using weak references or finalizer objects.\nHowever, this approach would likely require a non-trivial amount of\ndesign work to refactor the entire LDAP backend. The LDAP backend has\nother issues that would complicate the re-design process:\n\n  - Handlers and connection are generalized to mean the same thing\n  - Method names don\u0027t follow a convention\n  - Domain-specific language from python-ldap bleeds into keystone\u0027s\n    implementation (e.g., get_all, _ldap_get_all, add_member) at\n    different points in the backend (e.g., UserApi (BaseLdap), GroupApi\n    (BaseLdap), KeystoneLDAPHandler, PooledLDAPHandler,\n    PythonLDAPHandler)\n  - Backend contains dead code from when keystone supported writeable\n    LDAP backends\n  - Responsibility for connections and connection handling is spread\n    across objects (BaseLdap, LDAPHandler)\n  - Handlers will invoke methods differently based on configuration at\n    runtime, which is a sign that the relationship between the driver,\n    handlers, and connection objects isn\u0027t truely polymorphic\n\nWhile keeping the logic for properly handling context managers and\nconnections in the Handlers might not be ideal, it is a relatively\nminimal fix in comparison to a re-design or backend refactor. These\nissues can be considered during a refactor of the LDAP backend if or\nwhen the community decides to re-design the LDAP backend.\n\n[0] https://www.python-ldap.org/en/python-ldap-3.3.0/reference/ldap.html#ldap.LDAPObject.search_ext\n[1] https://docs.python.org/3/library/weakref.html#weakref.ref\n[2] https://docs.python.org/3/library/weakref.html#finalizer-objects\n\nCloses-Bug: 1896125\nChange-Id: Ia45a45ff852d0d4e3a713dae07a46d4ff8d370f3\n","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/keystone/commit/f6df6d1ec496bce7e977d04b4f040790f2ad52aa"}],"resolve_conflicts_web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/keystone/commit/f6df6d1ec496bce7e977d04b4f040790f2ad52aa"}]},"branch":"refs/heads/stable/train"},"105f95795f661f8106b3f33b87662024e5bf6dcb":{"kind":"TRIVIAL_REBASE","_number":4,"created":"2020-11-03 00:15:43.000000000","uploader":{"_account_id":27954,"name":"Moisés Guimarães de Medeiros","email":"guimaraes@pm.me","username":"moguimar"},"ref":"refs/changes/36/755736/4","fetch":{"anonymous http":{"url":"https://review.opendev.org/openstack/keystone","ref":"refs/changes/36/755736/4","commands":{"Checkout":"git fetch https://review.opendev.org/openstack/keystone refs/changes/36/755736/4 \u0026\u0026 git checkout FETCH_HEAD","Cherry Pick":"git fetch https://review.opendev.org/openstack/keystone refs/changes/36/755736/4 \u0026\u0026 git cherry-pick FETCH_HEAD","Format Patch":"git fetch https://review.opendev.org/openstack/keystone refs/changes/36/755736/4 \u0026\u0026 git format-patch -1 --stdout FETCH_HEAD","Pull":"git pull https://review.opendev.org/openstack/keystone refs/changes/36/755736/4"}}},"commit":{"parents":[{"commit":"28d2dd19e10d5d58d11f6319ae70a30251be1ef1","subject":"Make opensuse jobs nonvoting","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/keystone/commit/28d2dd19e10d5d58d11f6319ae70a30251be1ef1"}]}],"author":{"name":"Lance Bragstad","email":"lbragstad@gmail.com","date":"2020-09-29 15:20:13.000000000","tz":-300},"committer":{"name":"Moisés Guimarães","email":"moguimar@redhat.com","date":"2020-11-03 00:15:43.000000000","tz":0},"subject":"Implement more robust connection handling for asynchronous LDAP calls","message":"Implement more robust connection handling for asynchronous LDAP calls\n\nKeystone\u0027s paging implementation contains a memory leak. The issue is\nnoticeable if you integrate keystone with an LDAP server that supports\npaging and set `keystone.conf [ldap] page_size` to a low integer\n(e.g., 5).\n\nKeystone\u0027s LDAP backend uses `python-ldap` to interact with LDAP\nservers. For paged requests, it uses `search_ext()`, which is an\nasynchronous API [0]. The server responds with a message ID, which the\nclient uses to retrieve all data for the request. In keystone\u0027s case,\nthe `search_ext()` method is invoked with a page control that tells\nthe server to deliver responses in increments according to the page\nsize configured with `keystone.conf [ldap] page_size`. So long as the\nclient has the original connection used to fetch the message ID, it\ncan request the rest of the information associated to the request.\n\nKeystone\u0027s paging implementation loops continuously for paged\nrequests. It takes the message ID it gets from `search_ext()` and\ncalls `result3()`, asking the server for the data associated with that\nspecific message. Keystone continues to do this until the server sends\nan indicator that it has no more data relevant to the query (via a\ncookie). The `search_ext()` and `result3()` methods must use the same\nLDAP connection.\n\nGiven the above information, keystone uses context managers to provide\nconnections. This is relevant when deploying connection pools, where\ncertain connections are re-used from a pool. Keystone relies on Python\ncontext managers to handle connections, which is pretty typical\nuse-case for context managers. Connection managers allow us to do the\nfollowing (assuming pseudocode):\n\n  with self.get_connection as conn:\n      response \u003d conn.search_s()\n      return format(response)\n\nThe above snippet assumes the `get_connection` method provides a\nconnection object and a callable that implements `search_s`. Upon\nexiting the `with` statement, the connection is disconnected, or put\nback into the pool, or whatever the implementation of the context\nmanager decides to do. Most connections in the LDAP backend are\nhandled in this fashion.\n\nUnfortunately, the LDAP driver is somewhat oblivious to paging, it\u0027s\ncontrol implementation, or the fact that it uses an asynchronous API.\nInstead, the driver leaves it up to the handler objects it uses for\nconnections to determine if the request should be controlled via\npaging. This is an anti-pattern since the backend establishes the\nconnection for the request but doesn\u0027t ensure that connection is\nsafely handled for asynchronous APIs.\n\nThis forces the `search_ext()` and `result3()` implementations in the\nPooledLDAPHandler to know how to handle connections and context\nmanagers, since it needs to ensure the same connection is used for\npaged requests. The current code tried to clean up the context\nmanager responsible for connections after the results are collected\nfrom the server using the message ID. I believe it does this because\nit needs to get a new connection for each message in the paged\nresults, even though it already operates from within a connection\nestablished via a context manager and the PooledLDAPHandler almost\nalways returns the same connection object from the pool. The code\ntries to use a weak reference to create a callback that tears down the\ncontext manager when nothing else references it. At a high-level, the\nidea is similar to the following pseudocode:\n\n  with self.get_connection as conn:\n      while True:\n\tldap_data \u003d []\n\tcontext_manager \u003d self.get_connection()\n\tconnection \u003d context_manager.__enter__()\n\tmessage_id \u003d connection.search_ext()\n\tresults \u003d connection.result3(message_id)\n\tldap_data.append(results)\n\tcontext_manager.__exit__()\n\nI wasn\u0027t able to see the callback get invoked or work as described in\ncomments, resulting in memory bloat, especially with low page sizes\nwhich results in more requests. A weak reference invokes the callback\nwhen the weak reference is called, but there are no other references\nto the original object [1]. In our case, I don\u0027t think we invoke that\npath because we don\u0027t actually do anything with the weak reference. We\nassume it\u0027s going to run the callback when the object is garbage\ncollected.\n\nThis commit attempts to address this issue by using the concept of a\nfinalizer [2], which was designed for similar cases. It also attempts\nto hide the cleanup implementation in the AsynchronousMessage object,\nso that callers don\u0027t have to worry about making sure they invoke the\nfinalizer.\n\nAn alternative approach would be to push more of the paging logic and\nimplementation up into the LDAP driver. This would make it easier to\nput the entire asynchronous API flow for paging into a `with`\nstatement and relying on the normal behavior of context managers to\nclean up accordingly. This approach would remove the manual cleanup\ninvocation, regardless of using weak references or finalizer objects.\nHowever, this approach would likely require a non-trivial amount of\ndesign work to refactor the entire LDAP backend. The LDAP backend has\nother issues that would complicate the re-design process:\n\n  - Handlers and connection are generalized to mean the same thing\n  - Method names don\u0027t follow a convention\n  - Domain-specific language from python-ldap bleeds into keystone\u0027s\n    implementation (e.g., get_all, _ldap_get_all, add_member) at\n    different points in the backend (e.g., UserApi (BaseLdap), GroupApi\n    (BaseLdap), KeystoneLDAPHandler, PooledLDAPHandler,\n    PythonLDAPHandler)\n  - Backend contains dead code from when keystone supported writeable\n    LDAP backends\n  - Responsibility for connections and connection handling is spread\n    across objects (BaseLdap, LDAPHandler)\n  - Handlers will invoke methods differently based on configuration at\n    runtime, which is a sign that the relationship between the driver,\n    handlers, and connection objects isn\u0027t truely polymorphic\n\nWhile keeping the logic for properly handling context managers and\nconnections in the Handlers might not be ideal, it is a relatively\nminimal fix in comparison to a re-design or backend refactor. These\nissues can be considered during a refactor of the LDAP backend if or\nwhen the community decides to re-design the LDAP backend.\n\n[0] https://www.python-ldap.org/en/python-ldap-3.3.0/reference/ldap.html#ldap.LDAPObject.search_ext\n[1] https://docs.python.org/3/library/weakref.html#weakref.ref\n[2] https://docs.python.org/3/library/weakref.html#finalizer-objects\n\nCloses-Bug: 1896125\nChange-Id: Ia45a45ff852d0d4e3a713dae07a46d4ff8d370f3\n","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/keystone/commit/105f95795f661f8106b3f33b87662024e5bf6dcb"}],"resolve_conflicts_web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/keystone/commit/105f95795f661f8106b3f33b87662024e5bf6dcb"}]},"branch":"refs/heads/stable/train"}},"requirements":[],"submit_records":[],"submit_requirements":[]}
