)]}'
{"releasenotes/notes/fix-bfv-disk-accounting-773a95ec368843d5.yaml":[{"robot_id":"zuul","robot_run_id":"8db52338b3144f4b9bcbbcaac5befd90","url":"https://zuul.teim.app/t/main/buildset/8db52338b3144f4b9bcbbcaac5befd90","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"a609da58328651f5fafbc2cccedb361641c94487","patch_set":2,"id":"abb66620_4f9dfe1f","line":1,"updated":"2026-04-28 14:23:04.000000000","message":"The release note uses the \u0027features\u0027 category but this change is arguably a bug fix for incorrect disk accounting rather than a new feature.\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: Accurate release note categorization helps operators and downstream consumers understand the nature of changes when upgrading.\n\n**Recommendation**:\nConsider using \u0027fixes\u0027 instead of \u0027features\u0027 since the change corrects incorrect behavior. If the blueprint specifically tracks this as a feature, the current categorization is acceptable.","commit_id":"78d28052ad0817d3758306ef623b1d6fd709d839"},{"robot_id":"zuul","robot_run_id":"8107c8e09146437aae606ff5b27388c3","url":"https://zuul.teim.app/t/main/buildset/8107c8e09146437aae606ff5b27388c3","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"35139598206959165ff6ce719427d329aa5cd26b","patch_set":3,"id":"0995341c_6f602217","line":2,"updated":"2026-04-28 16:10:54.000000000","message":"The release note is filed under the \u0027features\u0027 section but this is arguably a bug fix since Watcher was incorrectly modeling disk usage. Consider using \u0027fixes\u0027 section instead.\n\n**Severity**: SUGGESTION | **Confidence**: 0.8\n\n**Benefit**: Users scanning release notes for bug fixes would more easily find this change.\n\n**Recommendation**:\nSince this implements a blueprint, using \u0027features\u0027 is acceptable. Consider changing to \u0027fixes\u0027 or adding both sections since the primary user impact is corrected behavior.","commit_id":"ce81e7b46e67982ea0fdd9dbd0fe6bae508b13ed"},{"robot_id":"zuul","robot_run_id":"43cd1395962840a2b773ae60be9a242c","url":"https://zuul.teim.app/t/main/buildset/43cd1395962840a2b773ae60be9a242c","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"5c0888095013a0aff7a6d98de8802271d1a49b98","patch_set":4,"id":"37f55814_0029df39","line":2,"updated":"2026-04-28 19:38:55.000000000","message":"The release note is categorised under \u0027features\u0027 but this is fundamentally a bug fix that corrects an incorrect model. Consider using the \u0027fixes\u0027 category instead.\n\n**Severity**: SUGGESTION | **Confidence**: 0.8\n\n**Benefit**: Using the correct category ensures operators scanning release notes find this under the right section. The file name implies a fix but the content uses features.\n\n**Recommendation**:\nConsider changing \u0027features:\u0027 to \u0027fixes:\u0027 and optionally adding a \u0027Bug:\u0027 reference. This aligns better with the intent of the change.","commit_id":"02b41922fe516c62ff2a889f3dd49f8c90707271"},{"robot_id":"zuul","robot_run_id":"6eb60bee38f345c5a79c458b91360f6d","url":"https://zuul.teim.app/t/main/buildset/6eb60bee38f345c5a79c458b91360f6d","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"75e2313acaec17ee7efbe434a4776bad40b188c3","patch_set":6,"id":"112727f0_f8f6d9b0","line":2,"updated":"2026-04-29 10:22:38.000000000","message":"The release note uses the \u0027features\u0027 category, but this change primarily fixes incorrect disk accounting behavior that caused valid migration destinations to be rejected.\n\n**Severity**: SUGGESTION | **Confidence**: 0.8\n\n**Benefit**: Using \u0027fixes\u0027 or a combination of \u0027fixes\u0027 and \u0027features\u0027 would more accurately communicate the nature of the change to operators upgrading their Watcher deployment.\n\n**Recommendation**:\nConsider using \u0027fixes\u0027 as the release note category since the primary effect is correcting a bug (wrong disk estimation). The ephemeral/swap addition could be listed as a separate \u0027features\u0027 entry if desired.","commit_id":"54b8ee7058c14fb0e7233e3fcb63d2a5110ee38c"},{"robot_id":"zuul","robot_run_id":"d7d5f386aced4204a347c14d7b21675e","url":"https://zuul.teim.app/t/main/buildset/d7d5f386aced4204a347c14d7b21675e","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"12d6f1dff28b66c7663ecefc381b23a2e6a2bd37","patch_set":7,"id":"5cb35839_39aac159","line":2,"updated":"2026-04-29 12:44:14.000000000","message":"The release note is categorized under \u0027features:\u0027 but this change is primarily a bug fix -- Watcher was incorrectly counting root disk for BFV instances. Using \u0027fixes:\u0027 would be more accurate for users scanning release notes.\n\n**Severity**: WARNING | **Confidence**: 0.7\n\n**Impact**: Operators scanning release notes for bug fixes may miss this important correction if it is listed only under features. The filename contains \u0027fix-\u0027 which suggests it was intended as a fix.\n\n**Suggestion**:\nConsider using \u0027fixes:\u0027 as the section key, or add both a \u0027fixes:\u0027 and \u0027features:\u0027 entry if the ephemeral/swap addition is considered a new feature separate from the BFV bug fix.","commit_id":"99ce421c0c7590d5ab33eed29cc51235e4140793"},{"robot_id":"zuul","robot_run_id":"ee7ccaf9f09948cdb4f6ba29af0cb2ed","url":"https://zuul.teim.app/t/main/buildset/ee7ccaf9f09948cdb4f6ba29af0cb2ed","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"da6287e35dbe5341062ecbe7d11dcb4fe7ad68a1","patch_set":8,"id":"b9715eef_4a420181","line":2,"updated":"2026-04-30 06:43:15.000000000","message":"The release note categorizes the fix as \u0027features\u0027 but this is primarily a bug fix. The release note should use \u0027fixes\u0027 for the BFV disk accounting correction.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: Users scanning release notes for bug fixes may miss this important correction. The BFV disk accounting issue is a bug while adding ephemeral/swap tracking is a feature.\n\n**Suggestion**:\nSplit into \u0027fixes\u0027 for the BFV root disk correction and \u0027features\u0027 for the ephemeral/swap disk accounting enhancement.","commit_id":"5b5b752366bfec42b2aad33dfb6b3040c5a1bd35"},{"robot_id":"zuul","robot_run_id":"430306f87f724ed58bf94cd471a4f72e","url":"https://zuul.teim.app/t/main/buildset/430306f87f724ed58bf94cd471a4f72e","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"04b4d790606164a1f829ecfb6362910f2dcda23f","patch_set":9,"id":"afae802e_62c8f3b4","line":2,"updated":"2026-04-30 08:09:24.000000000","message":"The release note is filed under \u0027features\u0027 but this is primarily a bug fix. The change corrects incorrect disk accounting behavior that caused migration strategy failures for BFV instances.\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: Filing under \u0027fixes\u0027 or adding a \u0027fixes\u0027 section helps users and operators find this change when looking for resolved issues.\n\n**Recommendation**:\nConsider adding a \u0027fixes:\u0027 section alongside \u0027features:\u0027 to note the corrected behavior, or use \u0027fixes:\u0027 as the primary section since this resolves incorrect model behavior.","commit_id":"5461b3611d211286d856282a44ae727e88242259"}],"watcher/common/nova_helper.py":[{"robot_id":"zuul","robot_run_id":"8db52338b3144f4b9bcbbcaac5befd90","url":"https://zuul.teim.app/t/main/buildset/8db52338b3144f4b9bcbbcaac5befd90","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"a609da58328651f5fafbc2cccedb361641c94487","patch_set":2,"id":"1b582f82_8dd32b69","line":128,"updated":"2026-04-28 14:23:04.000000000","message":"The is_boot_from_volume property returns True when image is None but lacks a docstring explaining that it relies on from_openstacksdk to normalize edge cases (None, empty string, empty dict, {\u0027id\u0027: None}) to None.\n\n**Severity**: WARNING | **Confidence**: 0.7\n\n**Impact**: Future maintainers might not understand the normalization contract and could add incorrect checks to the property directly, or pass raw image data that bypasses from_openstacksdk.\n\n**Suggestion**:\nAdd a brief docstring to is_boot_from_volume explaining the normalization contract: \u0027True when image is None. Relies on from_openstacksdk to normalize None, empty string, empty dict, and {id: None} to None.\u0027","commit_id":"78d28052ad0817d3758306ef623b1d6fd709d839"},{"robot_id":"zuul","robot_run_id":"8107c8e09146437aae606ff5b27388c3","url":"https://zuul.teim.app/t/main/buildset/8107c8e09146437aae606ff5b27388c3","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"35139598206959165ff6ce719427d329aa5cd26b","patch_set":3,"id":"fcc5d575_ed370ee2","line":128,"updated":"2026-04-28 16:10:54.000000000","message":"The Server.from_openstacksdk method normalizes image data by checking for None, empty string, and missing id, but the is_boot_from_volume property is a simple None check. This is correct but could benefit from a note that it relies on the normalization.\n\n**Severity**: SUGGESTION | **Confidence**: 0.8\n\n**Benefit**: Future maintainers would understand that the property relies on the normalization done in from_openstacksdk and would not add redundant checks.\n\n**Recommendation**:\nAdd a brief comment to is_boot_from_volume noting that from_openstacksdk normalizes all non-image cases (None, empty string, empty dict, dict with id\u003dNone) to None, so a simple None check is sufficient.","commit_id":"ce81e7b46e67982ea0fdd9dbd0fe6bae508b13ed"},{"robot_id":"zuul","robot_run_id":"8107c8e09146437aae606ff5b27388c3","url":"https://zuul.teim.app/t/main/buildset/8107c8e09146437aae606ff5b27388c3","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"35139598206959165ff6ce719427d329aa5cd26b","patch_set":3,"id":"0a3aeecf_754952fb","line":130,"updated":"2026-04-28 16:10:54.000000000","message":"The is_boot_from_volume property docstring has a typo: \"Check if server os boot from volume\" should be \"Check if server is boot from volume\" or better \"Check if the server boots from volume\".\n\n**Severity**: WARNING | **Confidence**: 1.0\n\n**Impact**: Minor documentation clarity issue. The docstring will be read by other developers and should use correct grammar to avoid confusion about the method\u0027s purpose.\n\n**Suggestion**:\nChange \"Check if server os boot from volume\" to \"Check if the server boots from volume\".","commit_id":"ce81e7b46e67982ea0fdd9dbd0fe6bae508b13ed"},{"robot_id":"zuul","robot_run_id":"43cd1395962840a2b773ae60be9a242c","url":"https://zuul.teim.app/t/main/buildset/43cd1395962840a2b773ae60be9a242c","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"5c0888095013a0aff7a6d98de8802271d1a49b98","patch_set":4,"id":"41ff42a8_e9ad0b47","line":1,"updated":"2026-04-28 19:38:55.000000000","message":"The commit message uses \u0027Assisted-By: Claude\u0027 which follows the AI policy, but could be more specific about what was assisted.\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: More specific AI attribution helps future readers understand the degree of AI involvement in the code.\n\n**Recommendation**:\nConsider using \u0027Assisted-By: Claude Code\u0027 or adding context like \u0027Assisted-By: Claude (test generation and code review)\u0027 to be more precise about AI contributions.","commit_id":"02b41922fe516c62ff2a889f3dd49f8c90707271"},{"robot_id":"zuul","robot_run_id":"43cd1395962840a2b773ae60be9a242c","url":"https://zuul.teim.app/t/main/buildset/43cd1395962840a2b773ae60be9a242c","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"5c0888095013a0aff7a6d98de8802271d1a49b98","patch_set":4,"id":"2fe67699_c20f5ed1","line":128,"updated":"2026-04-28 19:38:55.000000000","message":"The BFV detection heuristic (image is None) does not cover all cases. A BFV instance created from an image and then re-imaged or volume-attached may retain image metadata. This is an inherent limitation worth documenting.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: In edge cases where a BFV instance has residual image metadata, the model would incorrectly count root_gb as local disk. This mirrors how Nova itself detects BFV, so it is consistent but could be called out.\n\n**Suggestion**:\nAdd a comment near the is_boot_from_volume property noting this limitation and that it matches the Nova API convention (image\u003d\u0027\u0027 is normalised to None by openstacksdk for BFV).","commit_id":"02b41922fe516c62ff2a889f3dd49f8c90707271"},{"robot_id":"zuul","robot_run_id":"43cd1395962840a2b773ae60be9a242c","url":"https://zuul.teim.app/t/main/buildset/43cd1395962840a2b773ae60be9a242c","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"5c0888095013a0aff7a6d98de8802271d1a49b98","patch_set":4,"id":"d5c3552e_76bec016","line":130,"updated":"2026-04-28 19:38:55.000000000","message":"The docstring for is_boot_from_volume contains a grammatical error: \u0027Check if server os boot from volume\u0027 should be \u0027Check if server is boot from volume\u0027 or better \u0027Check if the server boots from volume\u0027.\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: Minor documentation clarity issue. Misleading docstring could confuse future contributors.\n\n**Suggestion**:\nFix the docstring to read: \u0027Check if the server boots from volume.\u0027 Also consider improving the :returns text from \u0027True when is boot from volume\u0027 to \u0027True when the server boots from volume\u0027.","commit_id":"02b41922fe516c62ff2a889f3dd49f8c90707271"},{"robot_id":"zuul","robot_run_id":"6eb60bee38f345c5a79c458b91360f6d","url":"https://zuul.teim.app/t/main/buildset/6eb60bee38f345c5a79c458b91360f6d","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"75e2313acaec17ee7efbe434a4776bad40b188c3","patch_set":6,"id":"3b6b40fb_55e33f85","line":157,"updated":"2026-04-29 10:22:38.000000000","message":"The is_boot_from_volume property returns True when image is None, but the from_openstacksdk factory can set image to None for several edge cases (image\u003dNone, image\u003d\u0027\u0027, image\u003d{}) that may not all strictly mean boot-from-volume in Nova\u0027s semantics.\n\n**Severity**: WARNING | **Confidence**: 0.7\n\n**Impact**: An instance that temporarily has no image metadata during a rebuild or error state could be incorrectly classified as BFV, setting disk to 0 and under-reporting local disk usage.\n\n**Suggestion**:\nConsider adding a defensive log message in from_openstacksdk when image is resolved to None from a non-standard input (empty string, empty dict), to aid future debugging. The current behaviour is likely correct for production scenarios but the edge case handling is implicit.","commit_id":"54b8ee7058c14fb0e7233e3fcb63d2a5110ee38c"},{"robot_id":"zuul","robot_run_id":"d7d5f386aced4204a347c14d7b21675e","url":"https://zuul.teim.app/t/main/buildset/d7d5f386aced4204a347c14d7b21675e","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"12d6f1dff28b66c7663ecefc381b23a2e6a2bd37","patch_set":7,"id":"03d36cfc_d6f3408b","line":131,"updated":"2026-04-29 12:44:14.000000000","message":"The is_boot_from_volume property docstring says \u0027True when is boot from volume\u0027 which has a grammatical error. Should read \u0027True when booting from volume\u0027 or \u0027True when the server boots from volume\u0027.\n\n**Severity**: SUGGESTION | **Confidence**: 0.8\n\n**Benefit**: Improves clarity and professionalism of the API documentation for the Server dataclass property.\n\n**Recommendation**:\nChange the docstring to \u0027:returns: True when the server boots from volume (image is None). False when booting from a local image.\u0027","commit_id":"99ce421c0c7590d5ab33eed29cc51235e4140793"},{"robot_id":"zuul","robot_run_id":"d7d5f386aced4204a347c14d7b21675e","url":"https://zuul.teim.app/t/main/buildset/d7d5f386aced4204a347c14d7b21675e","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"12d6f1dff28b66c7663ecefc381b23a2e6a2bd37","patch_set":7,"id":"9a1295c5_c12a2e90","line":157,"updated":"2026-04-29 12:44:14.000000000","message":"The from_openstacksdk method extracts image_data but stores only the image id string (or None), losing the full image dict. The Server.image field type annotation is \u0027dict | None\u0027 but the stored value is a str | None.\n\n**Severity**: SUGGESTION | **Confidence**: 0.8\n\n**Benefit**: Fixing the type annotation to \u0027str | None\u0027 would accurately reflect what is stored and prevent confusion for consumers of the dataclass that might expect a dict.\n\n**Recommendation**:\nChange the Server.image type annotation from \u0027dict | None\u0027 to \u0027str | None\u0027 to match the actual values stored by from_openstacksdk (which stores nova_server.image.id, a string, or None).","commit_id":"99ce421c0c7590d5ab33eed29cc51235e4140793"},{"robot_id":"zuul","robot_run_id":"ee7ccaf9f09948cdb4f6ba29af0cb2ed","url":"https://zuul.teim.app/t/main/buildset/ee7ccaf9f09948cdb4f6ba29af0cb2ed","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"da6287e35dbe5341062ecbe7d11dcb4fe7ad68a1","patch_set":8,"id":"9dac838d_aa5f4a4a","line":1,"updated":"2026-04-30 06:43:15.000000000","message":"The commit message uses \u0027Assisted-By: Claude\u0027 correctly per the AI policy but could provide more detail about what Claude specifically assisted with versus manual modifications.\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: Per the OpenInfra AI policy, commits should document what the AI generated and what was manually modified for better reviewer transparency.\n\n**Recommendation**:\nConsider expanding the commit body to note which parts Claude assisted with and which were manual, e.g., \u0027Claude assisted with the initial is_boot_from_volume property and disk calculation logic.\u0027","commit_id":"5b5b752366bfec42b2aad33dfb6b3040c5a1bd35"},{"robot_id":"zuul","robot_run_id":"ee7ccaf9f09948cdb4f6ba29af0cb2ed","url":"https://zuul.teim.app/t/main/buildset/ee7ccaf9f09948cdb4f6ba29af0cb2ed","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"da6287e35dbe5341062ecbe7d11dcb4fe7ad68a1","patch_set":8,"id":"24c4c17c_70d76795","line":126,"updated":"2026-04-30 06:43:15.000000000","message":"The image field type annotation is dict | None but from_openstacksdk stores image_data as a string (the image ID) or None, not a dict. This is a type inconsistency.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: Code that checks instance.image expecting a dict will fail at runtime. The is_boot_from_volume property works because it only checks None, but consumers expecting dict access would get an error.\n\n**Suggestion**:\nChange the type annotation from `dict | None` to `str | None` to reflect that image_data is extracted as nova_server.image.id (a string).","commit_id":"5b5b752366bfec42b2aad33dfb6b3040c5a1bd35"},{"robot_id":"zuul","robot_run_id":"430306f87f724ed58bf94cd471a4f72e","url":"https://zuul.teim.app/t/main/buildset/430306f87f724ed58bf94cd471a4f72e","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"04b4d790606164a1f829ecfb6362910f2dcda23f","patch_set":9,"id":"8eafbedd_ed5775a3","line":126,"updated":"2026-04-30 08:09:24.000000000","message":"The image field on the Server dataclass stores only the image UUID string. The naming \u0027image\u0027 for a string (not an object) could be slightly misleading when compared to \u0027image_uuid\u0027 used in notification payloads.\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: Renaming to \u0027image_id\u0027 would make it clearer that this stores a UUID string rather than an image object, and align with the naming convention in the notification path.\n\n**Recommendation**:\nConsider renaming the field to \u0027image_id\u0027 to clarify it stores a UUID string rather than an image object. This is a minor naming suggestion and not blocking.","commit_id":"5461b3611d211286d856282a44ae727e88242259"},{"robot_id":"zuul","robot_run_id":"430306f87f724ed58bf94cd471a4f72e","url":"https://zuul.teim.app/t/main/buildset/430306f87f724ed58bf94cd471a4f72e","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"04b4d790606164a1f829ecfb6362910f2dcda23f","patch_set":9,"id":"382b5e51_30fcbba9","line":157,"updated":"2026-04-30 08:09:24.000000000","message":"The from_openstacksdk method accesses nova_server.image.id without guarding against image being a dict with no \u0027id\u0027 key or an object without an \u0027id\u0027 attribute. If openstacksdk ever returns image\u003d{\u0027name\u0027: \u0027foo\u0027} (no id), this raises AttributeError.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: Could crash the data model build for a server with an unexpected image format from openstacksdk, causing audit failures.\n\n**Suggestion**:\nUse a safer extraction: `image_data \u003d getattr(nova_server.image, \u0027id\u0027, None) if nova_server.image else None` or wrap in a try/except AttributeError to be consistent with the defensive comment already present in the code.","commit_id":"5461b3611d211286d856282a44ae727e88242259"}],"watcher/decision_engine/model/collector/nova.py":[{"robot_id":"zuul","robot_run_id":"8db52338b3144f4b9bcbbcaac5befd90","url":"https://zuul.teim.app/t/main/buildset/8db52338b3144f4b9bcbbcaac5befd90","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"a609da58328651f5fafbc2cccedb361641c94487","patch_set":2,"id":"b6ac9abb_9f5c2314","line":496,"updated":"2026-04-28 14:23:04.000000000","message":"The disk calculation logic is duplicated between collector/nova.py (_build_instance_node) and notification/nova.py (update_instance) with different access patterns: direct key access vs .get() with defaults. This violates DRY and is the root cause of the KeyError bug.\n\n**Severity**: HIGH | **Confidence**: 0.9\n\n**Risk**: Divergent logic between the two code paths can lead to inconsistent disk values appearing in the model, depending on whether an instance was created via the initial collector sync or via a notification update.\n\n**Priority**: Before merge\n**Why This Matters**: Having two independent implementations of the same calculation means any future fix or enhancement must be applied in two places, and inconsistencies like the KeyError bug are almost inevitable.\n\n**Recommendation**:\nExtract a shared helper function (e.g., compute_local_disk_gb(is_bfv, flavor_dict)) in nova_helper.py or a shared utility module, and call it from both paths. This would also make it easy to unit test the disk calculation in isolation.","commit_id":"78d28052ad0817d3758306ef623b1d6fd709d839"},{"robot_id":"zuul","robot_run_id":"8db52338b3144f4b9bcbbcaac5befd90","url":"https://zuul.teim.app/t/main/buildset/8db52338b3144f4b9bcbbcaac5befd90","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"a609da58328651f5fafbc2cccedb361641c94487","patch_set":2,"id":"72339f95_2ff01e07","line":497,"updated":"2026-04-28 14:23:04.000000000","message":"The ceiling division pattern -(-x // 1024) for swap MB-to-GB conversion is correct but obscure. A brief explanatory comment exists but the pattern itself is not self-documenting and is duplicated in two files.\n\n**Severity**: SUGGESTION | **Confidence**: 0.8\n\n**Benefit**: Improved readability for reviewers and future maintainers. Extracting the pattern would also eliminate the duplication concern raised in the high-severity issue.\n\n**Recommendation**:\nConsider extracting a small helper like def mb_to_gb_ceil(mb): return -(-mb // 1024) if mb else 0, or use math.ceil(mb / 1024) with an explicit import, to make the intent self-documenting.","commit_id":"78d28052ad0817d3758306ef623b1d6fd709d839"},{"robot_id":"zuul","robot_run_id":"8db52338b3144f4b9bcbbcaac5befd90","url":"https://zuul.teim.app/t/main/buildset/8db52338b3144f4b9bcbbcaac5befd90","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"a609da58328651f5fafbc2cccedb361641c94487","patch_set":2,"id":"461c8085_14758eae","line":500,"updated":"2026-04-28 14:23:04.000000000","message":"The collector path uses flavor[\"ephemeral\"] and flavor[\"swap\"] with direct dict indexing, raising KeyError when the flavor dict lacks these keys. Both existing and new tests will crash due to this.\n\n**Severity**: CRITICAL | **Confidence**: 1.0\n\n**Risk**: KeyError at runtime when processing any instance whose flavor dict does not contain \u0027ephemeral\u0027 or \u0027swap\u0027 keys. This would break the entire model build for the compute node, preventing Watcher from generating any optimization decisions.\n\n**Priority**: Immediate\n**Why This Matters**: The OpenStackSDK server flavor dict is not guaranteed to include ephemeral or swap keys. Some flavors and some API responses omit them. The notification path correctly uses .get() with defaults but the collector path does not, creating an inconsistency and a crash path.\n\n**Recommendation**:\nUse flavor.get(\"ephemeral\", 0) and flavor.get(\"swap\", 0) in the collector path to match the notification path\u0027s safe access pattern. Also update the existing test__build_instance_node_extended_fields flavor dict to include ephemeral and swap keys.","commit_id":"78d28052ad0817d3758306ef623b1d6fd709d839"},{"robot_id":"zuul","robot_run_id":"8107c8e09146437aae606ff5b27388c3","url":"https://zuul.teim.app/t/main/buildset/8107c8e09146437aae606ff5b27388c3","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"35139598206959165ff6ce719427d329aa5cd26b","patch_set":3,"id":"e9129b80_2fdc975a","line":496,"updated":"2026-04-28 16:10:54.000000000","message":"The disk calculation logic (root_disk + ephemeral + ceil(swap/1024)) is duplicated between nova.py:496-500 and nova.py (notification):88-97. The ceiling division formula -(-x // 1024) appears in both places with the same inline comment.\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: Duplicated calculation logic increases maintenance burden. If the formula changes (e.g., swap handling), both locations must be updated in lockstep. The ceiling division idiom -(-x // 1024) is also non-obvious without the comment.\n\n**Suggestion**:\nConsider extracting a shared helper function (e.g., _compute_local_disk_gb(root_disk_gb, ephemeral_gb, swap_mb)) in a common module that both the collector and notification code can import. This would also make the swap ceiling division self-documenting.","commit_id":"ce81e7b46e67982ea0fdd9dbd0fe6bae508b13ed"},{"robot_id":"zuul","robot_run_id":"8107c8e09146437aae606ff5b27388c3","url":"https://zuul.teim.app/t/main/buildset/8107c8e09146437aae606ff5b27388c3","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"35139598206959165ff6ce719427d329aa5cd26b","patch_set":3,"id":"851539fc_e609ff44","line":500,"updated":"2026-04-28 16:10:54.000000000","message":"flavor[\"ephemeral\"] and flavor[\"swap\"] use direct dict key access in _build_instance_node but the openstacksdk-embedded flavor dict may not always include these keys, causing KeyError at runtime.\n\n**Severity**: HIGH | **Confidence**: 0.9\n\n**Risk**: Runtime KeyError crash when processing instances whose embedded flavor dict lacks the ephemeral or swap keys. This would break the entire model build for a compute node if any instance has an incomplete flavor dict.\n\n**Priority**: Before merge\n**Why This Matters**: The existing test test__build_instance_node_extended_fields creates a flavor dict without ephemeral and swap keys and will now crash. In production, the openstacksdk server response embeds flavor as a dict that may omit keys with zero values, or may include them as Flavor objects. The notification path correctly uses .get() with defaults.\n\n**Recommendation**:\nUse .get() with default 0 for both keys, matching the notification path pattern: flavor.get(\"ephemeral\", 0) and flavor.get(\"swap\", 0). This ensures defensive handling consistent with the notification code at nova.py:94-97.","commit_id":"ce81e7b46e67982ea0fdd9dbd0fe6bae508b13ed"},{"robot_id":"zuul","robot_run_id":"43cd1395962840a2b773ae60be9a242c","url":"https://zuul.teim.app/t/main/buildset/43cd1395962840a2b773ae60be9a242c","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"5c0888095013a0aff7a6d98de8802271d1a49b98","patch_set":4,"id":"12095bbb_9180b0ac","line":498,"updated":"2026-04-28 19:38:55.000000000","message":"The collector path uses flavor[\u0027ephemeral\u0027] and flavor[\u0027swap\u0027] with direct dict key access, but flavor dict from openstacksdk may not include \u0027ephemeral\u0027 or \u0027swap\u0027 keys for all flavors, causing a potential KeyError.\n\n**Severity**: WARNING | **Confidence**: 0.7\n\n**Impact**: If a flavor dict returned by openstacksdk lacks the \u0027ephemeral\u0027 or \u0027swap\u0027 keys, a KeyError would crash the model build. The notification path correctly uses .get() with defaults.\n\n**Suggestion**:\nUse flavor.get(\u0027ephemeral\u0027, 0) and flavor.get(\u0027swap\u0027, 0) instead of direct key access, matching the defensive pattern in the notification path. This ensures consistency and robustness against unexpected flavor dict shapes.","commit_id":"02b41922fe516c62ff2a889f3dd49f8c90707271"},{"robot_id":"zuul","robot_run_id":"43cd1395962840a2b773ae60be9a242c","url":"https://zuul.teim.app/t/main/buildset/43cd1395962840a2b773ae60be9a242c","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"5c0888095013a0aff7a6d98de8802271d1a49b98","patch_set":4,"id":"fcbb1702_a8994763","line":498,"updated":"2026-04-28 19:38:55.000000000","message":"The disk calculation logic (root disk + ephemeral + ceil(swap/1024)) is duplicated between the collector path and the notification path, increasing maintenance burden.\n\n**Severity**: SUGGESTION | **Confidence**: 0.8\n\n**Benefit**: Extracting this into a shared helper function would ensure both paths stay in sync and make the arithmetic easier to test in isolation.\n\n**Recommendation**:\nConsider creating a small helper like _calculate_local_disk(root_gb, ephemeral_gb, swap_mb, is_bfv) in a shared module. This is a follow-up improvement, not a blocker for this patch.","commit_id":"02b41922fe516c62ff2a889f3dd49f8c90707271"},{"robot_id":"zuul","robot_run_id":"6eb60bee38f345c5a79c458b91360f6d","url":"https://zuul.teim.app/t/main/buildset/6eb60bee38f345c5a79c458b91360f6d","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"75e2313acaec17ee7efbe434a4776bad40b188c3","patch_set":6,"id":"fbe65ba5_a83756b8","line":502,"updated":"2026-04-29 10:22:38.000000000","message":"The swap unit conversion assumes swap is always in MB, but this is not documented or validated. If a flavor has swap in a different unit, the math.ceil(swap / 1024) calculation would silently produce wrong results.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: Incorrect disk accounting for flavors with non-standard swap values could lead to incorrect migration decisions, though in practice Nova always stores swap in MB.\n\n**Suggestion**:\nAdd a brief inline comment or a defensive assertion that clarifies the assumed unit, or consider extracting the disk calculation into a shared helper function that documents the unit assumption.","commit_id":"54b8ee7058c14fb0e7233e3fcb63d2a5110ee38c"},{"robot_id":"zuul","robot_run_id":"d7d5f386aced4204a347c14d7b21675e","url":"https://zuul.teim.app/t/main/buildset/d7d5f386aced4204a347c14d7b21675e","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"12d6f1dff28b66c7663ecefc381b23a2e6a2bd37","patch_set":7,"id":"a1b06a54_f621ccd0","line":499,"updated":"2026-04-29 12:44:14.000000000","message":"The comment \u0027swap is in MB; math.ceil(x / 1024) is ceiling division to GB\u0027 appears identically in both collector/nova.py and notification/nova.py. Consider extracting the disk calculation into a shared utility function.\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: A shared function would guarantee the two paths remain consistent if the formula ever changes, and would reduce duplication across the collector and notification code paths.\n\n**Recommendation**:\nConsider creating a helper like compute_local_disk_gb(root_gb, ephemeral_gb, swap_mb) in a shared module, then calling it from both _build_instance_node and update_instance.","commit_id":"99ce421c0c7590d5ab33eed29cc51235e4140793"},{"robot_id":"zuul","robot_run_id":"d7d5f386aced4204a347c14d7b21675e","url":"https://zuul.teim.app/t/main/buildset/d7d5f386aced4204a347c14d7b21675e","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"12d6f1dff28b66c7663ecefc381b23a2e6a2bd37","patch_set":7,"id":"780a7d1a_0d34d90c","line":501,"updated":"2026-04-29 12:44:14.000000000","message":"In _build_instance_node, flavor[\u0027ephemeral\u0027] and flavor[\u0027swap\u0027] use direct key access rather than .get() with defaults. While SDK flavor dicts normally include these keys, the notification path uses .get() for safety. Inconsistent defensive coding between the two paths.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: If a flavor dict ever omits \u0027ephemeral\u0027 or \u0027swap\u0027 keys, a KeyError would crash the model builder at audit time. The notification path handles this gracefully with .get().\n\n**Suggestion**:\nUse flavor.get(\u0027ephemeral\u0027, 0) and flavor.get(\u0027swap\u0027, 0) to match the defensive style in the notification path and guard against unexpected flavor dict shapes.","commit_id":"99ce421c0c7590d5ab33eed29cc51235e4140793"},{"robot_id":"zuul","robot_run_id":"ee7ccaf9f09948cdb4f6ba29af0cb2ed","url":"https://zuul.teim.app/t/main/buildset/ee7ccaf9f09948cdb4f6ba29af0cb2ed","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"da6287e35dbe5341062ecbe7d11dcb4fe7ad68a1","patch_set":8,"id":"2edc9ae5_3a60731b","line":498,"updated":"2026-04-30 06:43:15.000000000","message":"The collector path and the notification path compute local disk independently with similar logic. Consider extracting a shared utility function to prevent the two paths from drifting apart.\n\n**Severity**: SUGGESTION | **Confidence**: 0.8\n\n**Benefit**: A shared function would prevent the two disk calculation code paths from drifting apart in behavior and make the logic easier to maintain.\n\n**Recommendation**:\nConsider creating a helper like compute_local_disk(root_disk_gb, ephemeral_gb, swap_mb) that both paths can call with appropriate parameters.","commit_id":"5b5b752366bfec42b2aad33dfb6b3040c5a1bd35"},{"robot_id":"zuul","robot_run_id":"ee7ccaf9f09948cdb4f6ba29af0cb2ed","url":"https://zuul.teim.app/t/main/buildset/ee7ccaf9f09948cdb4f6ba29af0cb2ed","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"da6287e35dbe5341062ecbe7d11dcb4fe7ad68a1","patch_set":8,"id":"2ffcab5a_571cd7b2","line":501,"updated":"2026-04-30 06:43:15.000000000","message":"flavor[\"ephemeral\"] and flavor[\"swap\"] use direct key access in _build_instance_node() but existing tests and some OpenStackSDK responses omit these keys, causing KeyError.\n\n**Severity**: CRITICAL | **Confidence**: 0.9\n\n**Risk**: Runtime KeyError crashes the model builder for any server whose embedded flavor dict lacks \u0027ephemeral\u0027 or \u0027swap\u0027 keys. Existing unit tests already demonstrate this pattern.\n\n**Priority**: Before merge\n**Why This Matters**: This will break existing tests and potentially production code paths when the flavor dict returned by OpenStackSDK does not include ephemeral or swap keys.\n\n**Recommendation**:\nUse flavor.get(\"ephemeral\", 0) and flavor.get(\"swap\", 0) instead of direct key access, matching the defensive pattern already used in the notification path.","commit_id":"5b5b752366bfec42b2aad33dfb6b3040c5a1bd35"},{"robot_id":"zuul","robot_run_id":"430306f87f724ed58bf94cd471a4f72e","url":"https://zuul.teim.app/t/main/buildset/430306f87f724ed58bf94cd471a4f72e","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"04b4d790606164a1f829ecfb6362910f2dcda23f","patch_set":9,"id":"b2a9ac82_31f12212","line":501,"updated":"2026-04-30 08:09:24.000000000","message":"The collector path uses flavor[\"ephemeral\"] (direct key access) while the notification path uses .get(\u0027ephemeral_gb\u0027, 0). The two paths should use consistent access patterns to reduce maintenance risk.\n\n**Severity**: SUGGESTION | **Confidence**: 0.8\n\n**Benefit**: Consistent access patterns between the collector and notification code paths reduce the chance of one path failing on edge cases the other handles.\n\n**Recommendation**:\nConsider using flavor.get(\u0027ephemeral\u0027, 0) in the collector path to match the defensive style of the notification path, even though openstacksdk always provides the ephemeral key.","commit_id":"5461b3611d211286d856282a44ae727e88242259"},{"robot_id":"zuul","robot_run_id":"430306f87f724ed58bf94cd471a4f72e","url":"https://zuul.teim.app/t/main/buildset/430306f87f724ed58bf94cd471a4f72e","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"04b4d790606164a1f829ecfb6362910f2dcda23f","patch_set":9,"id":"1235f691_a9145574","line":502,"updated":"2026-04-30 08:09:24.000000000","message":"The collector path (nova.py) does not use defensive access for the swap key. It uses flavor[\"swap\"] while the notification path uses .get(\u0027swap\u0027, 0). If a flavor dict were ever missing the swap key, the collector would raise KeyError.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: If a flavor dict from openstacksdk is missing the \u0027swap\u0027 key entirely, the collector would raise KeyError. In practice openstacksdk always includes swap, but the two code paths use different access patterns which is inconsistent.\n\n**Suggestion**:\nUse flavor.get(\u0027swap\u0027, 0) in the collector path to match the notification path\u0027s defensive style, and to guard against any future API changes: `math.ceil(flavor.get(\u0027swap\u0027, 0) / 1024)`","commit_id":"5461b3611d211286d856282a44ae727e88242259"}],"watcher/decision_engine/model/element/instance.py":[{"robot_id":"zuul","robot_run_id":"ee7ccaf9f09948cdb4f6ba29af0cb2ed","url":"https://zuul.teim.app/t/main/buildset/ee7ccaf9f09948cdb4f6ba29af0cb2ed","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"da6287e35dbe5341062ecbe7d11dcb4fe7ad68a1","patch_set":8,"id":"3541f8b6_84983802","line":52,"updated":"2026-04-30 06:43:15.000000000","message":"The comment in instance.py says \u0027disk is the size of storage resource assigned to the Instance in the compute node in GB\u0027 but the semantics now exclude remote BFV root disk. The comment should reflect the new meaning.\n\n**Severity**: WARNING | **Confidence**: 0.7\n\n**Impact**: Future developers may misunderstand what the \u0027disk\u0027 field represents since it no longer means total assigned storage but only local consumption.\n\n**Suggestion**:\nUpdate the comment to clarify that disk represents local disk consumption only, including root (for image-backed), ephemeral, and swap, with root set to 0 for BFV instances.","commit_id":"5b5b752366bfec42b2aad33dfb6b3040c5a1bd35"}],"watcher/decision_engine/model/notification/nova.py":[{"robot_id":"zuul","robot_run_id":"8107c8e09146437aae606ff5b27388c3","url":"https://zuul.teim.app/t/main/buildset/8107c8e09146437aae606ff5b27388c3","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"35139598206959165ff6ce719427d329aa5cd26b","patch_set":3,"id":"4520502e_9e3cf1f2","line":90,"updated":"2026-04-28 16:10:54.000000000","message":"The notification path determines BFV status via image_uuid from instance_data, while the collector path uses the Server.is_boot_from_volume property which checks the image field. These two BFV detection approaches rely on different data sources.\n\n**Severity**: WARNING | **Confidence**: 0.7\n\n**Impact**: If the Nova API ever returns inconsistent image data between the server detail response and the notification payload, the two code paths could disagree on whether an instance is BFV, leading to incorrect disk values after notification updates.\n\n**Suggestion**:\nDocument the rationale for using different detection methods in each path. The notification payload provides image_uuid directly, while server detail uses the image object. Both are correct for their respective data sources but a comment would help future reviewers.","commit_id":"ce81e7b46e67982ea0fdd9dbd0fe6bae508b13ed"},{"robot_id":"zuul","robot_run_id":"6eb60bee38f345c5a79c458b91360f6d","url":"https://zuul.teim.app/t/main/buildset/6eb60bee38f345c5a79c458b91360f6d","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"75e2313acaec17ee7efbe434a4776bad40b188c3","patch_set":6,"id":"ca2acd65_108171ad","line":91,"updated":"2026-04-29 10:22:38.000000000","message":"The disk calculation logic is duplicated between collector/nova.py (_build_instance_node) and notification/nova.py (update_instance). Both compute root_disk\u003d0 for BFV, add ephemeral, and ceil(swap/1024) independently.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: If the disk calculation formula changes in the future, one path could be updated while the other is missed, leading to inconsistent model state between collector-refreshed and notification-updated data.\n\n**Suggestion**:\nExtract the local disk calculation into a shared utility function (e.g., compute_local_disk_gb(root_gb, ephemeral_gb, swap_mb, is_bfv)) in nova_helper.py and call it from both paths. This also makes the formula trivially testable in isolation.","commit_id":"54b8ee7058c14fb0e7233e3fcb63d2a5110ee38c"}],"watcher/tests/unit/common/test_nova_helper.py":[{"robot_id":"zuul","robot_run_id":"43cd1395962840a2b773ae60be9a242c","url":"https://zuul.teim.app/t/main/buildset/43cd1395962840a2b773ae60be9a242c","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"5c0888095013a0aff7a6d98de8802271d1a49b98","patch_set":4,"id":"beebed35_901681ff","line":1697,"updated":"2026-04-28 19:38:55.000000000","message":"The test for BFV with empty string image (image\u003d\u0027\u0027) tests openstacksdk behavior where empty string is truthy but lacks an \u0027id\u0027 attribute. Verify this edge case matches actual openstacksdk normalization.\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: Confirms the guard in from_openstacksdk correctly handles all edge cases from the SDK.\n\n**Recommendation**:\nThe test passes a plain string \u0027\u0027 to server.Server(image\u003d\u0027\u0027). Verify that openstacksdk would actually produce this value (it normally normalizes \u0027\u0027 to None). If not, the test is still useful as a defensive guard but could have a comment noting this.","commit_id":"02b41922fe516c62ff2a889f3dd49f8c90707271"},{"robot_id":"zuul","robot_run_id":"d7d5f386aced4204a347c14d7b21675e","url":"https://zuul.teim.app/t/main/buildset/d7d5f386aced4204a347c14d7b21675e","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"12d6f1dff28b66c7663ecefc381b23a2e6a2bd37","patch_set":7,"id":"5c9821f6_2c9e7257","line":1697,"updated":"2026-04-29 12:44:14.000000000","message":"Test helper create_openstacksdk_server in utils.py now defaults image to a dict with an id, but the test_server_boot_from_volume_empty_string_image and test_server_boot_from_volume_empty_dict_image tests pass falsy values that may not be how real SDK behaves.\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: Documenting that empty string and empty dict are theoretical edge cases rather than observed SDK behavior would help future maintainers understand the test intent.\n\n**Recommendation**:\nAdd a brief comment in the test methods noting that empty string and empty dict are defensive edge cases not necessarily observed in production SDK responses.","commit_id":"99ce421c0c7590d5ab33eed29cc51235e4140793"},{"robot_id":"zuul","robot_run_id":"ee7ccaf9f09948cdb4f6ba29af0cb2ed","url":"https://zuul.teim.app/t/main/buildset/ee7ccaf9f09948cdb4f6ba29af0cb2ed","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"da6287e35dbe5341062ecbe7d11dcb4fe7ad68a1","patch_set":8,"id":"aced55e7_90e89f6a","line":1697,"updated":"2026-04-30 06:43:15.000000000","message":"The test_server_boot_from_volume_empty_string_image and test_server_boot_from_volume_empty_dict_image tests exercise edge cases but from_openstacksdk relies on implicit falsy evaluation without explicit handling.\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: Making the BFV detection logic more explicit would improve readability and reduce reliance on implicit falsy behavior of empty string and empty dict.\n\n**Recommendation**:\nConsider adding a brief inline comment in from_openstacksdk explaining why the falsy check on nova_server.image is sufficient for all BFV cases including empty string and empty dict.","commit_id":"5b5b752366bfec42b2aad33dfb6b3040c5a1bd35"}],"watcher/tests/unit/decision_engine/cluster/test_nova_cdmc.py":[{"robot_id":"zuul","robot_run_id":"8107c8e09146437aae606ff5b27388c3","url":"https://zuul.teim.app/t/main/buildset/8107c8e09146437aae606ff5b27388c3","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"35139598206959165ff6ce719427d329aa5cd26b","patch_set":3,"id":"3d476126_90fa919c","line":360,"updated":"2026-04-28 16:10:54.000000000","message":"The test_build_instance_node_boot_from_volume test does not include ephemeral or swap in its flavor dict, meaning it only verifies the BFV root_disk\u003d0 path but not the interaction with missing ephemeral/swap keys.\n\n**Severity**: SUGGESTION | **Confidence**: 0.8\n\n**Benefit**: Adding a test case with a flavor dict that omits ephemeral and swap keys would expose the KeyError issue and provide a regression test for the defensive .get() fix.\n\n**Recommendation**:\nAfter fixing the direct key access to use .get(), add a test case where the flavor dict omits ephemeral and swap keys entirely, verifying that the code defaults them to 0.","commit_id":"ce81e7b46e67982ea0fdd9dbd0fe6bae508b13ed"},{"robot_id":"zuul","robot_run_id":"6eb60bee38f345c5a79c458b91360f6d","url":"https://zuul.teim.app/t/main/buildset/6eb60bee38f345c5a79c458b91360f6d","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"75e2313acaec17ee7efbe434a4776bad40b188c3","patch_set":6,"id":"2240a226_4a547d31","line":360,"updated":"2026-04-29 10:22:38.000000000","message":"The _build_instance_node test methods in test_nova_cdmc.py create a mock model and set extended_attributes_enabled\u003dFalse inline. A helper method or base setup could reduce repetition across the three new test methods.\n\n**Severity**: SUGGESTION | **Confidence**: 0.6\n\n**Benefit**: A shared test setup helper would reduce boilerplate and make it easier to add more test variations in the future.\n\n**Recommendation**:\nConsider extracting the common model_builder setup into a small helper method like _create_model_builder() within the test class, reducing the repeated 4-line setup block to a single call.","commit_id":"54b8ee7058c14fb0e7233e3fcb63d2a5110ee38c"},{"robot_id":"zuul","robot_run_id":"ee7ccaf9f09948cdb4f6ba29af0cb2ed","url":"https://zuul.teim.app/t/main/buildset/ee7ccaf9f09948cdb4f6ba29af0cb2ed","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"da6287e35dbe5341062ecbe7d11dcb4fe7ad68a1","patch_set":8,"id":"afc1f876_8f06ec4a","line":254,"updated":"2026-04-30 06:43:15.000000000","message":"Existing tests test_add_instance_node and test_execute_multiple_scenarios pass flavor dicts without \u0027ephemeral\u0027 or \u0027swap\u0027 keys and will break with the new direct key access.\n\n**Severity**: HIGH | **Confidence**: 0.9\n\n**Risk**: Unit test suite will fail with KeyError when running existing tests that were not updated to include ephemeral/swap in their flavor dicts.\n\n**Priority**: Before merge\n**Why This Matters**: CI will fail on pre-existing tests that exercise _build_instance_node with incomplete flavor dicts. These tests must continue to pass.\n\n**Recommendation**:\nEither fix _build_instance_node to use .get() with defaults, or add \u0027ephemeral\u0027: 0 and \u0027swap\u0027: 0 to all existing test flavor dicts. Using .get() is preferred as it matches the notification code path.","commit_id":"5b5b752366bfec42b2aad33dfb6b3040c5a1bd35"},{"robot_id":"zuul","robot_run_id":"430306f87f724ed58bf94cd471a4f72e","url":"https://zuul.teim.app/t/main/buildset/430306f87f724ed58bf94cd471a4f72e","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"04b4d790606164a1f829ecfb6362910f2dcda23f","patch_set":9,"id":"c6b021da_a60db76e","line":388,"updated":"2026-04-30 08:09:24.000000000","message":"The test_build_instance_node_boot_from_volume_with_ephemeral test does not verify that memory and vcpus are correctly preserved when ephemeral and swap are present. The plain BFV test checks all three fields but the ephemeral variant only checks disk.\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: Adding memory/vcpus assertions to the BFV-with-ephemeral test ensures the new disk logic does not interfere with other fields in edge cases.\n\n**Recommendation**:\nAdd self.assertEqual(2048, fake_instance.memory) and self.assertEqual(2, fake_instance.vcpus) to test_build_instance_node_boot_from_volume_with_ephemeral for completeness, mirroring the plain BFV test.","commit_id":"5461b3611d211286d856282a44ae727e88242259"}],"watcher/tests/unit/decision_engine/model/notification/test_nova_notifications.py":[{"robot_id":"zuul","robot_run_id":"8db52338b3144f4b9bcbbcaac5befd90","url":"https://zuul.teim.app/t/main/buildset/8db52338b3144f4b9bcbbcaac5befd90","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"a609da58328651f5fafbc2cccedb361641c94487","patch_set":2,"id":"9aefa967_c90e05c3","line":279,"updated":"2026-04-28 14:23:04.000000000","message":"The instance-update.json fixture lacks a \u0027swap\u0027 key in the flavor data. Tests that set swap add it dynamically, but test_nova_instance_update_boot_from_volume does not verify swap\u003d0 behavior when the key is absent from the fixture.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: The notification path is safe because it uses .get() with defaults, but the test fixture does not exercise the real-world scenario where Nova omits the swap key entirely from the notification payload.\n\n**Suggestion**:\nConsider adding a \u0027swap\u0027: 0 field to the instance-update.json fixture for completeness and to ensure the .get(\u0027swap\u0027, 0) fallback is explicitly tested.","commit_id":"78d28052ad0817d3758306ef623b1d6fd709d839"},{"robot_id":"zuul","robot_run_id":"6eb60bee38f345c5a79c458b91360f6d","url":"https://zuul.teim.app/t/main/buildset/6eb60bee38f345c5a79c458b91360f6d","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"75e2313acaec17ee7efbe434a4776bad40b188c3","patch_set":6,"id":"3ed685f8_7373f180","line":325,"updated":"2026-04-29 10:22:38.000000000","message":"The test_nova_instance_update_bfv_with_swap_above_1g test name and other notification test methods have long names that could be shortened for readability.\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: Shorter test names are easier to read in test output and maintain consistency with the rest of the test suite where names are more concise.\n\n**Recommendation**:\nConsider shortening the test name to test_nova_instance_update_bfv_large_swap which conveys the same information more concisely.","commit_id":"54b8ee7058c14fb0e7233e3fcb63d2a5110ee38c"}]}
