Example #1
0
    def _validate_pci_irq_affinity_mask(flavor):
        key = 'hw:pci_irq_affinity_mask'
        if key in flavor.extra_specs:
            value = flavor.extra_specs[key]

            # check that we can properly parse the mask
            try:
                cpuset_ids = hardware._get_pci_affinity_mask(flavor)
            except Exception as e:
                msg = (_("Invalid %(K)s '%(V)s'; reason: %(R)s.") %
                       {'K': key,
                        'V': value,
                        'R': e.format_message()
                        })
                raise webob.exc.HTTPBadRequest(explanation=msg)

            # check that cpuset_ids are within valid range
            flavor_cpuset = set(range(flavor.vcpus))
            if not cpuset_ids.issubset(flavor_cpuset):
                msg = _('%(K)s value (%(V)s) must be a subset of vcpus '
                        '(%(S)s)') \
                        % {'K': key, 'V': value,
                           'S': utils.list_to_range(list(flavor_cpuset))}
                raise webob.exc.HTTPBadRequest(explanation=msg)

            # Check that we have specified dedicated cpus
            if flavor.extra_specs.get(CPU_POLICY_KEY) != \
                    fields.CPUAllocationPolicy.DEDICATED:
                msg = _('%(K)s is only valid when %(P)s is %(D)s.  Either '
                        'set extra spec %(P)s to %(D)s or do not set %(K)s.') \
                      % {'K': key,
                         'P': CPU_POLICY_KEY,
                         'D': fields.CPUAllocationPolicy.DEDICATED}
                raise webob.exc.HTTPConflict(explanation=msg)
Example #2
0
def get_pci_irqs_pinned_cpuset(flavor=None,
                               numa_topology=None,
                               pci_numa_node=None):
    """Get pinned cpuset where pci irq are affined.

    :param flavor: flavor
    :param pci_numa_node: numa node of a specific PCI device
    :param numa_topology: instance numa topology
    :return: cpuset, cpulist
    """
    cpuset = set()
    cpulist = ''

    if numa_topology is None or pci_numa_node is None or pci_numa_node < 0:
        return (cpuset, cpulist)

    # Determine full affinity cpuset, but restrict to pci's numa node
    for cell in numa_topology.cells:
        if cell.id == pci_numa_node:
            if cell.cpu_pinning is not None:
                cpuset.update(set(cell.cpu_pinning.values()))

    # Use extra-spec hw:pci_irq_affinity_mask only when the instance is pinned.
    if cpuset:
        pci_cpuset = hardware._get_pci_affinity_mask(flavor)
        if pci_cpuset:
            cpuset = set()
            for cell in numa_topology.cells:
                if cell.cpu_pinning is not None:
                    for vcpu in cell.cpuset:
                        if vcpu in pci_cpuset:
                            vcpu_cell, pcpu = numa_topology.vcpu_to_pcpu(vcpu)
                            cpuset.update(set([pcpu]))

    cpulist = utils.list_to_range(input_list=list(cpuset))
    return (cpuset, cpulist)
Example #3
0
    def _validate_cache_node(flavor):
        # Split a list into evenly sized chunks
        def chunk(it, size):
            it = iter(it)
            return iter(lambda: tuple(islice(it, size)), ())

        specs = flavor.extra_specs
        KEYS = ['hw:cache_l3', 'hw:cache_l3_code', 'hw:cache_l3_data']
        for this_key in KEYS:
            this_prefix = this_key + '.'
            for key in specs:
                if key.startswith(this_prefix):
                    # Check that we have specified dedicated cpus
                    if specs.get(CPU_POLICY_KEY) != \
                            fields.CPUAllocationPolicy.DEDICATED:
                        msg = (_('%(K)s is not permitted when %(P)s is set to'
                                 ' shared.') %
                               {'K': this_key,
                                'P': CPU_POLICY_KEY})
                        raise webob.exc.HTTPConflict(explanation=msg)

                    # Virtual numa node must be valid
                    suffix = key.split(this_prefix, 1)[1]
                    try:
                        vnode = int(suffix)
                    except ValueError:
                        msg = _('%s virtual numa node number must be an '
                                'integer') % this_key
                        raise webob.exc.HTTPBadRequest(explanation=msg)
                    if vnode < 0:
                        msg = _('%s virtual numa node number must be greater '
                                'than or equal to 0') % this_key
                        raise webob.exc.HTTPBadRequest(explanation=msg)

                    # Cache size must be valid and positive
                    try:
                        value = int(specs[key])
                    except ValueError:
                        msg = _('%s must be an integer') % key
                        raise webob.exc.HTTPBadRequest(explanation=msg)
                    if value <= 0:
                        msg = _('%s must be positive') % key
                        raise webob.exc.HTTPBadRequest(explanation=msg)

        # Check that we can properly parse hw:cache_vcpus.x cpulist,
        # and that vcpus are within valid range.
        flavor_cpuset = set(range(flavor.vcpus))
        cache_key = 'hw:cache_vcpus'
        cache_prefix = cache_key + '.'
        for key in specs:
            if key.startswith(cache_prefix):
                suffix = key.split(cache_prefix, 1)[1]
                try:
                    vnode = int(suffix)
                except ValueError:
                    msg = _('%s virtual numa node number must be an '
                            'integer') % cache_key
                    raise webob.exc.HTTPBadRequest(explanation=msg)
                if vnode < 0:
                    msg = _('%s virtual numa node number must be greater '
                            'than or equal to 0') % cache_key
                    raise webob.exc.HTTPBadRequest(explanation=msg)

                try:
                    value = specs[key]
                    cpuset_ids = hardware.parse_cpu_spec(value)
                except Exception as e:
                    msg = (_("Invalid %(K)s '%(V)s'; reason: %(R)s.") %
                           {'K': key,
                            'V': value,
                            'R': e.format_message()
                            })
                    raise webob.exc.HTTPBadRequest(explanation=msg)

                if not cpuset_ids:
                    msg = (_("Invalid %(K)s '%(V)s'; reason: %(R)s.") %
                           {'K': key,
                            'V': value,
                            'R': 'no vcpus specified'
                            })
                    raise webob.exc.HTTPBadRequest(explanation=msg)

                if not cpuset_ids.issubset(flavor_cpuset):
                    msg = _('%(K)s value (%(V)s) must be a subset of vcpus '
                            '(%(S)s)') \
                            % {'K': key, 'V': value,
                               'S': utils.list_to_range(list(flavor_cpuset))}
                    raise webob.exc.HTTPBadRequest(explanation=msg)

                # Check whether hw:cache_vcpus.x are subset of hw:numa_cpus.x
                cpus_key = 'hw:numa_cpus.' + suffix
                if cpus_key in specs:
                    try:
                        cpus_value = specs[cpus_key]
                        numa_cpuset = hardware.parse_cpu_spec(cpus_value)
                    except Exception as e:
                        msg = (_("Invalid %(K)s '%(V)s'; reason: %(R)s.") %
                               {'K': cpus_key,
                                'V': cpus_value,
                                'R': e.format_message()
                                })
                        raise webob.exc.HTTPBadRequest(explanation=msg)
                else:
                    NUMA_NODES_KEY = 'hw:numa_nodes'
                    try:
                        hw_numa_nodes = int(specs.get(NUMA_NODES_KEY, 1))
                    except ValueError:
                        msg = _('hw:numa_nodes value must be an integer')
                        raise webob.exc.HTTPBadRequest(explanation=msg)
                    if vnode >= hw_numa_nodes:
                        msg = (_('%(K)s must use vnode id less than the '
                                 'specified hw:numa_nodes value %(N)s.') %
                               {'K': this_key,
                                'N': hw_numa_nodes})
                        raise webob.exc.HTTPBadRequest(explanation=msg)
                    chunk_size = flavor.vcpus / hw_numa_nodes
                    numa_cpus = list(chunk(range(flavor.vcpus), chunk_size))
                    try:
                        numa_cpuset = set(numa_cpus[vnode])
                    except IndexError:
                        msg = _('%s virtual numa node number must be subset '
                                'of numa nodes') % vnode
                        raise webob.exc.HTTPBadRequest(explanation=msg)
                if not cpuset_ids.issubset(numa_cpuset):
                    msg = (_('%(K)s value (%(V)s) must be a subset of '
                             'vcpus (%(S)s)') %
                           {'K': cache_key, 'V': value,
                            'S': utils.list_to_range(list(numa_cpuset))
                            })
                    raise webob.exc.HTTPBadRequest(explanation=msg)

                # Check that we have specified dedicated cpus
                if specs.get(CPU_POLICY_KEY) != \
                        fields.CPUAllocationPolicy.DEDICATED:
                    msg = (_('%(K)s is not permitted when %(P)s is set to'
                             ' shared.') %
                           {'K': key,
                            'P': CPU_POLICY_KEY})
                    raise webob.exc.HTTPConflict(explanation=msg)