)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"b9fef7195b53a96b03e9fec918748f4a93107bce","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":16,"id":"54ca63a5_f2044c6f","updated":"2026-08-21 11:45:38.000000000","message":"Note ready for review till above patches, testing and fixing few more stuff.","commit_id":"1cce5d939d252144a2fb283b3e88a425b6145a6c"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"2dcea0b956d7372e56b51d2e9d4dca6dea23f848","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":16,"id":"7424ca1a_9c020725","updated":"2026-08-21 15:33:11.000000000","message":"ready for review till https://review.opendev.org/c/openstack/cyborg/+/999939/18?usp\u003drelated-change","commit_id":"1cce5d939d252144a2fb283b3e88a425b6145a6c"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"6685173bf4512895aee861a4ce9917b04ec204b2","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":19,"id":"6643e157_c8c040a1","updated":"2026-09-03 09:53:57.000000000","message":"Last patchset only updates tests to use ovo object.","commit_id":"c19360c84c3d103d2a7bb96b394082076ae61326"}],"cyborg/accelerator/drivers/nvme/driver.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":"07c645424e723deff16e93e504bc5fe1d16bff28","unresolved":false,"context_lines":[{"line_number":64,"context_line":"        path \u003d pathlib.Path(self._pci_sysfs_path) / pci_address / filename"},{"line_number":65,"context_line":"        try:"},{"line_number":66,"context_line":"            return path.read_text().strip().removeprefix(\u00270x\u0027)"},{"line_number":67,"context_line":"        except Exception:"},{"line_number":68,"context_line":"            return \u0027unknown\u0027"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"    def _enumerate_nvme_pci_devices(self):"}],"source_content_type":"text/x-python","patch_set":2,"id":"522b6950_3560a06a","line":67,"updated":"2026-08-06 11:00:08.000000000","message":"Three locations in the new driver.py use bare `except Exception:` for file I/O and subprocess operations. The OpenStack style guide requires specific exception types. These broad catches could mask programming errors like AttributeError or TypeError as silent fallbacks.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: Broad exception handlers in device discovery can silently mask programming bugs (e.g., an AttributeError from a None value) by treating them as expected I/O failures. A device that should raise an error during development instead silently disappears from the pool with no actionable diagnostic bey...\n\n**Suggestion**:\nReplace `except Exception:` with specific exception types: `OSError` for file reads in `_read_sysfs_id` and `_enumerate_nvme_pci_devices`; `(exception.DeviceNotFound, processutils.ProcessExecutionError)` for `_query_capabilities` in `discover()`.","commit_id":"a767f912bd7dd82515b099bf9bd81cd6894d41be"},{"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":"07c645424e723deff16e93e504bc5fe1d16bff28","unresolved":false,"context_lines":[{"line_number":140,"context_line":""},{"line_number":141,"context_line":"        return None"},{"line_number":142,"context_line":""},{"line_number":143,"context_line":"    def _build_traits(self, vendor_id, product_id, caps):"},{"line_number":144,"context_line":"        traits \u003d [constants.OWNER_CYBORG]"},{"line_number":145,"context_line":"        traits.append(\u0027CUSTOM_NVME_PRODUCT_ID_%s\u0027 % product_id.upper())"},{"line_number":146,"context_line":"        if caps[\u0027ces\u0027]:"}],"source_content_type":"text/x-python","patch_set":2,"id":"99350085_e40c514a","line":143,"updated":"2026-08-06 11:00:08.000000000","message":"The _build_traits method accepts vendor_id as its first parameter but never references it in the method body. The caller passes vendor_id but it has no effect on the output.\n\n**Severity**: SUGGESTION | **Confidence**: 0.9\n\n**Benefit**: The unused parameter is misleading — future maintainers may assume vendor_id is used for trait generation. It also makes the method signature wider than necessary.\n\n**Recommendation**:\nRemove the vendor_id parameter from _build_traits and update the call site at line 228 to not pass it. If vendor-specific traits are planned for the future, add a comment explaining the intent.","commit_id":"a767f912bd7dd82515b099bf9bd81cd6894d41be"},{"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":"37c01b150be1a809eddb9072a7d0d6e1d0af1525","unresolved":false,"context_lines":[{"line_number":11,"context_line":"# License for the specific language governing permissions and limitations"},{"line_number":12,"context_line":"# under the License."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"import pathlib"},{"line_number":15,"context_line":""},{"line_number":16,"context_line":"from oslo_log import log as logging"},{"line_number":17,"context_line":"from oslo_serialization import jsonutils"}],"source_content_type":"text/x-python","patch_set":4,"id":"b4e2af26_303de035","line":14,"updated":"2026-08-06 16:51:09.000000000","message":"The new file cyborg/accelerator/drivers/nvme/driver.py has no module-level docstring after the Apache license header. Every other driver module in the project includes one (e.g., \u0027Cyborg NVIDIA GPU driver implementation.\u0027, \u0027Cyborg PCI driver implementation.\u0027, \u0027Cyborg Intel FPGA driver implementat...\n\n**Severity**: SUGGESTION | **Confidence**: 0.9\n\n**Benefit**: Reduces discoverability and self-documentation of the module. New contributors and automated documentation tools cannot determine the module\u0027s purpose from a standard docstring. Minor maintainability concern for a new production module.\n\n**Recommendation**:\nAdd a module-level docstring after the license header, e.g.: \u0027\\n\"\"\"Cyborg NVMe accelerator driver implementation.\"\"\"\\n\u0027","commit_id":"4b1a9cf3f76b167bc0928f088e911a3cc80210d9"},{"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":"af99da5739eed8ae74d7e36401d20f0efb340a49","unresolved":false,"context_lines":[{"line_number":208,"context_line":""},{"line_number":209,"context_line":"            try:"},{"line_number":210,"context_line":"                caps \u003d self._query_capabilities(pci_addr)"},{"line_number":211,"context_line":"            except Exception:"},{"line_number":212,"context_line":"                LOG.exception("},{"line_number":213,"context_line":"                    \u0027Failed to query capabilities for %s\u0027,"},{"line_number":214,"context_line":"                    pci_addr,"}],"source_content_type":"text/x-python","patch_set":5,"id":"405f2989_cfaafa2d","line":211,"updated":"2026-08-07 07:02:11.000000000","message":"NVMeDriver.discover() catches `except Exception:` around _query_capabilities(). While the intent is to skip devices that fail nvme-cli queries, the broad catch also swallows programming errors (TypeError, AttributeError, KeyError) that indicate real bugs. The project quick rules list \u0027no broad Ex...\n\n**Severity**: SUGGESTION | **Confidence**: 0.8\n\n**Benefit**: Unexpected programming errors (e.g., nvme-cli output format change causing KeyError) would be silently logged and the device excluded from the pool without operator awareness. This makes debugging harder in production.\n\n**Recommendation**:\nReplace `except Exception:` with specific exceptions: `except (exception.DeviceNotFound, processutils.ProcessExecutionError, ValueError, OSError):`. This preserves skip-on-failure behavior while allowing truly unexpected errors to surface.","commit_id":"a1079c30416c0f14b9da5db329efe1678c515ba9"},{"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":"6f6d87758d679a0776bac9db7b8314c6d03ded16","unresolved":false,"context_lines":[{"line_number":290,"context_line":"                )"},{"line_number":291,"context_line":"                continue"},{"line_number":292,"context_line":""},{"line_number":293,"context_line":"            if self._rp_exists_without_owner_cyborg(hostname, pci_addr):"},{"line_number":294,"context_line":"                LOG.error("},{"line_number":295,"context_line":"                    \u0027Device %s: resource provider exists without \u0027"},{"line_number":296,"context_line":"                    \u0027OWNER_CYBORG trait; skipping.\u0027,"}],"source_content_type":"text/x-python","patch_set":7,"id":"44b59116_4b7df80e","line":293,"updated":"2026-08-09 05:13:18.000000000","message":"NVMeDriver.discover() calls _rp_exists_without_owner_cyborg() for each NVMe device, which makes two HTTP round-trips to Placement (resource_providers lookup + traits lookup). Because ResourceTracker.update_usage() calls discover() on every periodic refresh, this results in 2*N Placement HTTP call...\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: On a compute host with multiple NVMe devices, every periodic interval generates unnecessary Placement API traffic. At scale this adds load to the Placement service and increases agent startup/refresh latency.\n\n**Suggestion**:\nConsider caching the OWNER_CYBORG check result per device, adding a flag to skip the Placement check when discover() is called from the periodic path, or moving the ownership check to init_host/startup only rather than every discover() call.","commit_id":"c1d148aa055ad4f431daff8a3111d2b59cdb0f0f"},{"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":"269aadf8fb60e2ab2db41ef226e697c7c8a09408","unresolved":false,"context_lines":[{"line_number":84,"context_line":"                    put_resp \u003d client.put("},{"line_number":85,"context_line":"                        \u0027/traits/%s\u0027 % trait, None, version\u003d\u00271.6\u0027"},{"line_number":86,"context_line":"                    )"},{"line_number":87,"context_line":"                    if put_resp.status_code !\u003d 201:"},{"line_number":88,"context_line":"                        raise exception.InvalidConfiguration("},{"line_number":89,"context_line":"                            reason\u003d("},{"line_number":90,"context_line":"                                \u0027Failed to register NVMe trait %s in \u0027"}],"source_content_type":"text/x-python","patch_set":8,"id":"1b992578_a2642de0","line":87,"updated":"2026-08-11 09:34:14.000000000","message":"The trait-registration code does GET /traits/{name}; if 404, it PUTs the trait and requires status 201. However, Placement\u0027s PUT /traits/{name} returns 200 OK when the trait already exists and 201 Created when newly created. If another agent or process creates the same trait between the GET (404)...\n\n**Severity**: HIGH | **Confidence**: 0.8\n\n**Risk**: In a multi-agent deployment where two agents start concurrently (e.g., after a cluster-wide restart), one agent\u0027s GET may return 404 while the other has already PUT the trait. The second PUT returns 200, raising InvalidConfiguration and crashing the agent. This is intermittent and depends on timing.\n\n**Priority**: Before merge\n**Why This Matters**: In a multi-agent deployment where two agents start concurrently (e.g., after a cluster-wide restart), one agent\u0027s GET may return 404 while the other has already PUT the trait. The second PUT returns 200, raising InvalidConfiguration and crashing the agent. This is intermittent and depends on timing.\n\n**Recommendation**:\nAccept both 200 and 201 as success: change the check to `if put_resp.status_code not in (200, 201):`. Alternatively, skip the GET check entirely and just PUT (idempotent), accepting 200 or 201.","commit_id":"025c61667ca956836966b60c97274d59276a0aa3"},{"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":"269aadf8fb60e2ab2db41ef226e697c7c8a09408","unresolved":false,"context_lines":[{"line_number":225,"context_line":"            )"},{"line_number":226,"context_line":"            return False"},{"line_number":227,"context_line":""},{"line_number":228,"context_line":"    def _build_traits(self, caps):"},{"line_number":229,"context_line":"        traits \u003d [constants.OWNER_CYBORG]"},{"line_number":230,"context_line":"        if caps[\u0027ces\u0027]:"},{"line_number":231,"context_line":"            traits.append(TRAIT_HW_NVME_CES)"}],"source_content_type":"text/x-python","patch_set":8,"id":"bca2ce4f_70495b72","line":228,"updated":"2026-08-11 09:34:14.000000000","message":"The NVMe driver defines _build_traits twice. The first (line 184) accepts (self, caps, vendor_id, product_id) and emits CUSTOM_NVME_PRODUCT_ID_\u003cpid\u003e. The second (line 228) accepts only (self, caps). Python uses the second, silently overriding the first. discover() calls self._build_traits(caps, v...\n\n**Severity**: CRITICAL | **Confidence**: 1.0\n\n**Risk**: discover() is completely non-functional - every call raises TypeError before any device is returned. The CUSTOM_NVME_PRODUCT_ID_\u003cpid\u003e trait is never emitted, so device profiles that require it cannot be satisfied by the scheduler, producing \u0027No valid host was found\u0027 for all NVMe lifecycle tests a...\n\n**Priority**: Immediate\n**Why This Matters**: discover() is completely non-functional - every call raises TypeError before any device is returned. The CUSTOM_NVME_PRODUCT_ID_\u003cpid\u003e trait is never emitted, so device profiles that require it cannot be satisfied by the scheduler, producing \u0027No valid host was found\u0027 for all NVMe lifecycle tests a...\n\n**Recommendation**:\nDelete the second _build_traits definition at line 228-236. The first definition (line 184-194) is the correct one that accepts vendor_id/product_id and emits the product-id trait.","commit_id":"025c61667ca956836966b60c97274d59276a0aa3"},{"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":"1ebc13b6c260dbf263540e6b6d611ec154de7d22","unresolved":false,"context_lines":[{"line_number":182,"context_line":""},{"line_number":183,"context_line":"        return None"},{"line_number":184,"context_line":""},{"line_number":185,"context_line":"    def _build_traits(self, caps):"},{"line_number":186,"context_line":"        traits \u003d [constants.OWNER_CYBORG]"},{"line_number":187,"context_line":"        if caps[\u0027ces\u0027]:"},{"line_number":188,"context_line":"            traits.append(TRAIT_HW_NVME_CES)"}],"source_content_type":"text/x-python","patch_set":10,"id":"2f3e5ee8_e6a56732","line":185,"updated":"2026-08-12 08:56:46.000000000","message":"The commit message explicitly states that _build_traits should accept vendor_id and product_id to emit a CUSTOM_NVME_PRODUCT_ID_\u003cpid\u003e trait, and that without it \u0027No valid host was found\u0027 for all NVMe lifecycle tests. However the actual _build_traits method only accepts caps and emits OWNER_CYBORG...\n\n**Severity**: HIGH | **Confidence**: 0.9\n\n**Risk**: Device profiles that require trait CUSTOM_NVME_PRODUCT_ID_\u003cpid\u003e (such as those created by the devstack fixture described in the commit message) will fail to match NVMe devices, resulting in \u0027No valid host was found\u0027 errors. This breaks the core use case described in the commit message.\n\n**Priority**: Before merge\n**Why This Matters**: Device profiles that require trait CUSTOM_NVME_PRODUCT_ID_\u003cpid\u003e (such as those created by the devstack fixture described in the commit message) will fail to match NVMe devices, resulting in \u0027No valid host was found\u0027 errors. This breaks the core use case described in the commit message.\n\n**Recommendation**:\nUpdate _build_traits to accept vendor_id and product_id parameters and emit a CUSTOM_NVME_PRODUCT_ID_\u003cpid\u003e trait, matching the pattern used by other Cyborg drivers. Update the call site at line 309 to pass vendor_id and product_id. Add a test assertion for the trait.","commit_id":"d09974242d75ead54403c47e2a7c830d2d7e3389"},{"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":"1ebc13b6c260dbf263540e6b6d611ec154de7d22","unresolved":false,"context_lines":[{"line_number":345,"context_line":"    def get_stats(self):"},{"line_number":346,"context_line":"        return {}"},{"line_number":347,"context_line":""},{"line_number":348,"context_line":"    def cleanup(self, device):"},{"line_number":349,"context_line":"        pass"}],"source_content_type":"text/x-python","patch_set":10,"id":"a7195987_98639e6d","line":348,"updated":"2026-08-12 08:56:46.000000000","message":"The release note states the driver \u0027supports post-teardown cleanup via NVMe sanitize (crypto-erase or block-erase) and write-zeroes, with configurable policy.\u0027 While the driver resolves a cleanup_action policy during discover() and stores it in std_board_info, the actual cleanup() method is an em...\n\n**Severity**: SUGGESTION | **Confidence**: 0.8\n\n**Benefit**: Operators reading the release note will expect NVMe sanitize/write-zeroes cleanup to function. The policy resolution and std_board_info storage give the appearance of a working feature, but no cleanup is ever executed. This could lead to devices being returned to the pool without data sanitization.\n\n**Recommendation**:\nEither implement cleanup() to execute the stored cleanup_action using the nvme_cli helper functions, or adjust the release note to clarify that cleanup execution is planned but not yet implemented in this release. At minimum, document the current limitation.","commit_id":"d09974242d75ead54403c47e2a7c830d2d7e3389"},{"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":"a016e687c14f6fcd7f4553653bf46cf1135eab29","unresolved":false,"context_lines":[{"line_number":54,"context_line":""},{"line_number":55,"context_line":"# os-traits companion change has not landed in requirements yet, so keep"},{"line_number":56,"context_line":"# the Placement trait names local to this driver for now."},{"line_number":57,"context_line":"TRAIT_HW_NVME_CES \u003d \u0027HW_NVME_CES\u0027"},{"line_number":58,"context_line":"TRAIT_HW_NVME_BES \u003d \u0027HW_NVME_BES\u0027"},{"line_number":59,"context_line":"TRAIT_HW_NVME_WZS \u003d \u0027HW_NVME_WZS\u0027"},{"line_number":60,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"892540ee_30e98529","line":57,"updated":"2026-08-14 15:33:02.000000000","message":"_ensure_nvme_traits() PUTs traits named \u0027HW_NVME_CES\u0027/\u0027HW_NVME_BES\u0027/\u0027HW_NVME_WZS\u0027, but the Placement API requires custom trait names to start with CUSTOM_; a PUT /traits/HW_NVME_CES returns 400, which the code turns into a raised InvalidConfiguration and agent startup abort.\n\n**Severity**: HIGH | **Confidence**: 0.8\n\n**Risk**: With the NVMe driver enabled, agent startup hits the hard InvalidConfiguration path (400 !\u003d 201), reproducing the whole-agent outage of CF-003 even on a fully provisioned host with Placement healthy. Trait-based scheduling on the capability traits also cannot work.\n\n**Priority**: Before merge\n**Why This Matters**: With the NVMe driver enabled, agent startup hits the hard InvalidConfiguration path (400 !\u003d 201), reproducing the whole-agent outage of CF-003 even on a fully provisioned host with Placement healthy. Trait-based scheduling on the capability traits also cannot work.\n\n**Recommendation**:\nRename the constants to CUSTOM_HW_NVME_* (or adopt standard os-traits names once available and rely on Placement already knowing them), and adjust the tests and _build_traits output consistently.","commit_id":"d0ed397ba88c229ca4f0746f113bb90851a0fd88"},{"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":"a016e687c14f6fcd7f4553653bf46cf1135eab29","unresolved":false,"context_lines":[{"line_number":182,"context_line":""},{"line_number":183,"context_line":"        return None"},{"line_number":184,"context_line":""},{"line_number":185,"context_line":"    def _build_traits(self, caps):"},{"line_number":186,"context_line":"        traits \u003d [constants.OWNER_CYBORG]"},{"line_number":187,"context_line":"        if caps[\u0027ces\u0027]:"},{"line_number":188,"context_line":"            traits.append(TRAIT_HW_NVME_CES)"}],"source_content_type":"text/x-python","patch_set":12,"id":"fdba0f29_7d29d38e","line":185,"updated":"2026-08-14 15:33:02.000000000","message":"The commit message and release note state that _build_traits emits CUSTOM_NVME_PRODUCT_ID_\u003cpid\u003e so devstack device profiles requiring that trait can be satisfied, but _build_traits() only ever emits OWNER_CYBORG plus the three HW_NVME_* capability traits.\n\n**Severity**: HIGH | **Confidence**: 0.9\n\n**Risk**: Any device profile requiring CUSTOM_NVME_PRODUCT_ID_\u003cpid\u003e (per the commit message, the devstack fixture profiles) will not match any NVMe deployable at scheduling time, causing \u0027No valid host was found\u0027 for NVMe lifecycle flows despite discovery succeeding.\n\n**Priority**: Before merge\n**Why This Matters**: Any device profile requiring CUSTOM_NVME_PRODUCT_ID_\u003cpid\u003e (per the commit message, the devstack fixture profiles) will not match any NVMe deployable at scheduling time, causing \u0027No valid host was found\u0027 for NVMe lifecycle flows despite discovery succeeding.\n\n**Recommendation**:\nEither accept vendor_id/product_id in _build_traits and append \u0027CUSTOM_NVME_PRODUCT_ID_%s\u0027 % product_id.upper() (mirroring the inspur/xilinx FPGA drivers) with a matching test, or update the commit message/release note and devstack fixture so the documented contract matches the code.","commit_id":"d0ed397ba88c229ca4f0746f113bb90851a0fd88"},{"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":"a016e687c14f6fcd7f4553653bf46cf1135eab29","unresolved":false,"context_lines":[{"line_number":345,"context_line":"    def get_stats(self):"},{"line_number":346,"context_line":"        return {}"},{"line_number":347,"context_line":""},{"line_number":348,"context_line":"    def cleanup(self, device):"},{"line_number":349,"context_line":"        pass"}],"source_content_type":"text/x-python","patch_set":12,"id":"d0816a01_2a87d41d","line":348,"updated":"2026-08-14 15:33:02.000000000","message":"The entire policy matrix, cleanup_action preservation logic, and the \u0027requires cleanup-policy resolution before safe allocation\u0027 rationale of this patch revolve around NVMe sanitize/write-zeroes, yet NVMeDriver.cleanup() does nothing and nothing else in the tree calls nvme_cli.nvme_sanitize or nv...\n\n**Severity**: HIGH | **Confidence**: 0.8\n\n**Risk**: Deallocated NVMe devices are returned to the pool without any data sanitization while the release note tells operators sanitization is performed - a data-hygiene gap and misleading operator documentation.\n\n**Priority**: Before merge\n**Why This Matters**: Deallocated NVMe devices are returned to the pool without any data sanitization while the release note tells operators sanitization is performed - a data-hygiene gap and misleading operator documentation.\n\n**Recommendation**:\nImplement cleanup() to dispatch on std_board_info cleanup_action to nvme_sanitize or nvme_write_zeroes (returning a pending/deferred status where sanitize is asynchronous), or land it in a fast-follow patch and remove the cleanup claim from this release note until it exists.","commit_id":"d0ed397ba88c229ca4f0746f113bb90851a0fd88"},{"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":"bae1a7942c7439ce9f098bc0c8f7a4216ffdaf7c","unresolved":false,"context_lines":[{"line_number":199,"context_line":"        \"\"\"Return True if an RP exists for this device but lacks OWNER_CYBORG.\"\"\""},{"line_number":200,"context_line":"        try:"},{"line_number":201,"context_line":"            client \u003d self._init_placement_client()"},{"line_number":202,"context_line":"            rp_name \u003d \u0027%s_%s\u0027 % (hostname, pci_addr)"},{"line_number":203,"context_line":"            encoded \u003d urllib.parse.quote(rp_name, safe\u003d\u0027\u0027)"},{"line_number":204,"context_line":"            resp \u003d client.get("},{"line_number":205,"context_line":"                \u0027/resource_providers?name\u003d%s\u0027 % encoded, version\u003d\u00271.6\u0027"}],"source_content_type":"text/x-python","patch_set":13,"id":"cba3b264_c5a574ad","line":202,"updated":"2026-08-15 16:25:22.000000000","message":"_rp_exists_without_owner_cyborg builds the resource provider name as \u0027\u003chostname\u003e_\u003cpci_addr\u003e\u0027 and queries Placement for it, but Placement RP names for cyborg devices elsewhere use UUIDs/other formats, so the query is unlikely to find the RP that actually represents the device.\n\n**Severity**: HIGH | **Confidence**: 0.8\n\n**Risk**: The safety check intended to skip devices whose RP is owned by another component may never match an RP, letting the driver claim devices it should not, or the check silently degrades to always-allow on naming mismatch.\n\n**Priority**: Before merge\n**Why This Matters**: The safety check intended to skip devices whose RP is owned by another component may never match an RP, letting the driver claim devices it should not, or the check silently degrades to always-allow on naming mismatch.\n\n**Recommendation**:\nDerive the RP identity the same way the conductor does (from the deployable/RP UUID mapping) instead of constructing \u0027\u003chostname\u003e_\u003cpci_addr\u003e\u0027, and add a unit test that asserts the guard trips on a real RP-shaped response.","commit_id":"939db56c2785af9a0203a3037f86d833efbebcc7"},{"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":"19e50c2ab65bf3fdd8d4ea6a48c4b521a24738f2","unresolved":false,"context_lines":[{"line_number":182,"context_line":""},{"line_number":183,"context_line":"        return None"},{"line_number":184,"context_line":""},{"line_number":185,"context_line":"    def _build_traits(self, caps):"},{"line_number":186,"context_line":"        traits \u003d [constants.OWNER_CYBORG]"},{"line_number":187,"context_line":"        if caps[\u0027ces\u0027]:"},{"line_number":188,"context_line":"            traits.append(TRAIT_HW_NVME_CES)"}],"source_content_type":"text/x-python","patch_set":14,"id":"57a69990_1c39e08e","line":185,"updated":"2026-08-17 08:04:31.000000000","message":"The commit message states _build_traits accepts vendor_id/product_id and emits CUSTOM_NVME_PRODUCT_ID_\u003cpid\u003e so device profiles requiring that trait can be satisfied by the scheduler. The implemented _build_traits(self, caps) takes no ids and emits only OWNER_CYBORG plus HW_NVME_* traits.\n\n**Severity**: HIGH | **Confidence**: 0.9\n\n**Risk**: Device profiles that require trait:CUSTOM_NVME_PRODUCT_ID_\u003cpid\u003e (e.g. the devstack fixture referenced in the commit message) will still fail trait matching in Placement scheduling, reproducing the exact \u0027No valid host was found\u0027 failure the patch claims to fix.\n\n**Priority**: Before merge\n**Why This Matters**: Device profiles that require trait:CUSTOM_NVME_PRODUCT_ID_\u003cpid\u003e (e.g. the devstack fixture referenced in the commit message) will still fail trait matching in Placement scheduling, reproducing the exact \u0027No valid host was found\u0027 failure the patch claims to fix.\n\n**Recommendation**:\nEither extend _build_traits to accept vendor_id/product_id and append CUSTOM_NVME_PRODUCT_ID_\u003cpid\u003e like pci/pci/sysinfo.py:62 does, or update the commit message/tests if the trait is intentionally dropped. Add a unit test asserting the trait is present in the deployable attribute_list.","commit_id":"44357c4f41a5b3695bf1f108cdfc11b2fab58f80"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"2fb89a7c17696125a492fa02f43e4c5b5c95dfd4","unresolved":true,"context_lines":[{"line_number":41,"context_line":"PCI_DEVICES_SYSFS_PATH \u003d \u0027/sys/bus/pci/devices\u0027"},{"line_number":42,"context_line":"NVME_CLASS_CODE \u003d \u00270x010802\u0027"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"CLEANUP_SANITIZE_CES \u003d \u0027sanitize_ces\u0027"},{"line_number":45,"context_line":"CLEANUP_SANITIZE_BES \u003d \u0027sanitize_bes\u0027"},{"line_number":46,"context_line":"CLEANUP_ZERO_WZ \u003d \u0027zero_wz\u0027"},{"line_number":47,"context_line":"CLEANUP_ZERO_SHRED \u003d \u0027zero_shred\u0027"},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"# Bit positions in NVMe id-ctrl fields"},{"line_number":50,"context_line":"SANICAP_CES \u003d 0"}],"source_content_type":"text/x-python","patch_set":15,"id":"96334b9b_d29b767a","line":47,"range":{"start_line":44,"start_character":0,"end_line":47,"end_character":33},"updated":"2026-08-18 14:24:14.000000000","message":"```\nclass CleanupAction(str, enum.Enum):\n    SANITIZE_CES \u003d \"sanitize_ces\"\n    SANITIZE_BES \u003d \"sanitize_bes\"\n    ZERO_WZ \u003d \"zero_wz\"\n    ZERO_SHRED \u003d \"zero_shred\"\n```","commit_id":"21392bef2b7b8ca0fd9cbd54abd0400a504514e9"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"2fb89a7c17696125a492fa02f43e4c5b5c95dfd4","unresolved":true,"context_lines":[{"line_number":46,"context_line":"CLEANUP_ZERO_WZ \u003d \u0027zero_wz\u0027"},{"line_number":47,"context_line":"CLEANUP_ZERO_SHRED \u003d \u0027zero_shred\u0027"},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"# Bit positions in NVMe id-ctrl fields"},{"line_number":50,"context_line":"SANICAP_CES \u003d 0"},{"line_number":51,"context_line":"SANICAP_BES \u003d 1"},{"line_number":52,"context_line":"ONCS_WZ \u003d 3"},{"line_number":53,"context_line":"OACS_NS_MGMT \u003d 3"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"# os-traits companion change has not landed in requirements yet, so keep"},{"line_number":56,"context_line":"# the Placement trait names local to this driver for now."}],"source_content_type":"text/x-python","patch_set":15,"id":"7a586a03_a16f4e1f","line":53,"range":{"start_line":49,"start_character":1,"end_line":53,"end_character":16},"updated":"2026-08-18 14:24:14.000000000","message":"```suggestion\n# Bit positions in NVMe id-ctrl fields\nclass SanicapFlag(enum.IntFlag):\n    CES \u003d 1 \u003c\u003c 0  # Crypto Erase Sanitize Support\n    BES \u003d 1 \u003c\u003c 1  # Block Erase Sanitize Support\n\n\nclass OncsFlag(enum.IntFlag):\n    WZ \u003d 1 \u003c\u003c 3  # Write Zeroes Support\n\n\nclass OacsFlag(enum.IntFlag):\n    NS_MGMT \u003d 1 \u003c\u003c 3  # Namespace Management and Attachment Support\n```","commit_id":"21392bef2b7b8ca0fd9cbd54abd0400a504514e9"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"2fb89a7c17696125a492fa02f43e4c5b5c95dfd4","unresolved":true,"context_lines":[{"line_number":113,"context_line":"        except OSError:"},{"line_number":114,"context_line":"            return \u0027unknown\u0027"},{"line_number":115,"context_line":""},{"line_number":116,"context_line":"    def _enumerate_nvme_pci_devices(self):"},{"line_number":117,"context_line":"        devices \u003d []"},{"line_number":118,"context_line":"        sysfs \u003d pathlib.Path(self._pci_sysfs_path)"},{"line_number":119,"context_line":"        if not sysfs.is_dir():"},{"line_number":120,"context_line":"            return devices"},{"line_number":121,"context_line":"        for entry in sorted(sysfs.iterdir()):"},{"line_number":122,"context_line":"            pci_address \u003d entry.name"},{"line_number":123,"context_line":"            try:"},{"line_number":124,"context_line":"                pci_class \u003d (entry / \u0027class\u0027).read_text().strip()"},{"line_number":125,"context_line":"            except OSError:"},{"line_number":126,"context_line":"                LOG.debug(\u0027Cannot read class for %s, skipping\u0027, pci_address)"},{"line_number":127,"context_line":"                continue"},{"line_number":128,"context_line":"            if not pci_class.startswith(NVME_CLASS_CODE):"},{"line_number":129,"context_line":"                continue"},{"line_number":130,"context_line":"            vendor_id \u003d self._read_sysfs_id(pci_address, \u0027vendor\u0027)"},{"line_number":131,"context_line":"            product_id \u003d self._read_sysfs_id(pci_address, \u0027device\u0027)"},{"line_number":132,"context_line":"            devices.append((pci_address, vendor_id, product_id))"},{"line_number":133,"context_line":"        return devices"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"    def _query_capabilities(self, pci_address):"},{"line_number":136,"context_line":"        nvme_dev \u003d nvme_cli.resolve_nvme_dev_from_pci(pci_address)"},{"line_number":137,"context_line":"        id_ctrl \u003d nvme_cli.nvme_id_ctrl(nvme_dev)"}],"source_content_type":"text/x-python","patch_set":15,"id":"db93313a_3e27d1e6","line":134,"range":{"start_line":116,"start_character":1,"end_line":134,"end_character":1},"updated":"2026-08-18 14:24:14.000000000","message":"you shoudl not be donig thid directly yourself.\nit was orgianlly inteded that you reuse the enmeration capablity form the pci driver\n\nspecificlly you shoudl be using \n\nhttps://github.com/openstack/cyborg/blob/master/cyborg/accelerator/common/utils.py#L185\n\nwhich is callign lspci and yeilds parsed dictionares form this regex\n\nhttps://github.com/openstack/cyborg/blob/master/cyborg/accelerator/common/utils.py#L32-L39\n\nthat includes the class.","commit_id":"21392bef2b7b8ca0fd9cbd54abd0400a504514e9"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"2fb89a7c17696125a492fa02f43e4c5b5c95dfd4","unresolved":true,"context_lines":[{"line_number":134,"context_line":""},{"line_number":135,"context_line":"    def _query_capabilities(self, pci_address):"},{"line_number":136,"context_line":"        nvme_dev \u003d nvme_cli.resolve_nvme_dev_from_pci(pci_address)"},{"line_number":137,"context_line":"        id_ctrl \u003d nvme_cli.nvme_id_ctrl(nvme_dev)"},{"line_number":138,"context_line":""},{"line_number":139,"context_line":"        sanicap \u003d id_ctrl.get(\u0027sanicap\u0027, 0)"},{"line_number":140,"context_line":"        oncs \u003d id_ctrl.get(\u0027oncs\u0027, 0)"}],"source_content_type":"text/x-python","patch_set":15,"id":"b594da79_d768fd4e","line":137,"range":{"start_line":137,"start_character":27,"end_line":137,"end_character":39},"updated":"2026-08-18 14:24:14.000000000","message":"I think we should return a dataclass with the bit-shifting and flag parsing\nalready handled. The current approach leaks too many implementation details into\nthe driver.\n\nIn fact, _query_capabilities should likely be replaced by a get_capabilities as the public method that encapsulates this logic and returns NvmeCapabilities directly:\n```\nimport dataclasses\n\n\n@dataclasses.dataclass(order\u003dTrue)\nclass NvmeCapabilities:\n    nvme_dev: str\n    ces: bool \u003d dataclasses.field(compare\u003dFalse, default\u003dFalse)\n    bes: bool \u003d dataclasses.field(compare\u003dFalse, default\u003dFalse)\n    wzs: bool \u003d dataclasses.field(compare\u003dFalse, default\u003dFalse)\n    ns_mgmt: bool \u003d dataclasses.field(compare\u003dFalse, default\u003dFalse)\n\n\ndef get_capabilities(self, pci_address: str) -\u003e NvmeCapabilities:\n    \"\"\"Queries controller ID and parses flags directly into NvmeCapabilities.\"\"\"\n    nvme_dev \u003d nvme_cli.resolve_nvme_dev_from_pci(pci_address)\n    raw_id \u003d nvme_cli.nvme_id_ctrl(nvme_dev)\n\n    sanicap \u003d raw_id.get(\"sanicap\", 0)\n    oncs \u003d raw_id.get(\"oncs\", 0)\n    oacs \u003d raw_id.get(\"oacs\", 0)\n\n    return NvmeCapabilities(\n        nvme_dev\u003dnvme_dev,\n        ces\u003dbool(sanicap \u0026 SanicapFlag.CES),\n        bes\u003dbool(sanicap \u0026 SanicapFlag.BES),\n        wzs\u003dbool(oncs \u0026 OncsFlag.WZ),\n        ns_mgmt\u003dbool(oacs \u0026 OacsFlag.NS_MGMT),\n    )\n```","commit_id":"21392bef2b7b8ca0fd9cbd54abd0400a504514e9"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"2fb89a7c17696125a492fa02f43e4c5b5c95dfd4","unresolved":true,"context_lines":[{"line_number":140,"context_line":"        oncs \u003d id_ctrl.get(\u0027oncs\u0027, 0)"},{"line_number":141,"context_line":"        oacs \u003d id_ctrl.get(\u0027oacs\u0027, 0)"},{"line_number":142,"context_line":""},{"line_number":143,"context_line":"        # OACS Namespace Management and Attachment bit (NVMe spec §5.15)."},{"line_number":144,"context_line":"        # Not reliable on its own: QEMU NVMe sets it without implementing the"},{"line_number":145,"context_line":"        # actual commands. Probe once per agent lifetime to confirm."},{"line_number":146,"context_line":"        ns_mgmt_claimed \u003d bool(oacs \u0026 (1 \u003c\u003c OACS_NS_MGMT))"},{"line_number":147,"context_line":"        if ns_mgmt_claimed and nvme_dev not in self._ns_mgmt_probed:"},{"line_number":148,"context_line":"            self._ns_mgmt_probed[nvme_dev] \u003d self._probe_ns_mgmt(nvme_dev)"},{"line_number":149,"context_line":"        ns_mgmt \u003d ("},{"line_number":150,"context_line":"            self._ns_mgmt_probed.get(nvme_dev, False)"},{"line_number":151,"context_line":"            if ns_mgmt_claimed"},{"line_number":152,"context_line":"            else False"},{"line_number":153,"context_line":"        )"},{"line_number":154,"context_line":""},{"line_number":155,"context_line":"        return {"},{"line_number":156,"context_line":"            \u0027ces\u0027: bool(sanicap \u0026 (1 \u003c\u003c SANICAP_CES)),"}],"source_content_type":"text/x-python","patch_set":15,"id":"17c69d37_bf92aa66","line":153,"range":{"start_line":143,"start_character":9,"end_line":153,"end_character":9},"updated":"2026-08-18 14:24:14.000000000","message":"having this be a sideefe of getign the capablity is not a good thing if we need to do this then we shoudl post process the device capablity seperatly.","commit_id":"21392bef2b7b8ca0fd9cbd54abd0400a504514e9"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"2fb89a7c17696125a492fa02f43e4c5b5c95dfd4","unresolved":true,"context_lines":[{"line_number":160,"context_line":"            \u0027nvme_dev\u0027: nvme_dev,"},{"line_number":161,"context_line":"        }"},{"line_number":162,"context_line":""},{"line_number":163,"context_line":"    def _probe_ns_mgmt(self, nvme_dev):"},{"line_number":164,"context_line":"        \"\"\"Return True only if the controller actually supports NS management."},{"line_number":165,"context_line":""},{"line_number":166,"context_line":"        Some controllers (e.g. QEMU NVMe) set the OACS Namespace Management"}],"source_content_type":"text/x-python","patch_set":15,"id":"f3117e9b_7b84a618","line":163,"range":{"start_line":163,"start_character":8,"end_line":163,"end_character":22},"updated":"2026-08-18 14:24:14.000000000","message":"this is dangourse we cannot probe for namespace capablity by deltign the namesapce on the device as a sideffect of geting the device capablities.\n\nif the device report this capablity we have to tust what was reproted and handel the case that it does not work later if we try to mange teh namespaces.","commit_id":"21392bef2b7b8ca0fd9cbd54abd0400a504514e9"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"2fb89a7c17696125a492fa02f43e4c5b5c95dfd4","unresolved":true,"context_lines":[{"line_number":185,"context_line":"        return True"},{"line_number":186,"context_line":""},{"line_number":187,"context_line":"    def _resolve_cleanup_action(self, spec, caps):"},{"line_number":188,"context_line":"        a, s \u003d spec.clear_action, spec.clear_strategy"},{"line_number":189,"context_line":""},{"line_number":190,"context_line":"        if a \u003d\u003d \u0027auto\u0027 and s \u003d\u003d \u0027auto\u0027:"},{"line_number":191,"context_line":"            if caps[\u0027ces\u0027]:"}],"source_content_type":"text/x-python","patch_set":15,"id":"f11449cd_a9948b82","line":188,"range":{"start_line":188,"start_character":8,"end_line":188,"end_character":53},"updated":"2026-08-18 14:24:14.000000000","message":"you shoudl use better names\n\ni would also use a match statement here\n```\n@staticmethod\ndef _resolve_cleanup_action(\n    spec, caps: NvmeCapabilities\n)-\u003e typing.Optional[CleanupAction]:\n    action \u003d spec.clear_action\n    strategy \u003d spec.clear_strategy\n\n    match (action, strategy):\n        case (\"auto\", \"auto\"):\n            if caps.ces:\n                return CLEANUP_SANITIZE_CES\n            if caps.bes:\n                return CLEANUP_SANITIZE_BES\n            if caps.wzs:\n                return CLEANUP_ZERO_WZ\n            return CLEANUP_ZERO_SHRED\n\n        case (\"auto\", \"crypto\") | (\"sanitize\", \"crypto\"):\n            return CLEANUP_SANITIZE_CES if caps.ces else None\n\n        case (\"auto\", \"block\"):\n            if caps.bes:\n                return CLEANUP_SANITIZE_BES\n            if caps.wzs:\n                return CLEANUP_ZERO_WZ\n            return CLEANUP_ZERO_SHRED\n\n        case (\"sanitize\", \"auto\"):\n            if caps.ces:\n                return CLEANUP_SANITIZE_CES\n            if caps.bes:\n                return CLEANUP_SANITIZE_BES\n            return None\n\n        case (\"sanitize\", \"block\"):\n            return CLEANUP_SANITIZE_BES if caps.bes else None\n\n        case (\"zero\", _):\n            return CLEANUP_ZERO_WZ if caps.wzs else CLEANUP_ZERO_SHRED\n\n        case _:\n            return None\n```","commit_id":"21392bef2b7b8ca0fd9cbd54abd0400a504514e9"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"2fb89a7c17696125a492fa02f43e4c5b5c95dfd4","unresolved":true,"context_lines":[{"line_number":221,"context_line":"            return CLEANUP_ZERO_WZ if caps[\u0027wzs\u0027] else CLEANUP_ZERO_SHRED"},{"line_number":222,"context_line":""},{"line_number":223,"context_line":"        return None"},{"line_number":224,"context_line":""},{"line_number":225,"context_line":"    def _build_traits(self, caps):"},{"line_number":226,"context_line":"        traits \u003d [constants.OWNER_CYBORG]"},{"line_number":227,"context_line":"        if caps[\u0027ces\u0027]:"},{"line_number":228,"context_line":"            traits.append(TRAIT_HW_NVME_CES)"},{"line_number":229,"context_line":"        if caps[\u0027bes\u0027]:"},{"line_number":230,"context_line":"            traits.append(TRAIT_HW_NVME_BES)"},{"line_number":231,"context_line":"        if caps[\u0027wzs\u0027]:"},{"line_number":232,"context_line":"            traits.append(TRAIT_HW_NVME_WZS)"},{"line_number":233,"context_line":"        return traits"},{"line_number":234,"context_line":""},{"line_number":235,"context_line":"    def _init_placement_client(self):"},{"line_number":236,"context_line":"        return pc_module.PlacementClient()"}],"source_content_type":"text/x-python","patch_set":15,"id":"4f5c2623_29b276fc","line":233,"range":{"start_line":224,"start_character":1,"end_line":233,"end_character":21},"updated":"2026-08-18 14:24:14.000000000","message":"if we have the NvmeCapabilities dataclass we can provide a traits property that will return the relevant discovered traits.","commit_id":"21392bef2b7b8ca0fd9cbd54abd0400a504514e9"},{"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":"fa107de0a808d431f45e06d6152ec25c38d014f9","unresolved":false,"context_lines":[{"line_number":237,"context_line":""},{"line_number":238,"context_line":"    def _rp_exists_without_owner_cyborg(self, hostname, pci_addr):"},{"line_number":239,"context_line":"        \"\"\"Return True if an RP exists for this device but lacks OWNER_CYBORG.\"\"\""},{"line_number":240,"context_line":"        try:"},{"line_number":241,"context_line":"            client \u003d self._init_placement_client()"},{"line_number":242,"context_line":"            rp_name \u003d \u0027%s_%s\u0027 % (hostname, pci_addr)"},{"line_number":243,"context_line":"            encoded \u003d urllib.parse.quote(rp_name, safe\u003d\u0027\u0027)"}],"source_content_type":"text/x-python","patch_set":15,"id":"9f79f7a0_b5340523","line":240,"updated":"2026-08-18 06:10:09.000000000","message":"_rp_exists_without_owner_cyborg() calls _init_placement_client(), which constructs a brand-new PlacementClient (a fresh openstacksdk connection.Connection with keystone session/adapter) for every NVMe device on every discover() run, and issues two synchronous GETs (provider lookup + traits). discover() is invoked from AgentManager.init_host and again from ResourceTracker.update_usage, which is registered with run_immediately\u003dTrue and re-runs every CONF.periodic_interval, so cost scales as (number of NVMe devices) x (2 HTTP round trips + keystone adapter construction) per cycle, forever, even when nothing changed.\n\n**Severity**: WARNING | **Confidence**: 0.85\n\n**Impact**: Each periodic tick performs repeated keystone session/adapter setup and 2N HTTP round trips to Placement, adding load to keystone and placement and delaying the agent\u0027s periodic task thread; on hosts with many NVMe devices this grows linearly with device count.\n\n**Suggestion**:\nCreate the PlacementClient once (e.g., in init_host or lazily memoized on the driver) and cache the OWNER_CYBORG ownership verdict per device/RP uuid, invalidating only when a device disappears or the check changes; the conductor re-asserts traits on report anyway, so a cached affirmative check is sufficient.","commit_id":"21392bef2b7b8ca0fd9cbd54abd0400a504514e9"}],"cyborg/agent/manager.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":"a016e687c14f6fcd7f4553653bf46cf1135eab29","unresolved":false,"context_lines":[{"line_number":97,"context_line":"        self.image_api \u003d ImageAPI()"},{"line_number":98,"context_line":"        self._rt \u003d ResourceTracker(self.resource_provider_name, self.cond_api)"},{"line_number":99,"context_line":""},{"line_number":100,"context_line":"    def init_host(self):"},{"line_number":101,"context_line":"        \"\"\"Hook called by RPCService.start() after the RPC server is up.\"\"\""},{"line_number":102,"context_line":"        self._rt.init_drivers()"},{"line_number":103,"context_line":"        all_devices \u003d self._rt.discover_all()"}],"source_content_type":"text/x-python","patch_set":12,"id":"a8e2b008_50560c96","line":100,"updated":"2026-08-14 15:33:02.000000000","message":"AgentManager.init_host() now calls init_drivers(), which propagates driver exceptions (e.g. InvalidConfiguration when nvme-cli is missing, per the new resource_tracker test test_init_drivers_propagates_exception). RPCService.start() hooks do not retry, so an agent missing nvme-cli enters a restar...\n\n**Severity**: HIGH | **Confidence**: 0.8\n\n**Risk**: On a host where the NVMe driver is enabled but nvme-cli is not installed (a common ordering gap during upgrades, acknowledged in the release note), the cyborg-agent crashes at startup, loops, and stops reporting all accelerator resources - not just NVMe - to conductor and Placement.\n\n**Priority**: Before merge\n**Why This Matters**: On a host where the NVMe driver is enabled but nvme-cli is not installed (a common ordering gap during upgrades, acknowledged in the release note), the cyborg-agent crashes at startup, loops, and stops reporting all accelerator resources - not just NVMe - to conductor and Placement.\n\n**Recommendation**:\nCatch per-driver exceptions in ResourceTracker.init_drivers(), LOG.exception and disable/skip that driver (matching how _initialize_drivers already tolerates unusable drivers), so one driver\u0027s missing prerequisite does not take down the whole agent; alternatively gate NVMeDriver loading on [nvme] device_spec being configured.","commit_id":"d0ed397ba88c229ca4f0746f113bb90851a0fd88"},{"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":"19e50c2ab65bf3fdd8d4ea6a48c4b521a24738f2","unresolved":false,"context_lines":[{"line_number":99,"context_line":""},{"line_number":100,"context_line":"    def init_host(self):"},{"line_number":101,"context_line":"        \"\"\"Hook called by RPCService.start() after the RPC server is up.\"\"\""},{"line_number":102,"context_line":"        self._rt.init_drivers()"},{"line_number":103,"context_line":"        all_devices \u003d self._rt.discover_all()"},{"line_number":104,"context_line":"        self._rt.check_duplicate_devices(all_devices)"},{"line_number":105,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"6ff92991_1031c725","line":102,"updated":"2026-08-17 08:04:31.000000000","message":"AgentManager.init_host() calls discover_all() but throws away the result, and update_usage is a periodic task with run_immediately\u003dTrue that re-runs discover() for every driver on the next beat, so the full NVMe discovery (sysfs scan, nvme id-ctrl subprocess per device, Placement REST checks) exe...\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: Each agent start runs the NVMe scan twice (subprocess nvme-cli per device plus two Placement REST calls per device), doubling startup latency and load; the design goal stated in the commit is not achieved.\n\n**Suggestion**:\nHave ResourceTracker cache the discover_all() result and have update_usage reuse/refresh it, or drop the discover_all() call from init_host and keep only init_drivers() plus the duplicate check driven from the periodic discovery.","commit_id":"44357c4f41a5b3695bf1f108cdfc11b2fab58f80"},{"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":"3418d49831337f801111a459f1da7af81f3f2a78","unresolved":false,"context_lines":[{"line_number":100,"context_line":"    def init_host(self):"},{"line_number":101,"context_line":"        \"\"\"Hook called by RPCService.start() after the RPC server is up.\"\"\""},{"line_number":102,"context_line":"        self._rt.init_drivers()"},{"line_number":103,"context_line":"        all_devices \u003d self._rt.discover_all()"},{"line_number":104,"context_line":"        self._rt.check_duplicate_devices(all_devices)"},{"line_number":105,"context_line":""},{"line_number":106,"context_line":"    def _get_resource_provider_name(self):"}],"source_content_type":"text/x-python","patch_set":21,"id":"5bc96a89_15325ee6","line":103,"updated":"2026-09-04 05:23:53.000000000","message":"AgentManager.init_host() calls self._rt.discover_all(), whose dict comprehension invokes drv.discover() on every driver with no exception isolation. Any driver whose discover() raises propagates out of init_host() and fails the whole agent RPC service, so no driver on the host reports resources. This contradicts the failure policy the same series established: update_usage() wraps each acc_driver.discover() in try/except Exception with the comment \u0027One bad driver must not silence the rest\u0027, and the prior change message (999937, supplied in review context) states discover() failures are caught per driver so a misconfigured NVMe entry cannot silence GPU or FPGA reporting. The run_immediately\u003dTrue periodic update_available_resource() executes the same discover() calls with tolerant handling seconds later, so startup is strictly stricter than steady state for the identical failure class.\n\n**Severity**: HIGH | **Confidence**: 0.75\n\n**Impact**: On a host where any single enabled driver\u0027s discover() raises at startup, the agent process fails to start entirely: the periodic update_available_resource never runs, so healthy GPU/FPGA/other drivers report nothing to the conductor and Placement, and accelerator operations are unavailable. This is the exact silent-failure scenario the series set out to prevent, now made worse (whole agent down instead of one driver skipped).\n\n**Priority**: Before merge\n**Recommendation**:\nIn discover_all() (or at the manager call site), wrap each drv.discover() in try/except Exception, log the failure with the driver name, and record an empty device list for that driver so the duplicate check still covers the remaining drivers. Keep init_drivers() failures fail-fast as the commit intends; that is a separate explicit decision covered by test_init_drivers_propagates_exception.","commit_id":"3a60e0fb34f6336a527c0c57b015c08e2fd5a849"}],"cyborg/agent/resource_tracker.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":"314095d6a6a7b3672f6d2c2ee4a2c498d9737177","unresolved":false,"context_lines":[{"line_number":72,"context_line":"            LOG.info(\u0027Calling init_host() for driver %s\u0027, name)"},{"line_number":73,"context_line":"            drv.init_host()"},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"    def check_duplicate_devices(self):"},{"line_number":76,"context_line":"        seen \u003d {}"},{"line_number":77,"context_line":"        for name, drv in self.acc_drivers.items():"},{"line_number":78,"context_line":"            devices \u003d drv.discover()"}],"source_content_type":"text/x-python","patch_set":6,"id":"699fd661_2872e8ce","line":75,"updated":"2026-08-07 16:26:37.000000000","message":"ResourceTracker.check_duplicate_devices() (new in this patch) calls drv.discover() on every loaded driver. ResourceTracker.update_usage() also calls drv.discover(). For NVMeDriver, discover() invokes nvme-cli subprocesses (resolve_nvme_dev_from_pci and nvme_id_ctrl) for each device. At agent star...\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: On hosts with multiple NVMe devices, startup latency doubles due to redundant nvme-cli invocations. Each subprocess call runs under sys_admin privsep context, adding overhead. While not a correctness bug, this is wasteful for a production service startup path.\n\n**Suggestion**:\nConsider caching the discover() results from check_duplicate_devices() and reusing them for the initial update_usage() call, or moving the duplicate check to operate on cached device data rather than calling discover() again.","commit_id":"de95d37c8b7853605419d0930962b42e7c6fb9cc"},{"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":"f26c2dd98eaebbeec53a85fff33719bae590e348","unresolved":false,"context_lines":[{"line_number":67,"context_line":"            acc_drivers[d] \u003d acc_driver"},{"line_number":68,"context_line":"        self.acc_drivers \u003d acc_drivers"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"    def init_drivers(self):"},{"line_number":71,"context_line":"        for name, drv in self.acc_drivers.items():"},{"line_number":72,"context_line":"            LOG.info(\u0027Calling init_host() for driver %s\u0027, name)"},{"line_number":73,"context_line":"            drv.init_host()"}],"source_content_type":"text/x-python","patch_set":9,"id":"5a9f9ae3_0c38c3b2","line":70,"updated":"2026-08-11 15:21:10.000000000","message":"init_drivers() iterates all enabled drivers calling init_host() without isolating per-driver failures. If the NVMe driver\u0027s init_host() raises InvalidConfiguration (e.g. nvme-cli not installed), the exception propagates up through init_host() and prevents the agent from starting even for non-NVMe...\n\n**Severity**: HIGH | **Confidence**: 0.8\n\n**Risk**: If any single driver fails init_host() (e.g. nvme-cli missing on a host that also has GPUs), the entire cyborg-agent service will fail to start, blocking all accelerator management for that host.\n\n**Priority**: Before merge\n**Why This Matters**: If any single driver fails init_host() (e.g. nvme-cli missing on a host that also has GPUs), the entire cyborg-agent service will fail to start, blocking all accelerator management for that host.\n\n**Recommendation**:\nWrap each driver\u0027s init_host() call in a try/except that logs the error and either skips the failed driver or marks it as unavailable, allowing other drivers to proceed. Consider whether a failed driver should be removed from acc_drivers before discover_all() runs.","commit_id":"0ece3d90c95e271c9875fb6bb92b80e60d738c22"},{"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":"4f5928fba5956a476cc5b4dce5c92856ec34acd5","unresolved":false,"context_lines":[{"line_number":71,"context_line":"        \"\"\"Run driver startup hooks before the first discovery pass.\"\"\""},{"line_number":72,"context_line":"        for name, acc_driver in self.acc_drivers.items():"},{"line_number":73,"context_line":"            LOG.info(\u0027Calling init_host() for driver %s\u0027, name)"},{"line_number":74,"context_line":"            acc_driver.init_host()"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"    def discover_all(self):"},{"line_number":77,"context_line":"        \"\"\"Return one discovery snapshot keyed by driver name.\"\"\""}],"source_content_type":"text/x-python","patch_set":16,"id":"6da18d0c_7fcfc754","line":74,"updated":"2026-08-21 11:45:14.000000000","message":"ResourceTracker.init_drivers() calls acc_driver.init_host() unconditionally. Only GenericDriver subclasses (fake_driver, nvme_driver, huawei_ascend_driver) and PciDriver (pci_driver) define init_host; the other eight documented drivers do not, so AgentManager.init_host() crashes with AttributeError during agent startup.\n\n**Severity**: HIGH | **Confidence**: 0.92\n\n**Impact**: Any deployment enabling one of the eight documented drivers lacking init_host fails agent startup with an unhandled AttributeError before the agent can serve, instead of starting normally or failing with a clean configuration error.\n\n**Priority**: Before merge\n**Recommendation**:\nRestore the tolerant lookup in init_drivers() (init_host \u003d getattr(acc_driver, \u0027init_host\u0027, None); if callable(init_host): init_host()), or add no-op init_host() stubs to GPUDriver, FPGADriver, NICDriver, QATDriver, SSDDriver, and SPDKDRIVER so every entry-point driver satisfies the new contract.","commit_id":"1cce5d939d252144a2fb283b3e88a425b6145a6c"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"699dd8554233f717db18187ed0439aad18aeb083","unresolved":false,"context_lines":[{"line_number":71,"context_line":"        \"\"\"Run driver startup hooks before the first discovery pass.\"\"\""},{"line_number":72,"context_line":"        for name, acc_driver in self.acc_drivers.items():"},{"line_number":73,"context_line":"            LOG.info(\u0027Calling init_host() for driver %s\u0027, name)"},{"line_number":74,"context_line":"            acc_driver.init_host()"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"    def discover_all(self):"},{"line_number":77,"context_line":"        \"\"\"Return one discovery snapshot keyed by driver name.\"\"\""}],"source_content_type":"text/x-python","patch_set":16,"id":"97ad9cc1_8dcf6be9","line":74,"in_reply_to":"1e2a400f_69c393f4","updated":"2026-09-03 01:30:26.000000000","message":"Done","commit_id":"1cce5d939d252144a2fb283b3e88a425b6145a6c"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"90919a147e8af454e51c571cacac2870bb6493a3","unresolved":true,"context_lines":[{"line_number":71,"context_line":"        \"\"\"Run driver startup hooks before the first discovery pass.\"\"\""},{"line_number":72,"context_line":"        for name, acc_driver in self.acc_drivers.items():"},{"line_number":73,"context_line":"            LOG.info(\u0027Calling init_host() for driver %s\u0027, name)"},{"line_number":74,"context_line":"            acc_driver.init_host()"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"    def discover_all(self):"},{"line_number":77,"context_line":"        \"\"\"Return one discovery snapshot keyed by driver name.\"\"\""}],"source_content_type":"text/x-python","patch_set":16,"id":"1e2a400f_69c393f4","line":74,"in_reply_to":"6da18d0c_7fcfc754","updated":"2026-08-21 17:30:52.000000000","message":"yep we need to fix this\n\nwe should add init_host() to all the direver in \nhttps://review.opendev.org/c/openstack/cyborg/+/999935/14","commit_id":"1cce5d939d252144a2fb283b3e88a425b6145a6c"},{"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":"40c3ac09ed57c4cfddb81e96227a893810649ab0","unresolved":false,"context_lines":[{"line_number":89,"context_line":"        )"},{"line_number":90,"context_line":"        for driver_name, dev in pairs:"},{"line_number":91,"context_line":"            cpid \u003d dev.controlpath_id.cpid_info"},{"line_number":92,"context_line":"            addr \u003d jsonutils.loads(cpid).get(\u0027address\u0027, cpid)"},{"line_number":93,"context_line":"            if addr in seen:"},{"line_number":94,"context_line":"                raise exception.InvalidConfiguration("},{"line_number":95,"context_line":"                    reason\u003d\u0027Device %s claimed by both %s and %s\u0027"}],"source_content_type":"text/x-python","patch_set":17,"id":"40bfe469_fa31ca40","line":92,"updated":"2026-08-24 15:36:21.000000000","message":"jsonutils.loads(cpid).get(\u0027address\u0027, cpid) never finds an \u0027address\u0027 key: every in-tree driver builds cpid_info via utils.pci_str_to_json with domain/bus/device/function keys (or a hand-written equivalent), and none serialize an \u0027address\u0027 key. The lookup therefore always falls back to the raw cpid string, so the check compares full JSON serializations instead of PCI addresses. Devices with the same address serialized differently are not flagged as duplicates, contradicting the commit\u0027s stated goal of preventing silent double-reporting to Placement. The cpid fallback also implies plain-string cpid_info was meant to be tolerated, but jsonutils.loads raises an uncaught ValueError on non-JSON before that fallback is reachable.\n\n**Severity**: WARNING | **Confidence**: 0.85\n\n**Impact**: The new startup guard silently misses duplicate device claims whenever two drivers serialize the same PCI address differently (key order, spacing, or extra keys such as physical_network), letting both report the device to Placement - the exact outcome the change claims to prevent. When the check does trigger, the operator-facing InvalidConfiguration message prints a raw JSON blob instead of the PCI address. A non-JSON cpid_info from a third-party stevedore driver would crash agent startup with a raw ValueError rather than a configuration error.\n\n**Suggestion**:\nParse the cpid JSON and build the comparison key from its domain/bus/device/function values (e.g. \u0027%(domain)s:%(bus)s:%(device)s.%(function)s\u0027) or compare the parsed dicts, so key order, spacing, or extra fields cannot mask a duplicate. Use the reconstructed address in the error message, and guard jsonutils.loads (or restrict comparison to cpid_type \u003d\u003d \u0027PCI\u0027) so non-JSON cpid_info degrades gracefully instead of raising ValueError. Extend the tests: the current test_duplicate_device_raises builds both devices with _make_dev/pci_str_to_json, producing byte-identical strings, so it passes even with the broken lookup; add a case where the two drivers serialize the same address differently and assert it still raises.","commit_id":"3d733f656d9ba02cc7500eb23889212a0e1a9bb5"},{"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":"7ffe8ba949db25f182bc4cc70c3dd82101817ae2","unresolved":false,"context_lines":[{"line_number":48,"context_line":"    def _initialize_drivers(self, enabled_drivers\u003dNone):"},{"line_number":49,"context_line":"        \"\"\"Load accelerator drivers; does not call init_host()."},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"        :return: {\u0027nvidia_gpu_driver\u0027: obj, \u0027intel_fpga_driver\u0027: obj}"},{"line_number":52,"context_line":"        \"\"\""},{"line_number":53,"context_line":"        acc_drivers \u003d {}"},{"line_number":54,"context_line":"        if not enabled_drivers:"}],"source_content_type":"text/x-python","patch_set":18,"id":"ce71e354_8cd4a89a","line":51,"updated":"2026-08-31 10:51:31.000000000","message":"The rewritten docstring says \u0027:return: {\\\u0027nvidia_gpu_driver\\\u0027: obj, \\\u0027intel_fpga_driver\\\u0027: obj}\u0027, but the method assigns the dict to self.acc_drivers and returns None. The shape documentation is useful, but the :return: tag misleads callers into expecting a value.\n\n**Severity**: SUGGESTION | **Confidence**: 0.9\n\n**Impact**: Minor contributor confusion: future edits may assume the method returns the driver map, or preserve the false contract during refactoring.\n\n**Recommendation**:\nReplace the \u0027:return:\u0027 tag with an attribute-oriented description, e.g. \u0027:returns: None; populates self.acc_drivers as {driver_name: driver_obj}.","commit_id":"9f7e3f874effe00a05c1d651b91454294f377178"},{"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":"3418d49831337f801111a459f1da7af81f3f2a78","unresolved":false,"context_lines":[{"line_number":89,"context_line":"        )"},{"line_number":90,"context_line":"        for driver_name, dev in pairs:"},{"line_number":91,"context_line":"            cpid \u003d dev.controlpath_id.cpid_info"},{"line_number":92,"context_line":"            addr \u003d jsonutils.loads(cpid).get(\u0027address\u0027, cpid)"},{"line_number":93,"context_line":"            if addr in seen:"},{"line_number":94,"context_line":"                raise exception.InvalidConfiguration("},{"line_number":95,"context_line":"                    reason\u003d\u0027Device %s claimed by both %s and %s\u0027"}],"source_content_type":"text/x-python","patch_set":21,"id":"c25887ce_5fa55954","line":92,"updated":"2026-09-04 05:23:53.000000000","message":"check_duplicate_devices() computes addr \u003d jsonutils.loads(cpid).get(\u0027address\u0027, cpid), but no in-tree driver ever emits an \u0027address\u0027 key: every PCI driver builds cpid_info with utils.pci_str_to_json(), which produces only {bus, device, domain, function} (+ optional physical_network). The .get(\u0027address\u0027, ...) branch is therefore dead for all shipped drivers and comparison always falls back to the full JSON string. Duplicate detection works today only because pci_str_to_json() is deterministic and universally used; any driver serialising the same address differently (different key order, extra keys, or the \u0027address\u0027 key this code anticipates) silently bypasses the check, defeating the commit\u0027s stated goal of preventing double-reporting to Placement. The code also crashes on the format its fallback anticipates: non-JSON cpid_info raises ValueError from jsonutils.loads() and aborts agent startup, and a JSON-encoded string would raise AttributeError on .get(). The InvalidConfiguration message prints the whole JSON blob as the device address.\n\n**Severity**: WARNING | **Confidence**: 0.85\n\n**Impact**: The advertised duplicate-device guard is enforced on JSON-string identity, not PCI address. It works only by accident of uniform serialisation; the next driver that formats cpid_info differently (including one using the \u0027address\u0027 key this code explicitly anticipates, or pci_str_to_json\u0027s physnet variant) reintroduces silent double-reporting to Placement. A non-JSON cpid_info from an out-of-tree driver crashes agent startup with a ValueError traceback instead of a clear InvalidConfiguration, and error messages print a JSON blob instead of an address.\n\n**Suggestion**:\nNormalise before comparing: parse cpid_info once, and for CPID_TYPE_PCI build a canonical key from the parsed fields, e.g. info \u003d jsonutils.loads(cpid); key \u003d (info.get(\u0027domain\u0027), info.get(\u0027bus\u0027), info.get(\u0027device\u0027), info.get(\u0027function\u0027)) if isinstance(info, dict) else cpid, compare that key, and format a readable BDF in the InvalidConfiguration message. Add a unit test where two drivers report the same address with different serialisations (e.g. one with an \u0027address\u0027 key) to lock in the semantics.","commit_id":"3a60e0fb34f6336a527c0c57b015c08e2fd5a849"},{"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":"5fdf56e722c0e0edd9556b002ca6d6a465a363bc","unresolved":false,"context_lines":[{"line_number":48,"context_line":"    def _initialize_drivers(self, enabled_drivers\u003dNone):"},{"line_number":49,"context_line":"        \"\"\"Load accelerator drivers; does not call init_host()."},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"        :return: {\u0027nvidia_gpu_driver\u0027: obj, \u0027intel_fpga_driver\u0027: obj}"},{"line_number":52,"context_line":"        \"\"\""},{"line_number":53,"context_line":"        acc_drivers \u003d {}"},{"line_number":54,"context_line":"        if not enabled_drivers:"}],"source_content_type":"text/x-python","patch_set":24,"id":"1544cf6a_df14ac47","line":51,"updated":"2026-09-04 15:08:00.000000000","message":"The rewritten docstring says \u0027:return: {\\\u0027nvidia_gpu_driver\\\u0027: obj, \\\u0027intel_fpga_driver\\\u0027: obj}\u0027, but _initialize_drivers() returns None; it stores the dict on self.acc_drivers. Callers reading the docstring (and the updated fake tests that mock this layer) may expect a returned mapping that will always be None.\n\n**Severity**: SUGGESTION | **Confidence**: 0.9\n\n**Impact**: Low: a caller or contributor relying on the documented return value gets None; the docstring hides that the result is only available via the self.acc_drivers attribute the rest of the class reads.\n\n**Recommendation**:\nReplace the \u0027:return:\u0027 field with \u0027:returns: None; the loaded drivers are stored on self.acc_drivers as a dict keyed by driver name.\u0027 or actually return the dict and keep self-assignment at the call site - the docstring fix is the smaller change.","commit_id":"0805158f40919b872b1cb1b32d1a21859192d449"},{"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":"5fdf56e722c0e0edd9556b002ca6d6a465a363bc","unresolved":false,"context_lines":[{"line_number":89,"context_line":"        )"},{"line_number":90,"context_line":"        for driver_name, dev in pairs:"},{"line_number":91,"context_line":"            cpid \u003d dev.controlpath_id.cpid_info"},{"line_number":92,"context_line":"            addr \u003d jsonutils.loads(cpid).get(\u0027address\u0027, cpid)"},{"line_number":93,"context_line":"            if addr in seen:"},{"line_number":94,"context_line":"                raise exception.InvalidConfiguration("},{"line_number":95,"context_line":"                    reason\u003d\u0027Device %s claimed by both %s and %s\u0027"}],"source_content_type":"text/x-python","patch_set":24,"id":"0bb7b228_dfb55017","line":92,"updated":"2026-09-04 15:08:00.000000000","message":"The new guard does addr \u003d jsonutils.loads(cpid).get(\u0027address\u0027, cpid), but no in-tree driver writes an \u0027address\u0027 key into cpid_info. Every producer uses acc_utils.pci_str_to_json(), which emits keys bus/device/domain/function (sorted, spaced JSON), and the in-tree FakeDriver hard-codes a different serialization: \u0027{\"domain\":\"0000\",\"bus\":\"0c\",\"device\":\"00\",\"function\":\"0\"}\u0027. So .get(\u0027address\u0027, cpid) always falls back to the whole JSON string, and duplicate detection only fires when two drivers serialize the same address byte-identically. Same address, different serialization (fake_driver alongside a real driver, or any driver that adds physical_network via pci_str_to_json\u0027s physnet parameter) passes the check, and the InvalidConfiguration reason then prints a raw JSON blob instead of an address. Additionally, the cpid fallback is unreachable for non-JSON cpid_info because jsonutils.loads would raise ValueError first.\n\n**Severity**: WARNING | **Confidence**: 0.85\n\n**Impact**: For driver combinations that serialize cpid_info differently (e.g. the enabled-by-entry-point fake_driver claiming 0000:0c:00.0 next to a real QAT/FPGA/NVMe driver reporting the same BDF), a genuine duplicate passes the check and both reports still flow to Placement every update_usage cycle - the exact silent double-reporting the commit says it prevents. Error messages, when they do fire, show a JSON blob instead of the PCI address, hampering operators.\n\n**Suggestion**:\nParse the JSON and reconstruct the canonical BDF for comparison, e.g. `info \u003d jsonutils.loads(cpid); addr \u003d \u0027%(domain)s:%(bus)s:%(device)s.%(function)s\u0027 % info` (guarding for a missing/invalid JSON cpid_info so the fallback or a clear error is actually reachable). That makes the comparison serialization-independent and produces a readable address in the InvalidConfiguration reason. Add a unit test where two drivers report the same address with different cpid_info serializations.","commit_id":"0805158f40919b872b1cb1b32d1a21859192d449"}],"cyborg/conductor/manager.py":[{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"38c215fa903fca02d31e697ca060b4188d74ad03","unresolved":false,"context_lines":[{"line_number":243,"context_line":"                cpid_info \u003d new_driver_dev_obj.controlpath_id.cpid_info"},{"line_number":244,"context_line":"                dev_obj \u003d self._find_device_by_cpid(context, host, cpid_info)"},{"line_number":245,"context_line":"                if dev_obj is not None and dev_obj.device_state is None:"},{"line_number":246,"context_line":"                    dev_obj.device_state \u003d constants.DEVICE_STATE_AVAILABLE"},{"line_number":247,"context_line":"                    dev_obj.save(context)"},{"line_number":248,"context_line":"        for s in same:"},{"line_number":249,"context_line":"            # get the driver_dev_obj, diff the driver_device layer"}],"source_content_type":"text/x-python","patch_set":6,"id":"c63663d6_e027295c","line":246,"updated":"2026-08-07 17:19:25.000000000","message":"pep8: F821 Undefined name `constants`","commit_id":"de95d37c8b7853605419d0930962b42e7c6fb9cc"},{"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":"314095d6a6a7b3672f6d2c2ee4a2c498d9737177","unresolved":false,"context_lines":[{"line_number":550,"context_line":"                    break"},{"line_number":551,"context_line":""},{"line_number":552,"context_line":""},{"line_number":553,"context_line":"_NVME_CLEANUP_LOCKED_STATES \u003d frozenset(["},{"line_number":554,"context_line":"    constants.DEVICE_STATE_ALLOCATED,"},{"line_number":555,"context_line":"    constants.DEVICE_STATE_PENDING_CLEANING,"},{"line_number":556,"context_line":"    constants.DEVICE_STATE_CLEANING,"}],"source_content_type":"text/x-python","patch_set":6,"id":"b9d032a0_5a6fc275","line":553,"updated":"2026-08-07 16:26:37.000000000","message":"The patch adds references to constants.DEVICE_STATE_AVAILABLE (line 246) and constants.DEVICE_STATE_ALLOCATED/PENDING_CLEANING/CLEANING (lines 554-556) in conductor/manager.py, but never imports the constants module. The _NVME_CLEANUP_LOCKED_STATES frozenset is evaluated at module import time, so...\n\n**Severity**: CRITICAL | **Confidence**: 1.0\n\n**Risk**: The cyborg-conductor service will fail to start with an unhandled NameError. Additionally, any unit test that imports cyborg.conductor.manager will fail at collection time, potentially masking other test failures. This is a merge-blocking defect.\n\n**Priority**: Immediate\n**Why This Matters**: The cyborg-conductor service will fail to start with an unhandled NameError. Additionally, any unit test that imports cyborg.conductor.manager will fail at collection time, potentially masking other test failures. This is a merge-blocking defect.\n\n**Recommendation**:\nAdd \u0027from cyborg.common import constants\u0027 to the import block in cyborg/conductor/manager.py, alongside the existing \u0027from cyborg.common import data_migrations\u0027 and \u0027from cyborg.common import exception\u0027 imports.","commit_id":"de95d37c8b7853605419d0930962b42e7c6fb9cc"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"38c215fa903fca02d31e697ca060b4188d74ad03","unresolved":false,"context_lines":[{"line_number":551,"context_line":""},{"line_number":552,"context_line":""},{"line_number":553,"context_line":"_NVME_CLEANUP_LOCKED_STATES \u003d frozenset(["},{"line_number":554,"context_line":"    constants.DEVICE_STATE_ALLOCATED,"},{"line_number":555,"context_line":"    constants.DEVICE_STATE_PENDING_CLEANING,"},{"line_number":556,"context_line":"    constants.DEVICE_STATE_CLEANING,"},{"line_number":557,"context_line":"])"}],"source_content_type":"text/x-python","patch_set":6,"id":"fa52e5c2_f7da7998","line":554,"updated":"2026-08-07 17:19:25.000000000","message":"pep8: F821 Undefined name `constants`","commit_id":"de95d37c8b7853605419d0930962b42e7c6fb9cc"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"38c215fa903fca02d31e697ca060b4188d74ad03","unresolved":false,"context_lines":[{"line_number":552,"context_line":""},{"line_number":553,"context_line":"_NVME_CLEANUP_LOCKED_STATES \u003d frozenset(["},{"line_number":554,"context_line":"    constants.DEVICE_STATE_ALLOCATED,"},{"line_number":555,"context_line":"    constants.DEVICE_STATE_PENDING_CLEANING,"},{"line_number":556,"context_line":"    constants.DEVICE_STATE_CLEANING,"},{"line_number":557,"context_line":"])"},{"line_number":558,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"d24b0d7b_8fd38c00","line":555,"updated":"2026-08-07 17:19:25.000000000","message":"pep8: F821 Undefined name `constants`","commit_id":"de95d37c8b7853605419d0930962b42e7c6fb9cc"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"38c215fa903fca02d31e697ca060b4188d74ad03","unresolved":false,"context_lines":[{"line_number":553,"context_line":"_NVME_CLEANUP_LOCKED_STATES \u003d frozenset(["},{"line_number":554,"context_line":"    constants.DEVICE_STATE_ALLOCATED,"},{"line_number":555,"context_line":"    constants.DEVICE_STATE_PENDING_CLEANING,"},{"line_number":556,"context_line":"    constants.DEVICE_STATE_CLEANING,"},{"line_number":557,"context_line":"])"},{"line_number":558,"context_line":""},{"line_number":559,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"9f2b8ae9_7cb2fe38","line":556,"updated":"2026-08-07 17:19:25.000000000","message":"pep8: F821 Undefined name `constants`","commit_id":"de95d37c8b7853605419d0930962b42e7c6fb9cc"},{"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":"269aadf8fb60e2ab2db41ef226e697c7c8a09408","unresolved":false,"context_lines":[{"line_number":275,"context_line":"                old_val \u003d getattr(old_driver_dev_obj, c_k)"},{"line_number":276,"context_line":"                if new_val \u003d\u003d old_val:"},{"line_number":277,"context_line":"                    continue"},{"line_number":278,"context_line":"                if c_k \u003d\u003d \u0027std_board_info\u0027 and dev_obj.type \u003d\u003d \u0027NVME\u0027:"},{"line_number":279,"context_line":"                    new_val \u003d _merge_nvme_board_info("},{"line_number":280,"context_line":"                        old_val, new_val, dev_obj.device_state"},{"line_number":281,"context_line":"                    )"}],"source_content_type":"text/x-python","patch_set":8,"id":"4b3491aa_6d5d8ba4","line":278,"updated":"2026-08-11 09:34:14.000000000","message":"The conductor manager uses a hardcoded string literal \u0027NVME\u0027 to check the device type before merging board info, despite the constants module defining DEVICE_NVME \u003d \u0027NVME\u0027 and the constants module already being imported in this file.\n\n**Severity**: SUGGESTION | **Confidence**: 0.9\n\n**Benefit**: If the DEVICE_NVME constant value ever changes or the string is mistyped, the merge logic silently fails to trigger, potentially overwriting cleanup_action during in-flight sanitize operations. Low probability but directly actionable.\n\n**Recommendation**:\nReplace \u0027NVME\u0027 with constants.DEVICE_NVME: `if c_k \u003d\u003d \u0027std_board_info\u0027 and dev_obj.type \u003d\u003d constants.DEVICE_NVME:`","commit_id":"025c61667ca956836966b60c97274d59276a0aa3"},{"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":"f26c2dd98eaebbeec53a85fff33719bae590e348","unresolved":false,"context_lines":[{"line_number":275,"context_line":"                old_val \u003d getattr(old_driver_dev_obj, c_k)"},{"line_number":276,"context_line":"                if new_val \u003d\u003d old_val:"},{"line_number":277,"context_line":"                    continue"},{"line_number":278,"context_line":"                if c_k \u003d\u003d \u0027std_board_info\u0027 and dev_obj.type \u003d\u003d \u0027NVME\u0027:"},{"line_number":279,"context_line":"                    new_val \u003d _merge_nvme_board_info("},{"line_number":280,"context_line":"                        old_val, new_val, dev_obj.device_state"},{"line_number":281,"context_line":"                    )"}],"source_content_type":"text/x-python","patch_set":9,"id":"913c4941_d44c80c4","line":278,"updated":"2026-08-11 15:21:10.000000000","message":"In drv_device_make_diff(), the NVMe board info merge condition uses a hardcoded string literal \u0027NVME\u0027 to compare against dev_obj.type, while the rest of the codebase consistently uses constants.DEVICE_NVME for this comparison.\n\n**Severity**: SUGGESTION | **Confidence**: 0.9\n\n**Benefit**: If DEVICE_NVME is ever renamed or the value changes, this comparison will silently break, causing the merge logic to be skipped for all NVMe devices.\n\n**Recommendation**:\nReplace \u0027NVME\u0027 with constants.DEVICE_NVME (constants is already imported in this file).","commit_id":"0ece3d90c95e271c9875fb6bb92b80e60d738c22"},{"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":"75490aa828304f0778f4426ab19da1bbe4cb5f6f","unresolved":false,"context_lines":[{"line_number":275,"context_line":"                old_val \u003d getattr(old_driver_dev_obj, c_k)"},{"line_number":276,"context_line":"                if new_val \u003d\u003d old_val:"},{"line_number":277,"context_line":"                    continue"},{"line_number":278,"context_line":"                if c_k \u003d\u003d \u0027std_board_info\u0027 and dev_obj.type \u003d\u003d \u0027NVME\u0027:"},{"line_number":279,"context_line":"                    new_val \u003d _merge_nvme_board_info("},{"line_number":280,"context_line":"                        old_val, new_val, dev_obj.device_state"},{"line_number":281,"context_line":"                    )"}],"source_content_type":"text/x-python","patch_set":11,"id":"c28f5aa6_df78be2e","line":278,"updated":"2026-08-13 04:59:07.000000000","message":"The _merge_nvme_board_info dispatch in drv_device_make_diff uses a hardcoded string \u0027NVME\u0027 for the device type check instead of the existing constants.DEVICE_NVME constant, which is already imported and used elsewhere in the same file.\n\n**Severity**: SUGGESTION | **Confidence**: 0.9\n\n**Benefit**: Minor maintainability risk: if the DEVICE_NVME constant value ever changes, this comparison would silently break. Using the constant is the established pattern in this file.\n\n**Recommendation**:\nReplace the hardcoded \u0027NVME\u0027 with constants.DEVICE_NVME for consistency with the rest of the file and the constants module.","commit_id":"2fb1b5b4e81d79f57ff110dc1b4926ab784c1f40"},{"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":"19e50c2ab65bf3fdd8d4ea6a48c4b521a24738f2","unresolved":false,"context_lines":[{"line_number":275,"context_line":"                old_val \u003d getattr(old_driver_dev_obj, c_k)"},{"line_number":276,"context_line":"                if new_val \u003d\u003d old_val:"},{"line_number":277,"context_line":"                    continue"},{"line_number":278,"context_line":"                if c_k \u003d\u003d \u0027std_board_info\u0027 and dev_obj.type \u003d\u003d \u0027NVME\u0027:"},{"line_number":279,"context_line":"                    new_val \u003d _merge_nvme_board_info("},{"line_number":280,"context_line":"                        old_val, new_val, dev_obj.device_state"},{"line_number":281,"context_line":"                    )"}],"source_content_type":"text/x-python","patch_set":14,"id":"d51e4c69_a583a04f","line":278,"updated":"2026-08-17 08:04:31.000000000","message":"The conductor merge branch compares dev_obj.type \u003d\u003d \u0027NVME\u0027 with a string literal although constants.DEVICE_NVME is already imported and used elsewhere in the same change.\n\n**Severity**: SUGGESTION | **Confidence**: 0.9\n\n**Benefit**: If the device-type literal ever changes or the constant is refactored, the merge guard silently stops applying and cleanup_action preservation for allocated/cleaning NVMe devices breaks.\n\n**Recommendation**:\nReplace the literal with constants.DEVICE_NVME for consistency with the rest of the patch.","commit_id":"44357c4f41a5b3695bf1f108cdfc11b2fab58f80"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"90919a147e8af454e51c571cacac2870bb6493a3","unresolved":true,"context_lines":[{"line_number":204,"context_line":"                    dev_obj \u003d new_driver_dev_obj.get_device_obj(context, host)"},{"line_number":205,"context_line":"                    if dev_obj is not None and dev_obj.device_state is None:"},{"line_number":206,"context_line":"                        dev_obj.device_state \u003d constants.DEVICE_STATE_AVAILABLE"},{"line_number":207,"context_line":"                        dev_obj.save(context)"},{"line_number":208,"context_line":"            except Exception as exc:"},{"line_number":209,"context_line":"                LOG.exception("},{"line_number":210,"context_line":"                    \"Failed to add device %(device)s. Reason: %(reason)s\","}],"source_content_type":"text/x-python","patch_set":16,"id":"7b3e6e19_d8e7fd49","side":"PARENT","line":207,"updated":"2026-08-21 17:30:52.000000000","message":"you intoduced this in an early patch just ot delete it agin in this one\n\nit shoudl not be here but this shoudl have been removed in the prior patch not fixed up in this one","commit_id":"794cc29348626347bba68690276afa3d26603c97"}],"cyborg/tests/unit/accelerator/drivers/nvme/test_driver.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":"6f6d87758d679a0776bac9db7b8314c6d03ded16","unresolved":false,"context_lines":[{"line_number":64,"context_line":"class TestNVMeDriverDiscover(base.TestCase):"},{"line_number":65,"context_line":"    @mock.patch.object(nvme_cli, \u0027nvme_id_ctrl\u0027)"},{"line_number":66,"context_line":"    @mock.patch.object(nvme_cli, \u0027resolve_nvme_dev_from_pci\u0027)"},{"line_number":67,"context_line":"    def test_single_device(self, mock_resolve, mock_id):"},{"line_number":68,"context_line":"        mock_resolve.return_value \u003d \u0027/dev/nvme0\u0027"},{"line_number":69,"context_line":"        mock_id.return_value \u003d {"},{"line_number":70,"context_line":"            \u0027sanicap\u0027: 3,"}],"source_content_type":"text/x-python","patch_set":7,"id":"a3070226_56a542c8","line":67,"updated":"2026-08-09 05:13:18.000000000","message":"test_single_device calls NVMeDriver(pci_sysfs_path\u003dtmp).discover() without mocking _rp_exists_without_owner_cyborg or PlacementClient. The test passes only because _rp_exists_without_owner_cyborg has a broad except Exception that returns False when the real PlacementClient cannot connect. This ma...\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: The test could behave differently depending on the CI/network environment. If PlacementClient is ever stubbed at a higher level, or if a network call somehow succeeds and returns unexpected data, the test may fail or pass for the wrong reason. The test may also add unnecessary latency due to conn...\n\n**Suggestion**:\nAdd @mock.patch.object(NVMeDriver, \u0027_rp_exists_without_owner_cyborg\u0027, return_value\u003dFalse) to test_single_device (and other discover tests that exercise the full flow) to explicitly control the Placement check outcome.","commit_id":"c1d148aa055ad4f431daff8a3111d2b59cdb0f0f"},{"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":"a016e687c14f6fcd7f4553653bf46cf1135eab29","unresolved":false,"context_lines":[{"line_number":54,"context_line":"        NVMeDriver().init_host()"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"    @mock.patch(\u0027shutil.which\u0027, return_value\u003dNone)"},{"line_number":57,"context_line":"    def test_raises(self, mock_which):"},{"line_number":58,"context_line":"        self.assertRaises("},{"line_number":59,"context_line":"            exception.InvalidConfiguration,"},{"line_number":60,"context_line":"            NVMeDriver().init_host,"}],"source_content_type":"text/x-python","patch_set":12,"id":"9ebca73b_4c448b67","line":57,"updated":"2026-08-14 15:33:02.000000000","message":"TestNVMeDriverInitHost only mocks shutil.which; the Placement trait-registration logic (404-then-PUT flow, non-201 raising InvalidConfiguration, soft-fail on unreachable Placement) has zero coverage.\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: Placement contract violations such as the CUSTOM_ prefix problem ship undetected; regressions in the soft-fail behavior would also go unnoticed.\n\n**Suggestion**:\nAdd tests with a mocked placement client covering: trait already exists (200), trait created (404 then PUT 201), PUT failure raising InvalidConfiguration, and transport error falling through to LOG.warning without raising.","commit_id":"d0ed397ba88c229ca4f0746f113bb90851a0fd88"}],"cyborg/tests/unit/agent/test_manager.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":"6f6d87758d679a0776bac9db7b8314c6d03ded16","unresolved":false,"context_lines":[{"line_number":232,"context_line":"            self._create_manager_with_mocks,"},{"line_number":233,"context_line":"        )"},{"line_number":234,"context_line":""},{"line_number":235,"context_line":"    def test_init_host_calls_rt(self):"},{"line_number":236,"context_line":"        self.placement_mock.get.return_value.json.return_value \u003d {"},{"line_number":237,"context_line":"            \u0027resource_providers\u0027: [{\u0027uuid\u0027: \u0027test-uuid\u0027}]"},{"line_number":238,"context_line":"        }"}],"source_content_type":"text/x-python","patch_set":7,"id":"6e6df934_4d3e2242","line":235,"updated":"2026-08-09 05:13:18.000000000","message":"AgentManager.init_host() calls three methods: init_drivers(), discover_all(), and check_duplicate_devices(all_devices). The test asserts init_drivers and check_duplicate_devices are called but does not verify discover_all() is called, leaving the middle step of the startup sequence unverified.\n\n**Severity**: SUGGESTION | **Confidence**: 0.9\n\n**Benefit**: If discover_all() is accidentally removed from init_host(), the test would still pass because check_duplicate_devices receives a Mock return value from the mocked _rt. The test does not guard against regression of the discover_all call.\n\n**Recommendation**:\nAdd am._rt.discover_all.assert_called_once() after the existing assertions in test_init_host_calls_rt.","commit_id":"c1d148aa055ad4f431daff8a3111d2b59cdb0f0f"}],"cyborg/tests/unit/agent/test_resource_tracker.py":[{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"699dd8554233f717db18187ed0439aad18aeb083","unresolved":true,"context_lines":[{"line_number":26,"context_line":""},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"def _make_dev(pci_address):"},{"line_number":29,"context_line":"    dev \u003d mock.Mock()"},{"line_number":30,"context_line":"    cpid \u003d mock.Mock()"},{"line_number":31,"context_line":"    cpid.cpid_info \u003d utils.pci_str_to_json(pci_address)"},{"line_number":32,"context_line":"    dev.controlpath_id \u003d cpid"}],"source_content_type":"text/x-python","patch_set":18,"id":"da7ac9d5_62382514","line":29,"range":{"start_line":29,"start_character":4,"end_line":29,"end_character":21},"updated":"2026-09-03 01:30:26.000000000","message":"this is really not correct\nyou shoudl be useing real ovo obejct in most if not all your tests\n\nusign mock like this is very erro prone and generally shoudl be avoided\n\natht eh very least when you do this you shoudl be useing auto spec\n\ni generally do not trust unit test that are written like this to actuly provide any testing value.","commit_id":"9f7e3f874effe00a05c1d651b91454294f377178"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"fb276797a1b0a8739629297dcc7a30e9c7617efd","unresolved":true,"context_lines":[{"line_number":26,"context_line":""},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"def _make_dev(pci_address):"},{"line_number":29,"context_line":"    dev \u003d mock.Mock()"},{"line_number":30,"context_line":"    cpid \u003d mock.Mock()"},{"line_number":31,"context_line":"    cpid.cpid_info \u003d utils.pci_str_to_json(pci_address)"},{"line_number":32,"context_line":"    dev.controlpath_id \u003d cpid"}],"source_content_type":"text/x-python","patch_set":18,"id":"6f5b3aa7_cadc8e9d","line":29,"range":{"start_line":29,"start_character":4,"end_line":29,"end_character":21},"in_reply_to":"21ca8126_58a4c356","updated":"2026-09-03 10:26:42.000000000","message":"yep\n\nbasicly we shoudl use real type where possibel and or use thing like the fake driver or build fakes/fixutre instead of bare mocks so this is much better.\n\n\nthe altherenitive was to sepcify the calss as  a spec to a mock so that the mock would raise on functions that dont exsits or that are called gith the wrong args.\n\nwhere its safe to do so using the real objects is generally better overall.\nit catches more issues over time","commit_id":"9f7e3f874effe00a05c1d651b91454294f377178"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"3fcadea21b8d84594bb6c3412d400cc4d9fe7193","unresolved":false,"context_lines":[{"line_number":26,"context_line":""},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"def _make_dev(pci_address):"},{"line_number":29,"context_line":"    dev \u003d mock.Mock()"},{"line_number":30,"context_line":"    cpid \u003d mock.Mock()"},{"line_number":31,"context_line":"    cpid.cpid_info \u003d utils.pci_str_to_json(pci_address)"},{"line_number":32,"context_line":"    dev.controlpath_id \u003d cpid"}],"source_content_type":"text/x-python","patch_set":18,"id":"00a4d255_f35d0b2e","line":29,"range":{"start_line":29,"start_character":4,"end_line":29,"end_character":21},"in_reply_to":"6f5b3aa7_cadc8e9d","updated":"2026-09-04 12:37:10.000000000","message":"Done","commit_id":"9f7e3f874effe00a05c1d651b91454294f377178"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"6685173bf4512895aee861a4ce9917b04ec204b2","unresolved":true,"context_lines":[{"line_number":26,"context_line":""},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"def _make_dev(pci_address):"},{"line_number":29,"context_line":"    dev \u003d mock.Mock()"},{"line_number":30,"context_line":"    cpid \u003d mock.Mock()"},{"line_number":31,"context_line":"    cpid.cpid_info \u003d utils.pci_str_to_json(pci_address)"},{"line_number":32,"context_line":"    dev.controlpath_id \u003d cpid"}],"source_content_type":"text/x-python","patch_set":18,"id":"21ca8126_58a4c356","line":29,"range":{"start_line":29,"start_character":4,"end_line":29,"end_character":21},"in_reply_to":"da7ac9d5_62382514","updated":"2026-09-03 09:53:57.000000000","message":"Good Catch.\n\nI have addded `make_fake_driver_device(pci_address)` to fake_driver_device.py.\n\nIt constructs a real DriverDevice with a real DriverControlPathID, using the existing fake device dict as the base and overriding only the controlpath_id for the given PCI address. \n\nI have also removed _make_dev and the bare mock.Mock() OVO construction in favor of make_fake_driver_device(pci_address).\n\nWith this the duplicate-detection tests now call fake_driver_device.make_fake_driver_device method directly.\n\nDoes this match what you had in mind or something else?","commit_id":"9f7e3f874effe00a05c1d651b91454294f377178"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"29d543018eb407c726f9b3488c7085d7f45402de","unresolved":true,"context_lines":[{"line_number":84,"context_line":"        )"},{"line_number":85,"context_line":""},{"line_number":86,"context_line":"    def test_init_drivers_calls_each(self):"},{"line_number":87,"context_line":"        drv1 \u003d mock.Mock()"},{"line_number":88,"context_line":"        drv2 \u003d mock.Mock()"},{"line_number":89,"context_line":"        self.rt.acc_drivers \u003d {\u0027a\u0027: drv1, \u0027b\u0027: drv2}"},{"line_number":90,"context_line":"        self.rt.init_drivers()"},{"line_number":91,"context_line":"        drv1.init_host.assert_called_once()"}],"source_content_type":"text/x-python","patch_set":19,"id":"c74ead76_9dc018d9","line":88,"range":{"start_line":87,"start_character":1,"end_line":88,"end_character":26},"updated":"2026-09-03 12:33:21.000000000","message":"nit: these should really be autospect mocs of the generic drvier or just instance of the generic/fake driver but tis fine for now","commit_id":"c19360c84c3d103d2a7bb96b394082076ae61326"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"ace87d9c7e2a536553dfa40485742e0fc40d8784","unresolved":false,"context_lines":[{"line_number":84,"context_line":"        )"},{"line_number":85,"context_line":""},{"line_number":86,"context_line":"    def test_init_drivers_calls_each(self):"},{"line_number":87,"context_line":"        drv1 \u003d mock.Mock()"},{"line_number":88,"context_line":"        drv2 \u003d mock.Mock()"},{"line_number":89,"context_line":"        self.rt.acc_drivers \u003d {\u0027a\u0027: drv1, \u0027b\u0027: drv2}"},{"line_number":90,"context_line":"        self.rt.init_drivers()"},{"line_number":91,"context_line":"        drv1.init_host.assert_called_once()"}],"source_content_type":"text/x-python","patch_set":19,"id":"92c2c526_693c3f20","line":88,"range":{"start_line":87,"start_character":1,"end_line":88,"end_character":26},"in_reply_to":"c74ead76_9dc018d9","updated":"2026-09-04 08:12:35.000000000","message":"Done","commit_id":"c19360c84c3d103d2a7bb96b394082076ae61326"}],"cyborg/tests/unit/conductor/test_manager.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":"314095d6a6a7b3672f6d2c2ee4a2c498d9737177","unresolved":false,"context_lines":[{"line_number":223,"context_line":"        self.cm.init_host()"},{"line_number":224,"context_line":"        mock_heal.assert_called_once()"},{"line_number":225,"context_line":""},{"line_number":226,"context_line":"    @mock.patch(\u0027cyborg.conductor.manager.ConductorManager._find_device_by_cpid\u0027)"},{"line_number":227,"context_line":"    @mock.patch(\u0027cyborg.conductor.manager.ConductorManager.drv_device_make_diff\u0027)"},{"line_number":228,"context_line":"    def test_new_nvme_device_initialized_as_available("},{"line_number":229,"context_line":"        self, mock_diff, mock_find_cpid"}],"source_content_type":"text/x-python","patch_set":6,"id":"6340a1df_bd3fdf9d","line":226,"updated":"2026-08-07 16:26:37.000000000","message":"The test named test_new_nvme_device_initialized_as_available mocks _find_device_by_cpid, then calls the mocked _find_device_by_cpid directly. It never invokes drv_device_make_diff, which is the method containing the actual device_state initialization logic (lines 243-247). The test only verifies...\n\n**Severity**: HIGH | **Confidence**: 0.9\n\n**Risk**: A reviewer seeing this test pass would believe the NVMe device-state initialization is verified. In reality, the critical logic that sets device_state to DEVICE_STATE_AVAILABLE for newly discovered NVMe devices is untested and could silently break.\n\n**Priority**: Before merge\n**Why This Matters**: A reviewer seeing this test pass would believe the NVMe device-state initialization is verified. In reality, the critical logic that sets device_state to DEVICE_STATE_AVAILABLE for newly discovered NVMe devices is untested and could silently break.\n\n**Recommendation**:\nRewrite the test to call drv_device_make_diff with appropriate fake driver device objects, and assert that the resulting dev_obj.device_state equals constants.DEVICE_STATE_AVAILABLE and that dev_obj.save() was called. Do not mock _find_device_by_cpid; instead mock Device.get_list_by_hostname and ControlpathID.get_by_device_id_cpidinfo to return the needed objects.","commit_id":"de95d37c8b7853605419d0930962b42e7c6fb9cc"},{"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":"314095d6a6a7b3672f6d2c2ee4a2c498d9737177","unresolved":false,"context_lines":[{"line_number":249,"context_line":"        old \u003d \u0027{\"cleanup_action\": \"sanitize_ces\", \"nvme_dev\": \"/dev/nvme0\"}\u0027"},{"line_number":250,"context_line":"        new \u003d \u0027{\"cleanup_action\": \"zero_wz\", \"nvme_dev\": \"/dev/nvme0\"}\u0027"},{"line_number":251,"context_line":"        result \u003d self._merge(old, new, \u0027allocated\u0027)"},{"line_number":252,"context_line":"        import json"},{"line_number":253,"context_line":"        self.assertEqual(\u0027sanitize_ces\u0027, json.loads(result)[\u0027cleanup_action\u0027])"},{"line_number":254,"context_line":""},{"line_number":255,"context_line":"    def test_preserves_action_in_pending_cleaning(self):"}],"source_content_type":"text/x-python","patch_set":6,"id":"803fceb4_c30d5245","line":252,"updated":"2026-08-07 16:26:37.000000000","message":"The TestMergeNVMeBoardInfo test class has \u0027import json\u0027 inside each of its 6 test methods (lines 252, 259, 266, 273, 280, 287) rather than a single import at the top of the test module. This is unconventional and makes the tests harder to maintain.\n\n**Severity**: SUGGESTION | **Confidence**: 0.9\n\n**Benefit**: Minor maintainability concern. The repeated inline import adds visual noise and inconsistency with the rest of the cyborg codebase which uses oslo_serialization.jsonutils. Not a correctness issue.\n\n**Recommendation**:\nMove \u0027import json\u0027 to the top of the test module, or better, use jsonutils.loads() which is already available from the existing oslo_serialization import, consistent with the rest of the cyborg codebase.","commit_id":"de95d37c8b7853605419d0930962b42e7c6fb9cc"},{"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":"6f6d87758d679a0776bac9db7b8314c6d03ded16","unresolved":false,"context_lines":[{"line_number":229,"context_line":"    @mock.patch("},{"line_number":230,"context_line":"        \u0027cyborg.conductor.manager.ConductorManager.drv_device_make_diff\u0027"},{"line_number":231,"context_line":"    )"},{"line_number":232,"context_line":"    def test_new_nvme_device_initialized_as_available("},{"line_number":233,"context_line":"        self, mock_diff, mock_find_cpid"},{"line_number":234,"context_line":"    ):"},{"line_number":235,"context_line":"        dev_obj \u003d mock.Mock()"}],"source_content_type":"text/x-python","patch_set":7,"id":"667f303f_b049e3a5","line":232,"updated":"2026-08-09 05:13:18.000000000","message":"The test named test_new_nvme_device_initialized_as_available calls _find_device_by_cpid directly (which is already mocked) and only asserts it was called once. It never invokes drv_device_make_diff or report_data, so the code path that sets device_state to DEVICE_STATE_AVAILABLE for newly added N...\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: A reviewer relying on this test name for coverage of the NVMe device-state initialization path would have false confidence. Regression in the initialization logic could go undetected.\n\n**Suggestion**:\nRewrite the test to call report_data or drv_device_make_diff with a new device (not in old list), mock _find_device_by_cpid to return a dev_obj with device_state\u003dNone, and assert that dev_obj.device_state is set to constants.DEVICE_STATE_AVAILABLE and that dev_obj.save was called.","commit_id":"c1d148aa055ad4f431daff8a3111d2b59cdb0f0f"},{"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":"f26c2dd98eaebbeec53a85fff33719bae590e348","unresolved":false,"context_lines":[{"line_number":267,"context_line":"        old \u003d \u0027{\"cleanup_action\": \"sanitize_ces\", \"nvme_dev\": \"/dev/nvme0\"}\u0027"},{"line_number":268,"context_line":"        new \u003d \u0027{\"cleanup_action\": \"zero_wz\", \"nvme_dev\": \"/dev/nvme0\"}\u0027"},{"line_number":269,"context_line":"        result \u003d self._merge(old, new, \u0027allocated\u0027)"},{"line_number":270,"context_line":"        import json"},{"line_number":271,"context_line":""},{"line_number":272,"context_line":"        self.assertEqual(\u0027sanitize_ces\u0027, json.loads(result)[\u0027cleanup_action\u0027])"},{"line_number":273,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"ac228d3c_6032fc74","line":270,"updated":"2026-08-11 15:21:10.000000000","message":"The TestMergeNVMeBoardInfo test class has six separate methods that each contain a local \u0027import json\u0027 statement to parse assertion results, rather than importing json at the module level.\n\n**Severity**: SUGGESTION | **Confidence**: 0.8\n\n**Benefit**: This is a code quality issue that makes the tests harder to maintain. It also signals that the tests should use jsonutils from oslo_serialization for consistency with the code under test.\n\n**Recommendation**:\nAdd `import json` (or preferably use the already-available `from oslo_serialization import jsonutils`) at the module level and remove the six inline imports.","commit_id":"0ece3d90c95e271c9875fb6bb92b80e60d738c22"},{"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":"75490aa828304f0778f4426ab19da1bbe4cb5f6f","unresolved":false,"context_lines":[{"line_number":267,"context_line":"        old \u003d \u0027{\"cleanup_action\": \"sanitize_ces\", \"nvme_dev\": \"/dev/nvme0\"}\u0027"},{"line_number":268,"context_line":"        new \u003d \u0027{\"cleanup_action\": \"zero_wz\", \"nvme_dev\": \"/dev/nvme0\"}\u0027"},{"line_number":269,"context_line":"        result \u003d self._merge(old, new, \u0027allocated\u0027)"},{"line_number":270,"context_line":"        import json"},{"line_number":271,"context_line":""},{"line_number":272,"context_line":"        self.assertEqual(\u0027sanitize_ces\u0027, json.loads(result)[\u0027cleanup_action\u0027])"},{"line_number":273,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"41babf3f_19da3ea5","line":270,"updated":"2026-08-13 04:59:07.000000000","message":"The TestMergeNVMeBoardInfo test class repeats `import json` inside each of its six test methods instead of importing json once at the module level. This is an anti-pattern that should use a module-level import or the already-available jsonutils module.\n\n**Severity**: SUGGESTION | **Confidence**: 0.9\n\n**Benefit**: Code smell that could trigger hacking checks and makes the test harder to read. Minor maintenance burden.\n\n**Recommendation**:\nAdd `import json` at the module level (or use jsonutils.loads for consistency with the production code being tested) and remove all six inline imports.","commit_id":"2fb1b5b4e81d79f57ff110dc1b4926ab784c1f40"}],"releasenotes/notes/add-nvme-generic-driver-a1b2c3d4e5f6.yaml":[{"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":"f26c2dd98eaebbeec53a85fff33719bae590e348","unresolved":false,"context_lines":[{"line_number":8,"context_line":"    configurable policy through ``[nvme] device_spec`` entries."},{"line_number":9,"context_line":"    See the `NVMe driver admin guide"},{"line_number":10,"context_line":"    \u003chttps://docs.openstack.org/cyborg/latest/admin/nvme_driver.html\u003e`_"},{"line_number":11,"context_line":"    for configuration details."},{"line_number":12,"context_line":"upgrade:"},{"line_number":13,"context_line":"  - |"},{"line_number":14,"context_line":"    The NVMe driver requires ``nvme-cli`` to be installed on compute"}],"source_content_type":"text/x-yaml","patch_set":9,"id":"85e5b0fa_60e5c668","line":11,"updated":"2026-08-11 15:21:10.000000000","message":"The release note links to https://docs.openstack.org/cyborg/latest/admin/nvme_driver.html for configuration details, but no such documentation page is created or referenced anywhere in the codebase.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: Users following the release note link will encounter a 404 error. Operators cannot find configuration guidance for the new [nvme] device_spec format.\n\n**Suggestion**:\nEither add the admin guide RST document in this change or remove the dead link from the release note and reference the configuration options help text instead.","commit_id":"0ece3d90c95e271c9875fb6bb92b80e60d738c22"},{"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":"f26c2dd98eaebbeec53a85fff33719bae590e348","unresolved":false,"context_lines":[{"line_number":15,"context_line":"    hosts.  The cyborg-agent will fail ``init_host()`` if nvme-cli is"},{"line_number":16,"context_line":"    not found and the NVMe driver is enabled in"},{"line_number":17,"context_line":"    ``[agent] enabled_drivers``."},{"line_number":18,"context_line":"deprecations:"},{"line_number":19,"context_line":"  - |"},{"line_number":20,"context_line":"    The vendor-specific SSD and Inspur NVMe drivers are deprecated in"},{"line_number":21,"context_line":"    favor of the new generic NVMe driver.  They will be removed in a"}],"source_content_type":"text/x-yaml","patch_set":9,"id":"4c7cc06f_404c6c4d","line":18,"updated":"2026-08-11 15:21:10.000000000","message":"The release note under \u0027deprecations\u0027 states that vendor-specific SSD and Inspur NVMe drivers are deprecated in favor of the new generic driver. However, no deprecation warning, LOG.warning, or deprecation marker is added to the InspurNVMeSSDDriver or SSDDriver code in this change.\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: Operators who read the release note may be confused by the absence of runtime deprecation warnings. The deprecation is announced but not enforced or communicated through the usual OpenStack deprecation pattern (LOG.warning on import or first use).\n\n**Suggestion**:\nEither add a deprecation warning to the Inspur NVMe SSD driver (e.g. in __init__ or discover) using the standard oslo_log warning, or remove the deprecations section from the release note if the deprecation is not yet official.","commit_id":"0ece3d90c95e271c9875fb6bb92b80e60d738c22"},{"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":"a016e687c14f6fcd7f4553653bf46cf1135eab29","unresolved":false,"context_lines":[{"line_number":7,"context_line":"    NVMe sanitize (crypto-erase or block-erase) and write-zeroes, with"},{"line_number":8,"context_line":"    configurable policy through ``[nvme] device_spec`` entries."},{"line_number":9,"context_line":"    See the `NVMe driver admin guide"},{"line_number":10,"context_line":"    \u003chttps://docs.openstack.org/cyborg/latest/admin/nvme_driver.html\u003e`_"},{"line_number":11,"context_line":"    for configuration details."},{"line_number":12,"context_line":"upgrade:"},{"line_number":13,"context_line":"  - |"}],"source_content_type":"text/x-yaml","patch_set":12,"id":"c01e96c9_7f02f69a","line":10,"updated":"2026-08-14 15:33:02.000000000","message":"The release note references https://docs.openstack.org/cyborg/latest/admin/nvme_driver.html but no admin/nvme_driver.rst exists in the tree, and it deprecates the vendor-specific SSD and Inspur NVMe drivers without any deprecation logging or documentation in those drivers or their config help.\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: Operators following the published release note hit a 404 doc link and see a deprecation commitment that no code or config warning reflects, eroding trust in upgrade guidance.\n\n**Suggestion**:\nAdd doc/source/admin/nvme_driver.rst (and register it in the admin toctree) or point at the existing contributor guide; add a deprecation LOG.warning in the inspur SSD/NVMe drivers\u0027 init_host and update the [agent] enabled_drivers help before announcing the deprecation in a release note.","commit_id":"d0ed397ba88c229ca4f0746f113bb90851a0fd88"},{"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":"bae1a7942c7439ce9f098bc0c8f7a4216ffdaf7c","unresolved":false,"context_lines":[{"line_number":7,"context_line":"    NVMe sanitize (crypto-erase or block-erase) and write-zeroes, with"},{"line_number":8,"context_line":"    configurable policy through ``[nvme] device_spec`` entries."},{"line_number":9,"context_line":"    See the `NVMe driver admin guide"},{"line_number":10,"context_line":"    \u003chttps://docs.openstack.org/cyborg/latest/admin/nvme_driver.html\u003e`_"},{"line_number":11,"context_line":"    for configuration details."},{"line_number":12,"context_line":"upgrade:"},{"line_number":13,"context_line":"  - |"}],"source_content_type":"text/x-yaml","patch_set":13,"id":"f31cc776_d1e9f27d","line":10,"updated":"2026-08-15 16:25:22.000000000","message":"The release note references https://docs.openstack.org/cyborg/latest/admin/nvme_driver.html, but the only NVMe documentation in the tree is a contributor guide (doc/source/contributor/nvme-driver.rst) with no admin page added by this patch.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: Published release notes will contain a broken documentation link for the new driver.\n\n**Suggestion**:\nEither add the admin documentation page in this patch or link to the existing contributor guide until an admin page exists.","commit_id":"939db56c2785af9a0203a3037f86d833efbebcc7"}]}
