)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":8482,"name":"Colleen Murphy","email":"colleen@gazlene.net","username":"krinkle"},"change_message_id":"3635fc7cecb366fa05a2b666571933f2f0a065f3","unresolved":false,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"WIP: Two level limit enforcer"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Building on the flat enforce, added POC for two lovel enforcement."},{"line_number":10,"context_line":""},{"line_number":11,"context_line":"Clearly needs more testing to shake out issues, but it shows how it"},{"line_number":12,"context_line":"could work in a way that when there is no hierarchy its almost as"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":6,"id":"3fa7e38b_2723f708","line":9,"range":{"start_line":9,"start_character":48,"end_line":9,"end_character":53},"updated":"2019-11-27 19:19:56.000000000","message":"typo :)","commit_id":"0a54c217286ec26b18d97a554c0b0104142992c8"},{"author":{"_account_id":6928,"name":"Ben Nemec","email":"openstack@nemebean.com","username":"bnemec"},"change_message_id":"82e0c3f11faed5c675f2a73c90681e4be4e737b4","unresolved":false,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"WIP: Two level limit enforcer"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Building on the flat enforce, added POC for two lovel enforcement."},{"line_number":10,"context_line":""},{"line_number":11,"context_line":"Clearly needs more testing to shake out issues, but it shows how it"},{"line_number":12,"context_line":"could work in a way that when there is no hierarchy its almost as"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":6,"id":"3fa7e38b_7b0c0393","line":9,"range":{"start_line":9,"start_character":48,"end_line":9,"end_character":53},"in_reply_to":"3fa7e38b_2723f708","updated":"2019-12-18 22:39:18.000000000","message":"Would be more appropriate in a couple of months. \u003c3","commit_id":"0a54c217286ec26b18d97a554c0b0104142992c8"}],"/PATCHSET_LEVEL":[{"author":{"_account_id":782,"name":"John Garbutt","email":"john@johngarbutt.com","username":"johngarbutt"},"change_message_id":"709ad11914550c912449bc278afe27fd49885697","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":10,"id":"33ad0e42_b3db395e","updated":"2023-05-02 15:15:38.000000000","message":"So I finally got time to refresh these patches.\n\nFixed up some issues I found when I expanded the unit test coverage.\n\nGoing to add this into the test environment where I have unified limits working (and I will report back),","commit_id":"544a8f863c85c3d755eb30b854ed554a40c99629"},{"author":{"_account_id":782,"name":"John Garbutt","email":"john@johngarbutt.com","username":"johngarbutt"},"change_message_id":"ed613825147ca5e2b64ee71f02da8e3c478c6d08","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":14,"id":"0b8fe3a5_33769b3a","updated":"2024-04-10 09:47:21.000000000","message":"I can confirm this worked when I tested this on a yoga based cloud, before the most recent rebase due to some test changes.","commit_id":"036839887db592e0b4468f63c288b856fcb97ac3"},{"author":{"_account_id":9816,"name":"Takashi Kajinami","email":"kajinamit@oss.nttdata.com","username":"kajinamit"},"change_message_id":"b41c1b4a321a2e83dd3d4c09aa0f83b886506e9a","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":15,"id":"483a3d23_36f0a7bc","updated":"2024-10-26 16:48:33.000000000","message":"I don\u0027t know the full discussions behind this design so might be asking for something you\u0027ve already discussed.\n\nWhile the proposed logic is quite clear, I\u0027m concerned with the scalability problem It poses. If you have 1 top level project and have 10 sub projects in it, you need additional 11 API calls to get all usages in the tree and check the top level enforcement. I wonder if we should rather consider implementing a new API in keystone and offload some tasks ?","commit_id":"20224481172d8a20b1ac1fa8b0f8d46f391cbdd4"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"783e3cadce065466df0314e33ed9421d6f8baf99","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":15,"id":"ea79bd71_b8436257","updated":"2024-07-12 17:42:15.000000000","message":"recheck get fresh results","commit_id":"20224481172d8a20b1ac1fa8b0f8d46f391cbdd4"},{"author":{"_account_id":782,"name":"John Garbutt","email":"john@johngarbutt.com","username":"johngarbutt"},"change_message_id":"0708c81957a426877cc643d26109420bd3cca80f","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":15,"id":"97693976_ceb4910a","in_reply_to":"483a3d23_36f0a7bc","updated":"2024-10-27 21:47:55.000000000","message":"\u003e I don\u0027t know the full discussions behind this design so might be asking for something you\u0027ve already discussed.\n\u003e \n\u003e While the proposed logic is quite clear, I\u0027m concerned with the scalability problem It poses. If you have 1 top level project and have 10 sub projects in it, you need additional 11 API calls to get all usages in the tree and check the top level enforcement. I wonder if we should rather consider implementing a new API in keystone and offload some tasks ?\n\nThe caching should stop that being too much of a problem, in theory, at least.\n\nThat being said, there is a lot of resource counting going on that is pretty expensive, but that is mostly unavoidable.\n\nThe aim here is get something that is correct, then optimise if we have too. We designed this many years ago, possibly the first Vancouver summit, I forget. There is detailed docs in the keystone spec:\nhttps://review.opendev.org/c/openstack/keystone-specs/+/540803","commit_id":"20224481172d8a20b1ac1fa8b0f8d46f391cbdd4"},{"author":{"_account_id":9816,"name":"Takashi Kajinami","email":"kajinamit@oss.nttdata.com","username":"kajinamit"},"change_message_id":"bcdfcd70613389967e763d01d272ae26d9647c3d","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":15,"id":"2f77fffc_f62c2c27","in_reply_to":"97693976_ceb4910a","updated":"2024-10-29 17:47:24.000000000","message":"Caching my help but it brings different concerns especially especially when you use caching for usage.\n\nI won\u0027t block this hard given the fact this is based on the design somehow agreed and I agree having not best but working implementation is better. I left a few suggestions inline to potentially improve efficiency but will +A if you want to cover these in follow-up.","commit_id":"20224481172d8a20b1ac1fa8b0f8d46f391cbdd4"}],"oslo_limit/limit.py":[{"author":{"_account_id":8482,"name":"Colleen Murphy","email":"colleen@gazlene.net","username":"krinkle"},"change_message_id":"2ebd97709cdf12f211d239ff38bd5fd5d3611d37","unresolved":false,"context_lines":[{"line_number":150,"context_line":""},{"line_number":151,"context_line":"class _StrictTwoLevelEnforcer(object):"},{"line_number":152,"context_line":""},{"line_number":153,"context_line":"    name \u003d \u0027strict-two-level\u0027"},{"line_number":154,"context_line":""},{"line_number":155,"context_line":"    def __init__(self, usage_callback):"},{"line_number":156,"context_line":"        self._usage_callback \u003d usage_callback"}],"source_content_type":"text/x-python","patch_set":6,"id":"3fa7e38b_6151060c","line":153,"updated":"2020-02-14 23:05:56.000000000","message":"This needs to be strict_two_level https://opendev.org/openstack/keystone/src/commit/b3cbf60c3c764bd9e0cf6168156e5de71c081449/keystone/limit/models/strict_two_level.py#L27","commit_id":"0a54c217286ec26b18d97a554c0b0104142992c8"},{"author":{"_account_id":8482,"name":"Colleen Murphy","email":"colleen@gazlene.net","username":"krinkle"},"change_message_id":"8e573aa8127e4ba60ab97a60ed6dfe1bdfd8b7f7","unresolved":false,"context_lines":[{"line_number":162,"context_line":""},{"line_number":163,"context_line":"    def _get_all_projects_in_tree(self, project_id):"},{"line_number":164,"context_line":"        # TODO(johngarbutt) call keystone"},{"line_number":165,"context_line":"        return [project_id]"},{"line_number":166,"context_line":""},{"line_number":167,"context_line":"    def enforce(self, owner_project_id, deltas):"},{"line_number":168,"context_line":"        resources_to_check \u003d list([name for name, value in deltas.items()])"}],"source_content_type":"text/x-python","patch_set":6,"id":"3fa7e38b_e1ef367d","line":165,"updated":"2020-02-15 01:12:50.000000000","message":"Took a stab at writing up this bit, ran into https://bugs.launchpad.net/keystone/+bug/1863393\n\nWorkaround was easy though: http://paste.openstack.org/show/789602/","commit_id":"0a54c217286ec26b18d97a554c0b0104142992c8"},{"author":{"_account_id":8482,"name":"Colleen Murphy","email":"colleen@gazlene.net","username":"krinkle"},"change_message_id":"3635fc7cecb366fa05a2b666571933f2f0a065f3","unresolved":false,"context_lines":[{"line_number":170,"context_line":"        resources_to_check.sort()"},{"line_number":171,"context_line":""},{"line_number":172,"context_line":"        parent_project \u003d self._get_parent_project(owner_project_id)"},{"line_number":173,"context_line":"        is_parent_project \u003d parent_project \u003d\u003d owner_project_id"},{"line_number":174,"context_line":""},{"line_number":175,"context_line":"        # First check limits in the project the resource is being created in"},{"line_number":176,"context_line":"        # but skip the check if we are the parent project"}],"source_content_type":"text/x-python","patch_set":6,"id":"3fa7e38b_e74abfab","line":173,"updated":"2019-11-27 19:19:56.000000000","message":"I don\u0027t think a project can be its own parent, what is this for?","commit_id":"0a54c217286ec26b18d97a554c0b0104142992c8"},{"author":{"_account_id":782,"name":"John Garbutt","email":"john@johngarbutt.com","username":"johngarbutt"},"change_message_id":"502f1b2dc423f37605db167b7057f541f979575d","unresolved":false,"context_lines":[{"line_number":170,"context_line":"        resources_to_check.sort()"},{"line_number":171,"context_line":""},{"line_number":172,"context_line":"        parent_project \u003d self._get_parent_project(owner_project_id)"},{"line_number":173,"context_line":"        is_parent_project \u003d parent_project \u003d\u003d owner_project_id"},{"line_number":174,"context_line":""},{"line_number":175,"context_line":"        # First check limits in the project the resource is being created in"},{"line_number":176,"context_line":"        # but skip the check if we are the parent project"}],"source_content_type":"text/x-python","patch_set":6,"id":"3fa7e38b_a0cfaa89","line":173,"in_reply_to":"3fa7e38b_e74abfab","updated":"2019-12-02 10:16:01.000000000","message":"What I mean here find the parent of the current limit tree.\n\nIn the two level tree, you are either the parent, or one of the children. The sum of all usage in the tree must not exceed the parent limit, etc.\n\nI am assuming a \"tree of one\" means the only project in that limit tree is the parent.\n\nAgreed this is different to the keystone project hierarchy. As you see, I haven\u0027t looked into how I build the limit project hierarchy yet.","commit_id":"0a54c217286ec26b18d97a554c0b0104142992c8"},{"author":{"_account_id":782,"name":"John Garbutt","email":"john@johngarbutt.com","username":"johngarbutt"},"change_message_id":"502f1b2dc423f37605db167b7057f541f979575d","unresolved":false,"context_lines":[{"line_number":175,"context_line":"        # First check limits in the project the resource is being created in"},{"line_number":176,"context_line":"        # but skip the check if we are the parent project"},{"line_number":177,"context_line":"        current_owner_usage \u003d None"},{"line_number":178,"context_line":"        if not is_parent_project:"},{"line_number":179,"context_line":"            project_limits \u003d self._utils.get_project_limits("},{"line_number":180,"context_line":"                owner_project_id, resources_to_check)"},{"line_number":181,"context_line":"            current_owner_usage \u003d self._usage_callback("}],"source_content_type":"text/x-python","patch_set":6,"id":"3fa7e38b_40c7d666","line":178,"updated":"2019-12-02 10:16:01.000000000","message":"Basically if you create resources in the parent project, there is no child limit to check before you check the limit on the whole tree.","commit_id":"0a54c217286ec26b18d97a554c0b0104142992c8"},{"author":{"_account_id":6928,"name":"Ben Nemec","email":"openstack@nemebean.com","username":"bnemec"},"change_message_id":"ade44dc9707685fc8cf93411421229f62e1332d2","unresolved":false,"context_lines":[{"line_number":188,"context_line":"                owner_project_id, project_limits, current_owner_usage, deltas)"},{"line_number":189,"context_line":""},{"line_number":190,"context_line":"        # Work out total usage of all projects in the one level deep tree"},{"line_number":191,"context_line":"        # TODO(johngarbutt): consider using DLM to stop quota races for this"},{"line_number":192,"context_line":"        #  case where its expensive to recompute"},{"line_number":193,"context_line":"        tree_limits \u003d self._utils.get_project_limits("},{"line_number":194,"context_line":"            parent_project, resources_to_check)"}],"source_content_type":"text/x-python","patch_set":7,"id":"bf51134e_ad606b34","line":191,"updated":"2020-06-15 16:02:44.000000000","message":"Good luck getting people to deploy a DLM. :-)","commit_id":"46c4f026e5e8cac6d5581e5909f500edca98ceff"},{"author":{"_account_id":9816,"name":"Takashi Kajinami","email":"kajinamit@oss.nttdata.com","username":"kajinamit"},"change_message_id":"bcdfcd70613389967e763d01d272ae26d9647c3d","unresolved":true,"context_lines":[{"line_number":245,"context_line":"        subtree_raw \u003d self.connection.get(url).json()[\u0027project\u0027][\u0027subtree\u0027]"},{"line_number":246,"context_line":""},{"line_number":247,"context_line":"        # project with no children has a subtree of None"},{"line_number":248,"context_line":"        child_projects \u003d ("},{"line_number":249,"context_line":"            list(subtree_raw.keys())"},{"line_number":250,"context_line":"            if subtree_raw is not None else []"},{"line_number":251,"context_line":"        )"}],"source_content_type":"text/x-python","patch_set":15,"id":"13870f5a_541a6a82","line":248,"updated":"2024-10-29 17:47:24.000000000","message":"This probably needs to be created right before L270","commit_id":"20224481172d8a20b1ac1fa8b0f8d46f391cbdd4"},{"author":{"_account_id":9816,"name":"Takashi Kajinami","email":"kajinamit@oss.nttdata.com","username":"kajinamit"},"change_message_id":"bcdfcd70613389967e763d01d272ae26d9647c3d","unresolved":true,"context_lines":[{"line_number":256,"context_line":"            if subtree_raw is not None else []"},{"line_number":257,"context_line":"        )"},{"line_number":258,"context_line":"        child_project_children \u003d ["},{"line_number":259,"context_line":"            tree for tree in child_project_children_raw if tree is not None"},{"line_number":260,"context_line":"        ]"},{"line_number":261,"context_line":"        if child_project_children:"},{"line_number":262,"context_line":"            raise ValueError(f\"Project tree for {project_id} is too deep!\")"}],"source_content_type":"text/x-python","patch_set":15,"id":"6256d42c_cbf81cce","line":259,"updated":"2024-10-29 17:47:24.000000000","message":"Creating a dedicated list is redundant here, in case the list contains 100 projects but the first one is a nested project.\n\nI\u0027d rather suggest quite bare for-loop instead for efficiency.\n\n```\nif subtree_raw is not None:\n    for tree in subtree_raw.values():\n        if tree:\n            raise ValueError()\n```","commit_id":"20224481172d8a20b1ac1fa8b0f8d46f391cbdd4"},{"author":{"_account_id":9816,"name":"Takashi Kajinami","email":"kajinamit@oss.nttdata.com","username":"kajinamit"},"change_message_id":"bcdfcd70613389967e763d01d272ae26d9647c3d","unresolved":true,"context_lines":[{"line_number":263,"context_line":""},{"line_number":264,"context_line":"        # double check the parent project is the root"},{"line_number":265,"context_line":"        if project_id !\u003d parent_id:"},{"line_number":266,"context_line":"            parent_parent_id \u003d self._get_parent_project(parent_id)"},{"line_number":267,"context_line":"            if parent_parent_id !\u003d parent_id:"},{"line_number":268,"context_line":"                raise ValueError(f\"Project tree for {project_id} is too deep!\")"},{"line_number":269,"context_line":""}],"source_content_type":"text/x-python","patch_set":15,"id":"5d101580_082ad505","line":266,"updated":"2024-10-29 17:47:24.000000000","message":"Can we run this check right after L243 ?","commit_id":"20224481172d8a20b1ac1fa8b0f8d46f391cbdd4"}],"oslo_limit/tests/test_limit.py":[{"author":{"_account_id":6928,"name":"Ben Nemec","email":"openstack@nemebean.com","username":"bnemec"},"change_message_id":"ade44dc9707685fc8cf93411421229f62e1332d2","unresolved":false,"context_lines":[{"line_number":214,"context_line":"        mock_usage.assert_any_call(project_id, [\"a\", \"b\"])"},{"line_number":215,"context_line":""},{"line_number":216,"context_line":"    @mock.patch.object(limit._EnforcerUtils, \"get_project_limits\")"},{"line_number":217,"context_line":"    def test_enforce_raises_on_child_over_two_level(self, mock_get_limits):"},{"line_number":218,"context_line":"        mock_usage \u003d mock.MagicMock()"},{"line_number":219,"context_line":""},{"line_number":220,"context_line":"        project_id \u003d uuid.uuid4().hex"}],"source_content_type":"text/x-python","patch_set":7,"id":"bf51134e_501cc269","line":217,"updated":"2020-06-15 16:02:44.000000000","message":"Would be nice to have a few more test cases since there are multiple reasons that a quota check might fail for this enforcer.","commit_id":"46c4f026e5e8cac6d5581e5909f500edca98ceff"}]}
