Beispiel #1
0
 def setUp(self):
     super(TestCPUAllocationPolicy, self).setUp()
     self.field = fields.CPUAllocationPolicyField()
     self.coerce_good_values = [('dedicated', 'dedicated'),
                                ('shared', 'shared')]
     self.coerce_bad_values = ['acme']
     self.to_primitive_values = self.coerce_good_values[0:1]
     self.from_primitive_values = self.coerce_good_values[0:1]
Beispiel #2
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
Beispiel #3
0
class ImageMetaProps(base.NovaObject):
    # Version 1.0: Initial version
    # Version 1.1: added os_require_quiesce field
    # Version 1.2: added img_hv_type and img_hv_requested_version fields
    # Version 1.3: HVSpec version 1.1
    # Version 1.4: added hw_vif_multiqueue_enabled field
    # Version 1.5: added os_admin_user field
    VERSION = ImageMeta.VERSION

    # Maximum number of NUMA nodes permitted for the guest topology
    NUMA_NODES_MAX = 128

    # 'hw_' - settings affecting the guest virtual machine hardware
    # 'img_' - settings affecting the use of images by the compute node
    # 'os_' - settings affecting the guest operating system setup

    fields = {
        # name of guest hardware architecture eg i686, x86_64, ppc64
        'hw_architecture': fields.ArchitectureField(),

        # used to decide to expand root disk partition and fs to full size of
        # root disk
        'hw_auto_disk_config': fields.StringField(),

        # whether to display BIOS boot device menu
        'hw_boot_menu': fields.FlexibleBooleanField(),

        # name of the CDROM bus to use eg virtio, scsi, ide
        'hw_cdrom_bus': fields.DiskBusField(),

        # preferred number of CPU cores per socket
        'hw_cpu_cores': fields.IntegerField(),

        # preferred number of CPU sockets
        'hw_cpu_sockets': fields.IntegerField(),

        # maximum number of CPU cores per socket
        'hw_cpu_max_cores': fields.IntegerField(),

        # maximum number of CPU sockets
        'hw_cpu_max_sockets': fields.IntegerField(),

        # maximum number of CPU threads per core
        'hw_cpu_max_threads': fields.IntegerField(),

        # CPU thread allocation policy
        'hw_cpu_policy': fields.CPUAllocationPolicyField(),

        # preferred number of CPU threads per core
        'hw_cpu_threads': fields.IntegerField(),

        # guest ABI version for guest xentools either 1 or 2 (or 3 - depends on
        # Citrix PV tools version installed in image)
        'hw_device_id': fields.IntegerField(),

        # name of the hard disk bus to use eg virtio, scsi, ide
        'hw_disk_bus': fields.DiskBusField(),

        # allocation mode eg 'preallocated'
        'hw_disk_type': fields.StringField(),

        # name of the floppy disk bus to use eg fd, scsi, ide
        'hw_floppy_bus': fields.DiskBusField(),

        # boolean - used to trigger code to inject networking when booting a CD
        # image with a network boot image
        'hw_ipxe_boot': fields.FlexibleBooleanField(),

        # There are sooooooooooo many possible machine types in
        # QEMU - several new ones with each new release - that it
        # is not practical to enumerate them all. So we use a free
        # form string
        'hw_machine_type': fields.StringField(),

        # One of the magic strings 'small', 'any', 'large'
        # or an explicit page size in KB (eg 4, 2048, ...)
        'hw_mem_page_size': fields.StringField(),

        # Number of guest NUMA nodes
        'hw_numa_nodes': fields.IntegerField(),

        # Each list entry corresponds to a guest NUMA node and the
        # set members indicate CPUs for that node
        'hw_numa_cpus': fields.ListOfSetsOfIntegersField(),

        # Each list entry corresponds to a guest NUMA node and the
        # list value indicates the memory size of that node.
        'hw_numa_mem': fields.ListOfIntegersField(),

        # boolean 'yes' or 'no' to enable QEMU guest agent
        'hw_qemu_guest_agent': fields.FlexibleBooleanField(),

        # name of the RNG device type eg virtio
        'hw_rng_model': fields.RNGModelField(),

        # number of serial ports to create
        'hw_serial_port_count': fields.IntegerField(),

        # name of the SCSI bus controller eg 'virtio-scsi', 'lsilogic', etc
        'hw_scsi_model': fields.SCSIModelField(),

        # name of the video adapter model to use, eg cirrus, vga, xen, qxl
        'hw_video_model': fields.VideoModelField(),

        # MB of video RAM to provide eg 64
        'hw_video_ram': fields.IntegerField(),

        # name of a NIC device model eg virtio, e1000, rtl8139
        'hw_vif_model': fields.VIFModelField(),

        # "xen" vs "hvm"
        'hw_vm_mode': fields.VMModeField(),

        # action to take when watchdog device fires eg reset, poweroff, pause,
        # none
        'hw_watchdog_action': fields.WatchdogActionField(),

        # boolean - If true, this will enable the virtio-multiqueue feature
        'hw_vif_multiqueue_enabled': fields.FlexibleBooleanField(),

        # if true download using bittorrent
        'img_bittorrent': fields.FlexibleBooleanField(),

        # Which data format the 'img_block_device_mapping' field is
        # using to represent the block device mapping
        'img_bdm_v2': fields.FlexibleBooleanField(),

        # Block device mapping - the may can be in one or two completely
        # different formats. The 'img_bdm_v2' field determines whether
        # it is in legacy format, or the new current format. Ideally
        # we would have a formal data type for this field instead of a
        # dict, but with 2 different formats to represent this is hard.
        # See nova/block_device.py from_legacy_mapping() for the complex
        # conversion code. So for now leave it as a dict and continue
        # to use existing code that is able to convert dict into the
        # desired internal BDM formats
        'img_block_device_mapping': fields.ListOfDictOfNullableStringsField(),

        # boolean - if True, and image cache set to "some" decides if image
        # should be cached on host when server is booted on that host
        'img_cache_in_nova': fields.FlexibleBooleanField(),

        # Compression level for images. (1-9)
        'img_compression_level': fields.IntegerField(),

        # hypervisor supported version, eg. '>=2.6'
        'img_hv_requested_version': fields.VersionPredicateField(),

        # type of the hypervisor, eg kvm, ironic, xen
        'img_hv_type': fields.HVTypeField(),

        # boolean flag to set space-saving or performance behavior on the
        # Datastore
        'img_linked_clone': fields.FlexibleBooleanField(),

        # Image mappings - related to Block device mapping data - mapping
        # of virtual image names to device names. This could be represented
        # as a formatl data type, but is left as dict for same reason as
        # img_block_device_mapping field. It would arguably make sense for
        # the two to be combined into a single field and data type in the
        # future.
        'img_mappings': fields.ListOfDictOfNullableStringsField(),

        # image project id (set on upload)
        'img_owner_id': fields.StringField(),

        # root device name, used in snapshotting eg /dev/<blah>
        'img_root_device_name': fields.StringField(),

        # boolean - if false don't talk to nova agent
        'img_use_agent': fields.FlexibleBooleanField(),

        # integer value 1
        'img_version': fields.IntegerField(),

        # string of username with admin privileges
        'os_admin_user': fields.StringField(),

        # string of boot time command line arguments for the guest kernel
        'os_command_line': fields.StringField(),

        # the name of the specific guest operating system distro. This
        # is not done as an Enum since the list of operating systems is
        # growing incredibly fast, and valid values can be arbitrarily
        # user defined. Nova has no real need for strict validation so
        # leave it freeform
        'os_distro': fields.StringField(),

        # boolean - if true, then guest must support disk quiesce
        # or snapshot operation will be denied
        'os_require_quiesce': fields.FlexibleBooleanField(),

        # boolean - if using agent don't inject files, assume someone else is
        # doing that (cloud-init)
        'os_skip_agent_inject_files_at_boot': fields.FlexibleBooleanField(),

        # boolean - if using agent don't try inject ssh key, assume someone
        # else is doing that (cloud-init)
        'os_skip_agent_inject_ssh': fields.FlexibleBooleanField(),

        # The guest operating system family such as 'linux', 'windows' - this
        # is a fairly generic type. For a detailed type consider os_distro
        # instead
        'os_type': fields.OSTypeField(),
    }

    # The keys are the legacy property names and
    # the values are the current preferred names
    _legacy_property_map = {
        'architecture': 'hw_architecture',
        'owner_id': 'img_owner_id',
        'vmware_disktype': 'hw_disk_type',
        'vmware_image_version': 'img_version',
        'vmware_ostype': 'os_distro',
        'auto_disk_config': 'hw_auto_disk_config',
        'ipxe_boot': 'hw_ipxe_boot',
        'xenapi_device_id': 'hw_device_id',
        'xenapi_image_compression_level': 'img_compression_level',
        'vmware_linked_clone': 'img_linked_clone',
        'xenapi_use_agent': 'img_use_agent',
        'xenapi_skip_agent_inject_ssh': 'os_skip_agent_inject_ssh',
        'xenapi_skip_agent_inject_files_at_boot':
        'os_skip_agent_inject_files_at_boot',
        'cache_in_nova': 'img_cache_in_nova',
        'vm_mode': 'hw_vm_mode',
        'bittorrent': 'img_bittorrent',
        'mappings': 'img_mappings',
        'block_device_mapping': 'img_block_device_mapping',
        'bdm_v2': 'img_bdm_v2',
        'root_device_name': 'img_root_device_name',
        'hypervisor_version_requires': 'img_hv_requested_version',
    }

    # TODO(berrange): Need to run this from a data migration
    # at some point so we can eventually kill off the compat
    def _set_attr_from_legacy_names(self, image_props):
        for legacy_key in self._legacy_property_map:
            new_key = self._legacy_property_map[legacy_key]

            if legacy_key not in image_props:
                continue

            setattr(self, new_key, image_props[legacy_key])

        vmware_adaptertype = image_props.get("vmware_adaptertype")
        if vmware_adaptertype == "ide":
            setattr(self, "hw_disk_bus", "ide")
        elif vmware_adaptertype is not None:
            setattr(self, "hw_disk_bus", "scsi")
            setattr(self, "hw_scsi_model", vmware_adaptertype)

    def _set_numa_mem(self, image_props):
        hw_numa_mem = []
        hw_numa_mem_set = False
        for cellid in range(ImageMetaProps.NUMA_NODES_MAX):
            memprop = "hw_numa_mem.%d" % cellid
            if memprop not in image_props:
                break
            hw_numa_mem.append(int(image_props[memprop]))
            hw_numa_mem_set = True
            del image_props[memprop]

        if hw_numa_mem_set:
            self.hw_numa_mem = hw_numa_mem

    def _set_numa_cpus(self, image_props):
        hw_numa_cpus = []
        hw_numa_cpus_set = False
        for cellid in range(ImageMetaProps.NUMA_NODES_MAX):
            cpuprop = "hw_numa_cpus.%d" % cellid
            if cpuprop not in image_props:
                break
            hw_numa_cpus.append(hardware.parse_cpu_spec(image_props[cpuprop]))
            hw_numa_cpus_set = True
            del image_props[cpuprop]

        if hw_numa_cpus_set:
            self.hw_numa_cpus = hw_numa_cpus

    def _set_attr_from_current_names(self, image_props):
        for key in self.fields:
            # The two NUMA fields need special handling to
            # un-stringify them correctly
            if key == "hw_numa_mem":
                self._set_numa_mem(image_props)
            elif key == "hw_numa_cpus":
                self._set_numa_cpus(image_props)
            else:
                if key not in image_props:
                    continue

                setattr(self, key, image_props[key])

    @classmethod
    def from_dict(cls, image_props):
        """Create instance from image properties dict

        :param image_props: dictionary of image metdata properties

        Creates a new object instance, initializing from a
        dictionary of image metadata properties

        :returns: an ImageMetaProps instance
        """
        obj = cls()
        # We look to see if the dict has entries for any
        # of the legacy property names first. Then we use
        # the current property names. That way if both the
        # current and legacy names are set, the value
        # associated with the current name takes priority
        obj._set_attr_from_legacy_names(image_props)
        obj._set_attr_from_current_names(image_props)
        return obj

    def get(self, name, defvalue=None):
        """Get the value of an attribute
        :param name: the attribute to request
        :param defvalue: the default value if not set

        This returns the value of an attribute if it is currently
        set, otherwise it will return None.

        This differs from accessing props.attrname, because that
        will raise an exception if the attribute has no value set.

        So instead of

          if image_meta.properties.obj_attr_is_set("some_attr"):
             val = image_meta.properties.some_attr
          else
             val = None

        Callers can rely on unconditional access

             val = image_meta.properties.get("some_attr")

        :returns: the attribute value or None
        """

        if not self.obj_attr_is_set(name):
            return defvalue

        return getattr(self, name)
Beispiel #4
0
class ImageMetaPropsPayload(base.NotificationPayloadBase):
    # Version 1.0: Initial version
    # Version 1.1: Added 'gop', 'virtio' and  'none' to hw_video_model field
    VERSION = '1.1'

    SCHEMA = {
        'hw_architecture': ('image_meta_props', 'hw_architecture'),
        'hw_auto_disk_config': ('image_meta_props', 'hw_auto_disk_config'),
        'hw_boot_menu': ('image_meta_props', 'hw_boot_menu'),
        'hw_cdrom_bus': ('image_meta_props', 'hw_cdrom_bus'),
        'hw_cpu_cores': ('image_meta_props', 'hw_cpu_cores'),
        'hw_cpu_sockets': ('image_meta_props', 'hw_cpu_sockets'),
        'hw_cpu_max_cores': ('image_meta_props', 'hw_cpu_max_cores'),
        'hw_cpu_max_sockets': ('image_meta_props', 'hw_cpu_max_sockets'),
        'hw_cpu_max_threads': ('image_meta_props', 'hw_cpu_max_threads'),
        'hw_cpu_policy': ('image_meta_props', 'hw_cpu_policy'),
        'hw_cpu_thread_policy': ('image_meta_props', 'hw_cpu_thread_policy'),
        'hw_cpu_realtime_mask': ('image_meta_props', 'hw_cpu_realtime_mask'),
        'hw_cpu_threads': ('image_meta_props', 'hw_cpu_threads'),
        'hw_device_id': ('image_meta_props', 'hw_device_id'),
        'hw_disk_bus': ('image_meta_props', 'hw_disk_bus'),
        'hw_disk_type': ('image_meta_props', 'hw_disk_type'),
        'hw_floppy_bus': ('image_meta_props', 'hw_floppy_bus'),
        'hw_firmware_type': ('image_meta_props', 'hw_firmware_type'),
        'hw_ipxe_boot': ('image_meta_props', 'hw_ipxe_boot'),
        'hw_machine_type': ('image_meta_props', 'hw_machine_type'),
        'hw_mem_page_size': ('image_meta_props', 'hw_mem_page_size'),
        'hw_numa_nodes': ('image_meta_props', 'hw_numa_nodes'),
        'hw_numa_cpus': ('image_meta_props', 'hw_numa_cpus'),
        'hw_numa_mem': ('image_meta_props', 'hw_numa_mem'),
        'hw_pointer_model': ('image_meta_props', 'hw_pointer_model'),
        'hw_qemu_guest_agent': ('image_meta_props', 'hw_qemu_guest_agent'),
        'hw_rescue_bus': ('image_meta_props', 'hw_rescue_bus'),
        'hw_rescue_device': ('image_meta_props', 'hw_rescue_device'),
        'hw_rng_model': ('image_meta_props', 'hw_rng_model'),
        'hw_serial_port_count': ('image_meta_props', 'hw_serial_port_count'),
        'hw_scsi_model': ('image_meta_props', 'hw_scsi_model'),
        'hw_video_model': ('image_meta_props', 'hw_video_model'),
        'hw_video_ram': ('image_meta_props', 'hw_video_ram'),
        'hw_vif_model': ('image_meta_props', 'hw_vif_model'),
        'hw_vm_mode': ('image_meta_props', 'hw_vm_mode'),
        'hw_watchdog_action': ('image_meta_props', 'hw_watchdog_action'),
        'hw_vif_multiqueue_enabled':
        ('image_meta_props', 'hw_vif_multiqueue_enabled'),
        'img_bittorrent': ('image_meta_props', 'img_bittorrent'),
        'img_bdm_v2': ('image_meta_props', 'img_bdm_v2'),
        'img_block_device_mapping':
        ('image_meta_props', 'img_block_device_mapping'),
        'img_cache_in_nova': ('image_meta_props', 'img_cache_in_nova'),
        'img_compression_level': ('image_meta_props', 'img_compression_level'),
        'img_hv_requested_version':
        ('image_meta_props', 'img_hv_requested_version'),
        'img_hv_type': ('image_meta_props', 'img_hv_type'),
        'img_config_drive': ('image_meta_props', 'img_config_drive'),
        'img_linked_clone': ('image_meta_props', 'img_linked_clone'),
        'img_mappings': ('image_meta_props', 'img_mappings'),
        'img_owner_id': ('image_meta_props', 'img_owner_id'),
        'img_root_device_name': ('image_meta_props', 'img_root_device_name'),
        'img_use_agent': ('image_meta_props', 'img_use_agent'),
        'img_version': ('image_meta_props', 'img_version'),
        'img_signature': ('image_meta_props', 'img_signature'),
        'img_signature_hash_method': ('image_meta_props',
                                      'img_signature_hash_method'),
        'img_signature_certificate_uuid': ('image_meta_props',
                                           'img_signature_certificate_uuid'),
        'img_signature_key_type': ('image_meta_props',
                                   'img_signature_key_type'),
        'img_hide_hypervisor_id': ('image_meta_props',
                                   'img_hide_hypervisor_id'),
        'os_admin_user': ('image_meta_props', 'os_admin_user'),
        'os_command_line': ('image_meta_props', 'os_command_line'),
        'os_distro': ('image_meta_props', 'os_distro'),
        'os_require_quiesce': ('image_meta_props', 'os_require_quiesce'),
        'os_secure_boot': ('image_meta_props', 'os_secure_boot'),
        'os_skip_agent_inject_files_at_boot':
        ('image_meta_props', 'os_skip_agent_inject_files_at_boot'),
        'os_skip_agent_inject_ssh': ('image_meta_props',
                                     'os_skip_agent_inject_ssh'),
        'os_type': ('image_meta_props', 'os_type'),
        'traits_required': ('image_meta_props', 'traits_required')
    }

    fields = {
        'hw_architecture': fields.ArchitectureField(),
        'hw_auto_disk_config': fields.StringField(),
        'hw_boot_menu': fields.FlexibleBooleanField(),
        'hw_cdrom_bus': fields.DiskBusField(),
        'hw_cpu_cores': fields.IntegerField(),
        'hw_cpu_sockets': fields.IntegerField(),
        'hw_cpu_max_cores': fields.IntegerField(),
        'hw_cpu_max_sockets': fields.IntegerField(),
        'hw_cpu_max_threads': fields.IntegerField(),
        'hw_cpu_policy': fields.CPUAllocationPolicyField(),
        'hw_cpu_thread_policy': fields.CPUThreadAllocationPolicyField(),
        'hw_cpu_realtime_mask': fields.StringField(),
        'hw_cpu_threads': fields.IntegerField(),
        'hw_device_id': fields.IntegerField(),
        'hw_disk_bus': fields.DiskBusField(),
        'hw_disk_type': fields.StringField(),
        'hw_floppy_bus': fields.DiskBusField(),
        'hw_firmware_type': fields.FirmwareTypeField(),
        'hw_ipxe_boot': fields.FlexibleBooleanField(),
        'hw_machine_type': fields.StringField(),
        'hw_mem_page_size': fields.StringField(),
        'hw_numa_nodes': fields.IntegerField(),
        'hw_numa_cpus': fields.ListOfSetsOfIntegersField(),
        'hw_numa_mem': fields.ListOfIntegersField(),
        'hw_pointer_model': fields.PointerModelField(),
        'hw_qemu_guest_agent': fields.FlexibleBooleanField(),
        'hw_rescue_bus': fields.DiskBusField(),
        'hw_rescue_device': fields.BlockDeviceTypeField(),
        'hw_rng_model': fields.RNGModelField(),
        'hw_serial_port_count': fields.IntegerField(),
        'hw_scsi_model': fields.SCSIModelField(),
        'hw_video_model': fields.VideoModelField(),
        'hw_video_ram': fields.IntegerField(),
        'hw_vif_model': fields.VIFModelField(),
        'hw_vm_mode': fields.VMModeField(),
        'hw_watchdog_action': fields.WatchdogActionField(),
        'hw_vif_multiqueue_enabled': fields.FlexibleBooleanField(),
        'img_bittorrent': fields.FlexibleBooleanField(),
        'img_bdm_v2': fields.FlexibleBooleanField(),
        'img_block_device_mapping': fields.ListOfDictOfNullableStringsField(),
        'img_cache_in_nova': fields.FlexibleBooleanField(),
        'img_compression_level': fields.IntegerField(),
        'img_hv_requested_version': fields.VersionPredicateField(),
        'img_hv_type': fields.HVTypeField(),
        'img_config_drive': fields.ConfigDrivePolicyField(),
        'img_linked_clone': fields.FlexibleBooleanField(),
        'img_mappings': fields.ListOfDictOfNullableStringsField(),
        'img_owner_id': fields.StringField(),
        'img_root_device_name': fields.StringField(),
        'img_use_agent': fields.FlexibleBooleanField(),
        'img_version': fields.IntegerField(),
        'img_signature': fields.StringField(),
        'img_signature_hash_method': fields.ImageSignatureHashTypeField(),
        'img_signature_certificate_uuid': fields.UUIDField(),
        'img_signature_key_type': fields.ImageSignatureKeyTypeField(),
        'img_hide_hypervisor_id': fields.FlexibleBooleanField(),
        'os_admin_user': fields.StringField(),
        'os_command_line': fields.StringField(),
        'os_distro': fields.StringField(),
        'os_require_quiesce': fields.FlexibleBooleanField(),
        'os_secure_boot': fields.SecureBootField(),
        'os_skip_agent_inject_files_at_boot': fields.FlexibleBooleanField(),
        'os_skip_agent_inject_ssh': fields.FlexibleBooleanField(),
        'os_type': fields.OSTypeField(),
        'traits_required': fields.ListOfStringsField()
    }

    def __init__(self, image_meta_props):
        super(ImageMetaPropsPayload, self).__init__()
        # NOTE(takashin): If fields are not set in the ImageMetaProps object,
        # it will not set the fields in the ImageMetaPropsPayload
        # in order to avoid too many fields whose values are None.
        self.populate_schema(set_none=False, image_meta_props=image_meta_props)
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
Beispiel #6
0
class ImageMetaProps(base.NovaObject):
    # Version 1.0: Initial version
    # Version 1.1: added os_require_quiesce field
    # Version 1.2: added img_hv_type and img_hv_requested_version fields
    # Version 1.3: HVSpec version 1.1
    # Version 1.4: added hw_vif_multiqueue_enabled field
    # Version 1.5: added os_admin_user field
    # Version 1.6: Added 'lxc' and 'uml' enum types to DiskBusField
    # Version 1.7: added img_config_drive field
    # Version 1.8: Added 'lxd' to hypervisor types
    # Version 1.9: added hw_cpu_thread_policy field
    # Version 1.10: added hw_cpu_realtime_mask field
    # Version 1.11: Added hw_firmware_type field
    # Version 1.12: Added properties for image signature verification
    # Version 1.13: added os_secure_boot field
    # Version 1.14: Added 'hw_pointer_model' field
    # Version 1.15: Added hw_rescue_bus and hw_rescue_device.
    # Version 1.16: WatchdogActionField supports 'disabled' enum.
    # Version 1.17: Add lan9118 as valid nic for hw_vif_model property for qemu
    # Version 1.18: Pull signature properties from cursive library
    # Version 1.19: Added 'img_hide_hypervisor_id' type field
    # Version 1.20: Added 'traits_required' list field
    # Version 1.21: Added 'hw_time_hpet' field
    # Version 1.22: Added 'gop', 'virtio' and 'none' to hw_video_model field
    # Version 1.23: Added 'hw_pmu' field
    VERSION = '1.23'

    def obj_make_compatible(self, primitive, target_version):
        super(ImageMetaProps,
              self).obj_make_compatible(primitive, target_version)
        target_version = versionutils.convert_version_to_tuple(target_version)
        if target_version < (1, 23):
            primitive.pop('hw_pmu', None)
        # NOTE(sean-k-mooney): unlike other nova object we version this object
        # when composed object are updated.
        if target_version < (1, 22):
            video = primitive.get('hw_video_model', None)
            if video in ('gop', 'virtio', 'none'):
                raise exception.ObjectActionError(
                    action='obj_make_compatible',
                    reason='hw_video_model=%s not supported in version %s' %
                    (video, target_version))
        if target_version < (1, 21):
            primitive.pop('hw_time_hpet', None)
        if target_version < (1, 20):
            primitive.pop('traits_required', None)
        if target_version < (1, 19):
            primitive.pop('img_hide_hypervisor_id', None)
        if target_version < (1, 16) and 'hw_watchdog_action' in primitive:
            # Check to see if hw_watchdog_action was set to 'disabled' and if
            # so, remove it since not specifying it is the same behavior.
            if primitive['hw_watchdog_action'] == \
                    fields.WatchdogAction.DISABLED:
                primitive.pop('hw_watchdog_action')
        if target_version < (1, 15):
            primitive.pop('hw_rescue_bus', None)
            primitive.pop('hw_rescue_device', None)
        if target_version < (1, 14):
            primitive.pop('hw_pointer_model', None)
        if target_version < (1, 13):
            primitive.pop('os_secure_boot', None)
        if target_version < (1, 11):
            primitive.pop('hw_firmware_type', None)
        if target_version < (1, 10):
            primitive.pop('hw_cpu_realtime_mask', None)
        if target_version < (1, 9):
            primitive.pop('hw_cpu_thread_policy', None)
        if target_version < (1, 7):
            primitive.pop('img_config_drive', None)
        if target_version < (1, 5):
            primitive.pop('os_admin_user', None)
        if target_version < (1, 4):
            primitive.pop('hw_vif_multiqueue_enabled', None)
        if target_version < (1, 2):
            primitive.pop('img_hv_type', None)
            primitive.pop('img_hv_requested_version', None)
        if target_version < (1, 1):
            primitive.pop('os_require_quiesce', None)

        if target_version < (1, 6):
            bus = primitive.get('hw_disk_bus', None)
            if bus in ('lxc', 'uml'):
                raise exception.ObjectActionError(
                    action='obj_make_compatible',
                    reason='hw_disk_bus=%s not supported in version %s' %
                    (bus, target_version))

    # Maximum number of NUMA nodes permitted for the guest topology
    NUMA_NODES_MAX = 128

    # 'hw_' - settings affecting the guest virtual machine hardware
    # 'img_' - settings affecting the use of images by the compute node
    # 'os_' - settings affecting the guest operating system setup
    # 'traits_required' - The required traits associated with the image

    fields = {
        # name of guest hardware architecture eg i686, x86_64, ppc64
        'hw_architecture': fields.ArchitectureField(),

        # used to decide to expand root disk partition and fs to full size of
        # root disk
        'hw_auto_disk_config': fields.StringField(),

        # whether to display BIOS boot device menu
        'hw_boot_menu': fields.FlexibleBooleanField(),

        # name of the CDROM bus to use eg virtio, scsi, ide
        'hw_cdrom_bus': fields.DiskBusField(),

        # preferred number of CPU cores per socket
        'hw_cpu_cores': fields.IntegerField(),

        # preferred number of CPU sockets
        'hw_cpu_sockets': fields.IntegerField(),

        # maximum number of CPU cores per socket
        'hw_cpu_max_cores': fields.IntegerField(),

        # maximum number of CPU sockets
        'hw_cpu_max_sockets': fields.IntegerField(),

        # maximum number of CPU threads per core
        'hw_cpu_max_threads': fields.IntegerField(),

        # CPU allocation policy
        'hw_cpu_policy': fields.CPUAllocationPolicyField(),

        # CPU thread allocation policy
        'hw_cpu_thread_policy': fields.CPUThreadAllocationPolicyField(),

        # CPU mask indicates which vCPUs will have realtime enable,
        # example ^0-1 means that all vCPUs except 0 and 1 will have a
        # realtime policy.
        'hw_cpu_realtime_mask': fields.StringField(),

        # preferred number of CPU threads per core
        'hw_cpu_threads': fields.IntegerField(),

        # guest ABI version for guest xentools either 1 or 2 (or 3 - depends on
        # Citrix PV tools version installed in image)
        'hw_device_id': fields.IntegerField(),

        # name of the hard disk bus to use eg virtio, scsi, ide
        'hw_disk_bus': fields.DiskBusField(),

        # allocation mode eg 'preallocated'
        'hw_disk_type': fields.StringField(),

        # name of the floppy disk bus to use eg fd, scsi, ide
        'hw_floppy_bus': fields.DiskBusField(),

        # This indicates the guest needs UEFI firmware
        'hw_firmware_type': fields.FirmwareTypeField(),

        # boolean - used to trigger code to inject networking when booting a CD
        # image with a network boot image
        'hw_ipxe_boot': fields.FlexibleBooleanField(),

        # There are sooooooooooo many possible machine types in
        # QEMU - several new ones with each new release - that it
        # is not practical to enumerate them all. So we use a free
        # form string
        'hw_machine_type': fields.StringField(),

        # One of the magic strings 'small', 'any', 'large'
        # or an explicit page size in KB (eg 4, 2048, ...)
        'hw_mem_page_size': fields.StringField(),

        # Number of guest NUMA nodes
        'hw_numa_nodes': fields.IntegerField(),

        # Each list entry corresponds to a guest NUMA node and the
        # set members indicate CPUs for that node
        'hw_numa_cpus': fields.ListOfSetsOfIntegersField(),

        # Each list entry corresponds to a guest NUMA node and the
        # list value indicates the memory size of that node.
        'hw_numa_mem': fields.ListOfIntegersField(),

        # Generic property to specify the pointer model type.
        'hw_pointer_model': fields.PointerModelField(),

        # boolean 'true' or 'false' to enable virtual performance
        # monitoring unit (vPMU).
        'hw_pmu': fields.FlexibleBooleanField(),

        # boolean 'yes' or 'no' to enable QEMU guest agent
        'hw_qemu_guest_agent': fields.FlexibleBooleanField(),

        # name of the rescue bus to use with the associated rescue device.
        'hw_rescue_bus': fields.DiskBusField(),

        # name of rescue device to use.
        'hw_rescue_device': fields.BlockDeviceTypeField(),

        # name of the RNG device type eg virtio
        'hw_rng_model': fields.RNGModelField(),

        # boolean 'true' or 'false' to enable HPET
        'hw_time_hpet': fields.FlexibleBooleanField(),

        # number of serial ports to create
        'hw_serial_port_count': fields.IntegerField(),

        # name of the SCSI bus controller eg 'virtio-scsi', 'lsilogic', etc
        'hw_scsi_model': fields.SCSIModelField(),

        # name of the video adapter model to use, eg cirrus, vga, xen, qxl
        'hw_video_model': fields.VideoModelField(),

        # MB of video RAM to provide eg 64
        'hw_video_ram': fields.IntegerField(),

        # name of a NIC device model eg virtio, e1000, rtl8139
        'hw_vif_model': fields.VIFModelField(),

        # "xen" vs "hvm"
        'hw_vm_mode': fields.VMModeField(),

        # action to take when watchdog device fires eg reset, poweroff, pause,
        # none
        'hw_watchdog_action': fields.WatchdogActionField(),

        # boolean - If true, this will enable the virtio-multiqueue feature
        'hw_vif_multiqueue_enabled': fields.FlexibleBooleanField(),

        # if true download using bittorrent
        'img_bittorrent': fields.FlexibleBooleanField(),

        # Which data format the 'img_block_device_mapping' field is
        # using to represent the block device mapping
        'img_bdm_v2': fields.FlexibleBooleanField(),

        # Block device mapping - the may can be in one or two completely
        # different formats. The 'img_bdm_v2' field determines whether
        # it is in legacy format, or the new current format. Ideally
        # we would have a formal data type for this field instead of a
        # dict, but with 2 different formats to represent this is hard.
        # See nova/block_device.py from_legacy_mapping() for the complex
        # conversion code. So for now leave it as a dict and continue
        # to use existing code that is able to convert dict into the
        # desired internal BDM formats
        'img_block_device_mapping': fields.ListOfDictOfNullableStringsField(),

        # boolean - if True, and image cache set to "some" decides if image
        # should be cached on host when server is booted on that host
        'img_cache_in_nova': fields.FlexibleBooleanField(),

        # Compression level for images. (1-9)
        'img_compression_level': fields.IntegerField(),

        # hypervisor supported version, eg. '>=2.6'
        'img_hv_requested_version': fields.VersionPredicateField(),

        # type of the hypervisor, eg kvm, ironic, xen
        'img_hv_type': fields.HVTypeField(),

        # Whether the image needs/expected config drive
        'img_config_drive': fields.ConfigDrivePolicyField(),

        # boolean flag to set space-saving or performance behavior on the
        # Datastore
        'img_linked_clone': fields.FlexibleBooleanField(),

        # Image mappings - related to Block device mapping data - mapping
        # of virtual image names to device names. This could be represented
        # as a formal data type, but is left as dict for same reason as
        # img_block_device_mapping field. It would arguably make sense for
        # the two to be combined into a single field and data type in the
        # future.
        'img_mappings': fields.ListOfDictOfNullableStringsField(),

        # image project id (set on upload)
        'img_owner_id': fields.StringField(),

        # root device name, used in snapshotting eg /dev/<blah>
        'img_root_device_name': fields.StringField(),

        # boolean - if false don't talk to nova agent
        'img_use_agent': fields.FlexibleBooleanField(),

        # integer value 1
        'img_version': fields.IntegerField(),

        # base64 of encoding of image signature
        'img_signature': fields.StringField(),

        # string indicating hash method used to compute image signature
        'img_signature_hash_method': fields.ImageSignatureHashTypeField(),

        # string indicating Castellan uuid of certificate
        # used to compute the image's signature
        'img_signature_certificate_uuid': fields.UUIDField(),

        # string indicating type of key used to compute image signature
        'img_signature_key_type': fields.ImageSignatureKeyTypeField(),

        # boolean - hide hypervisor signature on instance
        'img_hide_hypervisor_id': fields.FlexibleBooleanField(),

        # string of username with admin privileges
        'os_admin_user': fields.StringField(),

        # string of boot time command line arguments for the guest kernel
        'os_command_line': fields.StringField(),

        # the name of the specific guest operating system distro. This
        # is not done as an Enum since the list of operating systems is
        # growing incredibly fast, and valid values can be arbitrarily
        # user defined. Nova has no real need for strict validation so
        # leave it freeform
        'os_distro': fields.StringField(),

        # boolean - if true, then guest must support disk quiesce
        # or snapshot operation will be denied
        'os_require_quiesce': fields.FlexibleBooleanField(),

        # Secure Boot feature will be enabled by setting the "os_secure_boot"
        # image property to "required". Other options can be: "disabled" or
        # "optional".
        # "os:secure_boot" flavor extra spec value overrides the image property
        # value.
        'os_secure_boot': fields.SecureBootField(),

        # boolean - if using agent don't inject files, assume someone else is
        # doing that (cloud-init)
        'os_skip_agent_inject_files_at_boot': fields.FlexibleBooleanField(),

        # boolean - if using agent don't try inject ssh key, assume someone
        # else is doing that (cloud-init)
        'os_skip_agent_inject_ssh': fields.FlexibleBooleanField(),

        # The guest operating system family such as 'linux', 'windows' - this
        # is a fairly generic type. For a detailed type consider os_distro
        # instead
        'os_type': fields.OSTypeField(),

        # The required traits associated with the image. Traits are expected to
        # be defined as starting with `trait:` like below:
        # trait:HW_CPU_X86_AVX2=required
        # for trait in image_meta.traits_required:
        # will yield trait strings such as 'HW_CPU_X86_AVX2'
        'traits_required': fields.ListOfStringsField(),
    }

    # The keys are the legacy property names and
    # the values are the current preferred names
    _legacy_property_map = {
        'architecture': 'hw_architecture',
        'owner_id': 'img_owner_id',
        'vmware_disktype': 'hw_disk_type',
        'vmware_image_version': 'img_version',
        'vmware_ostype': 'os_distro',
        'auto_disk_config': 'hw_auto_disk_config',
        'ipxe_boot': 'hw_ipxe_boot',
        'xenapi_device_id': 'hw_device_id',
        'xenapi_image_compression_level': 'img_compression_level',
        'vmware_linked_clone': 'img_linked_clone',
        'xenapi_use_agent': 'img_use_agent',
        'xenapi_skip_agent_inject_ssh': 'os_skip_agent_inject_ssh',
        'xenapi_skip_agent_inject_files_at_boot':
        'os_skip_agent_inject_files_at_boot',
        'cache_in_nova': 'img_cache_in_nova',
        'vm_mode': 'hw_vm_mode',
        'bittorrent': 'img_bittorrent',
        'mappings': 'img_mappings',
        'block_device_mapping': 'img_block_device_mapping',
        'bdm_v2': 'img_bdm_v2',
        'root_device_name': 'img_root_device_name',
        'hypervisor_version_requires': 'img_hv_requested_version',
        'hypervisor_type': 'img_hv_type',
    }

    # TODO(berrange): Need to run this from a data migration
    # at some point so we can eventually kill off the compat
    def _set_attr_from_legacy_names(self, image_props):
        for legacy_key in self._legacy_property_map:
            new_key = self._legacy_property_map[legacy_key]

            if legacy_key not in image_props:
                continue

            setattr(self, new_key, image_props[legacy_key])

        vmware_adaptertype = image_props.get("vmware_adaptertype")
        if vmware_adaptertype == "ide":
            setattr(self, "hw_disk_bus", "ide")
        elif vmware_adaptertype:
            setattr(self, "hw_disk_bus", "scsi")
            setattr(self, "hw_scsi_model", vmware_adaptertype)

    def _set_numa_mem(self, image_props):
        hw_numa_mem = []
        hw_numa_mem_set = False
        for cellid in range(ImageMetaProps.NUMA_NODES_MAX):
            memprop = "hw_numa_mem.%d" % cellid
            if memprop not in image_props:
                break
            hw_numa_mem.append(int(image_props[memprop]))
            hw_numa_mem_set = True
            del image_props[memprop]

        if hw_numa_mem_set:
            self.hw_numa_mem = hw_numa_mem

    def _set_numa_cpus(self, image_props):
        hw_numa_cpus = []
        hw_numa_cpus_set = False
        for cellid in range(ImageMetaProps.NUMA_NODES_MAX):
            cpuprop = "hw_numa_cpus.%d" % cellid
            if cpuprop not in image_props:
                break
            hw_numa_cpus.append(hardware.parse_cpu_spec(image_props[cpuprop]))
            hw_numa_cpus_set = True
            del image_props[cpuprop]

        if hw_numa_cpus_set:
            self.hw_numa_cpus = hw_numa_cpus

    def _set_attr_from_current_names(self, image_props):
        for key in self.fields:
            # The two NUMA fields need special handling to
            # un-stringify them correctly
            if key == "hw_numa_mem":
                self._set_numa_mem(image_props)
            elif key == "hw_numa_cpus":
                self._set_numa_cpus(image_props)
            else:
                # traits_required will be populated by
                # _set_attr_from_trait_names
                if key not in image_props or key == "traits_required":
                    continue

                setattr(self, key, image_props[key])

    def _set_attr_from_trait_names(self, image_props):
        for trait in [
                six.text_type(k[6:]) for k, v in image_props.items()
                if six.text_type(k).startswith("trait:")
                and six.text_type(v) == six.text_type('required')
        ]:
            if 'traits_required' not in self:
                self.traits_required = []
            self.traits_required.append(trait)

    @classmethod
    def from_dict(cls, image_props):
        """Create instance from image properties dict

        :param image_props: dictionary of image metadata properties

        Creates a new object instance, initializing from a
        dictionary of image metadata properties

        :returns: an ImageMetaProps instance
        """
        obj = cls()
        # We look to see if the dict has entries for any
        # of the legacy property names first. Then we use
        # the current property names. That way if both the
        # current and legacy names are set, the value
        # associated with the current name takes priority
        obj._set_attr_from_legacy_names(image_props)
        obj._set_attr_from_current_names(image_props)
        obj._set_attr_from_trait_names(image_props)

        return obj

    def get(self, name, defvalue=None):
        """Get the value of an attribute
        :param name: the attribute to request
        :param defvalue: the default value if not set

        This returns the value of an attribute if it is currently
        set, otherwise it will return None.

        This differs from accessing props.attrname, because that
        will raise an exception if the attribute has no value set.

        So instead of

          if image_meta.properties.obj_attr_is_set("some_attr"):
             val = image_meta.properties.some_attr
          else
             val = None

        Callers can rely on unconditional access

             val = image_meta.properties.get("some_attr")

        :returns: the attribute value or None
        """

        if not self.obj_attr_is_set(name):
            return defvalue

        return getattr(self, name)
Beispiel #7
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
Beispiel #8
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
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,
        )