)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"a0ff0232dadc24ec2856867dd8854e4e31bcc2bb","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":20,"id":"f758fbfd_81f38777","updated":"2026-09-04 12:35:39.000000000","message":"this is pretty close tomerging but the create healing in the conductor is not quite right","commit_id":"49bf6e0290b9e3c8fb3e63292c316143de02cae6"}],"bindep.txt":[{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"f357672bd2b87a33217b4527949aa082f78edd76","unresolved":true,"context_lines":[{"line_number":8,"context_line":"pciutils"},{"line_number":9,"context_line":""},{"line_number":10,"context_line":"# Required for the generic NVMe driver init_host/discovery path"},{"line_number":11,"context_line":"nvme-cli"},{"line_number":12,"context_line":""},{"line_number":13,"context_line":"# libsrvg2 is needed for sphinxcontrib-svg2pdfconverter in docs builds."},{"line_number":14,"context_line":"librsvg2-tools [doc platform:rpm]"}],"source_content_type":"text/plain","patch_set":17,"id":"f1a4358d_3659c506","line":11,"updated":"2026-09-03 12:30:51.000000000","message":"so this shoudl have some profiels assocated with it\n\n\n\nnit we can refien this next cycle.\n\nbut this shoudl proably be an optional depency and as such shoudl becauged vai the test and a new nvme profile in beindeps.\n\n```suggestion\nnvme-cli [test nvme]\n\n```\n\nwe want to install it by defualt for our testign but its an optiona dep for the nvme drvier\n\n\nyou could argue the same for pciutils but that used by almost every other drvier so that feels less optional","commit_id":"8221f14f14e9bb0be568cc1cc6fcaea7d912ac37"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"2567793a3ef340c8f8b24c5cd642ddadd0f49b08","unresolved":false,"context_lines":[{"line_number":8,"context_line":"pciutils"},{"line_number":9,"context_line":""},{"line_number":10,"context_line":"# Required for the generic NVMe driver init_host/discovery path"},{"line_number":11,"context_line":"nvme-cli"},{"line_number":12,"context_line":""},{"line_number":13,"context_line":"# libsrvg2 is needed for sphinxcontrib-svg2pdfconverter in docs builds."},{"line_number":14,"context_line":"librsvg2-tools [doc platform:rpm]"}],"source_content_type":"text/plain","patch_set":17,"id":"2eb2492f_aa76738e","line":11,"in_reply_to":"f1a4358d_3659c506","updated":"2026-09-04 08:12:18.000000000","message":"Make sense!\n\nI have added test nvme profle to bindep.txt","commit_id":"8221f14f14e9bb0be568cc1cc6fcaea7d912ac37"}],"cyborg/accelerator/drivers/nvme/devspec.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":"bab78373f9ea23f3ddfde88ee1a5f0e808880f25","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 fnmatch"},{"line_number":15,"context_line":"import re"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"from oslo_serialization import jsonutils"}],"source_content_type":"text/x-python","patch_set":2,"id":"80cf7c3a_a5e8ae0b","line":14,"updated":"2026-08-06 10:51:31.000000000","message":"Both new source files devspec.py and nvme_cli.py lack module-level docstrings after the Apache license header. Existing driver modules in the cyborg codebase consistently include module docstrings.\n\n**Severity**: SUGGESTION | **Confidence**: 0.8\n\n**Benefit**: New files missing module docstrings are inconsistent with the project convention and reduce code discoverability. This is a low-impact documentation gap.\n\n**Recommendation**:\nAdd a brief module docstring to each file, e.g. \u0027\"\"\"NVMe device spec parsing for [nvme] device_spec configuration.\"\"\"\u0027 in devspec.py and \u0027\"\"\"Privileged nvme-cli wrappers for NVMe device operations.\"\"\"\u0027 in nvme_cli.py.","commit_id":"8398e9c8a6b24df1a46fcfd061548e6486d50e27"},{"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":"bab78373f9ea23f3ddfde88ee1a5f0e808880f25","unresolved":false,"context_lines":[{"line_number":72,"context_line":"            return False"},{"line_number":73,"context_line":"        return True"},{"line_number":74,"context_line":""},{"line_number":75,"context_line":"    def _match_address(self, pci_address):"},{"line_number":76,"context_line":"        pattern \u003d self.address"},{"line_number":77,"context_line":"        if pattern.startswith(\u0027/\u0027) and pattern.endswith(\u0027/\u0027):"},{"line_number":78,"context_line":"            return bool(re.match(pattern[1:-1], pci_address))"}],"source_content_type":"text/x-python","patch_set":2,"id":"7d1a2fd7_6347822d","line":75,"updated":"2026-08-06 10:51:31.000000000","message":"The _match_address method allows regex patterns delimited by forward slashes but passes the raw pattern to re.match without catching re.error. An invalid regex in [nvme] device_spec address config will raise an unhandled re.error at runtime during device matching.\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: An operator misconfiguring a regex PCI address pattern will get an unhandled re.error exception during runtime device matching instead of a clear configuration error at parse time. This could crash the cyborg agent when it tries to enumerate and match NVMe devices.\n\n**Suggestion**:\nWrap the regex compilation in a try/except re.error block inside _match_address, or better yet, pre-compile and validate the regex during __init__ by calling re.compile(pattern[1:-1]) and raising PciConfigInvalidWhitelist with a helpful message on failure.","commit_id":"8398e9c8a6b24df1a46fcfd061548e6486d50e27"},{"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":"7a25d3563b8557ad992721d293c5f3241a357562","unresolved":false,"context_lines":[{"line_number":34,"context_line":""},{"line_number":35,"context_line":"    def __init__(self, spec_dict):"},{"line_number":36,"context_line":"        if not isinstance(spec_dict, dict):"},{"line_number":37,"context_line":"            raise exception.PciConfigInvalidWhitelist("},{"line_number":38,"context_line":"                reason\u003d\u0027nvme device_spec is not a dict: %s\u0027 % spec_dict"},{"line_number":39,"context_line":"            )"},{"line_number":40,"context_line":"        self.vendor_id \u003d spec_dict.get(\u0027vendor_id\u0027)"}],"source_content_type":"text/x-python","patch_set":8,"id":"193918c9_7ac61f96","line":37,"updated":"2026-08-11 15:03:42.000000000","message":"The existing cyborg PCI devspec.py and whitelist.py consistently wrap all PciConfigInvalidWhitelist reason strings with _() for translation. The new NVMe devspec.py uses bare strings for all eight reason\u003d arguments, breaking the established convention.\n\n**Severity**: SUGGESTION | **Confidence**: 0.8\n\n**Benefit**: Error messages from nvme device_spec validation will not be translatable, while equivalent PCI error messages are. This creates an inconsistent operator experience across driver types.\n\n**Recommendation**:\nImport _ from cyborg.common.i18n and wrap all reason\u003d strings with _(), matching the PCI devspec.py pattern.","commit_id":"7c7aadb5c16eb1e30b5b16259eb81dc15d57ad36"},{"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":"d81ff1599cc52a9e1fa6ba22d69e8f6ecf86a39e","unresolved":false,"context_lines":[{"line_number":34,"context_line":""},{"line_number":35,"context_line":"    def __init__(self, spec_dict):"},{"line_number":36,"context_line":"        if not isinstance(spec_dict, dict):"},{"line_number":37,"context_line":"            raise exception.PciConfigInvalidWhitelist("},{"line_number":38,"context_line":"                reason\u003d\u0027nvme device_spec is not a dict: %s\u0027 % spec_dict"},{"line_number":39,"context_line":"            )"},{"line_number":40,"context_line":"        self.vendor_id \u003d spec_dict.get(\u0027vendor_id\u0027)"}],"source_content_type":"text/x-python","patch_set":11,"id":"e89a6278_15c4bf65","line":37,"updated":"2026-08-14 15:10:20.000000000","message":"All validation failures in the new [nvme] device_spec parser raise exception.PciConfigInvalidWhitelist, whose _msg_fmt is \u0027Invalid PCI devices whitelist config: %(reason)s\u0027. This patch is parsing [nvme] device_spec entries, not a PCI whitelist, so operators debugging configuration errors will see...\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: Operators configuring [nvme] device_spec who make a JSON or validation error get an error message pointing at \u0027PCI devices whitelist config\u0027, making troubleshooting the [nvme] option harder and creating confusion in log triage.\n\n**Suggestion**:\nRaise exception.InvalidConfiguration (added in this same patch) for nvme device_spec validation failures, or add a dedicated NvmeDeviceSpecInvalid exception; update the four raise sites and the unit tests accordingly.","commit_id":"ec66479f4f52629aeb7098aae038cc2907a4a550"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"9d591742bde2cee9067dd1c73ab69686dde62510","unresolved":true,"context_lines":[{"line_number":25,"context_line":"VALID_CLEAR_STRATEGIES \u003d (\u0027auto\u0027, \u0027crypto\u0027, \u0027block\u0027)"},{"line_number":26,"context_line":""},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"class NVMeDeviceSpec:"},{"line_number":29,"context_line":"    \"\"\"Single [nvme] device_spec JSON entry."},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"    Validates fields and exposes typed accessors for address"}],"source_content_type":"text/x-python","patch_set":14,"id":"0c9520f8_a9daa942","line":28,"updated":"2026-08-18 12:15:39.000000000","message":"lets make this a dataclass and properly define the fields","commit_id":"eb1da94748ebee9e2cc530fb0749d2ee08f96e2c"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"716ce162502ebb68eda3e31919df967b34bd8615","unresolved":true,"context_lines":[{"line_number":25,"context_line":"VALID_CLEAR_STRATEGIES \u003d (\u0027auto\u0027, \u0027crypto\u0027, \u0027block\u0027)"},{"line_number":26,"context_line":""},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"class NVMeDeviceSpec:"},{"line_number":29,"context_line":"    \"\"\"Single [nvme] device_spec JSON entry."},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"    Validates fields and exposes typed accessors for address"}],"source_content_type":"text/x-python","patch_set":14,"id":"dd4515f0_a5f7727d","line":28,"in_reply_to":"0c9520f8_a9daa942","updated":"2026-08-18 12:20:38.000000000","message":"https://review.opendev.org/c/openstack/cyborg/+/997048/12/cyborg/accelerator/bus_managers/mdev.py \n\nsi a good exampel fo this\n\ni think i will proceed with that patch so that we have the filesystem helpers form it for use in the nvme series\n\nbut i also wonder if it makes sense to create and NVME busManager like the MDEV buss manager or shoudl we defer that until i create the Generic PCIBusManager next cycle","commit_id":"eb1da94748ebee9e2cc530fb0749d2ee08f96e2c"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"9fb0349b61e0cd71ee4199ee299511520c036ce4","unresolved":false,"context_lines":[{"line_number":25,"context_line":"VALID_CLEAR_STRATEGIES \u003d (\u0027auto\u0027, \u0027crypto\u0027, \u0027block\u0027)"},{"line_number":26,"context_line":""},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"class NVMeDeviceSpec:"},{"line_number":29,"context_line":"    \"\"\"Single [nvme] device_spec JSON entry."},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"    Validates fields and exposes typed accessors for address"}],"source_content_type":"text/x-python","patch_set":14,"id":"a50ebebe_b0ad55a2","line":28,"in_reply_to":"dd4515f0_a5f7727d","updated":"2026-08-21 17:25:56.000000000","message":"Done","commit_id":"eb1da94748ebee9e2cc530fb0749d2ee08f96e2c"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"9d591742bde2cee9067dd1c73ab69686dde62510","unresolved":true,"context_lines":[{"line_number":32,"context_line":"    matching, vendor/product filtering, and cleanup policy."},{"line_number":33,"context_line":"    \"\"\""},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"    def __init__(self, spec_dict):"},{"line_number":36,"context_line":"        if not isinstance(spec_dict, dict):"},{"line_number":37,"context_line":"            raise exception.PciConfigInvalidWhitelist("},{"line_number":38,"context_line":"                reason\u003d\u0027nvme device_spec is not a dict: %s\u0027 % spec_dict"}],"source_content_type":"text/x-python","patch_set":14,"id":"e2ed8a83_cc947e65","line":35,"range":{"start_line":35,"start_character":23,"end_line":35,"end_character":32},"updated":"2026-08-18 12:15:39.000000000","message":"we shoudl take specific fiels rather then a dict here","commit_id":"eb1da94748ebee9e2cc530fb0749d2ee08f96e2c"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"f357672bd2b87a33217b4527949aa082f78edd76","unresolved":false,"context_lines":[{"line_number":32,"context_line":"    matching, vendor/product filtering, and cleanup policy."},{"line_number":33,"context_line":"    \"\"\""},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"    def __init__(self, spec_dict):"},{"line_number":36,"context_line":"        if not isinstance(spec_dict, dict):"},{"line_number":37,"context_line":"            raise exception.PciConfigInvalidWhitelist("},{"line_number":38,"context_line":"                reason\u003d\u0027nvme device_spec is not a dict: %s\u0027 % spec_dict"}],"source_content_type":"text/x-python","patch_set":14,"id":"b703af5d_235fb1ea","line":35,"range":{"start_line":35,"start_character":23,"end_line":35,"end_character":32},"in_reply_to":"e2ed8a83_cc947e65","updated":"2026-09-03 12:30:51.000000000","message":"Done","commit_id":"eb1da94748ebee9e2cc530fb0749d2ee08f96e2c"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"9d591742bde2cee9067dd1c73ab69686dde62510","unresolved":true,"context_lines":[{"line_number":40,"context_line":"        self.vendor_id \u003d spec_dict.get(\u0027vendor_id\u0027)"},{"line_number":41,"context_line":"        self.product_id \u003d spec_dict.get(\u0027product_id\u0027)"},{"line_number":42,"context_line":"        self.address \u003d spec_dict.get(\u0027address\u0027)"},{"line_number":43,"context_line":"        self._address_re \u003d None"},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"        if not self.vendor_id and not self.product_id and not self.address:"},{"line_number":46,"context_line":"            raise exception.PciConfigInvalidWhitelist("},{"line_number":47,"context_line":"                reason\u003d\u0027device_spec needs vendor_id, product_id, or address\u0027"},{"line_number":48,"context_line":"            )"},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"        if ("},{"line_number":51,"context_line":"            self.address"},{"line_number":52,"context_line":"            and self.address.startswith(\u0027/\u0027)"},{"line_number":53,"context_line":"            and self.address.endswith(\u0027/\u0027)"},{"line_number":54,"context_line":"        ):"},{"line_number":55,"context_line":"            try:"},{"line_number":56,"context_line":"                self._address_re \u003d re.compile(self.address[1:-1])"},{"line_number":57,"context_line":"            except re.error as e:"},{"line_number":58,"context_line":"                raise exception.PciConfigInvalidWhitelist("},{"line_number":59,"context_line":"                    reason\u003d\u0027invalid regex in address %s: %s\u0027"},{"line_number":60,"context_line":"                    % (self.address, e)"},{"line_number":61,"context_line":"                )"},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"        self.clear_action \u003d spec_dict.get(\u0027clear_action\u0027, \u0027auto\u0027)"},{"line_number":64,"context_line":"        self.clear_strategy \u003d spec_dict.get(\u0027clear_strategy\u0027, \u0027auto\u0027)"}],"source_content_type":"text/x-python","patch_set":14,"id":"c2c51abd_09a01034","line":61,"range":{"start_line":43,"start_character":0,"end_line":61,"end_character":17},"updated":"2026-08-18 12:15:39.000000000","message":"this is not compatibel with \n\nhttps://github.com/openstack/cyborg/blob/master/cyborg/accelerator/drivers/pci/devspec.py#L218-L228\n\nwe supprot globs if the adress field is a sting and regexes only if the adress filed is a dict\n\nwe do not use / to enable regex mode\n\nyou shoudl be modeling this as a WhitelistPciAddress\n\nand next cycle this will be hideen form this driver entirly by the PciBusManaer as it will own discovery/enmeration of the devices.","commit_id":"eb1da94748ebee9e2cc530fb0749d2ee08f96e2c"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"f357672bd2b87a33217b4527949aa082f78edd76","unresolved":false,"context_lines":[{"line_number":40,"context_line":"        self.vendor_id \u003d spec_dict.get(\u0027vendor_id\u0027)"},{"line_number":41,"context_line":"        self.product_id \u003d spec_dict.get(\u0027product_id\u0027)"},{"line_number":42,"context_line":"        self.address \u003d spec_dict.get(\u0027address\u0027)"},{"line_number":43,"context_line":"        self._address_re \u003d None"},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"        if not self.vendor_id and not self.product_id and not self.address:"},{"line_number":46,"context_line":"            raise exception.PciConfigInvalidWhitelist("},{"line_number":47,"context_line":"                reason\u003d\u0027device_spec needs vendor_id, product_id, or address\u0027"},{"line_number":48,"context_line":"            )"},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"        if ("},{"line_number":51,"context_line":"            self.address"},{"line_number":52,"context_line":"            and self.address.startswith(\u0027/\u0027)"},{"line_number":53,"context_line":"            and self.address.endswith(\u0027/\u0027)"},{"line_number":54,"context_line":"        ):"},{"line_number":55,"context_line":"            try:"},{"line_number":56,"context_line":"                self._address_re \u003d re.compile(self.address[1:-1])"},{"line_number":57,"context_line":"            except re.error as e:"},{"line_number":58,"context_line":"                raise exception.PciConfigInvalidWhitelist("},{"line_number":59,"context_line":"                    reason\u003d\u0027invalid regex in address %s: %s\u0027"},{"line_number":60,"context_line":"                    % (self.address, e)"},{"line_number":61,"context_line":"                )"},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"        self.clear_action \u003d spec_dict.get(\u0027clear_action\u0027, \u0027auto\u0027)"},{"line_number":64,"context_line":"        self.clear_strategy \u003d spec_dict.get(\u0027clear_strategy\u0027, \u0027auto\u0027)"}],"source_content_type":"text/x-python","patch_set":14,"id":"11c66afc_af86e026","line":61,"range":{"start_line":43,"start_character":0,"end_line":61,"end_character":17},"in_reply_to":"c2c51abd_09a01034","updated":"2026-09-03 12:30:51.000000000","message":"Done","commit_id":"eb1da94748ebee9e2cc530fb0749d2ee08f96e2c"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"9d591742bde2cee9067dd1c73ab69686dde62510","unresolved":true,"context_lines":[{"line_number":93,"context_line":"            return bool(self._address_re.match(pci_address))"},{"line_number":94,"context_line":"        return fnmatch.fnmatch(pci_address, self.address)"},{"line_number":95,"context_line":""},{"line_number":96,"context_line":"    @staticmethod"},{"line_number":97,"context_line":"    def from_config(spec_str):"},{"line_number":98,"context_line":"        try:"},{"line_number":99,"context_line":"            spec_dict \u003d jsonutils.loads(spec_str)"},{"line_number":100,"context_line":"        except (ValueError, TypeError):"},{"line_number":101,"context_line":"            raise exception.PciConfigInvalidWhitelist("},{"line_number":102,"context_line":"                reason\u003d\u0027Invalid JSON in nvme device_spec: %s\u0027 % spec_str"},{"line_number":103,"context_line":"            )"},{"line_number":104,"context_line":"        return NVMeDeviceSpec(spec_dict)"},{"line_number":105,"context_line":""},{"line_number":106,"context_line":"    @staticmethod"},{"line_number":107,"context_line":"    def from_config_list(spec_strings):"},{"line_number":108,"context_line":"        return [NVMeDeviceSpec.from_config(s) for s in spec_strings]"},{"line_number":109,"context_line":""},{"line_number":110,"context_line":"    @staticmethod"},{"line_number":111,"context_line":"    def find_spec(specs, vendor_id, product_id, pci_address):"}],"source_content_type":"text/x-python","patch_set":14,"id":"8ebc11f3_519a46e4","line":108,"range":{"start_line":96,"start_character":4,"end_line":108,"end_character":68},"updated":"2026-08-18 12:15:39.000000000","message":"these are concturctore function and should be class methods not static mathods","commit_id":"eb1da94748ebee9e2cc530fb0749d2ee08f96e2c"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"f357672bd2b87a33217b4527949aa082f78edd76","unresolved":false,"context_lines":[{"line_number":93,"context_line":"            return bool(self._address_re.match(pci_address))"},{"line_number":94,"context_line":"        return fnmatch.fnmatch(pci_address, self.address)"},{"line_number":95,"context_line":""},{"line_number":96,"context_line":"    @staticmethod"},{"line_number":97,"context_line":"    def from_config(spec_str):"},{"line_number":98,"context_line":"        try:"},{"line_number":99,"context_line":"            spec_dict \u003d jsonutils.loads(spec_str)"},{"line_number":100,"context_line":"        except (ValueError, TypeError):"},{"line_number":101,"context_line":"            raise exception.PciConfigInvalidWhitelist("},{"line_number":102,"context_line":"                reason\u003d\u0027Invalid JSON in nvme device_spec: %s\u0027 % spec_str"},{"line_number":103,"context_line":"            )"},{"line_number":104,"context_line":"        return NVMeDeviceSpec(spec_dict)"},{"line_number":105,"context_line":""},{"line_number":106,"context_line":"    @staticmethod"},{"line_number":107,"context_line":"    def from_config_list(spec_strings):"},{"line_number":108,"context_line":"        return [NVMeDeviceSpec.from_config(s) for s in spec_strings]"},{"line_number":109,"context_line":""},{"line_number":110,"context_line":"    @staticmethod"},{"line_number":111,"context_line":"    def find_spec(specs, vendor_id, product_id, pci_address):"}],"source_content_type":"text/x-python","patch_set":14,"id":"effe48a7_30eba33c","line":108,"range":{"start_line":96,"start_character":4,"end_line":108,"end_character":68},"in_reply_to":"8ebc11f3_519a46e4","updated":"2026-09-03 12:30:51.000000000","message":"Done","commit_id":"eb1da94748ebee9e2cc530fb0749d2ee08f96e2c"}],"cyborg/accelerator/drivers/nvme/driver.py":[{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"9fb0349b61e0cd71ee4199ee299511520c036ce4","unresolved":true,"context_lines":[{"line_number":41,"context_line":"from cyborg.privsep import sys_admin_pctxt"},{"line_number":42,"context_line":""},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"try:"},{"line_number":45,"context_line":"    from os_traits.hw import nvme as nvme_traits"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    TRAIT_HW_NVME_CES \u003d nvme_traits.CES"},{"line_number":48,"context_line":"    TRAIT_HW_NVME_BES \u003d nvme_traits.BES"},{"line_number":49,"context_line":"    TRAIT_HW_NVME_WZS \u003d nvme_traits.WZS"},{"line_number":50,"context_line":"except ImportError:"},{"line_number":51,"context_line":"    TRAIT_HW_NVME_CES \u003d \u0027HW_NVME_CES\u0027"},{"line_number":52,"context_line":"    TRAIT_HW_NVME_BES \u003d \u0027HW_NVME_BES\u0027"},{"line_number":53,"context_line":"    TRAIT_HW_NVME_WZS \u003d \u0027HW_NVME_WZS\u0027"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"CONF \u003d cyborg.conf.CONF"}],"source_content_type":"text/x-python","patch_set":15,"id":"55901212_97b4568a","line":53,"range":{"start_line":44,"start_character":0,"end_line":53,"end_character":37},"updated":"2026-08-21 17:25:56.000000000","message":"we technilaly will need to check if these traits exist in the placement we are reporting the inventories too and only report them if they are listed in the standard traits.","commit_id":"794cc29348626347bba68690276afa3d26603c97"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"f357672bd2b87a33217b4527949aa082f78edd76","unresolved":false,"context_lines":[{"line_number":41,"context_line":"from cyborg.privsep import sys_admin_pctxt"},{"line_number":42,"context_line":""},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"try:"},{"line_number":45,"context_line":"    from os_traits.hw import nvme as nvme_traits"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    TRAIT_HW_NVME_CES \u003d nvme_traits.CES"},{"line_number":48,"context_line":"    TRAIT_HW_NVME_BES \u003d nvme_traits.BES"},{"line_number":49,"context_line":"    TRAIT_HW_NVME_WZS \u003d nvme_traits.WZS"},{"line_number":50,"context_line":"except ImportError:"},{"line_number":51,"context_line":"    TRAIT_HW_NVME_CES \u003d \u0027HW_NVME_CES\u0027"},{"line_number":52,"context_line":"    TRAIT_HW_NVME_BES \u003d \u0027HW_NVME_BES\u0027"},{"line_number":53,"context_line":"    TRAIT_HW_NVME_WZS \u003d \u0027HW_NVME_WZS\u0027"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"CONF \u003d cyborg.conf.CONF"}],"source_content_type":"text/x-python","patch_set":15,"id":"0f532a72_bed62192","line":53,"range":{"start_line":44,"start_character":0,"end_line":53,"end_character":37},"in_reply_to":"55901212_97b4568a","updated":"2026-09-03 12:30:51.000000000","message":"Done","commit_id":"794cc29348626347bba68690276afa3d26603c97"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"9fb0349b61e0cd71ee4199ee299511520c036ce4","unresolved":true,"context_lines":[{"line_number":139,"context_line":"        self._placement_client \u003d ("},{"line_number":140,"context_line":"            placement or placement_client.PlacementClient()"},{"line_number":141,"context_line":"        )"},{"line_number":142,"context_line":"        self._pci_sysfs_path \u003d pci_sysfs_path"},{"line_number":143,"context_line":""},{"line_number":144,"context_line":"    def init_host(self):"},{"line_number":145,"context_line":"        check_nvme_cli_installed()"}],"source_content_type":"text/x-python","patch_set":15,"id":"00e5523e_dfef5d76","line":142,"updated":"2026-08-21 17:25:56.000000000","message":"as noted later we shoudl use the placment client to list the standard traits cache them here as self.supported_traits for later use","commit_id":"794cc29348626347bba68690276afa3d26603c97"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"f357672bd2b87a33217b4527949aa082f78edd76","unresolved":false,"context_lines":[{"line_number":139,"context_line":"        self._placement_client \u003d ("},{"line_number":140,"context_line":"            placement or placement_client.PlacementClient()"},{"line_number":141,"context_line":"        )"},{"line_number":142,"context_line":"        self._pci_sysfs_path \u003d pci_sysfs_path"},{"line_number":143,"context_line":""},{"line_number":144,"context_line":"    def init_host(self):"},{"line_number":145,"context_line":"        check_nvme_cli_installed()"}],"source_content_type":"text/x-python","patch_set":15,"id":"421f85a2_9a462bdf","line":142,"in_reply_to":"00e5523e_dfef5d76","updated":"2026-09-03 12:30:51.000000000","message":"Done","commit_id":"794cc29348626347bba68690276afa3d26603c97"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"9fb0349b61e0cd71ee4199ee299511520c036ce4","unresolved":true,"context_lines":[{"line_number":166,"context_line":"            if spec is None:"},{"line_number":167,"context_line":"                continue"},{"line_number":168,"context_line":""},{"line_number":169,"context_line":"            if self._rp_exists_without_owner_cyborg(pci_dev[\u0027address\u0027]):"},{"line_number":170,"context_line":"                LOG.error("},{"line_number":171,"context_line":"                    \u0027Skipping NVMe device %(pci)s because resource provider \u0027"},{"line_number":172,"context_line":"                    \u0027ownership is not Cyborg.\u0027,"},{"line_number":173,"context_line":"                    {\u0027pci\u0027: pci_dev[\u0027address\u0027]},"},{"line_number":174,"context_line":"                )"},{"line_number":175,"context_line":"                continue"},{"line_number":176,"context_line":""},{"line_number":177,"context_line":"            try:"},{"line_number":178,"context_line":"                caps \u003d self.get_capabilities(pci_dev[\u0027address\u0027])"}],"source_content_type":"text/x-python","patch_set":15,"id":"6a77d831_68e11ffb","line":175,"range":{"start_line":169,"start_character":0,"end_line":175,"end_character":24},"updated":"2026-08-21 17:25:56.000000000","message":"this is not really correct\n\nif the device matchs our config, and it exist in placmetn without our owner trait we shoudl be treating this as a hard error because that shoudl never happen.","commit_id":"794cc29348626347bba68690276afa3d26603c97"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"f357672bd2b87a33217b4527949aa082f78edd76","unresolved":false,"context_lines":[{"line_number":166,"context_line":"            if spec is None:"},{"line_number":167,"context_line":"                continue"},{"line_number":168,"context_line":""},{"line_number":169,"context_line":"            if self._rp_exists_without_owner_cyborg(pci_dev[\u0027address\u0027]):"},{"line_number":170,"context_line":"                LOG.error("},{"line_number":171,"context_line":"                    \u0027Skipping NVMe device %(pci)s because resource provider \u0027"},{"line_number":172,"context_line":"                    \u0027ownership is not Cyborg.\u0027,"},{"line_number":173,"context_line":"                    {\u0027pci\u0027: pci_dev[\u0027address\u0027]},"},{"line_number":174,"context_line":"                )"},{"line_number":175,"context_line":"                continue"},{"line_number":176,"context_line":""},{"line_number":177,"context_line":"            try:"},{"line_number":178,"context_line":"                caps \u003d self.get_capabilities(pci_dev[\u0027address\u0027])"}],"source_content_type":"text/x-python","patch_set":15,"id":"24ba3e77_1297c026","line":175,"range":{"start_line":169,"start_character":0,"end_line":175,"end_character":24},"in_reply_to":"6a77d831_68e11ffb","updated":"2026-09-03 12:30:51.000000000","message":"Acknowledged","commit_id":"794cc29348626347bba68690276afa3d26603c97"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"9fb0349b61e0cd71ee4199ee299511520c036ce4","unresolved":true,"context_lines":[{"line_number":304,"context_line":"        device.vendor_board_info \u003d None"},{"line_number":305,"context_line":"        device.controlpath_id \u003d self._build_control_path(pci_address)"},{"line_number":306,"context_line":"        device.deployable_list \u003d ["},{"line_number":307,"context_line":"            self._build_deployable(pci_dev, pci_address, caps.traits)"},{"line_number":308,"context_line":"        ]"},{"line_number":309,"context_line":"        return device"},{"line_number":310,"context_line":""}],"source_content_type":"text/x-python","patch_set":15,"id":"cc4f5c30_93ab2b23","line":307,"range":{"start_line":307,"start_character":11,"end_line":307,"end_character":69},"updated":"2026-08-21 17:25:56.000000000","message":"so we need to support using older placement i.e. 2026.1 where the standard traits wont exist so before we build the deployable we need to fileter caps.traits to only the standard traits supported by the current placmet we are talkign too\n\nidally we woudl get the standard traits once on driver creation and save the to  self as self.supported_tratis and then we can filter this with a lilst comprehention or filter funciton","commit_id":"794cc29348626347bba68690276afa3d26603c97"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"f357672bd2b87a33217b4527949aa082f78edd76","unresolved":false,"context_lines":[{"line_number":304,"context_line":"        device.vendor_board_info \u003d None"},{"line_number":305,"context_line":"        device.controlpath_id \u003d self._build_control_path(pci_address)"},{"line_number":306,"context_line":"        device.deployable_list \u003d ["},{"line_number":307,"context_line":"            self._build_deployable(pci_dev, pci_address, caps.traits)"},{"line_number":308,"context_line":"        ]"},{"line_number":309,"context_line":"        return device"},{"line_number":310,"context_line":""}],"source_content_type":"text/x-python","patch_set":15,"id":"be9ecef0_0e0a3ac0","line":307,"range":{"start_line":307,"start_character":11,"end_line":307,"end_character":69},"in_reply_to":"cc4f5c30_93ab2b23","updated":"2026-09-03 12:30:51.000000000","message":"Done","commit_id":"794cc29348626347bba68690276afa3d26603c97"},{"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":"5d1e948826ce282b5ebf355a1b23317c3df39dbd","unresolved":false,"context_lines":[{"line_number":353,"context_line":"            pci_dev[\u0027device_id\u0027].upper(),"},{"line_number":354,"context_line":"        )"},{"line_number":355,"context_line":""},{"line_number":356,"context_line":"    def _rp_exists_without_owner_cyborg(self, pci_address):"},{"line_number":357,"context_line":"        rp_name \u003d \u0027%s_%s\u0027 % (CONF.host, pci_address)"},{"line_number":358,"context_line":"        response \u003d self._placement_client.get("},{"line_number":359,"context_line":"            \u0027/resource_providers?name\u003d\u0027 + urllib.parse.quote(rp_name)"}],"source_content_type":"text/x-python","patch_set":15,"id":"a6296148_bf86a324","line":356,"updated":"2026-08-21 07:12:24.000000000","message":"discover() calls _rp_exists_without_owner_cyborg() for every matched device, which performs live Placement HTTP calls whose error paths raise. resource_tracker.update_usage() invokes acc_driver.discover() outside its try/except, so a Placement error escapes and discards the whole acc_list for the cycle, including results from other enabled drivers.\n\n**Severity**: WARNING | **Confidence**: 0.85\n\n**Impact**: A transient Placement outage or an RP deleted concurrently causes the periodic update to fail repeatedly, suppressing reporting of all accelerators on the host (not just NVMe) until Placement recovers; agent sync latency and Placement load also grow linearly with the number of NVMe devices on every cycle.\n\n**Suggestion**:\nWrap the ownership check in try/except and skip the device with LOG.error (or conservatively treat it as not Cyborg-owned) so one Placement hiccup cannot abort update_usage. Consider caching ownership per device for the sync cycle, and expose a public PlacementClient method (e.g. get_rp_traits(rp_uuid)) instead of reaching into the private _get_rp_traits.","commit_id":"794cc29348626347bba68690276afa3d26603c97"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"9fb0349b61e0cd71ee4199ee299511520c036ce4","unresolved":true,"context_lines":[{"line_number":354,"context_line":"        )"},{"line_number":355,"context_line":""},{"line_number":356,"context_line":"    def _rp_exists_without_owner_cyborg(self, pci_address):"},{"line_number":357,"context_line":"        rp_name \u003d \u0027%s_%s\u0027 % (CONF.host, pci_address)"},{"line_number":358,"context_line":"        response \u003d self._placement_client.get("},{"line_number":359,"context_line":"            \u0027/resource_providers?name\u003d\u0027 + urllib.parse.quote(rp_name)"},{"line_number":360,"context_line":"        )"}],"source_content_type":"text/x-python","patch_set":15,"id":"b52ed1be_3226d7b7","line":357,"range":{"start_line":357,"start_character":7,"end_line":357,"end_character":52},"updated":"2026-08-21 17:25:56.000000000","message":"so we are using this format \u003chostname\u003e_\u003cpci_address\u003e\nto match the same format used by nova so that if this exists without the  owner trait  we know that the device is potially still manged by nova\n\nhttps://specs.openstack.org/openstack/cyborg-specs/specs/2026.2/approved/generic-nvme-driver-with-secure-cleanup.html#placement-integration\n\nbut in that case instead of ignoring the device we shoudl raise a config exctpion because that shoudl never happen and the agent shoudl not start up with invalid config\n\nso we should ideally make this raise instnead of return a bool i think","commit_id":"794cc29348626347bba68690276afa3d26603c97"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"f357672bd2b87a33217b4527949aa082f78edd76","unresolved":false,"context_lines":[{"line_number":354,"context_line":"        )"},{"line_number":355,"context_line":""},{"line_number":356,"context_line":"    def _rp_exists_without_owner_cyborg(self, pci_address):"},{"line_number":357,"context_line":"        rp_name \u003d \u0027%s_%s\u0027 % (CONF.host, pci_address)"},{"line_number":358,"context_line":"        response \u003d self._placement_client.get("},{"line_number":359,"context_line":"            \u0027/resource_providers?name\u003d\u0027 + urllib.parse.quote(rp_name)"},{"line_number":360,"context_line":"        )"}],"source_content_type":"text/x-python","patch_set":15,"id":"49f11226_50d30ab5","line":357,"range":{"start_line":357,"start_character":7,"end_line":357,"end_character":52},"in_reply_to":"b52ed1be_3226d7b7","updated":"2026-09-03 12:30:51.000000000","message":"Done","commit_id":"794cc29348626347bba68690276afa3d26603c97"},{"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":"151e74beae843bb37b6707e45039c4bdcaa36cec","unresolved":false,"context_lines":[{"line_number":376,"context_line":""},{"line_number":377,"context_line":"        rp_traits \u003d self._placement_client.get_rp_traits(providers[0][\u0027uuid\u0027])"},{"line_number":378,"context_line":"        if constants.OWNER_CYBORG not in rp_traits.get(\u0027traits\u0027, []):"},{"line_number":379,"context_line":"            raise exception.InvalidConfiguration("},{"line_number":380,"context_line":"                reason\u003d("},{"line_number":381,"context_line":"                    \u0027NVMe device %(pci)s has resource provider %(rp)s in \u0027"},{"line_number":382,"context_line":"                    \u0027Placement without OWNER_CYBORG. The device may be managed \u0027"}],"source_content_type":"text/x-python","patch_set":16,"id":"bcf12798_2fcbac41","line":379,"updated":"2026-08-24 15:26:14.000000000","message":"_check_rp_ownership() raises InvalidConfiguration from inside NVMeDriver.discover(), but discover() is invoked by ResourceTracker.update_usage() inside an unprotected per-driver loop. An exception from one NVMe device escapes update_usage() before report_data() is reached, so the agent\u0027s periodic update_available_resource task (run_immediately\u003dTrue) fails every cycle and no driver\u0027s resources are reported. The commit message states the intent is that \u0027the agent refuses to start\u0027, but init_host() performs no ownership check; the failure actually surfaces mid-periodic-task, repeatedly, and takes down reporting for all device types, not just the conflicting NVMe device.\n\n**Severity**: HIGH | **Confidence**: 0.78\n\n**Impact**: One device whose RP lacks OWNER_CYBORG stops resource reporting for every enabled driver on the host, on every periodic cycle, while the agent process appears healthy. This is a wider blast radius than the documented \u0027refuse to start\u0027 behavior, and operators get a repeated traceback instead of a single actionable startup failure.\n\n**Priority**: Before merge\n**Recommendation**:\nEither (a) move the RP-ownership check into init_host() so the failure genuinely prevents agent startup with a clear log message (matching the stated intent and the release note), or (b) keep it in discover() but log an error and skip the conflicting device, or (c) wrap per-driver discover() in try/except in ResourceTracker.update_usage() so one driver\u0027s failure cannot block other drivers\u0027 report_data. Add a test covering the chosen behavior for update_usage.","commit_id":"464886a0513fa09da932c3c8d925145ad6f60b7e"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"f357672bd2b87a33217b4527949aa082f78edd76","unresolved":true,"context_lines":[{"line_number":129,"context_line":"    if not controllers:"},{"line_number":130,"context_line":"        raise exception.DeviceNotFound(device\u003dpci_address)"},{"line_number":131,"context_line":""},{"line_number":132,"context_line":"    return \u0027/dev/\u0027 + controllers[0].name"},{"line_number":133,"context_line":""},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"class NVMeDriver(GenericDriver):"}],"source_content_type":"text/x-python","patch_set":17,"id":"9b396b68_f319e548","line":132,"range":{"start_line":132,"start_character":11,"end_line":132,"end_character":18},"updated":"2026-09-03 12:30:51.000000000","message":"nit: this should be a constant at teh moduel level so it can be patched in tests if needed similar to the sysfs var in the filesystem module","commit_id":"8221f14f14e9bb0be568cc1cc6fcaea7d912ac37"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"2567793a3ef340c8f8b24c5cd642ddadd0f49b08","unresolved":false,"context_lines":[{"line_number":129,"context_line":"    if not controllers:"},{"line_number":130,"context_line":"        raise exception.DeviceNotFound(device\u003dpci_address)"},{"line_number":131,"context_line":""},{"line_number":132,"context_line":"    return \u0027/dev/\u0027 + controllers[0].name"},{"line_number":133,"context_line":""},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"class NVMeDriver(GenericDriver):"}],"source_content_type":"text/x-python","patch_set":17,"id":"24c58a90_b9968658","line":132,"range":{"start_line":132,"start_character":11,"end_line":132,"end_character":18},"in_reply_to":"9b396b68_f319e548","updated":"2026-09-04 08:12:18.000000000","message":"Done","commit_id":"8221f14f14e9bb0be568cc1cc6fcaea7d912ac37"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"f357672bd2b87a33217b4527949aa082f78edd76","unresolved":true,"context_lines":[{"line_number":147,"context_line":"        check_nvme_cli_installed()"},{"line_number":148,"context_line":"        # Query Placement to learn which NVMe capability traits are registered."},{"line_number":149,"context_line":"        # Older deployments (pre-2026.2 os-traits) may not have HW_NVME_*."},{"line_number":150,"context_line":"        self.supported_traits \u003d {constants.OWNER_CYBORG}"},{"line_number":151,"context_line":"        for trait in (TRAIT_HW_NVME_CES, TRAIT_HW_NVME_BES, TRAIT_HW_NVME_WZS):"},{"line_number":152,"context_line":"            resp \u003d self._placement_client.get("},{"line_number":153,"context_line":"                f\u0027/traits/{trait}\u0027, version\u003d\u00271.6\u0027"},{"line_number":154,"context_line":"            )"},{"line_number":155,"context_line":"            if resp.status_code \u003d\u003d 204:"},{"line_number":156,"context_line":"                self.supported_traits.add(trait)"},{"line_number":157,"context_line":""},{"line_number":158,"context_line":"    def cleanup(self, device):"},{"line_number":159,"context_line":"        return None"}],"source_content_type":"text/x-python","patch_set":17,"id":"0497ddb1_7b0b0aca","line":156,"range":{"start_line":150,"start_character":5,"end_line":156,"end_character":48},"updated":"2026-09-03 12:30:51.000000000","message":"while this works its ineffeictn if you respin this patch can you use the list trait endpoint instead to do only one rest call\n\nhttps://docs.openstack.org/api-ref/placement/#list-traits\n\nit retuns a ditionary of all traits  but you can also pass the names as a list using the in: operator\n\nname\u003din:HW_CPU_X86_AVX,HW_CPU_X86_SSE,HW_CPU_X86_INVALID_FEATURE.\n\nso you can do a singel request which will return a list that will contain\n\nTRAIT_HW_NVME_CES, TRAIT_HW_NVME_BES, TRAIT_HW_NVME_WZS if they are defiedn\n\nthe return code is 200 wehn found although i dont know if it returns an empty list if tehy are not vaibel or a 404\n\nso we can defer this optimisation to a followup.\n\ni also feel like thi slogic shoudl live on our placement_cleint class since we shoudl be checking this in other drivers too in the future.","commit_id":"8221f14f14e9bb0be568cc1cc6fcaea7d912ac37"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"2567793a3ef340c8f8b24c5cd642ddadd0f49b08","unresolved":true,"context_lines":[{"line_number":147,"context_line":"        check_nvme_cli_installed()"},{"line_number":148,"context_line":"        # Query Placement to learn which NVMe capability traits are registered."},{"line_number":149,"context_line":"        # Older deployments (pre-2026.2 os-traits) may not have HW_NVME_*."},{"line_number":150,"context_line":"        self.supported_traits \u003d {constants.OWNER_CYBORG}"},{"line_number":151,"context_line":"        for trait in (TRAIT_HW_NVME_CES, TRAIT_HW_NVME_BES, TRAIT_HW_NVME_WZS):"},{"line_number":152,"context_line":"            resp \u003d self._placement_client.get("},{"line_number":153,"context_line":"                f\u0027/traits/{trait}\u0027, version\u003d\u00271.6\u0027"},{"line_number":154,"context_line":"            )"},{"line_number":155,"context_line":"            if resp.status_code \u003d\u003d 204:"},{"line_number":156,"context_line":"                self.supported_traits.add(trait)"},{"line_number":157,"context_line":""},{"line_number":158,"context_line":"    def cleanup(self, device):"},{"line_number":159,"context_line":"        return None"}],"source_content_type":"text/x-python","patch_set":17,"id":"ef6121d6_ac24462f","line":156,"range":{"start_line":150,"start_character":5,"end_line":156,"end_character":48},"in_reply_to":"0497ddb1_7b0b0aca","updated":"2026-09-04 08:12:18.000000000","message":"Yes, sounds good to move it under placement_client.py\n\nDone, https://review.opendev.org/c/openstack/cyborg/+/999937/20/cyborg/common/placement_client.py\n```\n    def get_standard_traits(self, trait_names):\n        \"\"\"Return the subset of trait_names that exist in placement.\"\"\"\n        query \u003d \u0027,\u0027.join(trait_names)\n        resp \u003d self.get(\u0027/traits?name\u003din:\u0027 + query, version\u003d\u00271.6\u0027)\n        if resp.status_code \u003d\u003d 200:\n            return set(resp.json().get(\u0027traits\u0027, []))\n        return set()\n```","commit_id":"8221f14f14e9bb0be568cc1cc6fcaea7d912ac37"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"f357672bd2b87a33217b4527949aa082f78edd76","unresolved":true,"context_lines":[{"line_number":156,"context_line":"                self.supported_traits.add(trait)"},{"line_number":157,"context_line":""},{"line_number":158,"context_line":"    def cleanup(self, device):"},{"line_number":159,"context_line":"        return None"},{"line_number":160,"context_line":""},{"line_number":161,"context_line":"    def discover(self):"},{"line_number":162,"context_line":"        if not CONF.nvme.device_spec:"}],"source_content_type":"text/x-python","patch_set":17,"id":"3efec058_d8b252fa","line":159,"updated":"2026-09-03 12:30:51.000000000","message":"so if we do not implemnt this in this patch we shoudl raise a config error in the current patch if you try to use this driver.. otherwse we have to merge patch and \nhttps://review.opendev.org/c/openstack/cyborg/+/999940/24  at the same time because it unsafe to use this driver without cleanup supprot\n\nit must not be possibel to use this driver end to end without cleanup implemnted\n\nthis is -2 worthy but we have ways to fix it\n\nif you rebase them one after another and we merge the 2 at the same time that might be ok\n\na better aprpoch woudl be to deleay registrying the driver in the entry point so it cant be loaded until after all of the cleanup code in \n\nhttps://review.opendev.org/c/openstack/cyborg/+/999939/21\nand \nhttps://review.opendev.org/c/openstack/cyborg/+/999940/24 \nare merged\n\nspecificly do not register it until \nhttps://review.opendev.org/c/openstack/cyborg/+/999942/27\n\nill comment on that in the pyproject.toml as well","commit_id":"8221f14f14e9bb0be568cc1cc6fcaea7d912ac37"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"a0ff0232dadc24ec2856867dd8854e4e31bcc2bb","unresolved":false,"context_lines":[{"line_number":156,"context_line":"                self.supported_traits.add(trait)"},{"line_number":157,"context_line":""},{"line_number":158,"context_line":"    def cleanup(self, device):"},{"line_number":159,"context_line":"        return None"},{"line_number":160,"context_line":""},{"line_number":161,"context_line":"    def discover(self):"},{"line_number":162,"context_line":"        if not CONF.nvme.device_spec:"}],"source_content_type":"text/x-python","patch_set":17,"id":"4159afc1_2b50b61d","line":159,"in_reply_to":"106f8212_6793d167","updated":"2026-09-04 12:35:39.000000000","message":"Acknowledged","commit_id":"8221f14f14e9bb0be568cc1cc6fcaea7d912ac37"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"2567793a3ef340c8f8b24c5cd642ddadd0f49b08","unresolved":true,"context_lines":[{"line_number":156,"context_line":"                self.supported_traits.add(trait)"},{"line_number":157,"context_line":""},{"line_number":158,"context_line":"    def cleanup(self, device):"},{"line_number":159,"context_line":"        return None"},{"line_number":160,"context_line":""},{"line_number":161,"context_line":"    def discover(self):"},{"line_number":162,"context_line":"        if not CONF.nvme.device_spec:"}],"source_content_type":"text/x-python","patch_set":17,"id":"106f8212_6793d167","line":159,"in_reply_to":"3efec058_d8b252fa","updated":"2026-09-04 08:12:18.000000000","message":"Moved the nvme driver entrypoint in https://review.opendev.org/c/openstack/cyborg/+/999942/31/pyproject.toml","commit_id":"8221f14f14e9bb0be568cc1cc6fcaea7d912ac37"},{"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":"94d6bb003a4cbc004c01959db75273a413db0519","unresolved":false,"context_lines":[{"line_number":177,"context_line":"            if spec is None:"},{"line_number":178,"context_line":"                continue"},{"line_number":179,"context_line":""},{"line_number":180,"context_line":"            self._check_rp_ownership(pci_dev[\u0027address\u0027])"},{"line_number":181,"context_line":""},{"line_number":182,"context_line":"            try:"},{"line_number":183,"context_line":"                caps \u003d self.get_capabilities(pci_dev[\u0027address\u0027])"}],"source_content_type":"text/x-python","patch_set":17,"id":"121fa9a2_00e41a18","line":180,"updated":"2026-08-31 10:40:49.000000000","message":"_check_rp_ownership() raises InvalidConfiguration from inside discover(), but discover() is invoked by ResourceTracker.update_usage() in a plain loop with no per-driver error isolation. The exception therefore propagates out of update_usage before report_data() is called, discarding devices already discovered by every other enabled driver for that cycle. The commit message states the intent is that \u0027the agent refuses to start rather than silently skipping a device\u0027; in fact the agent starts normally and then every periodic update_available_resource cycle errors out while the condition holds, so no accelerator resources on the host are reported at all.\n\n**Severity**: HIGH | **Confidence**: 0.75\n\n**Impact**: When the guard fires, the host reports no resources for any enabled driver (GPU, FPGA, QAT included) and recovers only by removing the device from [nvme] device_spec or manually fixing Placement, which is a much wider blast radius than the intended NVMe-only startup failure and contradicts the documented behavior.\n\n**Priority**: Before merge\n**Recommendation**:\nMove the ownership check into init_host() (where check_nvme_cli_installed already fails startup cleanly) or perform it once before the discover loop; alternatively catch per-device InvalidConfiguration in NVMeDriver.discover(), log the error, and skip only that device so update_usage for other drivers still completes. Also update the commit/release-note wording if the skip behavior is chosen.","commit_id":"8221f14f14e9bb0be568cc1cc6fcaea7d912ac37"},{"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":"c7c9578dc500b072016dfbff17690cb566de70fc","unresolved":false,"context_lines":[{"line_number":175,"context_line":"            if spec is None:"},{"line_number":176,"context_line":"                continue"},{"line_number":177,"context_line":""},{"line_number":178,"context_line":"            self._check_rp_ownership(pci_dev[\u0027address\u0027])"},{"line_number":179,"context_line":""},{"line_number":180,"context_line":"            try:"},{"line_number":181,"context_line":"                caps \u003d self.get_capabilities(pci_dev[\u0027address\u0027])"}],"source_content_type":"text/x-python","patch_set":18,"id":"c5fdc934_a3002a48","line":178,"updated":"2026-09-03 17:06:46.000000000","message":"The commit message states _check_rp_ownership() \u0027raises InvalidConfiguration so the agent refuses to start\u0027. In fact the check runs inside discover() (driver.py:178), which is invoked from ResourceTracker.update_usage(), a periodic task registered via RPCService.start()\u0027s add_dynamic_timer_args (common/service.py:66) after the RPC server is already up. AgentManager.init_host() is a no-op, so the agent starts successfully; the InvalidConfiguration then surfaces from the periodic task, where oslo_service logs/aborts the loop run. Because update_usage accumulates acc_list across all drivers (resource_tracker.py:76) before calling report_data, a raise from the NVMe driver aborts the whole run: no devices from any enabled driver (GPU, FPGA, etc.) are reported while the condition persists.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: A misconfigured [nvme] device_spec entry matching a Nova-owned RP leaves the agent apparently healthy (RPC server up) while silently stopping all accelerator reporting for every driver on the host until an operator correlates periodic-task error logs, rather than failing fast at startup as documented.\n\n**Suggestion**:\nPerform the ownership check in init_host() (which this change already gives the driver) or wrap the per-device check so the agent fails during startup validation as stated; alternatively log-and-skip just that device in discover() so unrelated drivers keep reporting. Also correct the commit-message wording if the periodic behavior is intended.","commit_id":"2eb5577d673c5b82d2b5f3c09978150fcbc67cb0"}],"cyborg/accelerator/drivers/nvme/nvme_cli.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":"bab78373f9ea23f3ddfde88ee1a5f0e808880f25","unresolved":false,"context_lines":[{"line_number":76,"context_line":""},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"@sys_admin_pctxt.entrypoint"},{"line_number":79,"context_line":"def nvme_id_ns(ns_dev):"},{"line_number":80,"context_line":"    out, _err \u003d processutils.execute("},{"line_number":81,"context_line":"        \u0027nvme\u0027,"},{"line_number":82,"context_line":"        \u0027id-ns\u0027,"}],"source_content_type":"text/x-python","patch_set":2,"id":"9d6e493d_29fc1e07","line":79,"updated":"2026-08-06 10:51:31.000000000","message":"The nvme_id_ns function is added to nvme_cli.py but has no corresponding test in test_nvme_cli.py. Every other nvme-cli wrapper function in the file has a dedicated test class.\n\n**Severity**: SUGGESTION | **Confidence**: 0.9\n\n**Benefit**: The nvme_id_ns function\u0027s JSON parsing behavior and argument passing are untested, creating a gap in regression protection for this new code.\n\n**Recommendation**:\nAdd a TestNvmeIdNs test class in test_nvme_cli.py following the same pattern as TestNvmeIdCtrl, mocking processutils.execute and verifying JSON parsing and argument passing.","commit_id":"8398e9c8a6b24df1a46fcfd061548e6486d50e27"},{"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":"bab78373f9ea23f3ddfde88ee1a5f0e808880f25","unresolved":false,"context_lines":[{"line_number":135,"context_line":""},{"line_number":136,"context_line":""},{"line_number":137,"context_line":"@sys_admin_pctxt.entrypoint"},{"line_number":138,"context_line":"def shred_device(block_dev):"},{"line_number":139,"context_line":"    processutils.execute(\u0027shred\u0027, \u0027-n0\u0027, \u0027-z\u0027, block_dev)"},{"line_number":140,"context_line":""},{"line_number":141,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"f2975583_9fcfc142","line":138,"updated":"2026-08-06 10:51:31.000000000","message":"The shred_device function calls \u0027shred -n0 -z\u0027 which performs zero random iterations plus one final zero overwrite. On NVMe SSDs, a single block-layer zero pass does not reliably erase data due to flash translation layer wear leveling and over-provisioning.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: Callers using shred_device expecting secure data erasure will get unreliable results on NVMe SSDs. Data from previous writes may persist in over-provisioned or remapped flash blocks. The NVMe sanitize command (also provided in this patch) is the proper mechanism for NVMe-level erasure.\n\n**Suggestion**:\nDocument that shred_device is not a secure-erase operation suitable for NVMe SSDs and should only be used as a quick clear, or remove the -n0 flag to use the default 3 random passes. Add a docstring clarifying limitations of block-layer shred on flash devices.","commit_id":"8398e9c8a6b24df1a46fcfd061548e6486d50e27"},{"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":"6b3f87138a1c37bd3836c692c8f58f8c9132bb1f","unresolved":false,"context_lines":[{"line_number":137,"context_line":""},{"line_number":138,"context_line":""},{"line_number":139,"context_line":"@sys_admin_pctxt.entrypoint"},{"line_number":140,"context_line":"def nvme_list_ns(nvme_dev):"},{"line_number":141,"context_line":"    \"\"\"Return the first active namespace ID on *nvme_dev*."},{"line_number":142,"context_line":""},{"line_number":143,"context_line":"    Handles both nvme-cli 1.x (bare JSON array) and 2.x"}],"source_content_type":"text/x-python","patch_set":6,"id":"41a3b2cc_4d660370","line":140,"updated":"2026-08-09 05:02:37.000000000","message":"The nvme_list_ns function contains the most complex branching logic in nvme_cli.py — it parses two different JSON output formats (nvme-cli 1.x bare array vs 2.x dict wrapper), falls back to an empty list for unexpected types, and raises DeviceNotFound when no namespaces are found. Despite this co...\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: Without tests, regressions in the 1.x/2.x format parsing or the DeviceNotFound raise path could go unnoticed. The function is intended for production use by the NVMe driver for device cleanup operations where silently returning the wrong value or failing to raise DeviceNotFound could lead to inco...\n\n**Suggestion**:\nAdd a TestNvmeListNs test class with at least three test cases: (1) nvme-cli 1.x bare-array output returns the first NSID, (2) nvme-cli 2.x dict-with-nsid_list output returns the first NSID, and (3) empty namespace list raises exception.DeviceNotFound. The test should use the _PrivsepFixture base class and mock processutils.execute as the other test classes do.","commit_id":"9dd236ab18d465227773e95ba57c059fedbd34e9"},{"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":"447d5025f8408c11eeb5bd5ab25014f2dc16e2c3","unresolved":false,"context_lines":[{"line_number":157,"context_line":"        ns_list \u003d []"},{"line_number":158,"context_line":"    if not ns_list:"},{"line_number":159,"context_line":"        raise exception.DeviceNotFound(device\u003dnvme_dev)"},{"line_number":160,"context_line":"    return ns_list[0]"},{"line_number":161,"context_line":""},{"line_number":162,"context_line":""},{"line_number":163,"context_line":"@sys_admin_pctxt.entrypoint"}],"source_content_type":"text/x-python","patch_set":7,"id":"6af69434_13fdcfc5","line":160,"updated":"2026-08-11 09:21:53.000000000","message":"The nvme_list_ns function documents that it returns an integer NSID, but for nvme-cli 1.x bare-array output it returns a dict (e.g. {\"nsid\": 1}) because ns_list[0] is the raw JSON object. For nvme-cli 2.x output ({\"nsid_list\": [1, 2]}), ns_list[0] is a bare integer. Callers cannot rely on a consi...\n\n**Severity**: HIGH | **Confidence**: 0.9\n\n**Risk**: Any caller of nvme_list_ns will receive a dict for nvme-cli 1.x and an int for 2.x. Using the result as an NSID (e.g., passing it to nvme_delete_ns or nvme_id_ns as the namespace ID) will fail silently or raise a TypeError on one format but not the other. The test itself uses a non-standard key \u0027...\n\n**Priority**: Before merge\n**Why This Matters**: Any caller of nvme_list_ns will receive a dict for nvme-cli 1.x and an int for 2.x. Using the result as an NSID (e.g., passing it to nvme_delete_ns or nvme_id_ns as the namespace ID) will fail silently or raise a TypeError on one format but not the other. The test itself uses a non-standard key \u0027...\n\n**Recommendation**:\nNormalize the return type by extracting the NSID integer from dict elements in the 1.x path. For example: after building ns_list from the bare array, map dict elements to their \u0027nsid\u0027 value: \u0027ns_list \u003d [e[\"nsid\"] if isinstance(e, dict) else e for e in ns_list]\u0027. Also update test_1x_bare_array to use the real \u0027nsid\u0027 key and assert an integer result.","commit_id":"5386a116dc121af99a299351906dc444f79bc4a4"},{"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":"7a25d3563b8557ad992721d293c5f3241a357562","unresolved":false,"context_lines":[{"line_number":144,"context_line":"    (``{\"nsid_list\": [...]}`` wrapper) output formats."},{"line_number":145,"context_line":""},{"line_number":146,"context_line":"    :param nvme_dev: NVMe controller path, e.g. ``/dev/nvme0``."},{"line_number":147,"context_line":"    :returns: integer NSID of the first active namespace."},{"line_number":148,"context_line":"    :raises DeviceNotFound: if no active namespaces are reported."},{"line_number":149,"context_line":"    \"\"\""},{"line_number":150,"context_line":"    out, _err \u003d processutils.execute(\u0027nvme\u0027, \u0027list-ns\u0027, nvme_dev, \u0027-o\u0027, \u0027json\u0027)"}],"source_content_type":"text/x-python","patch_set":8,"id":"2d9c2e39_e267b9a8","line":147,"updated":"2026-08-11 15:03:42.000000000","message":"The nvme_list_ns docstring states it returns an integer NSID, but when nvme-cli 1.x emits a bare JSON array of objects (e.g. [{\"id\": 1}, ...]), ns_list[0] returns a dict, not an int. This means callers cannot reliably use the return value as a namespace ID without first checking its type.\n\n**Severity**: HIGH | **Confidence**: 0.9\n\n**Risk**: Callers of nvme_list_ns will receive either a dict or an int depending on the nvme-cli version installed. Any code using the return value as a namespace ID (e.g., passing it to nvme_delete_ns or nvme_write_zeroes which str() it) will produce wrong results or cryptic failures when nvme-cli 1.x is...\n\n**Priority**: Before merge\n**Why This Matters**: Callers of nvme_list_ns will receive either a dict or an int depending on the nvme-cli version installed. Any code using the return value as a namespace ID (e.g., passing it to nvme_delete_ns or nvme_write_zeroes which str() it) will produce wrong results or cryptic failures when nvme-cli 1.x is...\n\n**Recommendation**:\nNormalize the return value to always be an integer NSID. For the 1.x array-of-dicts case, extract the NSID from the dict (e.g., ns_list[0][\u0027id\u0027] or ns_list[0][\u0027NSID\u0027]). Alternatively, return a consistent structure. Update the docstring to match.","commit_id":"7c7aadb5c16eb1e30b5b16259eb81dc15d57ad36"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"9d591742bde2cee9067dd1c73ab69686dde62510","unresolved":true,"context_lines":[{"line_number":36,"context_line":"        )"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"@sys_admin_pctxt.entrypoint"},{"line_number":40,"context_line":"def nvme_id_ctrl(nvme_dev):"},{"line_number":41,"context_line":"    out, _err \u003d processutils.execute("},{"line_number":42,"context_line":"        \u0027nvme\u0027,"},{"line_number":43,"context_line":"        \u0027id-ctrl\u0027,"}],"source_content_type":"text/x-python","patch_set":14,"id":"fa4ca958_8b0f4226","line":40,"range":{"start_line":39,"start_character":0,"end_line":40,"end_character":27},"updated":"2026-08-18 12:15:39.000000000","message":"there are 2 general rules about how you defiend and import privsep fucntions\n\nyou eithtehr define them in teh module where tehy are used (having a helper utiltiy module is generally not good practice, or you improt them with htere fully quealifed name\n\n\nand when you do defint them in a diffent moduel you are ment to add privileged to the name.\n\ni woudl prefer if you meved all of these to the driver\n\nhttps://review.opendev.org/c/openstack/cyborg/+/999938/15/cyborg/accelerator/drivers/nvme/driver.py\n\nand they shoudl be in the same change that uses them not in a sepreate patch\n\nso the driver and its tests should move one change eailer into this patch the agent changes can stay in the next patch","commit_id":"eb1da94748ebee9e2cc530fb0749d2ee08f96e2c"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"9d591742bde2cee9067dd1c73ab69686dde62510","unresolved":true,"context_lines":[{"line_number":60,"context_line":""},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"@sys_admin_pctxt.entrypoint"},{"line_number":63,"context_line":"def nvme_sanitize_log(nvme_dev):"},{"line_number":64,"context_line":"    out, _err \u003d processutils.execute("},{"line_number":65,"context_line":"        \u0027nvme\u0027,"},{"line_number":66,"context_line":"        \u0027sanitize-log\u0027,"}],"source_content_type":"text/x-python","patch_set":14,"id":"44357c84_48c8f32a","line":63,"updated":"2026-08-18 12:15:39.000000000","message":"im concerned you are defining this as i trided to make it very clear in the spec review that i did not want\nuse to end up useing this to poll for compeltion if there was any other way to do it\n\nthe fact it can return json helsp but its still concerning","commit_id":"eb1da94748ebee9e2cc530fb0749d2ee08f96e2c"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"9d591742bde2cee9067dd1c73ab69686dde62510","unresolved":true,"context_lines":[{"line_number":177,"context_line":"    processutils.execute(\u0027shred\u0027, \u0027-n0\u0027, \u0027-z\u0027, block_dev)"},{"line_number":178,"context_line":""},{"line_number":179,"context_line":""},{"line_number":180,"context_line":"def resolve_nvme_dev_from_pci(pci_address):"},{"line_number":181,"context_line":"    sysfs_path \u003d SYSFS_PCI_DEVICES / pci_address / \u0027nvme\u0027"},{"line_number":182,"context_line":"    if not sysfs_path.is_dir():"},{"line_number":183,"context_line":"        raise exception.DeviceNotFound(device\u003dpci_address)"},{"line_number":184,"context_line":"    controllers \u003d sorted(sysfs_path.iterdir())"},{"line_number":185,"context_line":"    if not controllers:"},{"line_number":186,"context_line":"        raise exception.DeviceNotFound(device\u003dpci_address)"},{"line_number":187,"context_line":"    return \u0027/dev/\u0027 + controllers[0].name"}],"source_content_type":"text/x-python","patch_set":14,"id":"ae085f48_8410e0f9","line":187,"range":{"start_line":180,"start_character":0,"end_line":187,"end_character":40},"updated":"2026-08-18 12:15:39.000000000","message":"this and all acces to /sys shoudl really go via\nhttps://review.opendev.org/c/openstack/cyborg/+/997048/12/cyborg/common/filesystem.py","commit_id":"eb1da94748ebee9e2cc530fb0749d2ee08f96e2c"}],"cyborg/agent/resource_tracker.py":[{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"9fb0349b61e0cd71ee4199ee299511520c036ce4","unresolved":true,"context_lines":[{"line_number":63,"context_line":"                name\u003dd,"},{"line_number":64,"context_line":"                invoke_on_load\u003dTrue,"},{"line_number":65,"context_line":"            ).driver"},{"line_number":66,"context_line":"            init_host \u003d getattr(acc_driver, \u0027init_host\u0027, None)"},{"line_number":67,"context_line":"            if callable(init_host):"},{"line_number":68,"context_line":"                init_host()"},{"line_number":69,"context_line":"            acc_drivers.append(acc_driver)"},{"line_number":70,"context_line":"        self.acc_drivers \u003d acc_drivers"},{"line_number":71,"context_line":""}],"source_content_type":"text/x-python","patch_set":15,"id":"0fddee25_76e3fba6","line":68,"range":{"start_line":66,"start_character":12,"end_line":68,"end_character":27},"updated":"2026-08-21 17:25:56.000000000","message":"this deserve a comment\n\nas by right we shoudl be adding init_host to all driver even if its a noop in this patch or a priror patch","commit_id":"794cc29348626347bba68690276afa3d26603c97"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"f357672bd2b87a33217b4527949aa082f78edd76","unresolved":true,"context_lines":[{"line_number":63,"context_line":"                name\u003dd,"},{"line_number":64,"context_line":"                invoke_on_load\u003dTrue,"},{"line_number":65,"context_line":"            ).driver"},{"line_number":66,"context_line":"            init_host \u003d getattr(acc_driver, \u0027init_host\u0027, None)"},{"line_number":67,"context_line":"            if callable(init_host):"},{"line_number":68,"context_line":"                init_host()"},{"line_number":69,"context_line":"            acc_drivers.append(acc_driver)"},{"line_number":70,"context_line":"        self.acc_drivers \u003d acc_drivers"},{"line_number":71,"context_line":""}],"source_content_type":"text/x-python","patch_set":15,"id":"b2e00124_73cfef01","line":68,"range":{"start_line":66,"start_character":12,"end_line":68,"end_character":27},"in_reply_to":"0fddee25_76e3fba6","updated":"2026-09-03 12:30:51.000000000","message":"i think its now on all drivers so we shoudl be able to remove this getattr adn callabel check","commit_id":"794cc29348626347bba68690276afa3d26603c97"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"2567793a3ef340c8f8b24c5cd642ddadd0f49b08","unresolved":false,"context_lines":[{"line_number":63,"context_line":"                name\u003dd,"},{"line_number":64,"context_line":"                invoke_on_load\u003dTrue,"},{"line_number":65,"context_line":"            ).driver"},{"line_number":66,"context_line":"            init_host \u003d getattr(acc_driver, \u0027init_host\u0027, None)"},{"line_number":67,"context_line":"            if callable(init_host):"},{"line_number":68,"context_line":"                init_host()"},{"line_number":69,"context_line":"            acc_drivers.append(acc_driver)"},{"line_number":70,"context_line":"        self.acc_drivers \u003d acc_drivers"},{"line_number":71,"context_line":""}],"source_content_type":"text/x-python","patch_set":15,"id":"cee7c7d6_9d5776c1","line":68,"range":{"start_line":66,"start_character":12,"end_line":68,"end_character":27},"in_reply_to":"b2e00124_73cfef01","updated":"2026-09-04 08:12:18.000000000","message":"Done","commit_id":"794cc29348626347bba68690276afa3d26603c97"}],"cyborg/common/placement_client.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":"c7c9578dc500b072016dfbff17690cb566de70fc","unresolved":false,"context_lines":[{"line_number":116,"context_line":"                )"},{"line_number":117,"context_line":"                continue"},{"line_number":118,"context_line":"            resp \u003d self.put(f\"/traits/{trait_name}\", None, version\u003d\u00271.6\u0027)"},{"line_number":119,"context_line":"            if resp.status_code in (200, 201):"},{"line_number":120,"context_line":"                LOG.info(\"Created trait %(trait)s\", {\"trait\": trait_name})"},{"line_number":121,"context_line":"            else:"},{"line_number":122,"context_line":"                raise Exception("}],"source_content_type":"text/x-python","patch_set":18,"id":"49a915d6_fb2ac4d3","line":119,"updated":"2026-09-03 17:06:46.000000000","message":"The change broadens the accepted PUT /traits/{name} statuses from 201 to (200, 201) to make trait creation idempotent, and adds a test asserting 200 is accepted. However the Placement API returns 201 when the trait is created and 204 when it already exists (verified in placement/handlers/trait.py put_trait: status\u003d201 on create, status\u003d204 when the trait was found or concurrently created); 200 is never returned. So the intended idempotency fix does not work: the GET-404-then-PUT-204 race (trait created between the preceding GET and the PUT) still falls into the else branch and raises a generic Exception, aborting add_traits_to_rp and the conductor\u0027s placement report.\n\n**Severity**: SUGGESTION | **Confidence**: 0.85\n\n**Impact**: The race path still crashes report_data with an opaque Exception, and the new unit test codifies an impossible status code, giving false confidence that trait re-creation is now idempotent.\n\n**Recommendation**:\nAccept (201, 204) instead of (200, 201) and update test_ensure_traits_accepts_existing_trait_put to mock 204; the change is two characters plus the test fixture.","commit_id":"2eb5577d673c5b82d2b5f3c09978150fcbc67cb0"},{"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":"3ede84005d8fb562f7cfa0a1bdd9357446006019","unresolved":false,"context_lines":[{"line_number":97,"context_line":"            )"},{"line_number":98,"context_line":"        return resp.json()"},{"line_number":99,"context_line":""},{"line_number":100,"context_line":"    def get_standard_traits(self, trait_names):"},{"line_number":101,"context_line":"        \"\"\"Return the subset of trait_names that exist in placement.\"\"\""},{"line_number":102,"context_line":"        query \u003d \u0027,\u0027.join(trait_names)"},{"line_number":103,"context_line":"        resp \u003d self.get(\u0027/traits?name\u003din:\u0027 + query, version\u003d\u00271.6\u0027)"}],"source_content_type":"text/x-python","patch_set":19,"id":"e11c6f4f_c1dd4aab","line":100,"updated":"2026-09-04 05:11:00.000000000","message":"PlacementClient.get_standard_traits() maps every non-200 response to set() with no logging and no exception. NVMeDriver.init_host() then sets supported_traits to {OWNER_CYBORG} only, and _build_driver_device() filters caps.traits by supported_traits. Any 4xx from Placement (policy denial on trait list, bad request, auth re-auth gone wrong) is indistinguishable from \u0027this deployment does not know HW_NVME_* traits\u0027.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: On a transient or policy-related Placement error, discovered NVMe devices are reported to Placement with OWNER_CYBORG only and no HW_NVME_* traits, with no log line explaining why. Operators cannot distinguish \u0027traits unsupported\u0027 from \u0027Placement call failed\u0027, and the missing traits silently persist until the agent restarts, because supported_traits is resolved only once in init_host().\n\n**Suggestion**:\nTreat only a genuine 200 as a trait answer: log a warning (or raise) for any other status before returning set(), e.g. `if resp.status_code !\u003d 200: LOG.warning(\u0027Failed to query standard traits: %s\u0027, resp.status_code); return set()`.","commit_id":"aee4a4fe390640e4438bce8cbb66e5704b58dd4d"},{"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":"f1cb9c4b11776db0d59f6bae76d14168b01d28c0","unresolved":false,"context_lines":[{"line_number":100,"context_line":"    def get_standard_traits(self, trait_names):"},{"line_number":101,"context_line":"        \"\"\"Return the subset of trait_names that exist in placement.\"\"\""},{"line_number":102,"context_line":"        query \u003d \u0027,\u0027.join(trait_names)"},{"line_number":103,"context_line":"        resp \u003d self.get(\u0027/traits?name\u003din:\u0027 + query, version\u003d\u00271.6\u0027)"},{"line_number":104,"context_line":"        if resp.status_code \u003d\u003d 200:"},{"line_number":105,"context_line":"            return set(resp.json().get(\u0027traits\u0027, []))"},{"line_number":106,"context_line":"        return set()"}],"source_content_type":"text/x-python","patch_set":20,"id":"c49b923e_aa063ace","line":103,"updated":"2026-09-04 06:25:38.000000000","message":"The new PlacementClient.get_standard_traits() sends \u0027/traits?name\u003din:CES,BES,WZS\u0027 with version\u003d\u00271.6\u0027. The `name` query parameter on GET /traits was added in Placement API microversion 1.17 (1.6 only introduced the base traits API with no name filtering). At microversion 1.6, placement either rejects the unknown query parameter (HTTP 400, since placement validates query-string keys), which this method silently converts to an empty set, or ignores the filter and returns the complete (paginated) trait collection instead of the requested subset.\n\n**Severity**: HIGH | **Confidence**: 0.78\n\n**Impact**: On a 400-returning placement, every NVMe RP is created with only OWNER_CYBORG and no HW_NVME_* traits, permanently degrading placement-based scheduling/filtering for NVMe devices with no error surfaced anywhere. On an ignoring placement, supported_traits is derived from the entire paginated trait list, so results depend on page size and unspecified behavior. The 400 case is fully silent because non-200 maps to an empty set.\n\n**Priority**: Before merge\n**Recommendation**:\nPass version\u003d\u00271.17\u0027 for this call (the microversion that introduced the name query parameter on GET /traits). Add a unit test that asserts the microversion argument passed to the SDK adapter (e.g. via self.mock_sdk.get call args), which the current mocked tests cannot catch.","commit_id":"49bf6e0290b9e3c8fb3e63292c316143de02cae6"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"a0ff0232dadc24ec2856867dd8854e4e31bcc2bb","unresolved":false,"context_lines":[{"line_number":100,"context_line":"    def get_standard_traits(self, trait_names):"},{"line_number":101,"context_line":"        \"\"\"Return the subset of trait_names that exist in placement.\"\"\""},{"line_number":102,"context_line":"        query \u003d \u0027,\u0027.join(trait_names)"},{"line_number":103,"context_line":"        resp \u003d self.get(\u0027/traits?name\u003din:\u0027 + query, version\u003d\u00271.6\u0027)"},{"line_number":104,"context_line":"        if resp.status_code \u003d\u003d 200:"},{"line_number":105,"context_line":"            return set(resp.json().get(\u0027traits\u0027, []))"},{"line_number":106,"context_line":"        return set()"}],"source_content_type":"text/x-python","patch_set":20,"id":"5d151afe_6a338f06","line":103,"in_reply_to":"c49b923e_aa063ace","updated":"2026-09-04 12:35:39.000000000","message":"hum ok 1.6 is for the trais api but teim thinks name is 1.17\n\nthat is actully 1.17 - Add ‘required’ parameter to the allocation candidates¶\n\n\nlooking at the code its in 1.6\n\nhttps://github.com/openstack/placement/commit/465d17ba10ac51c6a6dce4b609c3e1b2b4fa826c \n\ncodepilet thigns its in 1.40 whic does not exits and we dont docuemtn this specific in the api version history\n\nso this is incorrect but without the placement souce code aviabel to it teim coudl not actully check this it was relying on its inbuilt knowldage and or any docs checks it did.","commit_id":"49bf6e0290b9e3c8fb3e63292c316143de02cae6"},{"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":"cb280bb1bf300ae72393e3d5c1d6384b3d064e69","unresolved":false,"context_lines":[{"line_number":100,"context_line":"    def get_standard_traits(self, trait_names):"},{"line_number":101,"context_line":"        \"\"\"Return the subset of trait_names that exist in placement.\"\"\""},{"line_number":102,"context_line":"        query \u003d \u0027,\u0027.join(trait_names)"},{"line_number":103,"context_line":"        resp \u003d self.get(\u0027/traits?name\u003din:\u0027 + query, version\u003d\u00271.6\u0027)"},{"line_number":104,"context_line":"        if resp.status_code \u003d\u003d 200:"},{"line_number":105,"context_line":"            return set(resp.json().get(\u0027traits\u0027, []))"},{"line_number":106,"context_line":"        return set()"}],"source_content_type":"text/x-python","patch_set":21,"id":"f5ee2fa2_226e66bc","line":103,"updated":"2026-09-04 14:56:20.000000000","message":"PlacementClient.get_standard_traits() calls self.get(\u0027/traits?name\u003din:\u0027 + query, version\u003d\u00271.6\u0027). The \u0027name\u0027 query parameter on GET /traits, including the \u0027in:\u0027 prefix form, was introduced in Placement API microversion 1.37 (Stein). Requesting it at 1.6 makes Placement return a 400 error; the method\u0027s status check then silently returns an empty set with no log. NVMeDriver.init_host() therefore caches supported_traits \u003d {OWNER_CYBORG} only, so discover() strips HW_NVME_CES/BES/WZS from every device it reports, regardless of hardware sanitize/zero capabilities or whether the traits exist in Placement.\n\n**Severity**: HIGH | **Confidence**: 0.8\n\n**Impact**: The sanitize/zero capability traits advertised by the new driver are silently never reported: on every supported deployment the devices land in Placement with only OWNER_CYBORG, so consumers cannot select NVMe devices by CES/BES/WZS capability. The failure is invisible (no log, no exception), contradicting the commit message\u0027s claim that discover() reports HW_NVME_* traits known to the deployment\u0027s Placement.\n\n**Priority**: Before merge\n**Recommendation**:\nRequest version\u003d\u00271.37\u0027 for the \u0027/traits?name\u003din:\u0027 call (Placement services since Stein support it, which covers every deployment running current cyborg). Additionally log a warning when the response is not 200 instead of silently returning an empty set, and add a unit test asserting the microversion passed to the adapter.","commit_id":"ad7a4f96f6ae9838bbd33e04a42263aabaff0e53"}],"cyborg/conductor/manager.py":[{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"9fb0349b61e0cd71ee4199ee299511520c036ce4","unresolved":true,"context_lines":[{"line_number":200,"context_line":"            new_driver_dev_obj \u003d new_driver_device_list[new_cpid_list.index(a)]"},{"line_number":201,"context_line":"            try:"},{"line_number":202,"context_line":"                new_driver_dev_obj.create(context, host)"},{"line_number":203,"context_line":"                if new_driver_dev_obj.type \u003d\u003d constants.DEVICE_NVME:"},{"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":15,"id":"baf9505a_44e6215b","line":207,"range":{"start_line":203,"start_character":15,"end_line":207,"end_character":45},"updated":"2026-08-21 17:25:56.000000000","message":"this is not the right place to do that it should be happing on the agent side or in create but the conductor shoudl not need to special case for the nvme device here.\n\nalso this logic device_state shoudl be set on all device not jsut nvme devices","commit_id":"794cc29348626347bba68690276afa3d26603c97"},{"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":"3ede84005d8fb562f7cfa0a1bdd9357446006019","unresolved":false,"context_lines":[{"line_number":202,"context_line":"                new_driver_dev_obj.create(context, host)"},{"line_number":203,"context_line":"                # Best-effort: initialise device_state for all newly created"},{"line_number":204,"context_line":"                # devices. The conductor init_host backfill covers any failures."},{"line_number":205,"context_line":"                try:"},{"line_number":206,"context_line":"                    dev_obj \u003d new_driver_dev_obj.get_device_obj(context, host)"},{"line_number":207,"context_line":"                    if dev_obj is not None and dev_obj.device_state is None:"},{"line_number":208,"context_line":"                        dev_obj.device_state \u003d constants.DEVICE_STATE_AVAILABLE"}],"source_content_type":"text/x-python","patch_set":19,"id":"504979dd_8ee26c5b","line":205,"updated":"2026-09-04 05:11:00.000000000","message":"The nested try block added to ConductorManager.drv_device_make_diff() checks dev_obj.device_state is None after DriverDevice.create(). But Device.create() (cyborg/objects/device.py:113-116) already defaults device_state to DEVICE_STATE_AVAILABLE whenever the driver did not set it, and no driver in this change sets device_state to None. So the new block can never fire on the success path; it only adds queries. DriverDevice.get_device_obj() lists every Device on the host and issues a ControlpathID lookup per device, so each newly added device costs an O(devices-on-host) DB scan, inside the periodic report path.\n\n**Severity**: WARNING | **Confidence**: 0.85\n\n**Impact**: Wasted DB queries per newly added device on every periodic report cycle, dead code that future readers must reason about, and a stated intent in the commit message that the implementation cannot actually exercise. Also, the inner `except Exception` logs a warning without exc_info, hiding the failure cause.\n\n**Suggestion**:\nRemove the nested try block; the default in Device.create() already guarantees non-NULL device_state for newly created devices. If the intent is to make the state explicit for NVMe, set device_state on the DriverDevice before create() instead of re-reading from the DB.","commit_id":"aee4a4fe390640e4438bce8cbb66e5704b58dd4d"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"a0ff0232dadc24ec2856867dd8854e4e31bcc2bb","unresolved":true,"context_lines":[{"line_number":201,"context_line":"            try:"},{"line_number":202,"context_line":"                new_driver_dev_obj.create(context, host)"},{"line_number":203,"context_line":"                # Best-effort: initialise device_state for all newly created"},{"line_number":204,"context_line":"                # devices. The conductor init_host backfill covers any failures."},{"line_number":205,"context_line":"                try:"},{"line_number":206,"context_line":"                    dev_obj \u003d new_driver_dev_obj.get_device_obj(context, host)"},{"line_number":207,"context_line":"                    if dev_obj is not None and dev_obj.device_state is None:"}],"source_content_type":"text/x-python","patch_set":20,"id":"aa24bea7_9aa9f231","line":204,"updated":"2026-09-04 12:35:39.000000000","message":"the conductor shoudl not do this this shoudl be done by the comptue agent excludivly for create\n\nwe can keep this for now as its somewhat useful for old agents instead of healing on load but normally this woudl be gated by a min service version check and then deleted after a slurp release.\n\nso it proably shoudl ahve a TODO to remove it\n\nin genreal i would have relied on the heal on load personally and remove this entirly.","commit_id":"49bf6e0290b9e3c8fb3e63292c316143de02cae6"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"9b2e38c3b6457fb1f0c6a46d07887d365b13389c","unresolved":false,"context_lines":[{"line_number":201,"context_line":"            try:"},{"line_number":202,"context_line":"                new_driver_dev_obj.create(context, host)"},{"line_number":203,"context_line":"                # Best-effort: initialise device_state for all newly created"},{"line_number":204,"context_line":"                # devices. The conductor init_host backfill covers any failures."},{"line_number":205,"context_line":"                try:"},{"line_number":206,"context_line":"                    dev_obj \u003d new_driver_dev_obj.get_device_obj(context, host)"},{"line_number":207,"context_line":"                    if dev_obj is not None and dev_obj.device_state is None:"}],"source_content_type":"text/x-python","patch_set":20,"id":"044401d6_71c3a833","line":204,"in_reply_to":"aa24bea7_9aa9f231","updated":"2026-09-10 05:32:48.000000000","message":"Done, Added the todo","commit_id":"49bf6e0290b9e3c8fb3e63292c316143de02cae6"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"a0ff0232dadc24ec2856867dd8854e4e31bcc2bb","unresolved":true,"context_lines":[{"line_number":197,"context_line":"            old_driver_dev_obj.destroy(context, host)"},{"line_number":198,"context_line":"        # device is added"},{"line_number":199,"context_line":"        for a in added:"},{"line_number":200,"context_line":"            new_driver_dev_obj \u003d new_driver_device_list[new_cpid_list.index(a)]"},{"line_number":201,"context_line":"            try:"},{"line_number":202,"context_line":"                new_driver_dev_obj.create(context, host)"},{"line_number":203,"context_line":"                # Best-effort: initialise device_state for all newly created"},{"line_number":204,"context_line":"                # devices. The conductor init_host backfill covers any failures."},{"line_number":205,"context_line":"                try:"},{"line_number":206,"context_line":"                    dev_obj \u003d new_driver_dev_obj.get_device_obj(context, host)"},{"line_number":207,"context_line":"                    if dev_obj is not None and dev_obj.device_state is None:"},{"line_number":208,"context_line":"                        dev_obj.device_state \u003d constants.DEVICE_STATE_AVAILABLE"},{"line_number":209,"context_line":"                        dev_obj.save(context)"},{"line_number":210,"context_line":"                except Exception:"},{"line_number":211,"context_line":"                    LOG.warning("},{"line_number":212,"context_line":"                        \u0027Failed to initialise device_state for %(device)s\u0027,"},{"line_number":213,"context_line":"                        {\u0027device\u0027: new_driver_dev_obj},"},{"line_number":214,"context_line":"                    )"},{"line_number":215,"context_line":"            except Exception as exc:"},{"line_number":216,"context_line":"                LOG.exception("},{"line_number":217,"context_line":"                    \"Failed to add device %(device)s. Reason: %(reason)s\","}],"source_content_type":"text/x-python","patch_set":20,"id":"8d2b2017_8b7284d6","line":214,"range":{"start_line":200,"start_character":5,"end_line":214,"end_character":21},"updated":"2026-09-04 12:35:39.000000000","message":"this is inefficent you coudl have done this healing before the create call.\n\n\n```suggestion\n            new_driver_dev_obj \u003d new_driver_device_list[new_cpid_list.index(a)]\n            if (\u0027device_state\u0027 not in new_driver_dev_obj or\n                new_driver_dev_obj.device_state is None):\n                new_driver_dev_obj.device_state \u003d constants.DEVICE_STATE_AVAILABLE\n            new_driver_dev_obj.create(context, host)\n```\n\nalso the current try expct swallows all db errors with is incorrect","commit_id":"49bf6e0290b9e3c8fb3e63292c316143de02cae6"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"9b2e38c3b6457fb1f0c6a46d07887d365b13389c","unresolved":false,"context_lines":[{"line_number":197,"context_line":"            old_driver_dev_obj.destroy(context, host)"},{"line_number":198,"context_line":"        # device is added"},{"line_number":199,"context_line":"        for a in added:"},{"line_number":200,"context_line":"            new_driver_dev_obj \u003d new_driver_device_list[new_cpid_list.index(a)]"},{"line_number":201,"context_line":"            try:"},{"line_number":202,"context_line":"                new_driver_dev_obj.create(context, host)"},{"line_number":203,"context_line":"                # Best-effort: initialise device_state for all newly created"},{"line_number":204,"context_line":"                # devices. The conductor init_host backfill covers any failures."},{"line_number":205,"context_line":"                try:"},{"line_number":206,"context_line":"                    dev_obj \u003d new_driver_dev_obj.get_device_obj(context, host)"},{"line_number":207,"context_line":"                    if dev_obj is not None and dev_obj.device_state is None:"},{"line_number":208,"context_line":"                        dev_obj.device_state \u003d constants.DEVICE_STATE_AVAILABLE"},{"line_number":209,"context_line":"                        dev_obj.save(context)"},{"line_number":210,"context_line":"                except Exception:"},{"line_number":211,"context_line":"                    LOG.warning("},{"line_number":212,"context_line":"                        \u0027Failed to initialise device_state for %(device)s\u0027,"},{"line_number":213,"context_line":"                        {\u0027device\u0027: new_driver_dev_obj},"},{"line_number":214,"context_line":"                    )"},{"line_number":215,"context_line":"            except Exception as exc:"},{"line_number":216,"context_line":"                LOG.exception("},{"line_number":217,"context_line":"                    \"Failed to add device %(device)s. Reason: %(reason)s\","}],"source_content_type":"text/x-python","patch_set":20,"id":"994e5ca8_3ace110f","line":214,"range":{"start_line":200,"start_character":5,"end_line":214,"end_character":21},"in_reply_to":"8d2b2017_8b7284d6","updated":"2026-09-10 05:32:48.000000000","message":"Done","commit_id":"49bf6e0290b9e3c8fb3e63292c316143de02cae6"}],"cyborg/conf/agent.py":[{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"f357672bd2b87a33217b4527949aa082f78edd76","unresolved":true,"context_lines":[{"line_number":26,"context_line":"        help\u003d_("},{"line_number":27,"context_line":"            \u0027The accelerator drivers enabled on this agent. Such \u0027"},{"line_number":28,"context_line":"            \u0027as intel_fpga_driver, inspur_fpga_driver,\u0027"},{"line_number":29,"context_line":"            \u0027nvidia_gpu_driver, intel_qat_driver, nvme_driver,\u0027"},{"line_number":30,"context_line":"            \u0027inspur_nvme_ssd_driver, xilinx_fpga_driver, etc.\u0027"},{"line_number":31,"context_line":"        ),"},{"line_number":32,"context_line":"    ),"}],"source_content_type":"text/x-python","patch_set":17,"id":"c866f972_30ee63b9","line":29,"updated":"2026-09-03 12:30:51.000000000","message":"this shoudl also eb deferred","commit_id":"8221f14f14e9bb0be568cc1cc6fcaea7d912ac37"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"2567793a3ef340c8f8b24c5cd642ddadd0f49b08","unresolved":false,"context_lines":[{"line_number":26,"context_line":"        help\u003d_("},{"line_number":27,"context_line":"            \u0027The accelerator drivers enabled on this agent. Such \u0027"},{"line_number":28,"context_line":"            \u0027as intel_fpga_driver, inspur_fpga_driver,\u0027"},{"line_number":29,"context_line":"            \u0027nvidia_gpu_driver, intel_qat_driver, nvme_driver,\u0027"},{"line_number":30,"context_line":"            \u0027inspur_nvme_ssd_driver, xilinx_fpga_driver, etc.\u0027"},{"line_number":31,"context_line":"        ),"},{"line_number":32,"context_line":"    ),"}],"source_content_type":"text/x-python","patch_set":17,"id":"2b713c00_8c310f07","line":29,"in_reply_to":"c866f972_30ee63b9","updated":"2026-09-04 08:12:18.000000000","message":"Done","commit_id":"8221f14f14e9bb0be568cc1cc6fcaea7d912ac37"}],"cyborg/tests/unit/accelerator/drivers/nvme/test_devspec.py":[{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"f357672bd2b87a33217b4527949aa082f78edd76","unresolved":true,"context_lines":[{"line_number":18,"context_line":""},{"line_number":19,"context_line":"class TestNVMeDeviceSpec(base.TestCase):"},{"line_number":20,"context_line":"    def test_vendor_product_match(self):"},{"line_number":21,"context_line":"        spec \u003d NVMeDeviceSpec.from_config("},{"line_number":22,"context_line":"            \u0027{\"vendor_id\": \"8086\", \"product_id\": \"0001\"}\u0027"},{"line_number":23,"context_line":"        )"},{"line_number":24,"context_line":"        self.assertTrue(spec.match(\u00278086\u0027, \u00270001\u0027, \u00270000:01:00.0\u0027))"},{"line_number":25,"context_line":"        self.assertFalse(spec.match(\u0027144d\u0027, \u00270001\u0027, \u00270000:01:00.0\u0027))"},{"line_number":26,"context_line":""},{"line_number":27,"context_line":"    def test_vendor_only_matches_any_product(self):"},{"line_number":28,"context_line":"        spec \u003d NVMeDeviceSpec.from_config(\u0027{\"vendor_id\": \"8086\"}\u0027)"},{"line_number":29,"context_line":"        self.assertTrue(spec.match(\u00278086\u0027, \u0027anything\u0027, \u00270000:01:00.0\u0027))"}],"source_content_type":"text/x-python","patch_set":17,"id":"255d8c74_533d90d3","line":26,"range":{"start_line":21,"start_character":0,"end_line":26,"end_character":1},"updated":"2026-09-03 12:30:51.000000000","message":"this work but you shoudl also use self.flags to actully set the config option and test that at least once somewhere although probaly in the driver tests","commit_id":"8221f14f14e9bb0be568cc1cc6fcaea7d912ac37"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"a0ff0232dadc24ec2856867dd8854e4e31bcc2bb","unresolved":false,"context_lines":[{"line_number":18,"context_line":""},{"line_number":19,"context_line":"class TestNVMeDeviceSpec(base.TestCase):"},{"line_number":20,"context_line":"    def test_vendor_product_match(self):"},{"line_number":21,"context_line":"        spec \u003d NVMeDeviceSpec.from_config("},{"line_number":22,"context_line":"            \u0027{\"vendor_id\": \"8086\", \"product_id\": \"0001\"}\u0027"},{"line_number":23,"context_line":"        )"},{"line_number":24,"context_line":"        self.assertTrue(spec.match(\u00278086\u0027, \u00270001\u0027, \u00270000:01:00.0\u0027))"},{"line_number":25,"context_line":"        self.assertFalse(spec.match(\u0027144d\u0027, \u00270001\u0027, \u00270000:01:00.0\u0027))"},{"line_number":26,"context_line":""},{"line_number":27,"context_line":"    def test_vendor_only_matches_any_product(self):"},{"line_number":28,"context_line":"        spec \u003d NVMeDeviceSpec.from_config(\u0027{\"vendor_id\": \"8086\"}\u0027)"},{"line_number":29,"context_line":"        self.assertTrue(spec.match(\u00278086\u0027, \u0027anything\u0027, \u00270000:01:00.0\u0027))"}],"source_content_type":"text/x-python","patch_set":17,"id":"2d13bb17_d767e1c0","line":26,"range":{"start_line":21,"start_character":0,"end_line":26,"end_character":1},"in_reply_to":"255d8c74_533d90d3","updated":"2026-09-04 12:35:39.000000000","message":"you added self.cofnig instead of self.flags\n\nim planing to delete all useage of self.config in the fure whyich is why i asked you to use self.flags specficily.\n\nill resolve this for now but conider self.config as deprecated in the future and avoid adding new usage of it","commit_id":"8221f14f14e9bb0be568cc1cc6fcaea7d912ac37"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"9b2e38c3b6457fb1f0c6a46d07887d365b13389c","unresolved":false,"context_lines":[{"line_number":18,"context_line":""},{"line_number":19,"context_line":"class TestNVMeDeviceSpec(base.TestCase):"},{"line_number":20,"context_line":"    def test_vendor_product_match(self):"},{"line_number":21,"context_line":"        spec \u003d NVMeDeviceSpec.from_config("},{"line_number":22,"context_line":"            \u0027{\"vendor_id\": \"8086\", \"product_id\": \"0001\"}\u0027"},{"line_number":23,"context_line":"        )"},{"line_number":24,"context_line":"        self.assertTrue(spec.match(\u00278086\u0027, \u00270001\u0027, \u00270000:01:00.0\u0027))"},{"line_number":25,"context_line":"        self.assertFalse(spec.match(\u0027144d\u0027, \u00270001\u0027, \u00270000:01:00.0\u0027))"},{"line_number":26,"context_line":""},{"line_number":27,"context_line":"    def test_vendor_only_matches_any_product(self):"},{"line_number":28,"context_line":"        spec \u003d NVMeDeviceSpec.from_config(\u0027{\"vendor_id\": \"8086\"}\u0027)"},{"line_number":29,"context_line":"        self.assertTrue(spec.match(\u00278086\u0027, \u0027anything\u0027, \u00270000:01:00.0\u0027))"}],"source_content_type":"text/x-python","patch_set":17,"id":"6cb908a1_14b92ab0","line":26,"range":{"start_line":21,"start_character":0,"end_line":26,"end_character":1},"in_reply_to":"2d13bb17_d767e1c0","updated":"2026-09-10 05:32:48.000000000","message":"Done, replaces all occurances of self.config with self.flag in tests.","commit_id":"8221f14f14e9bb0be568cc1cc6fcaea7d912ac37"}],"cyborg/tests/unit/accelerator/drivers/nvme/test_nvme_cli.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":"447d5025f8408c11eeb5bd5ab25014f2dc16e2c3","unresolved":false,"context_lines":[{"line_number":179,"context_line":"class TestNvmeListNs(_PrivsepFixture):"},{"line_number":180,"context_line":"    @mock.patch(\u0027oslo_concurrency.processutils.execute\u0027)"},{"line_number":181,"context_line":"    def test_1x_bare_array(self, mock_exec):"},{"line_number":182,"context_line":"        mock_exec.return_value \u003d (\u0027[{\"id\": 1}, {\"id\": 2}]\u0027, \u0027\u0027)"},{"line_number":183,"context_line":"        result \u003d nvme_cli.nvme_list_ns(\u0027/dev/nvme0\u0027)"},{"line_number":184,"context_line":"        self.assertEqual({\u0027id\u0027: 1}, result)"},{"line_number":185,"context_line":"        mock_exec.assert_called_once_with("}],"source_content_type":"text/x-python","patch_set":7,"id":"0f1e052b_6170109b","line":182,"updated":"2026-08-11 09:21:53.000000000","message":"The test for nvme-cli 1.x list-ns output uses \u0027{\"id\": 1}\u0027 as the JSON object key, but real nvme-cli 1.x emits objects with a \u0027nsid\u0027 key (e.g., {\"nsid\": 1, ...}). This means the test does not reflect actual nvme-cli output and masks the return-type normalization bug in CF-001.\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: The test passes but does not exercise the real nvme-cli 1.x output format. If the return-type normalization suggested in CF-001 is implemented by extracting the \u0027nsid\u0027 key, this test would need to be updated and would reveal that the original code never handled the real format.\n\n**Suggestion**:\nUpdate the mock data to use the real \u0027nsid\u0027 key: \u0027[{\"nsid\": 1}, {\"nsid\": 2}]\u0027. Once CF-001 is fixed (normalizing to integer), the assertion should be self.assertEqual(1, result).","commit_id":"5386a116dc121af99a299351906dc444f79bc4a4"}],"pyproject.toml":[{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"f357672bd2b87a33217b4527949aa082f78edd76","unresolved":true,"context_lines":[{"line_number":60,"context_line":"intel_qat_driver \u003d \"cyborg.accelerator.drivers.qat.intel.driver:IntelQATDriver\""},{"line_number":61,"context_line":"intel_nic_driver \u003d \"cyborg.accelerator.drivers.nic.intel.driver:IntelNICDriver\""},{"line_number":62,"context_line":"inspur_nvme_ssd_driver \u003d \"cyborg.accelerator.drivers.ssd.inspur.driver:InspurNVMeSSDDriver\""},{"line_number":63,"context_line":"nvme_driver \u003d \"cyborg.accelerator.drivers.nvme.driver:NVMeDriver\""},{"line_number":64,"context_line":"pci_driver \u003d \"cyborg.accelerator.drivers.pci.pci.driver:PCIDriver\""},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"[tool.setuptools.packages.find]"}],"source_content_type":"text/x-toml","patch_set":17,"id":"c441895c_36f9b83a","line":63,"updated":"2026-09-03 12:30:51.000000000","message":"per my comment on cleanup pelase remove this and only add it in \n\nhttps://review.opendev.org/c/openstack/cyborg/+/999942/27","commit_id":"8221f14f14e9bb0be568cc1cc6fcaea7d912ac37"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"2567793a3ef340c8f8b24c5cd642ddadd0f49b08","unresolved":false,"context_lines":[{"line_number":60,"context_line":"intel_qat_driver \u003d \"cyborg.accelerator.drivers.qat.intel.driver:IntelQATDriver\""},{"line_number":61,"context_line":"intel_nic_driver \u003d \"cyborg.accelerator.drivers.nic.intel.driver:IntelNICDriver\""},{"line_number":62,"context_line":"inspur_nvme_ssd_driver \u003d \"cyborg.accelerator.drivers.ssd.inspur.driver:InspurNVMeSSDDriver\""},{"line_number":63,"context_line":"nvme_driver \u003d \"cyborg.accelerator.drivers.nvme.driver:NVMeDriver\""},{"line_number":64,"context_line":"pci_driver \u003d \"cyborg.accelerator.drivers.pci.pci.driver:PCIDriver\""},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"[tool.setuptools.packages.find]"}],"source_content_type":"text/x-toml","patch_set":17,"id":"8dfdb37d_bde3e666","line":63,"in_reply_to":"c441895c_36f9b83a","updated":"2026-09-04 08:12:18.000000000","message":"Done","commit_id":"8221f14f14e9bb0be568cc1cc6fcaea7d912ac37"}],"releasenotes/notes/add-nvme-generic-driver-a1b2c3d4e5f6.yaml":[{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"f357672bd2b87a33217b4527949aa082f78edd76","unresolved":true,"context_lines":[{"line_number":1,"context_line":"---"},{"line_number":2,"context_line":"features:"},{"line_number":3,"context_line":"  - |"},{"line_number":4,"context_line":"    Added support for the generic ``nvme_driver`` to discover local NVMe"},{"line_number":5,"context_line":"    controllers managed by Cyborg. Operators can target devices with the"},{"line_number":6,"context_line":"    ``[nvme] device_spec`` option."},{"line_number":7,"context_line":"upgrade:"}],"source_content_type":"text/x-yaml","patch_set":17,"id":"c7519f75_937ceb2e","line":4,"updated":"2026-09-03 12:30:51.000000000","message":"this shoudl be derefed to https://review.opendev.org/c/openstack/cyborg/+/999942/27","commit_id":"8221f14f14e9bb0be568cc1cc6fcaea7d912ac37"},{"author":{"_account_id":12393,"name":"chandan kumar","display_name":"Chandan Kumar","email":"chkumar@redhat.com","username":"chkumar246"},"change_message_id":"2567793a3ef340c8f8b24c5cd642ddadd0f49b08","unresolved":true,"context_lines":[{"line_number":1,"context_line":"---"},{"line_number":2,"context_line":"features:"},{"line_number":3,"context_line":"  - |"},{"line_number":4,"context_line":"    Added support for the generic ``nvme_driver`` to discover local NVMe"},{"line_number":5,"context_line":"    controllers managed by Cyborg. Operators can target devices with the"},{"line_number":6,"context_line":"    ``[nvme] device_spec`` option."},{"line_number":7,"context_line":"upgrade:"}],"source_content_type":"text/x-yaml","patch_set":17,"id":"2e946933_eff13046","line":4,"in_reply_to":"c7519f75_937ceb2e","updated":"2026-09-04 08:12:18.000000000","message":"Moved in https://review.opendev.org/c/openstack/cyborg/+/999942/31/releasenotes/notes/nvme-driver-edc31a48c8e003b0.yaml","commit_id":"8221f14f14e9bb0be568cc1cc6fcaea7d912ac37"}]}
