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)
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)
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)