)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"1009ffbde21373462188d74e7b850019a235a7f2","unresolved":true,"context_lines":[{"line_number":22,"context_line":"Placement is used as the authoritative source for resource class and"},{"line_number":23,"context_line":"traits rather than Cyborg\u0027s internal attributes_list. The"},{"line_number":24,"context_line":"attributes_list embeds traits as a JSON string that includes standard"},{"line_number":25,"context_line":"os-traits names such as OWNER_CYBORG, which the Cyborg device profile"},{"line_number":26,"context_line":"API rejects because it requires all trait names to start with CUSTOM_."},{"line_number":27,"context_line":"Querying placement directly avoids that ambiguity and validates the"},{"line_number":28,"context_line":"full Cyborg-\u003ePlacement sync path in the same step."},{"line_number":29,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"08263440_726763c8","line":26,"range":{"start_line":25,"start_character":38,"end_line":26,"end_character":69},"updated":"2026-06-17 13:50:00.000000000","message":"thats a limitation or bug that we likely should adreess as part fo your nvme spec so that we can request a device with the sanatization traits.","commit_id":"bb0f06b2dec6e39a11f145d010bfa1f237087bfe"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"27f0562e1ccde6d6a79fcf630c6b4385e7061ad8","unresolved":true,"context_lines":[{"line_number":22,"context_line":"Placement is used as the authoritative source for resource class and"},{"line_number":23,"context_line":"traits rather than Cyborg\u0027s internal attributes_list. The"},{"line_number":24,"context_line":"attributes_list embeds traits as a JSON string that includes standard"},{"line_number":25,"context_line":"os-traits names such as OWNER_CYBORG, which the Cyborg device profile"},{"line_number":26,"context_line":"API rejects because it requires all trait names to start with CUSTOM_."},{"line_number":27,"context_line":"Querying placement directly avoids that ambiguity and validates the"},{"line_number":28,"context_line":"full Cyborg-\u003ePlacement sync path in the same step."},{"line_number":29,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"409a8e69_8fb47f13","line":26,"range":{"start_line":25,"start_character":38,"end_line":26,"end_character":69},"in_reply_to":"08263440_726763c8","updated":"2026-06-19 10:13:06.000000000","message":"Opened the bug here https://bugs.launchpad.net/openstack-cyborg/+bug/2157586, I am thinking about os-traits here directly in the cyborg. I will propose a patch and take it from there.","commit_id":"bb0f06b2dec6e39a11f145d010bfa1f237087bfe"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"6a73e61ff8d2da8c091178e979d7905f6ce4099c","unresolved":true,"context_lines":[{"line_number":22,"context_line":"Placement is used as the authoritative source for resource class and"},{"line_number":23,"context_line":"traits rather than Cyborg\u0027s internal attributes_list. The"},{"line_number":24,"context_line":"attributes_list embeds traits as a JSON string that includes standard"},{"line_number":25,"context_line":"os-traits names such as OWNER_CYBORG, which the Cyborg device profile"},{"line_number":26,"context_line":"API rejects because it requires all trait names to start with CUSTOM_."},{"line_number":27,"context_line":"Querying placement directly avoids that ambiguity and validates the"},{"line_number":28,"context_line":"full Cyborg-\u003ePlacement sync path in the same step."},{"line_number":29,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"dd77e9ad_7b24ae58","line":26,"range":{"start_line":25,"start_character":38,"end_line":26,"end_character":69},"in_reply_to":"409a8e69_8fb47f13","updated":"2026-06-19 10:43:07.000000000","message":"os-traits can be used for normalising traits we reprot but it should nto be used for validation as the verion installed in the placmenet service host may not match ours\n\nwe basically should accpate any trait in the device profile but for the atibutes api we shoudl alwasy prefix them with CUSTOM_\n\neventually we will want to sandarize some of the traits reproted by cyborg drvier in os traits and we shoud not allwo those standard taits to be added out of band via the atirbute api","commit_id":"bb0f06b2dec6e39a11f145d010bfa1f237087bfe"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"bc5b04a83c5ee2b2109d88c0ca82be92769a4851","unresolved":true,"context_lines":[{"line_number":22,"context_line":"Placement is used as the authoritative source for resource class and"},{"line_number":23,"context_line":"traits rather than Cyborg\u0027s internal attributes_list. The"},{"line_number":24,"context_line":"attributes_list embeds traits as a JSON string that includes standard"},{"line_number":25,"context_line":"os-traits names such as OWNER_CYBORG, which the Cyborg device profile"},{"line_number":26,"context_line":"API rejects because it requires all trait names to start with CUSTOM_."},{"line_number":27,"context_line":"Querying placement directly avoids that ambiguity and validates the"},{"line_number":28,"context_line":"full Cyborg-\u003ePlacement sync path in the same step."},{"line_number":29,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"ec03261c_aa5445db","line":26,"range":{"start_line":25,"start_character":38,"end_line":26,"end_character":69},"in_reply_to":"dd77e9ad_7b24ae58","updated":"2026-06-22 06:46:44.000000000","message":"Ah good point about os-traits and placement version.\nComing to device profile, we need to fix device profile to accept any triats, Current It is hardcoded with `CUSTOM_` as mentioned in the bug.\n\nI will also check the attribut api that it always prfix with CUSTOM_ triats.","commit_id":"bb0f06b2dec6e39a11f145d010bfa1f237087bfe"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"2e54620bda93ce724ff661682cfd2f06c763c43b","unresolved":false,"context_lines":[{"line_number":22,"context_line":"Placement is used as the authoritative source for resource class and"},{"line_number":23,"context_line":"traits rather than Cyborg\u0027s internal attributes_list. The"},{"line_number":24,"context_line":"attributes_list embeds traits as a JSON string that includes standard"},{"line_number":25,"context_line":"os-traits names such as OWNER_CYBORG, which the Cyborg device profile"},{"line_number":26,"context_line":"API rejects because it requires all trait names to start with CUSTOM_."},{"line_number":27,"context_line":"Querying placement directly avoids that ambiguity and validates the"},{"line_number":28,"context_line":"full Cyborg-\u003ePlacement sync path in the same step."},{"line_number":29,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"e3cb1c27_28decd11","line":26,"range":{"start_line":25,"start_character":38,"end_line":26,"end_character":69},"in_reply_to":"ec03261c_aa5445db","updated":"2026-07-21 04:05:38.000000000","message":"Addressed by https://review.opendev.org/c/openstack/cyborg/+/997945","commit_id":"bb0f06b2dec6e39a11f145d010bfa1f237087bfe"}],"/PATCHSET_LEVEL":[{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"486942bd449df567103860ef9d5a971c13986bd8","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"307a5335_241eefc6","updated":"2026-07-07 11:06:16.000000000","message":"teim-ci:auto","commit_id":"bb0f06b2dec6e39a11f145d010bfa1f237087bfe"}],"cyborg_tempest_plugin/config.py":[{"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":"d5090e54434be3d55b45073cab52838769732f57","unresolved":false,"context_lines":[{"line_number":80,"context_line":"    ),"},{"line_number":81,"context_line":"]"},{"line_number":82,"context_line":""},{"line_number":83,"context_line":"cyborg_group \u003d cfg.OptGroup("},{"line_number":84,"context_line":"    name\u003d\"cyborg\","},{"line_number":85,"context_line":"    title\u003d\"Cyborg Service Options\""},{"line_number":86,"context_line":")"}],"source_content_type":"text/x-python","patch_set":9,"id":"3bede84f_aa16c02b","line":83,"updated":"2026-08-04 04:23:49.000000000","message":"The patch appends new cyborg_group and CyborgGroup definitions at the end of config.py (lines 83-93). Because these names already exist at lines 29-43, the new definitions silently overwrite the originals. The original CyborgGroup contains image_ref and flavor_ref StrOpts; after this patch only t...\n\n**Severity**: CRITICAL | **Confidence**: 1.0\n\n**Risk**: All scenario tests inheriting from driver_lifecycle_base.py will fail with oslo_config.cfg.NoSuchOptError when accessing CONF.cyborg.image_ref or CONF.cyborg.flavor_ref. This is a merge-blocking regression in existing test functionality.\n\n**Priority**: Immediate\n**Why This Matters**: All scenario tests inheriting from driver_lifecycle_base.py will fail with oslo_config.cfg.NoSuchOptError when accessing CONF.cyborg.image_ref or CONF.cyborg.flavor_ref. This is a merge-blocking regression in existing test functionality.\n\n**Recommendation**:\nRemove the redefined cyborg_group and CyborgGroup at lines 83-93. Instead, add the devices ListOpt to the existing CyborgGroup list at lines 34-43 alongside image_ref and flavor_ref.","commit_id":"42e2c00fd3ff1442b4b289b665fdcf7855ebd457"},{"author":{"_account_id":34452,"name":"Joan Gilabert","display_name":"jgilaber","email":"jgilaber@redhat.com","username":"jgilaber"},"change_message_id":"2c15013e82f19e57951af1b37d4b8d5d7a27a48c","unresolved":true,"context_lines":[{"line_number":41,"context_line":"               help\u003d\"Optional base flavor ID for Cyborg scenario \""},{"line_number":42,"context_line":"                    \"tests. Defaults to compute.flavor_ref when \""},{"line_number":43,"context_line":"                    \"unset.\"),"},{"line_number":44,"context_line":"    cfg.ListOpt(\"devices\", default\u003d[],"},{"line_number":45,"context_line":"                help\u003d\"List of devices to test, each as \""},{"line_number":46,"context_line":"                     \"vendor_id:product_id. \""},{"line_number":47,"context_line":"                     \"Example: devices \u003d 1d55:1001,0xABCD:0xabcd\"),"}],"source_content_type":"text/x-python","patch_set":10,"id":"0f8f2b6d_3174202a","line":44,"updated":"2026-08-04 08:49:34.000000000","message":"is this option only intended to be used for the placement integration tests added? If so, I would make the name more specific, like `placement_test_devices` or something similar","commit_id":"5d1ff903b03e400f31bf21142cb649e4a60d23d9"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"7ddbc1273edbf06745dba683ca09d573c581c7e8","unresolved":true,"context_lines":[{"line_number":41,"context_line":"               help\u003d\"Optional base flavor ID for Cyborg scenario \""},{"line_number":42,"context_line":"                    \"tests. Defaults to compute.flavor_ref when \""},{"line_number":43,"context_line":"                    \"unset.\"),"},{"line_number":44,"context_line":"    cfg.ListOpt(\"devices\", default\u003d[],"},{"line_number":45,"context_line":"                help\u003d\"List of devices to test, each as \""},{"line_number":46,"context_line":"                     \"vendor_id:product_id. \""},{"line_number":47,"context_line":"                     \"Example: devices \u003d 1d55:1001,0xABCD:0xabcd\"),"}],"source_content_type":"text/x-python","patch_set":10,"id":"d20f0310_3eec6720","line":44,"in_reply_to":"0f8f2b6d_3174202a","updated":"2026-08-04 11:23:12.000000000","message":"this need to be in a dreiver specifc section\n\nwe can assume that all test will have the same device either\n\nso this is the wrong group\n\ni suspect we will not want this to be a list","commit_id":"5d1ff903b03e400f31bf21142cb649e4a60d23d9"}],"cyborg_tempest_plugin/tests/scenario/test_pci.py":[{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"2f4fe78f7a1bf6ed5fe2c9f45d5726d5f85efef7","unresolved":false,"context_lines":[{"line_number":96,"context_line":"            t for t in traits_body[\u0027traits\u0027] if t.startswith(\u0027CUSTOM_\u0027)"},{"line_number":97,"context_line":"        ]"},{"line_number":98,"context_line":""},{"line_number":99,"context_line":"        inventories_body \u003d rp_client.list_resource_provider_inventories(rp_uuid)"},{"line_number":100,"context_line":"        # The resource class is the key in the inventories dict."},{"line_number":101,"context_line":"        rc \u003d next(iter(inventories_body[\u0027inventories\u0027]), None)"},{"line_number":102,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"41269984_e31f368a","line":99,"updated":"2026-06-09 07:50:29.000000000","message":"pep8: E501 line too long (80 \u003e 79 characters)","commit_id":"66baae58f924ce5fff3cdd33d3846b0d64973601"},{"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":"ca2529d207123c644cac85fb499db408299983f9","unresolved":false,"context_lines":[{"line_number":122,"context_line":"                \u0027Cyborg did not discover a device with vendor %s\u0027 % vendor_id)"},{"line_number":123,"context_line":"            LOG.info(\u0027Cyborg device found: %s\u0027, device.get(\u0027uuid\u0027))"},{"line_number":124,"context_line":""},{"line_number":125,"context_line":"            rp_uuid \u003d self._find_rp_by_product(product_id)"},{"line_number":126,"context_line":"            LOG.info(\u0027Placement RP for %s:%s: %s\u0027, vendor_id, product_id,"},{"line_number":127,"context_line":"                     rp_uuid)"},{"line_number":128,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"edfd9798_0c6c895a","line":125,"updated":"2026-07-07 11:15:25.000000000","message":"The _find_rp_by_product method returns None when no resource provider matches the product trait, but the test does not assert rp_uuid is not None before passing it to _extract_rc_and_traits. A None UUID will cause placement API calls (list_resource_provider_traits, list_resource_provider_inventor...\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: When the placement sync fails or the product trait is missing, the test fails with an unhelpful API error (e.g., 404 on /resource_providers/None/traits) rather than a descriptive assertion message. This makes diagnosing the failure significantly harder for CI operators.\n\n**Suggestion**:\nAdd self.assertIsNotNone(rp_uuid, \u0027Placement did not find a resource provider with trait %s for product %s\u0027 % (product_trait, product_id)) after line 125, before calling _extract_rc_and_traits.","commit_id":"bb0f06b2dec6e39a11f145d010bfa1f237087bfe"}],"cyborg_tempest_plugin/tests/scenario/test_placement_integration.py":[{"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":"853625c76eabe6770945ce2dc7bbb7396dc40ad3","unresolved":false,"context_lines":[{"line_number":122,"context_line":"                \u0027Cyborg did not discover a device with vendor %s\u0027 % vendor_id)"},{"line_number":123,"context_line":"            LOG.info(\u0027Cyborg device found: %s\u0027, device.get(\u0027uuid\u0027))"},{"line_number":124,"context_line":""},{"line_number":125,"context_line":"            rp_uuid \u003d self._find_rp_by_product(product_id)"},{"line_number":126,"context_line":"            LOG.info(\u0027Placement RP for %s:%s: %s\u0027, vendor_id, product_id,"},{"line_number":127,"context_line":"                     rp_uuid)"},{"line_number":128,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"bab8ff64_a3a57ee1","line":125,"updated":"2026-07-20 09:30:09.000000000","message":"When _find_rp_by_product returns None (no placement RP matching the product trait), the test proceeds to call _extract_rc_and_traits(None), which will produce an unhelpful API error from the placement client rather than a clear assertion failure explaining that the RP was not found.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: If Placement does not return a resource provider for the given product trait, the test will fail with an opaque API error from list_resource_provider_traits(None) instead of a clear, descriptive assertion message, making debugging harder.\n\n**Suggestion**:\nAdd an assertIsNotNone check for rp_uuid after _find_rp_by_product, e.g.: self.assertIsNotNone(rp_uuid, \u0027Placement did not return an RP for product %s\u0027 % product_id)","commit_id":"5fb3ba3cfa5b0c2560ca8a1b7ee2a99a9245dfe8"},{"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":"853625c76eabe6770945ce2dc7bbb7396dc40ad3","unresolved":false,"context_lines":[{"line_number":135,"context_line":"            self.create_device_profile(dp_data)"},{"line_number":136,"context_line":"            LOG.info(\u0027Device profile created: %s\u0027, dp_name)"},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"            # create_accel_flavor does not register its own cleanup."},{"line_number":139,"context_line":"            accel_flavor \u003d self.create_accel_flavor(dp_name)"},{"line_number":140,"context_line":"            self.addCleanup("},{"line_number":141,"context_line":"                self.admin_flavors_client.delete_flavor, accel_flavor)"}],"source_content_type":"text/x-python","patch_set":5,"id":"e4050327_18ef9dab","line":138,"updated":"2026-07-20 09:30:09.000000000","message":"The test comment at line 138 states \u0027create_accel_flavor does not register its own cleanup\u0027, but the base manager\u0027s create_accel_flavor method (manager.py lines 107-108) already registers addCleanup for the flavor deletion. The test then registers a second addCleanup for the same flavor, causing...\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: The redundant addCleanup will not crash due to LIFO ordering (test\u0027s cleanup runs first and deletes, manager\u0027s cleanup runs second and ignores the 404), but the misleading comment could cause future maintainers to incorrectly believe create_accel_flavor lacks cleanup, leading to confusion or inco...\n\n**Suggestion**:\nRemove the addCleanup call at lines 140-141 and correct the comment, since create_accel_flavor already handles cleanup. Alternatively, if extra cleanup safety is desired, update the comment to accurately reflect that create_accel_flavor does register cleanup and this is a redundant safety net.","commit_id":"5fb3ba3cfa5b0c2560ca8a1b7ee2a99a9245dfe8"},{"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":"71c58de4d73b7213cb163670930faf9f8e4e62b8","unresolved":false,"context_lines":[{"line_number":51,"context_line":"    @classmethod"},{"line_number":52,"context_line":"    def resource_setup(cls):"},{"line_number":53,"context_line":"        super().resource_setup()"},{"line_number":54,"context_line":"        cls.setup_api_microversion_fixture("},{"line_number":55,"context_line":"            placement_microversion\u003d_PLACEMENT_MIN_MICROVERSION)"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"    def _parse_devices(self):"}],"source_content_type":"text/x-python","patch_set":6,"id":"90c1e8e2_e49e073b","line":54,"updated":"2026-07-20 12:40:22.000000000","message":"resource_setup calls cls.setup_api_microversion_fixture(placement_microversion\u003d_PLACEMENT_MIN_MICROVERSION). This method does not exist on tempest\u0027s BaseTestCase, ScenarioTest, or the project\u0027s ScenarioTest subclass. The standard tempest pattern is to set placement_min_microversion and placement_...\n\n**Severity**: HIGH | **Confidence**: 0.8\n\n**Risk**: Even if CF-001 were fixed, this AttributeError during resource_setup would prevent the test from executing at all. Combined with the skip-when-empty behavior, the bug remains hidden in CI.\n\n**Priority**: Before merge\n**Why This Matters**: Even if CF-001 were fixed, this AttributeError during resource_setup would prevent the test from executing at all. Combined with the skip-when-empty behavior, the bug remains hidden in CI.\n\n**Recommendation**:\nReplace the method call with class attributes at class scope: placement_min_microversion \u003d \u00271.18\u0027 and placement_max_microversion \u003d \u0027latest\u0027. Remove the resource_setup override if it contains nothing else.","commit_id":"7a96d69922a1c3a3cf289fa1568a5cd4187f0bfe"},{"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":"71c58de4d73b7213cb163670930faf9f8e4e62b8","unresolved":false,"context_lines":[{"line_number":76,"context_line":""},{"line_number":77,"context_line":"    def _find_rp_by_product(self, product_id):"},{"line_number":78,"context_line":"        \"\"\"Return the placement RP UUID for the given product_id, or None.\"\"\""},{"line_number":79,"context_line":"        product_trait \u003d \u0027CUSTOM_PCI_PRODUCT_ID_%s\u0027 % product_id.upper()"},{"line_number":80,"context_line":"        body \u003d self.os_admin.resource_providers_client.list_resource_providers("},{"line_number":81,"context_line":"            required\u003dproduct_trait)"},{"line_number":82,"context_line":"        rps \u003d body.get(\u0027resource_providers\u0027, [])"}],"source_content_type":"text/x-python","patch_set":6,"id":"3093a8ce_dc4263af","line":79,"updated":"2026-07-20 12:40:22.000000000","message":"The config help text advertises \u00270xABCD:0xabcd\u0027 as a valid entry format, but _find_rp_by_product builds the product trait with product_id.upper() without stripping the 0x prefix. This produces CUSTOM_PCI_PRODUCT_ID_0XABCD instead of CUSTOM_PCI_PRODUCT_ID_ABCD, causing the RP lookup to fail.\n\n**Severity**: HIGH | **Confidence**: 0.8\n\n**Risk**: Any operator who configures a device using 0x-prefixed IDs (as the help text suggests is valid) will get a test failure because the placement trait lookup will not match. The 1d55:1001 format without 0x works correctly, masking the bug for the most common inputs.\n\n**Priority**: Before merge\n**Why This Matters**: Any operator who configures a device using 0x-prefixed IDs (as the help text suggests is valid) will get a test failure because the placement trait lookup will not match. The 1d55:1001 format without 0x works correctly, masking the bug for the most common inputs.\n\n**Recommendation**:\nNormalize vendor_id and product_id by stripping an optional 0x/0X prefix in _parse_devices before returning tuples. Alternatively, update the config help text to state that 0x prefixes are not supported. Reuse the _normalize_pci_id pattern from test_pci_driver_lifecycle.py for consistency.","commit_id":"7a96d69922a1c3a3cf289fa1568a5cd4187f0bfe"},{"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":"71c58de4d73b7213cb163670930faf9f8e4e62b8","unresolved":false,"context_lines":[{"line_number":77,"context_line":"    def _find_rp_by_product(self, product_id):"},{"line_number":78,"context_line":"        \"\"\"Return the placement RP UUID for the given product_id, or None.\"\"\""},{"line_number":79,"context_line":"        product_trait \u003d \u0027CUSTOM_PCI_PRODUCT_ID_%s\u0027 % product_id.upper()"},{"line_number":80,"context_line":"        body \u003d self.os_admin.resource_providers_client.list_resource_providers("},{"line_number":81,"context_line":"            required\u003dproduct_trait)"},{"line_number":82,"context_line":"        rps \u003d body.get(\u0027resource_providers\u0027, [])"},{"line_number":83,"context_line":"        return rps[0][\u0027uuid\u0027] if rps else None"}],"source_content_type":"text/x-python","patch_set":6,"id":"e8e61dd0_df5c37c1","line":80,"updated":"2026-07-20 12:40:22.000000000","message":"The test uses self.os_admin.resource_providers_client to call list_resource_providers, list_resource_provider_traits, and list_resource_provider_inventories. Tempest\u0027s manager exposes the placement service client as os_admin.placement_client, not resource_providers_client. This will raise Attribu...\n\n**Severity**: HIGH | **Confidence**: 0.8\n\n**Risk**: The test cannot execute its core assertions. Because skip_checks raises skipException when CONF.cyborg.devices is empty (the default in CI), this bug goes undetected in standard gate runs and will only surface when an operator configures devices.\n\n**Priority**: Before merge\n**Why This Matters**: The test cannot execute its core assertions. Because skip_checks raises skipException when CONF.cyborg.devices is empty (the default in CI), this bug goes undetected in standard gate runs and will only surface when an operator configures devices.\n\n**Recommendation**:\nReplace all three references to self.os_admin.resource_providers_client with self.os_admin.placement_client. Verify the fix by running the test with a non-empty [cyborg] devices configuration.","commit_id":"7a96d69922a1c3a3cf289fa1568a5cd4187f0bfe"},{"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":"32c7a67864c548d90080de118334befb05d1cf66","unresolved":false,"context_lines":[{"line_number":65,"context_line":"                            self._normalize_pci_id(product_id)))"},{"line_number":66,"context_line":"        return devices"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"    def _find_device(self, vendor_id):"},{"line_number":69,"context_line":"        \"\"\"Return the first Cyborg device matching vendor_id, or None.\"\"\""},{"line_number":70,"context_line":"        body \u003d self.os_admin.cyborg_client.list_devices("},{"line_number":71,"context_line":"            params\u003d{\u0027vendor\u0027: vendor_id})"}],"source_content_type":"text/x-python","patch_set":7,"id":"99c9de4f_5256de7b","line":68,"updated":"2026-07-20 15:05:11.000000000","message":"The test iterates over (vendor_id, product_id) tuples parsed from config, but _find_device only queries Cyborg devices by vendor_id and returns the first match. If a vendor has multiple accelerator products, the wrong device may be returned and the discovered device\u0027s product_id is never verified.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: If a single vendor has multiple products (e.g., 10ee:1234 and 10ee:5678) both listed in config, the test would find the same first device for both iterations and would not catch a scenario where Cyborg only discovered one of the two expected products.\n\n**Suggestion**:\nEither pass both vendor and product as filter parameters (e.g., params\u003d{\u0027vendor\u0027: vendor_id, \u0027product\u0027: product_id}), or after finding the device, assert that its product_id matches the expected value from the config entry.","commit_id":"6eb11c8297b4101ab883e0ec15804e1e77367e79"},{"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":"32c7a67864c548d90080de118334befb05d1cf66","unresolved":false,"context_lines":[{"line_number":97,"context_line":"        inventories_body \u003d rp_client.list_resource_provider_inventories("},{"line_number":98,"context_line":"            rp_uuid)"},{"line_number":99,"context_line":"        # The resource class is the key in the inventories dict."},{"line_number":100,"context_line":"        rc \u003d next(iter(inventories_body[\u0027inventories\u0027]), None)"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"        return rc, cyborg_traits"},{"line_number":103,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"82b3f5a2_01cf2645","line":100,"updated":"2026-07-20 15:05:11.000000000","message":"In _extract_rc_and_traits, the resource class is extracted via next(iter(inventories_body[\u0027inventories\u0027]), None). If the inventories dict is empty, rc is None, and the subsequent _build_device_profile_data call produces a malformed key \u0027resources:None\u0027 in the device profile payload instead of fai...\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: If a placement resource provider unexpectedly has no inventories, the test would create an invalid device profile with the key \u0027resources:None\u0027 and fail with a confusing error from the Cyborg API rather than a clear assertion failure pinpointing the missing resource class.\n\n**Suggestion**:\nAdd an assertion after _extract_rc_and_traits in test_placement_integration, e.g.: self.assertIsNotNone(rc, \u0027No resource class found in RP %s inventories\u0027 % rp_uuid), before calling _build_device_profile_data.","commit_id":"6eb11c8297b4101ab883e0ec15804e1e77367e79"},{"author":{"_account_id":34452,"name":"Joan Gilabert","display_name":"jgilaber","email":"jgilaber@redhat.com","username":"jgilaber"},"change_message_id":"00354f3632b55e1f2031bf7fa78e7ffdf7e5ed7f","unresolved":true,"context_lines":[{"line_number":145,"context_line":""},{"line_number":146,"context_line":"            dp_name \u003d \u0027cyborg-%s-%s\u0027 % (vendor_id, product_id)"},{"line_number":147,"context_line":"            dp_data \u003d self._build_device_profile_data(dp_name, rc, traits)"},{"line_number":148,"context_line":"            # create_device_profile registers addCleanup automatically."},{"line_number":149,"context_line":"            self.create_device_profile(dp_data)"},{"line_number":150,"context_line":"            LOG.info(\u0027Device profile created: %s\u0027, dp_name)"},{"line_number":151,"context_line":""}],"source_content_type":"text/x-python","patch_set":8,"id":"ca03d45b_50802e3e","line":148,"updated":"2026-07-22 15:39:08.000000000","message":"IIUC we create the device profile to catch any regression of the bug that prevents creating them with traits that are not custom, correct? Do we need to create the flavor then?","commit_id":"f4f0453155b7752a6aa6b6dc9bf4d078c04e56c1"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"026aa3fefc67290e35a414d8ff08881be961611b","unresolved":false,"context_lines":[{"line_number":145,"context_line":""},{"line_number":146,"context_line":"            dp_name \u003d \u0027cyborg-%s-%s\u0027 % (vendor_id, product_id)"},{"line_number":147,"context_line":"            dp_data \u003d self._build_device_profile_data(dp_name, rc, traits)"},{"line_number":148,"context_line":"            # create_device_profile registers addCleanup automatically."},{"line_number":149,"context_line":"            self.create_device_profile(dp_data)"},{"line_number":150,"context_line":"            LOG.info(\u0027Device profile created: %s\u0027, dp_name)"},{"line_number":151,"context_line":""}],"source_content_type":"text/x-python","patch_set":8,"id":"620f2f35_26f7eb16","line":148,"in_reply_to":"ca03d45b_50802e3e","updated":"2026-08-04 04:27:19.000000000","message":"yes correct.\n\nFlavor creation does not any value here unless we spin a instance from that flavor.","commit_id":"f4f0453155b7752a6aa6b6dc9bf4d078c04e56c1"}]}
