Esempio n. 1
0
class InstanceNUMACellPayload(base.NotificationPayloadBase):
    # Version 1.0: Initial version
    # Version 1.1: Added pcpuset field
    # Version 1.2: Added 'mixed' to cpu_policy field
    VERSION = '1.2'

    SCHEMA = {
        'id': ('numa_cell', 'id'),
        'cpuset': ('numa_cell', 'cpuset'),
        'pcpuset': ('numa_cell', 'pcpuset'),
        'cpuset_reserved': ('numa_cell', 'cpuset_reserved'),
        'memory': ('numa_cell', 'memory'),
        'pagesize': ('numa_cell', 'pagesize'),
        'cpu_pinning_raw': ('numa_cell', 'cpu_pinning_raw'),
        'cpu_policy': ('numa_cell', 'cpu_policy'),
        'cpu_thread_policy': ('numa_cell', 'cpu_thread_policy'),
    }

    fields = {
        'id': fields.IntegerField(),
        'cpuset': fields.SetOfIntegersField(),
        'pcpuset': fields.SetOfIntegersField(),
        'cpuset_reserved': fields.SetOfIntegersField(nullable=True),
        'memory': fields.IntegerField(),
        'pagesize': fields.IntegerField(nullable=True),
        'cpu_topology': fields.ObjectField('VirtCPUTopologyPayload',
                                           nullable=True),
        'cpu_pinning_raw': fields.DictOfIntegersField(nullable=True),
        'cpu_policy': fields.CPUAllocationPolicyField(nullable=True),
        'cpu_thread_policy':
        fields.CPUThreadAllocationPolicyField(nullable=True),
    }

    def __init__(self, numa_cell):
        super(InstanceNUMACellPayload, self).__init__()
        if (numa_cell.obj_attr_is_set('cpu_topology')
                and numa_cell.cpu_topology is not None):
            self.cpu_topology = VirtCPUTopologyPayload(numa_cell.cpu_topology)
        else:
            self.cpu_topology = None
        self.populate_schema(numa_cell=numa_cell)

    @classmethod
    def from_numa_cell_list_obj(cls, numa_cell_list):
        """Returns a list of InstanceNUMACellPayload objects
        based on the passed list of InstanceNUMACell objects.
        """
        payloads = []
        for numa_cell in numa_cell_list:
            payloads.append(cls(numa_cell))
        return payloads
Esempio n. 2
0
class NUMACell(base.NovaObject):
    # Version 1.0: Initial version
    VERSION = '1.0'

    fields = {
        'id': fields.IntegerField(read_only=True),
        'cpuset': fields.SetOfIntegersField(),
        'memory': fields.IntegerField(),
        'cpu_usage': fields.IntegerField(default=0),
        'memory_usage': fields.IntegerField(default=0),
    }

    def _to_dict(self):
        return {
            'id': self.id,
            'cpus': hardware.format_cpu_spec(self.cpuset, allow_ranges=False),
            'mem': {
                'total': self.memory,
                'used': self.memory_usage
            },
            'cpu_usage': self.cpu_usage
        }

    @classmethod
    def _from_dict(cls, data_dict):
        cpuset = hardware.parse_cpu_spec(data_dict.get('cpus', ''))
        cpu_usage = data_dict.get('cpu_usage', 0)
        memory = data_dict.get('mem', {}).get('total', 0)
        memory_usage = data_dict.get('mem', {}).get('used', 0)
        cell_id = data_dict.get('id')
        return cls(id=cell_id,
                   cpuset=cpuset,
                   memory=memory,
                   cpu_usage=cpu_usage,
                   memory_usage=memory_usage)
Esempio n. 3
0
class InstanceNUMACell(base.NovaObject):
    # Version 1.0: Initial version
    # Version 1.1: Add pagesize field
    VERSION = '1.1'

    fields = {
        'id': fields.IntegerField(read_only=True),
        'cpuset': fields.SetOfIntegersField(),
        'memory': fields.IntegerField(),
        'pagesize': fields.IntegerField(nullable=True),
        }

    def _to_dict(self):
        # NOTE(sahid): Used as legacy, could be renamed in
        # _legacy_to_dict_ to the future to avoid confusing.
        return {'cpus': hardware.format_cpu_spec(self.cpuset,
                                                 allow_ranges=False),
                'mem': {'total': self.memory},
                'id': self.id,
                'pagesize': self.pagesize}

    @classmethod
    def _from_dict(cls, data_dict):
        # NOTE(sahid): Used as legacy, could be renamed in
        # _legacy_from_dict_ to the future to avoid confusing.
        cpuset = hardware.parse_cpu_spec(data_dict.get('cpus', ''))
        memory = data_dict.get('mem', {}).get('total', 0)
        cell_id = data_dict.get('id')
        pagesize = data_dict.get('pagesize')
        return cls(id=cell_id, cpuset=cpuset,
                   memory=memory, pagesize=pagesize)
Esempio n. 4
0
 def setUp(self):
     super(TestSetOfIntegers, self).setUp()
     self.field = fields.SetOfIntegersField()
     self.coerce_good_values = [(set(['1', 2]), set([1, 2]))]
     self.coerce_bad_values = [set(['foo'])]
     self.to_primitive_values = [(set([1]), tuple([1]))]
     self.from_primitive_values = [(tuple([1]), set([1]))]
Esempio n. 5
0
class LibvirtLiveMigrateNUMAInfo(obj_base.NovaObject):
    # Version 1.0: Initial version
    VERSION = '1.0'

    fields = {
        # NOTE(artom) We need a 1:many cardinality here, so DictOfIntegers with
        # its 1:1 cardinality cannot work here. cpu_pins can have a single
        # guest CPU pinned to multiple host CPUs.
        'cpu_pins': fields.DictOfSetOfIntegersField(),
        # NOTE(artom) Currently we never pin a guest cell to more than a single
        # host cell, so cell_pins could be a DictOfIntegers, but
        # DictOfSetOfIntegers is more future-proof.
        'cell_pins': fields.DictOfSetOfIntegersField(),
        'emulator_pins': fields.SetOfIntegersField(),
        'sched_vcpus': fields.SetOfIntegersField(),
        'sched_priority': fields.IntegerField(),
    }
class InstanceNUMACell(base.NovaObject):
    # Version 1.0: Initial version
    VERSION = '1.0'

    fields = {
        'id': fields.IntegerField(read_only=True),
        'cpuset': fields.SetOfIntegersField(),
        'memory': fields.IntegerField(),
    }
Esempio n. 7
0
class InstanceNUMACell(base.NovaObject):
    # Version 1.0: Initial version
    # Version 1.1: Add pagesize field
    # Version 1.2: Add cpu_pinning_raw and topology fields
    VERSION = '1.2'

    fields = {
        'id': obj_fields.IntegerField(read_only=True),
        'cpuset': obj_fields.SetOfIntegersField(),
        'memory': obj_fields.IntegerField(),
        'pagesize': obj_fields.IntegerField(nullable=True),
        'cpu_topology': obj_fields.ObjectField('VirtCPUTopology',
                                               nullable=True),
        'cpu_pinning_raw': obj_fields.DictOfIntegersField(nullable=True)
    }

    obj_relationships = {'cpu_topology': [('1.2', '1.0')]}

    cpu_pinning = obj_fields.DictProxyField('cpu_pinning_raw')

    def __init__(self, **kwargs):
        super(InstanceNUMACell, self).__init__(**kwargs)
        if 'pagesize' not in kwargs:
            self.pagesize = None
            self.obj_reset_changes(['pagesize'])
        if 'cpu_topology' not in kwargs:
            self.cpu_topology = None
            self.obj_reset_changes(['cpu_topology'])
        if 'cpu_pinning' not in kwargs:
            self.cpu_pinning = None
            self.obj_reset_changes(['cpu_pinning_raw'])

    def __len__(self):
        return len(self.cpuset)

    def _to_dict(self):
        # NOTE(sahid): Used as legacy, could be renamed in
        # _legacy_to_dict_ to the future to avoid confusing.
        return {
            'cpus': hardware.format_cpu_spec(self.cpuset, allow_ranges=False),
            'mem': {
                'total': self.memory
            },
            'id': self.id,
            'pagesize': self.pagesize
        }

    @classmethod
    def _from_dict(cls, data_dict):
        # NOTE(sahid): Used as legacy, could be renamed in
        # _legacy_from_dict_ to the future to avoid confusing.
        cpuset = hardware.parse_cpu_spec(data_dict.get('cpus', ''))
        memory = data_dict.get('mem', {}).get('total', 0)
        cell_id = data_dict.get('id')
        pagesize = data_dict.get('pagesize')
        return cls(id=cell_id, cpuset=cpuset, memory=memory, pagesize=pagesize)
class InstanceNUMACell(base.NovaObject):
    # Version 1.0: Initial version
    # Version 1.1: Add pagesize field
    VERSION = '1.1'

    fields = {
        'id': fields.IntegerField(read_only=True),
        'cpuset': fields.SetOfIntegersField(),
        'memory': fields.IntegerField(),
        'pagesize': fields.IntegerField(nullable=True),
    }
Esempio n. 9
0
class NUMACell(base.NovaObject):
    # Version 1.0: Initial version
    # Version 1.1: Added pinned_cpus and siblings fields
    # Version 1.2: Added mempages field
    VERSION = '1.2'

    fields = {
        'id': fields.IntegerField(read_only=True),
        'cpuset': fields.SetOfIntegersField(),
        'memory': fields.IntegerField(),
        'cpu_usage': fields.IntegerField(default=0),
        'memory_usage': fields.IntegerField(default=0),
        'pinned_cpus': fields.SetOfIntegersField(),
        'siblings': fields.ListOfSetsOfIntegersField(),
        'mempages': fields.ListOfObjectsField('NUMAPagesTopology'),
    }

    obj_relationships = {'NUMAPagesTopology': [('1.2', '1.0')]}

    def __init__(self, **kwargs):
        super(NUMACell, self).__init__(**kwargs)
        if 'pinned_cpus' not in kwargs:
            self.pinned_cpus = set()
        if 'siblings' not in kwargs:
            self.siblings = []

    @property
    def free_cpus(self):
        return self.cpuset - self.pinned_cpus or set()

    def _to_dict(self):
        return {
            'id': self.id,
            'cpus': hardware.format_cpu_spec(self.cpuset, allow_ranges=False),
            'mem': {
                'total': self.memory,
                'used': self.memory_usage
            },
            'cpu_usage': self.cpu_usage
        }

    @classmethod
    def _from_dict(cls, data_dict):
        cpuset = hardware.parse_cpu_spec(data_dict.get('cpus', ''))
        cpu_usage = data_dict.get('cpu_usage', 0)
        memory = data_dict.get('mem', {}).get('total', 0)
        memory_usage = data_dict.get('mem', {}).get('used', 0)
        cell_id = data_dict.get('id')
        return cls(id=cell_id,
                   cpuset=cpuset,
                   memory=memory,
                   cpu_usage=cpu_usage,
                   memory_usage=memory_usage,
                   mempages=[])

    def can_fit_hugepages(self, pagesize, memory):
        """Returns whether memory can fit into hugepages size

        :param pagesize: a page size in KibB
        :param memory: a memory size asked to fit in KiB

        :returns: whether memory can fit in hugepages
        :raises: MemoryPageSizeNotSupported if page size not supported
        """
        for pages in self.mempages:
            if pages.size_kb == pagesize:
                return (memory <= pages.free_kb
                        and (memory % pages.size_kb) == 0)
        raise exception.MemoryPageSizeNotSupported(pagesize=pagesize)
Esempio n. 10
0
class InstanceNUMACell(base.NovaEphemeralObject, base.NovaObjectDictCompat):
    # Version 1.0: Initial version
    # Version 1.1: Add pagesize field
    # Version 1.2: Add cpu_pinning_raw and topology fields
    # Version 1.3: Add cpu_policy and cpu_thread_policy fields
    # Version 1.4: Add cpuset_reserved field
    # Version 1.5: Add pcpuset field
    # Version 1.6: Add 'mixed' to cpu_policy field
    VERSION = '1.6'

    def obj_make_compatible(self, primitive, target_version):
        super(InstanceNUMACell,
              self).obj_make_compatible(primitive, target_version)
        target_version = versionutils.convert_version_to_tuple(target_version)
        # Instance with a 'mixed' CPU policy could not provide a backward
        # compatibility.
        if target_version < (1, 6):
            if primitive['cpu_policy'] == obj_fields.CPUAllocationPolicy.MIXED:
                raise exception.ObjectActionError(
                    action='obj_make_compatible',
                    reason=_('%s policy is not supported in version %s') %
                    (primitive['cpu_policy'], target_version))

        # NOTE(huaqiang): Since version 1.5, 'cpuset' is modified to track the
        # unpinned CPUs only, with pinned CPUs tracked via 'pcpuset' instead.
        # For a backward compatibility, move the 'dedicated' instance CPU list
        # from 'pcpuset' to 'cpuset'.
        if target_version < (1, 5):
            if (primitive['cpu_policy'] ==
                    obj_fields.CPUAllocationPolicy.DEDICATED):
                primitive['cpuset'] = primitive['pcpuset']
            primitive.pop('pcpuset', None)

        if target_version < (1, 4):
            primitive.pop('cpuset_reserved', None)

        if target_version < (1, 3):
            primitive.pop('cpu_policy', None)
            primitive.pop('cpu_thread_policy', None)

    fields = {
        'id':
        obj_fields.IntegerField(),
        'cpuset':
        obj_fields.SetOfIntegersField(),
        'pcpuset':
        obj_fields.SetOfIntegersField(),
        # These physical CPUs are reserved for use by the hypervisor
        'cpuset_reserved':
        obj_fields.SetOfIntegersField(nullable=True, default=None),
        'memory':
        obj_fields.IntegerField(),
        'pagesize':
        obj_fields.IntegerField(nullable=True, default=None),
        # TODO(sean-k-mooney): This is no longer used and should be
        # removed in v2
        'cpu_topology':
        obj_fields.ObjectField('VirtCPUTopology', nullable=True),
        'cpu_pinning_raw':
        obj_fields.DictOfIntegersField(nullable=True, default=None),
        'cpu_policy':
        obj_fields.CPUAllocationPolicyField(nullable=True, default=None),
        'cpu_thread_policy':
        obj_fields.CPUThreadAllocationPolicyField(nullable=True, default=None),
    }

    cpu_pinning = obj_fields.DictProxyField('cpu_pinning_raw')

    def __len__(self):
        return len(self.total_cpus)

    @property
    def total_cpus(self):
        return self.cpuset | self.pcpuset

    @property
    def siblings(self):
        cpu_list = sorted(list(self.total_cpus))

        threads = 0
        if ('cpu_topology' in self) and self.cpu_topology:
            threads = self.cpu_topology.threads
        if threads == 1:
            threads = 0

        return list(map(set, zip(*[iter(cpu_list)] * threads)))

    def pin(self, vcpu, pcpu):
        if vcpu not in self.pcpuset:
            return
        pinning_dict = self.cpu_pinning or {}
        pinning_dict[vcpu] = pcpu
        self.cpu_pinning = pinning_dict

    def pin_vcpus(self, *cpu_pairs):
        for vcpu, pcpu in cpu_pairs:
            self.pin(vcpu, pcpu)

    def clear_host_pinning(self):
        """Clear any data related to how this cell is pinned to the host.

        Needed for aborting claims as we do not want to keep stale data around.
        """
        self.id = -1
        self.cpu_pinning = {}
        return self
Esempio n. 11
0
class NUMACell(base.NovaObject):
    # Version 1.0: Initial version
    # Version 1.1: Added pinned_cpus and siblings fields
    # Version 1.2: Added mempages field
    VERSION = '1.2'

    fields = {
        'id': fields.IntegerField(read_only=True),
        'cpuset': fields.SetOfIntegersField(),
        'memory': fields.IntegerField(),
        'cpu_usage': fields.IntegerField(default=0),
        'memory_usage': fields.IntegerField(default=0),
        'pinned_cpus': fields.SetOfIntegersField(),
        'siblings': fields.ListOfSetsOfIntegersField(),
        'mempages': fields.ListOfObjectsField('NUMAPagesTopology'),
    }

    def __eq__(self, other):
        return all_things_equal(self, other)

    def __ne__(self, other):
        return not (self == other)

    @property
    def free_cpus(self):
        return self.cpuset - self.pinned_cpus or set()

    @property
    def free_siblings(self):
        return [sibling_set & self.free_cpus for sibling_set in self.siblings]

    @property
    def avail_cpus(self):
        return len(self.free_cpus)

    @property
    def avail_memory(self):
        return self.memory - self.memory_usage

    def pin_cpus(self, cpus):
        if cpus - self.cpuset:
            raise exception.CPUPinningUnknown(requested=list(cpus),
                                              cpuset=list(self.pinned_cpus))
        if self.pinned_cpus & cpus:
            raise exception.CPUPinningInvalid(requested=list(cpus),
                                              pinned=list(self.pinned_cpus))
        self.pinned_cpus |= cpus

    def unpin_cpus(self, cpus):
        if cpus - self.cpuset:
            raise exception.CPUPinningUnknown(requested=list(cpus),
                                              cpuset=list(self.pinned_cpus))
        if (self.pinned_cpus & cpus) != cpus:
            raise exception.CPUPinningInvalid(requested=list(cpus),
                                              pinned=list(self.pinned_cpus))
        self.pinned_cpus -= cpus

    def _to_dict(self):
        return {
            'id': self.id,
            'cpus': hardware.format_cpu_spec(self.cpuset, allow_ranges=False),
            'mem': {
                'total': self.memory,
                'used': self.memory_usage
            },
            'cpu_usage': self.cpu_usage
        }

    @classmethod
    def _from_dict(cls, data_dict):
        cpuset = hardware.parse_cpu_spec(data_dict.get('cpus', ''))
        cpu_usage = data_dict.get('cpu_usage', 0)
        memory = data_dict.get('mem', {}).get('total', 0)
        memory_usage = data_dict.get('mem', {}).get('used', 0)
        cell_id = data_dict.get('id')
        return cls(id=cell_id,
                   cpuset=cpuset,
                   memory=memory,
                   cpu_usage=cpu_usage,
                   memory_usage=memory_usage,
                   mempages=[],
                   pinned_cpus=set([]),
                   siblings=[])

    def can_fit_hugepages(self, pagesize, memory):
        """Returns whether memory can fit into hugepages size

        :param pagesize: a page size in KibB
        :param memory: a memory size asked to fit in KiB

        :returns: whether memory can fit in hugepages
        :raises: MemoryPageSizeNotSupported if page size not supported
        """
        for pages in self.mempages:
            if pages.size_kb == pagesize:
                return (memory <= pages.free_kb
                        and (memory % pages.size_kb) == 0)
        raise exception.MemoryPageSizeNotSupported(pagesize=pagesize)
Esempio n. 12
0
class NUMACell(base.NovaObject):
    # Version 1.0: Initial version
    # Version 1.1: Added pinned_cpus and siblings fields
    # Version 1.2: Added mempages field
    # Version 1.3: Add network_metadata field
    VERSION = '1.3'

    fields = {
        'id': fields.IntegerField(read_only=True),
        'cpuset': fields.SetOfIntegersField(),
        'memory': fields.IntegerField(),
        'cpu_usage': fields.IntegerField(default=0),
        'memory_usage': fields.IntegerField(default=0),
        'pinned_cpus': fields.SetOfIntegersField(),
        'siblings': fields.ListOfSetsOfIntegersField(),
        'mempages': fields.ListOfObjectsField('NUMAPagesTopology'),
        'network_metadata': fields.ObjectField('NetworkMetadata'),
    }

    def obj_make_compatible(self, primitive, target_version):
        super(NUMACell, self).obj_make_compatible(primitive, target_version)
        target_version = versionutils.convert_version_to_tuple(target_version)
        if target_version < (1, 3):
            primitive.pop('network_metadata', None)

    def __eq__(self, other):
        return all_things_equal(self, other)

    def __ne__(self, other):
        return not (self == other)

    @property
    def free_cpus(self):
        return self.cpuset - self.pinned_cpus or set()

    @property
    def free_siblings(self):
        return [sibling_set & self.free_cpus for sibling_set in self.siblings]

    @property
    def avail_cpus(self):
        return len(self.free_cpus)

    @property
    def avail_memory(self):
        return self.memory - self.memory_usage

    @property
    def has_threads(self):
        """Check if SMT threads, a.k.a. HyperThreads, are present."""
        return any(len(sibling_set) > 1 for sibling_set in self.siblings)

    def pin_cpus(self, cpus):
        if cpus - self.cpuset:
            raise exception.CPUPinningUnknown(requested=list(cpus),
                                              cpuset=list(self.cpuset))
        if self.pinned_cpus & cpus:
            raise exception.CPUPinningInvalid(requested=list(cpus),
                                              free=list(self.cpuset -
                                                        self.pinned_cpus))
        self.pinned_cpus |= cpus

    def unpin_cpus(self, cpus):
        if cpus - self.cpuset:
            raise exception.CPUUnpinningUnknown(requested=list(cpus),
                                                cpuset=list(self.cpuset))
        if (self.pinned_cpus & cpus) != cpus:
            raise exception.CPUUnpinningInvalid(requested=list(cpus),
                                                pinned=list(self.pinned_cpus))
        self.pinned_cpus -= cpus

    def pin_cpus_with_siblings(self, cpus):
        pin_siblings = set()
        for sib in self.siblings:
            if cpus & sib:
                pin_siblings.update(sib)
        self.pin_cpus(pin_siblings)

    def unpin_cpus_with_siblings(self, cpus):
        pin_siblings = set()
        for sib in self.siblings:
            if cpus & sib:
                pin_siblings.update(sib)
        self.unpin_cpus(pin_siblings)

    @classmethod
    def _from_dict(cls, data_dict):
        cpuset = hardware.parse_cpu_spec(data_dict.get('cpus', ''))
        cpu_usage = data_dict.get('cpu_usage', 0)
        memory = data_dict.get('mem', {}).get('total', 0)
        memory_usage = data_dict.get('mem', {}).get('used', 0)
        cell_id = data_dict.get('id')
        return cls(id=cell_id,
                   cpuset=cpuset,
                   memory=memory,
                   cpu_usage=cpu_usage,
                   memory_usage=memory_usage,
                   mempages=[],
                   pinned_cpus=set([]),
                   siblings=[])

    def can_fit_hugepages(self, pagesize, memory):
        """Returns whether memory can fit into hugepages size

        :param pagesize: a page size in KibB
        :param memory: a memory size asked to fit in KiB

        :returns: whether memory can fit in hugepages
        :raises: MemoryPageSizeNotSupported if page size not supported
        """
        for pages in self.mempages:
            if pages.size_kb == pagesize:
                return (memory <= pages.free_kb
                        and (memory % pages.size_kb) == 0)
        raise exception.MemoryPageSizeNotSupported(pagesize=pagesize)
Esempio n. 13
0
class InstanceNUMACell(base.NovaEphemeralObject, base.NovaObjectDictCompat):
    # Version 1.0: Initial version
    # Version 1.1: Add pagesize field
    # Version 1.2: Add cpu_pinning_raw and topology fields
    # Version 1.3: Add cpu_policy and cpu_thread_policy fields
    # Version 1.4: Add cpuset_reserved field
    VERSION = '1.4'

    def obj_make_compatible(self, primitive, target_version):
        super(InstanceNUMACell,
              self).obj_make_compatible(primitive, target_version)
        target_version = versionutils.convert_version_to_tuple(target_version)
        if target_version < (1, 4):
            primitive.pop('cpuset_reserved', None)

        if target_version < (1, 3):
            primitive.pop('cpu_policy', None)
            primitive.pop('cpu_thread_policy', None)

    fields = {
        'id':
        obj_fields.IntegerField(),
        'cpuset':
        obj_fields.SetOfIntegersField(),
        'memory':
        obj_fields.IntegerField(),
        'pagesize':
        obj_fields.IntegerField(nullable=True, default=None),
        'cpu_topology':
        obj_fields.ObjectField('VirtCPUTopology', nullable=True),
        'cpu_pinning_raw':
        obj_fields.DictOfIntegersField(nullable=True, default=None),
        'cpu_policy':
        obj_fields.CPUAllocationPolicyField(nullable=True, default=None),
        'cpu_thread_policy':
        obj_fields.CPUThreadAllocationPolicyField(nullable=True, default=None),
        # These physical CPUs are reserved for use by the hypervisor
        'cpuset_reserved':
        obj_fields.SetOfIntegersField(nullable=True, default=None),
    }

    cpu_pinning = obj_fields.DictProxyField('cpu_pinning_raw')

    def __len__(self):
        return len(self.cpuset)

    @property
    def siblings(self):
        cpu_list = sorted(list(self.cpuset))

        threads = 0
        if ('cpu_topology' in self) and self.cpu_topology:
            threads = self.cpu_topology.threads
        if threads == 1:
            threads = 0

        return list(map(set, zip(*[iter(cpu_list)] * threads)))

    def pin(self, vcpu, pcpu):
        if vcpu not in self.cpuset:
            return
        pinning_dict = self.cpu_pinning or {}
        pinning_dict[vcpu] = pcpu
        self.cpu_pinning = pinning_dict

    def pin_vcpus(self, *cpu_pairs):
        for vcpu, pcpu in cpu_pairs:
            self.pin(vcpu, pcpu)

    def clear_host_pinning(self):
        """Clear any data related to how this cell is pinned to the host.

        Needed for aborting claims as we do not want to keep stale data around.
        """
        self.id = -1
        self.cpu_pinning = {}
        return self
Esempio n. 14
0
class NUMACell(base.NovaObject):
    # Version 1.0: Initial version
    # Version 1.1: Added pinned_cpus and siblings fields
    # Version 1.2: Added mempages field
    # Version 1.3: Add network_metadata field
    # Version 1.4: Add pcpuset
    VERSION = '1.4'

    fields = {
        'id': obj_fields.IntegerField(read_only=True),
        'cpuset': obj_fields.SetOfIntegersField(),
        'pcpuset': obj_fields.SetOfIntegersField(),
        'memory': obj_fields.IntegerField(),
        'cpu_usage': obj_fields.IntegerField(default=0),
        'memory_usage': obj_fields.IntegerField(default=0),
        'pinned_cpus': obj_fields.SetOfIntegersField(),
        'siblings': obj_fields.ListOfSetsOfIntegersField(),
        'mempages': obj_fields.ListOfObjectsField('NUMAPagesTopology'),
        'network_metadata': obj_fields.ObjectField('NetworkMetadata'),
    }

    def obj_make_compatible(self, primitive, target_version):
        super(NUMACell, self).obj_make_compatible(primitive, target_version)
        target_version = versionutils.convert_version_to_tuple(target_version)
        if target_version < (1, 4):
            primitive.pop('pcpuset', None)
        if target_version < (1, 3):
            primitive.pop('network_metadata', None)

    def __eq__(self, other):
        return base.all_things_equal(self, other)

    def __ne__(self, other):
        return not (self == other)

    @property
    def free_pcpus(self):
        """Return available dedicated CPUs."""
        return self.pcpuset - self.pinned_cpus or set()

    @property
    def free_siblings(self):
        """Return available dedicated CPUs in their sibling set form."""
        return [sibling_set & self.free_pcpus for sibling_set in self.siblings]

    @property
    def avail_pcpus(self):
        """Return number of available dedicated CPUs."""
        return len(self.free_pcpus)

    @property
    def avail_memory(self):
        return self.memory - self.memory_usage

    @property
    def has_threads(self):
        """Check if SMT threads, a.k.a. HyperThreads, are present."""
        return any(len(sibling_set) > 1 for sibling_set in self.siblings)

    def pin_cpus(self, cpus):
        if cpus - self.pcpuset:
            raise exception.CPUPinningUnknown(requested=list(cpus),
                                              available=list(self.pcpuset))

        if self.pinned_cpus & cpus:
            available = list(self.pcpuset - self.pinned_cpus)
            raise exception.CPUPinningInvalid(requested=list(cpus),
                                              available=available)

        self.pinned_cpus |= cpus

    def unpin_cpus(self, cpus):
        if cpus - self.pcpuset:
            raise exception.CPUUnpinningUnknown(requested=list(cpus),
                                                available=list(self.pcpuset))

        if (self.pinned_cpus & cpus) != cpus:
            raise exception.CPUUnpinningInvalid(requested=list(cpus),
                                                available=list(
                                                    self.pinned_cpus))

        self.pinned_cpus -= cpus

    def pin_cpus_with_siblings(self, cpus):
        pin_siblings = set()
        for sib in self.siblings:
            if cpus & sib:
                pin_siblings.update(sib)
        self.pin_cpus(pin_siblings)

    def unpin_cpus_with_siblings(self, cpus):
        pin_siblings = set()
        for sib in self.siblings:
            if cpus & sib:
                pin_siblings.update(sib)
        self.unpin_cpus(pin_siblings)

    def can_fit_pagesize(self, pagesize, memory, use_free=True):
        """Returns whether memory can fit into a given pagesize.

        :param pagesize: a page size in KibB
        :param memory: a memory size asked to fit in KiB
        :param use_free: if true, assess based on free memory rather than total
            memory. This means overcommit is not allowed, which should be the
            case for hugepages since these are memlocked by the kernel and
            can't be swapped out.

        :returns: whether memory can fit in hugepages
        :raises: MemoryPageSizeNotSupported if page size not supported
        """
        for pages in self.mempages:
            avail_kb = pages.free_kb if use_free else pages.total_kb
            if pages.size_kb == pagesize:
                return memory <= avail_kb and (memory % pages.size_kb) == 0
        raise exception.MemoryPageSizeNotSupported(pagesize=pagesize)
Esempio n. 15
0
class MigrationContext(base.NovaPersistentObject, base.NovaObject):
    """Data representing additional resources related to a migration.

    Some resources cannot be calculated from knowing the flavor alone for the
    purpose of resources tracking, but need to be persisted at the time the
    claim was made, for subsequent resource tracking runs to be consistent.
    MigrationContext objects are created when the claim is done and are there
    to facilitate resource tracking and final provisioning of the instance on
    the destination host.
    """

    # Version 1.0: Initial version
    # Version 1.1: Add old/new pci_devices and pci_requests
    #              WRS: add new_allowed_cpus
    VERSION = '1.1'

    fields = {
        'instance_uuid': fields.UUIDField(),
        'migration_id': fields.IntegerField(),
        'new_numa_topology': fields.ObjectField('InstanceNUMATopology',
                                                nullable=True),
        'old_numa_topology': fields.ObjectField('InstanceNUMATopology',
                                                nullable=True),
        'new_pci_devices': fields.ObjectField('PciDeviceList',
                                              nullable=True),
        'old_pci_devices': fields.ObjectField('PciDeviceList',
                                              nullable=True),
        'new_pci_requests': fields.ObjectField('InstancePCIRequests',
                                               nullable=True),
        'old_pci_requests': fields.ObjectField('InstancePCIRequests',
                                                nullable=True),
        # WRS: handle migration to hosts of different cpu topology.
        # This is also added in R3/Mitaka (v1.0) so don't need to make
        # compatible.
        'new_allowed_cpus': fields.SetOfIntegersField(),
    }

    def obj_make_compatible(cls, primitive, target_version):
        super(MigrationContext, cls).obj_make_compatible(primitive,
                                                         target_version)
        target_version = versionutils.convert_version_to_tuple(target_version)
        if target_version < (1, 1):
            primitive.pop('old_pci_devices', None)
            primitive.pop('new_pci_devices', None)
            primitive.pop('old_pci_requests', None)
            primitive.pop('new_pci_requests', None)

    @classmethod
    def obj_from_db_obj(cls, db_obj):
        primitive = jsonutils.loads(db_obj)
        return cls.obj_from_primitive(primitive)

    @base.remotable_classmethod
    def get_by_instance_uuid(cls, context, instance_uuid):
        db_extra = db.instance_extra_get_by_instance_uuid(
                context, instance_uuid, columns=['migration_context'])
        if not db_extra:
            raise exception.MigrationContextNotFound(
                instance_uuid=instance_uuid)

        if db_extra['migration_context'] is None:
            return None

        return cls.obj_from_db_obj(db_extra['migration_context'])
Esempio n. 16
0
class InstanceNUMACell(base.NovaObject, base.NovaObjectDictCompat):
    # Version 1.0: Initial version
    # Version 1.1: Add pagesize field
    # Version 1.2: Add cpu_pinning_raw and topology fields
    VERSION = '1.2'

    fields = {
        'id': obj_fields.IntegerField(),
        'cpuset': obj_fields.SetOfIntegersField(),
        'memory': obj_fields.IntegerField(),
        'pagesize': obj_fields.IntegerField(nullable=True),
        'cpu_topology': obj_fields.ObjectField('VirtCPUTopology',
                                               nullable=True),
        'cpu_pinning_raw': obj_fields.DictOfIntegersField(nullable=True)
    }

    obj_relationships = {'cpu_topology': [('1.2', '1.0')]}

    cpu_pinning = obj_fields.DictProxyField('cpu_pinning_raw')

    def __init__(self, **kwargs):
        super(InstanceNUMACell, self).__init__(**kwargs)
        if 'pagesize' not in kwargs:
            self.pagesize = None
            self.obj_reset_changes(['pagesize'])
        if 'cpu_topology' not in kwargs:
            self.cpu_topology = None
            self.obj_reset_changes(['cpu_topology'])
        if 'cpu_pinning' not in kwargs:
            self.cpu_pinning = None
            self.obj_reset_changes(['cpu_pinning_raw'])

    def __len__(self):
        return len(self.cpuset)

    def _to_dict(self):
        # NOTE(sahid): Used as legacy, could be renamed in
        # _legacy_to_dict_ to the future to avoid confusing.
        return {
            'cpus': hardware.format_cpu_spec(self.cpuset, allow_ranges=False),
            'mem': {
                'total': self.memory
            },
            'id': self.id,
            'pagesize': self.pagesize
        }

    @classmethod
    def _from_dict(cls, data_dict):
        # NOTE(sahid): Used as legacy, could be renamed in
        # _legacy_from_dict_ to the future to avoid confusing.
        cpuset = hardware.parse_cpu_spec(data_dict.get('cpus', ''))
        memory = data_dict.get('mem', {}).get('total', 0)
        cell_id = data_dict.get('id')
        pagesize = data_dict.get('pagesize')
        return cls(id=cell_id, cpuset=cpuset, memory=memory, pagesize=pagesize)

    @property
    def siblings(self):
        cpu_list = sorted(list(self.cpuset))

        threads = 0
        if self.cpu_topology:
            threads = self.cpu_topology.threads
        if threads == 1:
            threads = 0

        return list(map(set, zip(*[iter(cpu_list)] * threads)))

    @property
    def cpu_pinning_requested(self):
        return self.cpu_pinning is not None

    def pin(self, vcpu, pcpu):
        if vcpu not in self.cpuset:
            return
        pinning_dict = self.cpu_pinning or {}
        pinning_dict[vcpu] = pcpu
        self.cpu_pinning = pinning_dict

    def pin_vcpus(self, *cpu_pairs):
        for vcpu, pcpu in cpu_pairs:
            self.pin(vcpu, pcpu)
Esempio n. 17
0
class InstanceNUMACell(base.NovaObject, base.NovaObjectDictCompat):
    # Version 1.0: Initial version
    # Version 1.1: Add pagesize field
    # Version 1.2: Add cpu_pinning_raw and topology fields
    # Version 1.3: Add cpu_policy and cpu_thread_policy fields
    # Version 1.4: Add cpuset_reserved field
    VERSION = '1.4'

    def obj_make_compatible(self, primitive, target_version):
        super(InstanceNUMACell,
              self).obj_make_compatible(primitive, target_version)
        target_version = versionutils.convert_version_to_tuple(target_version)
        if target_version < (1, 4):
            primitive.pop('cpuset_reserved', None)

        if target_version < (1, 3):
            primitive.pop('cpu_policy', None)
            primitive.pop('cpu_thread_policy', None)

    fields = {
        'id':
        obj_fields.IntegerField(),
        'cpuset':
        obj_fields.SetOfIntegersField(),
        'memory':
        obj_fields.IntegerField(),
        'pagesize':
        obj_fields.IntegerField(nullable=True),
        'cpu_topology':
        obj_fields.ObjectField('VirtCPUTopology', nullable=True),
        'cpu_pinning_raw':
        obj_fields.DictOfIntegersField(nullable=True),
        'cpu_policy':
        obj_fields.CPUAllocationPolicyField(nullable=True),
        'cpu_thread_policy':
        obj_fields.CPUThreadAllocationPolicyField(nullable=True),
        # These physical CPUs are reserved for use by the hypervisor
        'cpuset_reserved':
        obj_fields.SetOfIntegersField(nullable=True),
    }

    cpu_pinning = obj_fields.DictProxyField('cpu_pinning_raw')

    def __init__(self, **kwargs):
        super(InstanceNUMACell, self).__init__(**kwargs)
        if 'pagesize' not in kwargs:
            self.pagesize = None
            self.obj_reset_changes(['pagesize'])
        if 'cpu_topology' not in kwargs:
            self.cpu_topology = None
            self.obj_reset_changes(['cpu_topology'])
        if 'cpu_pinning' not in kwargs:
            self.cpu_pinning = None
            self.obj_reset_changes(['cpu_pinning_raw'])
        if 'cpu_policy' not in kwargs:
            self.cpu_policy = None
            self.obj_reset_changes(['cpu_policy'])
        if 'cpu_thread_policy' not in kwargs:
            self.cpu_thread_policy = None
            self.obj_reset_changes(['cpu_thread_policy'])
        if 'cpuset_reserved' not in kwargs:
            self.cpuset_reserved = None
            self.obj_reset_changes(['cpuset_reserved'])

    def __len__(self):
        return len(self.cpuset)

    def _to_dict(self):
        # NOTE(sahid): Used as legacy, could be renamed in
        # _legacy_to_dict_ to the future to avoid confusing.
        return {
            'cpus': hardware.format_cpu_spec(self.cpuset, allow_ranges=False),
            'mem': {
                'total': self.memory
            },
            'id': self.id,
            'pagesize': self.pagesize
        }

    @classmethod
    def _from_dict(cls, data_dict):
        # NOTE(sahid): Used as legacy, could be renamed in
        # _legacy_from_dict_ to the future to avoid confusing.
        cpuset = hardware.parse_cpu_spec(data_dict.get('cpus', ''))
        memory = data_dict.get('mem', {}).get('total', 0)
        cell_id = data_dict.get('id')
        pagesize = data_dict.get('pagesize')
        return cls(id=cell_id, cpuset=cpuset, memory=memory, pagesize=pagesize)

    @property
    def siblings(self):
        cpu_list = sorted(list(self.cpuset))

        threads = 0
        if self.cpu_topology:
            threads = self.cpu_topology.threads
        if threads == 1:
            threads = 0

        return list(map(set, zip(*[iter(cpu_list)] * threads)))

    @property
    def cpu_pinning_requested(self):
        return self.cpu_policy == obj_fields.CPUAllocationPolicy.DEDICATED

    def pin(self, vcpu, pcpu):
        if vcpu not in self.cpuset:
            return
        pinning_dict = self.cpu_pinning or {}
        pinning_dict[vcpu] = pcpu
        self.cpu_pinning = pinning_dict

    def pin_vcpus(self, *cpu_pairs):
        for vcpu, pcpu in cpu_pairs:
            self.pin(vcpu, pcpu)

    def clear_host_pinning(self):
        """Clear any data related to how this cell is pinned to the host.

        Needed for aborting claims as we do not want to keep stale data around.
        """
        self.id = -1
        self.cpu_pinning = {}
        return self
Esempio n. 18
0
class InstanceNUMACell(base.NovaObject, base.NovaObjectDictCompat):
    # Version 1.0: Initial version
    # Version 1.1: Add pagesize field
    # Version 1.2: Add cpu_pinning_raw and topology fields
    # Version 1.3: Add cpu_policy and cpu_thread_policy fields
    # Version 1.4: Add cpuset_reserved field
    #              WRS: Add physnode
    #              WRS: Add shared_vcpu and shared_pcpu_for_vcpu
    VERSION = '1.4'

    def obj_make_compatible(self, primitive, target_version):
        super(InstanceNUMACell,
              self).obj_make_compatible(primitive, target_version)
        target_version = versionutils.convert_version_to_tuple(target_version)
        if target_version < (1, 4):
            primitive.pop('cpuset_reserved', None)

        if target_version < (1, 3):
            primitive.pop('cpu_policy', None)
            primitive.pop('cpu_thread_policy', None)
        # NOTE(jgauld): R4 to R5 upgrades, Pike upversion to 1.4. Drop L3
        #               related fields with R4/Newton.
        if target_version < (1, 4) or CONF.upgrade_levels.compute == 'newton':
            primitive.pop('l3_cpuset', None)
            primitive.pop('l3_both_size', None)
            primitive.pop('l3_code_size', None)
            primitive.pop('l3_data_size', None)

    fields = {
        'id':
        obj_fields.IntegerField(),
        'cpuset':
        obj_fields.SetOfIntegersField(),
        'memory':
        obj_fields.IntegerField(),
        'physnode':
        obj_fields.IntegerField(nullable=True),
        'pagesize':
        obj_fields.IntegerField(nullable=True),
        'cpu_topology':
        obj_fields.ObjectField('VirtCPUTopology', nullable=True),
        'cpu_pinning_raw':
        obj_fields.DictOfIntegersField(nullable=True),
        'shared_vcpu':
        obj_fields.IntegerField(nullable=True),
        'shared_pcpu_for_vcpu':
        obj_fields.IntegerField(nullable=True),
        'cpu_policy':
        obj_fields.CPUAllocationPolicyField(nullable=True),
        'cpu_thread_policy':
        obj_fields.CPUThreadAllocationPolicyField(nullable=True),
        # These physical CPUs are reserved for use by the hypervisor
        'cpuset_reserved':
        obj_fields.SetOfIntegersField(nullable=True),

        # L3 CAT
        'l3_cpuset':
        obj_fields.SetOfIntegersField(nullable=True),
        'l3_both_size':
        obj_fields.IntegerField(nullable=True),
        'l3_code_size':
        obj_fields.IntegerField(nullable=True),
        'l3_data_size':
        obj_fields.IntegerField(nullable=True),
    }

    cpu_pinning = obj_fields.DictProxyField('cpu_pinning_raw')

    def __init__(self, **kwargs):
        super(InstanceNUMACell, self).__init__(**kwargs)
        if 'pagesize' not in kwargs:
            self.pagesize = None
            self.obj_reset_changes(['pagesize'])
        if 'cpu_topology' not in kwargs:
            self.cpu_topology = None
            self.obj_reset_changes(['cpu_topology'])
        if 'cpu_pinning' not in kwargs:
            self.cpu_pinning = None
            self.obj_reset_changes(['cpu_pinning_raw'])
        if 'cpu_policy' not in kwargs:
            self.cpu_policy = None
            self.obj_reset_changes(['cpu_policy'])
        if 'cpu_thread_policy' not in kwargs:
            self.cpu_thread_policy = None
            self.obj_reset_changes(['cpu_thread_policy'])
        if 'cpuset_reserved' not in kwargs:
            self.cpuset_reserved = None
            self.obj_reset_changes(['cpuset_reserved'])
        if 'physnode' not in kwargs:
            self.physnode = None
            self.obj_reset_changes(['physnode'])
        if 'shared_vcpu' not in kwargs:
            self.shared_vcpu = None
            self.obj_reset_changes(['shared_vcpu'])
        if 'shared_pcpu_for_vcpu' not in kwargs:
            self.shared_pcpu_for_vcpu = None
            self.obj_reset_changes(['shared_pcpu_for_vcpu'])
        if 'l3_cpuset' not in kwargs:
            self.l3_cpuset = None
            self.obj_reset_changes(['l3_cpuset'])
        if 'l3_both_size' not in kwargs:
            self.l3_both_size = None
            self.obj_reset_changes(['l3_both_size'])
        if 'l3_code_size' not in kwargs:
            self.l3_code_size = None
            self.obj_reset_changes(['l3_code_size'])
        if 'l3_data_size' not in kwargs:
            self.l3_data_size = None
            self.obj_reset_changes(['l3_data_size'])

    def __len__(self):
        return len(self.cpuset)

    def _to_dict(self):
        # NOTE(sahid): Used as legacy, could be renamed in
        # _legacy_to_dict_ to the future to avoid confusing.
        return {
            'cpus': hardware.format_cpu_spec(self.cpuset, allow_ranges=False),
            'mem': {
                'total': self.memory
            },
            'id': self.id,
            'pagesize': self.pagesize
        }

    @classmethod
    def _from_dict(cls, data_dict):
        # NOTE(sahid): Used as legacy, could be renamed in
        # _legacy_from_dict_ to the future to avoid confusing.
        cpuset = hardware.parse_cpu_spec(data_dict.get('cpus', ''))
        memory = data_dict.get('mem', {}).get('total', 0)
        cell_id = data_dict.get('id')
        pagesize = data_dict.get('pagesize')
        return cls(id=cell_id, cpuset=cpuset, memory=memory, pagesize=pagesize)

    @property
    def siblings(self):
        cpu_list = sorted(list(self.cpuset))

        threads = 0
        if ('cpu_topology' in self) and self.cpu_topology:
            threads = self.cpu_topology.threads
        if threads == 1:
            threads = 0

        return list(map(set, zip(*[iter(cpu_list)] * threads)))

    @property
    def cpu_pinning_requested(self):
        return self.cpu_policy == obj_fields.CPUAllocationPolicy.DEDICATED

    def pin(self, vcpu, pcpu):
        if vcpu not in self.cpuset:
            return
        pinning_dict = self.cpu_pinning or {}
        pinning_dict[vcpu] = pcpu
        self.cpu_pinning = pinning_dict

    def pin_vcpus(self, *cpu_pairs):
        for vcpu, pcpu in cpu_pairs:
            self.pin(vcpu, pcpu)

    def clear_host_pinning(self):
        """Clear any data related to how this cell is pinned to the host.

        Needed for aborting claims as we do not want to keep stale data around.
        """
        self.id = -1
        self.cpu_pinning = {}
        return self

    @property
    def cachetune_requested(self):
        return (self.l3_cpuset is not None) and (len(self.l3_cpuset) > 0)

    # WRS extension
    @property
    def numa_pinning_requested(self):
        return self.physnode is not None

    # WRS: add a readable string representation
    def __str__(self):
        return '  {obj_name} (id: {id})\n' \
               '    cpuset: {cpuset}\n' \
               '    shared_vcpu: {shared_vcpu}\n' \
               '    shared_pcpu_for_vcpu: {shared_pcpu_for_vcpu}\n' \
               '    memory: {memory}\n' \
               '    physnode: {physnode}\n' \
               '    pagesize: {pagesize}\n' \
               '    cpu_topology: {cpu_topology}\n' \
               '    cpu_pinning: {cpu_pinning}\n' \
               '    siblings: {siblings}\n' \
               '    cpu_policy: {cpu_policy}\n' \
               '    cpu_thread_policy: {cpu_thread_policy}\n' \
               '    l3_cpuset: {l3_cpuset}\n' \
               '    l3_both_size: {l3_both_size}\n' \
               '    l3_code_size: {l3_code_size}\n' \
               '    l3_data_size: {l3_data_size}'.format(
            obj_name=self.obj_name(),
            id=self.id if ('id' in self) else None,
            cpuset=hardware.format_cpu_spec(
                self.cpuset, allow_ranges=True),
            shared_vcpu=self.shared_vcpu,
            shared_pcpu_for_vcpu=self.shared_pcpu_for_vcpu,
            memory=self.memory,
            physnode=self.physnode,
            pagesize=self.pagesize,
            cpu_topology=self.cpu_topology if (
                'cpu_topology' in self) else None,
            cpu_pinning=self.cpu_pinning,
            siblings=self.siblings,
            cpu_policy=self.cpu_policy,
            cpu_thread_policy=self.cpu_thread_policy,
            l3_cpuset=hardware.format_cpu_spec(
                self.l3_cpuset or [], allow_ranges=True),
            l3_both_size=self.l3_both_size,
            l3_code_size=self.l3_code_size,
            l3_data_size=self.l3_data_size,
        )

    # WRS: add a readable representation, without newlines
    def __repr__(self):
        return '{obj_name} (id: {id}) ' \
               'cpuset: {cpuset} ' \
               'shared_vcpu: {shared_vcpu} ' \
               'shared_pcpu_for_vcpu: {shared_pcpu_for_vcpu} ' \
               'memory: {memory} ' \
               'physnode: {physnode} ' \
               'pagesize: {pagesize} ' \
               'cpu_topology: {cpu_topology} ' \
               'cpu_pinning: {cpu_pinning} ' \
               'siblings: {siblings} ' \
               'cpu_policy: {cpu_policy} ' \
               'cpu_thread_policy: {cpu_thread_policy} ' \
               'l3_cpuset: {l3_cpuset} ' \
               'l3_both_size: {l3_both_size} ' \
               'l3_code_size: {l3_code_size} ' \
               'l3_data_size: {l3_data_size}'.format(
            obj_name=self.obj_name(),
            id=self.id if ('id' in self) else None,
            cpuset=hardware.format_cpu_spec(
                self.cpuset, allow_ranges=True),
            shared_vcpu=self.shared_vcpu,
            shared_pcpu_for_vcpu=self.shared_pcpu_for_vcpu,
            memory=self.memory,
            physnode=self.physnode,
            pagesize=self.pagesize,
            cpu_topology=self.cpu_topology if (
                'cpu_topology' in self) else None,
            cpu_pinning=self.cpu_pinning,
            siblings=self.siblings,
            cpu_policy=self.cpu_policy,
            cpu_thread_policy=self.cpu_thread_policy,
            l3_cpuset=hardware.format_cpu_spec(
                self.l3_cpuset or [], allow_ranges=True),
            l3_both_size=self.l3_both_size,
            l3_code_size=self.l3_code_size,
            l3_data_size=self.l3_data_size,
        )