def _parse_white_list_from_config(self, whitelists): """Parse and validate the pci whitelist from the nova config.""" specs = [] for jsonspec in whitelists: try: dev_spec = jsonutils.loads(jsonspec) except ValueError: raise exception.PciConfigInvalidWhitelist( reason=_("Invalid entry: '%s'") % jsonspec) if isinstance(dev_spec, dict): dev_spec = [dev_spec] elif not isinstance(dev_spec, list): raise exception.PciConfigInvalidWhitelist( reason=_("Invalid entry: '%s'; " "Expecting list or dict") % jsonspec) for ds in dev_spec: if not isinstance(ds, dict): raise exception.PciConfigInvalidWhitelist( reason=_("Invalid entry: '%s'; " "Expecting dict") % ds) spec = devspec.PciDeviceSpec(ds) specs.append(spec) return specs
def get_pci_dev_info(pci_obj, property, max, hex_value): a = getattr(pci_obj, property) if a == ANY: return try: v = int(a, 16) except ValueError: raise exception.PciConfigInvalidWhitelist(reason="invalid %s %s" % (property, a)) if v > max: raise exception.PciConfigInvalidWhitelist( reason=_("invalid %(property)s %(attr)s") % { 'property': property, 'attr': a }) setattr(pci_obj, property, hex_value % v)
def get_pci_dev_info(pci_obj, property, max, hex_value): a = getattr(pci_obj, property) if a == ANY: return v = get_value(a) if v > max: raise exception.PciConfigInvalidWhitelist(reason="invalid %s %s" % (property, a)) setattr(pci_obj, property, hex_value % v)
def get_pci_dev_info(pci_obj, property, max, hex_value): a = getattr(pci_obj, property) if a == ANY: return v = get_value(a) if v > max: raise exception.PciConfigInvalidWhitelist( reason=_("invalid %(property)s %(attr)s") % {'property': property, 'attr': a}) setattr(pci_obj, property, hex_value % v)
def _parse_white_list_from_config(self, whitelists): """Parse and validate the pci whitelist from the nova config.""" specs = [] try: for jsonspecs in whitelists: spec = jsonutils.loads(jsonspecs) jsonschema.validate(spec, _WHITELIST_SCHEMA) specs.extend(spec) except Exception as e: raise exception.PciConfigInvalidWhitelist(reason=str(e)) return specs
def _set_pci_dev_info(self, prop, maxval, hex_value): a = getattr(self, prop) if a == ANY: return try: v = int(a, 16) except ValueError: raise exception.PciConfigInvalidWhitelist( reason=_("property %(property)s ('%(attr)s') does not parse " "as a hex number.") % { 'property': prop, 'attr': a }) if v > maxval: raise exception.PciConfigInvalidWhitelist( reason=_("property %(property)s (%(attr)s) is greater than " "the maximum allowable value (%(max)X).") % { 'property': prop, 'attr': a, 'max': maxval }) setattr(self, prop, hex_value % v)
def _init_dev_details(self) -> None: self.vendor_id = self.tags.pop("vendor_id", ANY) self.product_id = self.tags.pop("product_id", ANY) self.dev_name = self.tags.pop("devname", None) self.address: ty.Optional[WhitelistPciAddress] = None # Note(moshele): The address attribute can be a string or a dict. # For glob syntax or specific pci it is a string and for regex syntax # it is a dict. The WhitelistPciAddress class handles both types. address = self.tags.pop("address", None) self.vendor_id = self.vendor_id.strip() self._set_pci_dev_info('vendor_id', MAX_VENDOR_ID, '%04x') self._set_pci_dev_info('product_id', MAX_PRODUCT_ID, '%04x') if address and self.dev_name: raise exception.PciDeviceInvalidDeviceName() if not self.dev_name: self.address = WhitelistPciAddress(address or '*:*:*.*', False) # PFs with remote_managed tags are explicitly not supported. If they # are tagged as such by mistake in the whitelist Nova will # raise an exception. The reason for excluding PFs is the lack of a way # for an instance to access the control plane at the remote side (e.g. # on a DPU) for managing the PF representor corresponding to the PF. address_obj = self._address_obj() self._remote_managed = strutils.bool_from_string( self.tags.get(PCI_REMOTE_MANAGED_TAG)) if self._remote_managed: if address_obj is None: # Note that this will happen if a netdev was specified in the # whitelist but it is not actually present on a system - in # this case Nova is not able to look up an address by # a netdev name. raise exception.PciDeviceRemoteManagedNotPresent() elif address_obj.is_physical_function: pf_addr = str(address_obj.pci_address_spec) vf_product_id = utils.get_vf_product_id_by_pf_addr(pf_addr) # VF vendor IDs have to match the corresponding PF vendor IDs # per the SR-IOV spec so we use it for matching here. pf_vendor_id, pf_product_id = utils.get_pci_ids_by_pci_addr( pf_addr) # Check the actual vendor ID and VF product ID of an assumed # VF (based on the actual PF). The VF product ID must match # the actual one if this is a VF device spec. if (self.product_id == vf_product_id and self.vendor_id in (pf_vendor_id, ANY)): pass elif (self.product_id in (pf_product_id, ANY) and self.vendor_id in (pf_vendor_id, ANY)): raise exception.PciDeviceInvalidPFRemoteManaged( address_obj.pci_address_spec) else: # The specified product and vendor IDs of what is supposed # to be a VF corresponding to the PF PCI address do not # match the actual ones for this PF. This means that the # whitelist is invalid. raise exception.PciConfigInvalidWhitelist( reason=_('the specified VF vendor ID %(vendor_id)s and' ' product ID %(product_id)s do not match the' ' expected VF IDs based on the corresponding' ' PF identified by PCI address %(pf_addr)s') % { 'vendor_id': self.vendor_id, 'product_id': self.product_id, 'pf_addr': pf_addr })