Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
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)
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
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)
Ejemplo n.º 5
0
    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
Ejemplo n.º 6
0
 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)
Ejemplo n.º 7
0
    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
                        })