)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":9816,"name":"Takashi Kajinami","email":"kajinamit@oss.nttdata.com","username":"kajinamit"},"change_message_id":"6b0f81be2bb48876e03aa6a28b348a4de6f9d25e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"72b4609f_dc12af44","updated":"2026-11-08 06:12:15.000000000","message":"The logic update looks correct to me, but I have a few suggestions about test code.","commit_id":"9912562c168a85525de0de6d6080e1ecc1eb26f7"},{"author":{"_account_id":39493,"name":"Daniel Gines","display_name":"Daniel Gines","email":"dangines@gmail.com","username":"danielgines"},"change_message_id":"d25afc16cf73568f9b5d812e1743d8d52a1470ba","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"800612dd_d8885ed4","in_reply_to":"72b4609f_dc12af44","updated":"2026-11-08 20:45:09.000000000","message":"Thanks. PS2 addresses the comments on the tests. The telemetry-dsvm-integration failure of PS1 was not related to this change: devstack failed with \"g-api did not start\".","commit_id":"9912562c168a85525de0de6d6080e1ecc1eb26f7"},{"author":{"_account_id":9816,"name":"Takashi Kajinami","email":"kajinamit@oss.nttdata.com","username":"kajinamit"},"change_message_id":"3b3bfeaad64b90d69baaed86d7d83222c2464f1d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"dbb9dec9_25274d51","updated":"2026-11-09 06:22:13.000000000","message":"Thanks","commit_id":"913aafd429cd27ca5b65fbd073f478d7078d9299"}],"aodh/api/controllers/v2/alarms.py":[{"author":{"_account_id":9816,"name":"Takashi Kajinami","email":"kajinamit@oss.nttdata.com","username":"kajinamit"},"change_message_id":"6b0f81be2bb48876e03aa6a28b348a4de6f9d25e","unresolved":true,"context_lines":[{"line_number":107,"context_line":"    user_default_alarm_quota \u003d pecan.request.cfg.api.user_alarm_quota"},{"line_number":108,"context_line":"    project_default_alarm_quota \u003d pecan.request.cfg.api.project_alarm_quota"},{"line_number":109,"context_line":""},{"line_number":110,"context_line":"    # 1. Check project quota: the limit set through the quota API, if any,"},{"line_number":111,"context_line":"    # overrides project_alarm_quota. Both limit the alarms of the project,"},{"line_number":112,"context_line":"    # -1 means no limit."},{"line_number":113,"context_line":"    project_alarm_quota \u003d project_default_alarm_quota"},{"line_number":114,"context_line":"    for quota in project_quotas:"},{"line_number":115,"context_line":"        if quota.resource \u003d\u003d \u0027alarms\u0027:"}],"source_content_type":"text/x-python","patch_set":1,"id":"c2209919_3af2311d","line":112,"range":{"start_line":110,"start_character":28,"end_line":112,"end_character":24},"updated":"2026-11-08 06:12:15.000000000","message":"This looks too verbose to me, and if we add this we may need the same for user quote comment, so I\u0027d suggest removing it.","commit_id":"9912562c168a85525de0de6d6080e1ecc1eb26f7"},{"author":{"_account_id":39493,"name":"Daniel Gines","display_name":"Daniel Gines","email":"dangines@gmail.com","username":"danielgines"},"change_message_id":"d25afc16cf73568f9b5d812e1743d8d52a1470ba","unresolved":false,"context_lines":[{"line_number":109,"context_line":""},{"line_number":110,"context_line":"    # 1. Check project quota: the limit set through the quota API, if any,"},{"line_number":111,"context_line":"    # overrides project_alarm_quota. Both limit the alarms of the project,"},{"line_number":112,"context_line":"    # -1 means no limit."},{"line_number":113,"context_line":"    project_alarm_quota \u003d project_default_alarm_quota"},{"line_number":114,"context_line":"    for quota in project_quotas:"},{"line_number":115,"context_line":"        if quota.resource \u003d\u003d \u0027alarms\u0027:"}],"source_content_type":"text/x-python","patch_set":1,"id":"10384b42_1ee90ea9","line":112,"in_reply_to":"c2209919_3af2311d","updated":"2026-11-08 20:45:09.000000000","message":"Done, removed.","commit_id":"9912562c168a85525de0de6d6080e1ecc1eb26f7"}],"aodh/tests/functional/api/v2/test_alarm_scenarios.py":[{"author":{"_account_id":9816,"name":"Takashi Kajinami","email":"kajinamit@oss.nttdata.com","username":"kajinamit"},"change_message_id":"6b0f81be2bb48876e03aa6a28b348a4de6f9d25e","unresolved":true,"context_lines":[{"line_number":1144,"context_line":"                                      headers\u003dheaders, expect_errors\u003dTrue)"},{"line_number":1145,"context_line":"                if resp.status_code \u003d\u003d 201:"},{"line_number":1146,"context_line":"                    created +\u003d 1"},{"line_number":1147,"context_line":"                else:"},{"line_number":1148,"context_line":"                    self.assertEqual(403, resp.status_code)"},{"line_number":1149,"context_line":"        return created"},{"line_number":1150,"context_line":""},{"line_number":1151,"context_line":"    def test_project_quota_by_quota_api_counts_project_alarms(self):"}],"source_content_type":"text/x-python","patch_set":1,"id":"70377a21_32631977","line":1148,"range":{"start_line":1147,"start_character":21,"end_line":1148,"end_character":59},"updated":"2026-11-08 06:12:15.000000000","message":"I\u0027m afraid this causes confusing error when we expect 201 but api returns a different respose (because assert expects it returns 403)\nAdding an argument to explicitly determine whether API should fail or succeed may allow us to explicit strict assert.\n\n\n```\ndef _post_as_users(self, users, per_user, fail\u003dFalse):\n    ...\n    \n        status \u003d 201 if not fail else 403\n        self.post_json(\u0027/alarms\u0027, params\u003dalarm,\n                       headers\u003dheaders, expect_errors\u003dfail,\n                       status\u003dstatus)\n        if not fail:\n            created +\u003d 1\n```","commit_id":"9912562c168a85525de0de6d6080e1ecc1eb26f7"},{"author":{"_account_id":39493,"name":"Daniel Gines","display_name":"Daniel Gines","email":"dangines@gmail.com","username":"danielgines"},"change_message_id":"d25afc16cf73568f9b5d812e1743d8d52a1470ba","unresolved":false,"context_lines":[{"line_number":1145,"context_line":"                if resp.status_code \u003d\u003d 201:"},{"line_number":1146,"context_line":"                    created +\u003d 1"},{"line_number":1147,"context_line":"                else:"},{"line_number":1148,"context_line":"                    self.assertEqual(403, resp.status_code)"},{"line_number":1149,"context_line":"        return created"},{"line_number":1150,"context_line":""},{"line_number":1151,"context_line":"    def test_project_quota_by_quota_api_counts_project_alarms(self):"}],"source_content_type":"text/x-python","patch_set":1,"id":"5c8dd658_d28998ef","line":1148,"in_reply_to":"70377a21_32631977","updated":"2026-11-08 20:45:09.000000000","message":"Done. _post_as_users() now takes fail\u003dFalse and passes the expected status (201 or 403) to post_json(), so an unexpected answer fails with the actual status. On 403 it also checks the error message.","commit_id":"9912562c168a85525de0de6d6080e1ecc1eb26f7"},{"author":{"_account_id":9816,"name":"Takashi Kajinami","email":"kajinamit@oss.nttdata.com","username":"kajinamit"},"change_message_id":"6b0f81be2bb48876e03aa6a28b348a4de6f9d25e","unresolved":true,"context_lines":[{"line_number":1153,"context_line":"        # the quota API: the limit applies to the alarms of the project,"},{"line_number":1154,"context_line":"        # not to the alarms of each user"},{"line_number":1155,"context_line":"        self._set_project_quota(4)"},{"line_number":1156,"context_line":"        users \u003d [uuidutils.generate_uuid() for i in range(3)]"},{"line_number":1157,"context_line":"        self.assertEqual(4, self._post_as_users(users, 2))"},{"line_number":1158,"context_line":"        self.assertEqual(4, len(list(self.alarm_conn.get_alarms("},{"line_number":1159,"context_line":"            project_id\u003dself.project_id))))"},{"line_number":1160,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"931783e2_fbb6b378","line":1157,"range":{"start_line":1156,"start_character":61,"end_line":1157,"end_character":58},"updated":"2026-11-08 06:12:15.000000000","message":"can we split this call to two calls to assert first 4 succeeds and the remaining 2 fails, to explicitly check when the API call fails ?\n(we may want to split the user list instead of using the index hack, though)","commit_id":"9912562c168a85525de0de6d6080e1ecc1eb26f7"},{"author":{"_account_id":39493,"name":"Daniel Gines","display_name":"Daniel Gines","email":"dangines@gmail.com","username":"danielgines"},"change_message_id":"d25afc16cf73568f9b5d812e1743d8d52a1470ba","unresolved":false,"context_lines":[{"line_number":1154,"context_line":"        # not to the alarms of each user"},{"line_number":1155,"context_line":"        self._set_project_quota(4)"},{"line_number":1156,"context_line":"        users \u003d [uuidutils.generate_uuid() for i in range(3)]"},{"line_number":1157,"context_line":"        self.assertEqual(4, self._post_as_users(users, 2))"},{"line_number":1158,"context_line":"        self.assertEqual(4, len(list(self.alarm_conn.get_alarms("},{"line_number":1159,"context_line":"            project_id\u003dself.project_id))))"},{"line_number":1160,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"59e14ced_7752c911","line":1157,"in_reply_to":"931783e2_fbb6b378","updated":"2026-11-08 20:45:09.000000000","message":"Done, the user list is split: users[:2] create 2 alarms each (201), then users[2:] gets 403 for both of its alarms, and the project has exactly 4 alarms. Without the fix, the second call fails on its first POST (201 instead of 403).","commit_id":"9912562c168a85525de0de6d6080e1ecc1eb26f7"}]}
