summaryrefslogtreecommitdiff
path: root/nova/notifications
diff options
context:
space:
mode:
authorAlex Szarka <szarka@inf.u-szeged.hu>2017-07-11 18:32:24 +0200
committerTakashi NATSUME <natsume.takashi@lab.ntt.co.jp>2018-11-21 16:23:28 +0900
commitfe4e47d9899b730abf06a120ba113f5f4a567d1e (patch)
treec9887de9d262b6915203972ff39b595b218c6988 /nova/notifications
parent7217e38bafb75e8a613763835b64e48e6b2c8ece (diff)
downloadnova-fe4e47d9899b730abf06a120ba113f5f4a567d1e.tar.gz
Transform compute_task notifications
The following notifications have been transformed to the versioned notification framework. * compute_task.build_instances * compute_task.migrate_server * compute_task.rebuild_server Co-Authored-By: Takashi Natsume <natsume.takashi@lab.ntt.co.jp> Change-Id: Ibfb0a6db5920d921c4fc7cabf3f4d2838ea7f421 Implements: bp versioned-notification-transformation-stein
Diffstat (limited to 'nova/notifications')
-rw-r--r--nova/notifications/objects/base.py23
-rw-r--r--nova/notifications/objects/compute_task.py54
-rw-r--r--nova/notifications/objects/image.py261
-rw-r--r--nova/notifications/objects/request_spec.py226
4 files changed, 554 insertions, 10 deletions
diff --git a/nova/notifications/objects/base.py b/nova/notifications/objects/base.py
index 26012dfbc8..70ce3391c9 100644
--- a/nova/notifications/objects/base.py
+++ b/nova/notifications/objects/base.py
@@ -67,7 +67,9 @@ class EventType(NotificationObject):
# NotificationActionField enum
# Version 1.16: CONNECT is added to NotificationActionField enum
# Version 1.17: USAGE is added to NotificationActionField enum
- VERSION = '1.17'
+ # Version 1.18: ComputeTask related values have been added to
+ # NotificationActionField enum
+ VERSION = '1.18'
fields = {
'object': fields.StringField(nullable=False),
@@ -119,7 +121,7 @@ class NotificationPayloadBase(NotificationObject):
self.populated = not self.SCHEMA
@rpc.if_notifications_enabled
- def populate_schema(self, **kwargs):
+ def populate_schema(self, set_none=True, **kwargs):
"""Populate the object based on the SCHEMA and the source objects
:param kwargs: A dict contains the source object at the key defined in
@@ -137,14 +139,15 @@ class NotificationPayloadBase(NotificationObject):
NotImplementedError,
exception.OrphanedObjectError,
ovo_exception.OrphanedObjectError):
- # If it is unset or non lazy loadable in the source object
- # then we cannot do anything else but try to default it in the
- # payload object we are generating here.
- # NOTE(gibi): This will fail if the payload field is not
- # nullable, but that means that either the source object is not
- # properly initialized or the payload field needs to be defined
- # as nullable
- setattr(self, key, None)
+ if set_none:
+ # If it is unset or non lazy loadable in the source object
+ # then we cannot do anything else but try to default it
+ # in the payload object we are generating here.
+ # NOTE(gibi): This will fail if the payload field is not
+ # nullable, but that means that either the source object
+ # is not properly initialized or the payload field needs
+ # to be defined as nullable
+ setattr(self, key, None)
except Exception:
with excutils.save_and_reraise_exception():
LOG.error('Failed trying to populate attribute "%s" '
diff --git a/nova/notifications/objects/compute_task.py b/nova/notifications/objects/compute_task.py
new file mode 100644
index 0000000000..fe087dbb93
--- /dev/null
+++ b/nova/notifications/objects/compute_task.py
@@ -0,0 +1,54 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from nova.notifications.objects import base
+from nova.notifications.objects import request_spec as reqspec_payload
+from nova.objects import base as nova_base
+from nova.objects import fields
+
+
+@nova_base.NovaObjectRegistry.register_notification
+class ComputeTaskPayload(base.NotificationPayloadBase):
+ # Version 1.0: Initial version
+ VERSION = '1.0'
+
+ fields = {
+ 'instance_uuid': fields.UUIDField(),
+ # There are some cases that request_spec is None.
+ # e.g. Old instances can still have no RequestSpec object
+ # attached to them.
+ 'request_spec': fields.ObjectField('RequestSpecPayload',
+ nullable=True),
+ 'state': fields.InstanceStateField(nullable=True),
+ 'reason': fields.ObjectField('ExceptionPayload')
+ }
+
+ def __init__(self, instance_uuid, request_spec, state, reason):
+ super(ComputeTaskPayload, self).__init__()
+ self.instance_uuid = instance_uuid
+ self.request_spec = reqspec_payload.RequestSpecPayload(
+ request_spec) if request_spec is not None else None
+ self.state = state
+ self.reason = reason
+
+
+@base.notification_sample('compute_task-build_instances-error.json')
+@base.notification_sample('compute_task-migrate_server-error.json')
+@base.notification_sample('compute_task-rebuild_server-error.json')
+@nova_base.NovaObjectRegistry.register_notification
+class ComputeTaskNotification(base.NotificationBase):
+ # Version 1.0: Initial version
+ VERSION = '1.0'
+
+ fields = {
+ 'payload': fields.ObjectField('ComputeTaskPayload')
+ }
diff --git a/nova/notifications/objects/image.py b/nova/notifications/objects/image.py
new file mode 100644
index 0000000000..d68259731c
--- /dev/null
+++ b/nova/notifications/objects/image.py
@@ -0,0 +1,261 @@
+# Copyright 2018 NTT Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from nova.notifications.objects import base
+from nova.objects import base as nova_base
+from nova.objects import fields
+
+
+@nova_base.NovaObjectRegistry.register_notification
+class ImageMetaPayload(base.NotificationPayloadBase):
+ # Version 1.0: Initial version
+ VERSION = '1.0'
+
+ SCHEMA = {
+ 'id': ('image_meta', 'id'),
+ 'name': ('image_meta', 'name'),
+ 'status': ('image_meta', 'status'),
+ 'visibility': ('image_meta', 'visibility'),
+ 'protected': ('image_meta', 'protected'),
+ 'checksum': ('image_meta', 'checksum'),
+ 'owner': ('image_meta', 'owner'),
+ 'size': ('image_meta', 'size'),
+ 'virtual_size': ('image_meta', 'virtual_size'),
+ 'container_format': ('image_meta', 'container_format'),
+ 'disk_format': ('image_meta', 'disk_format'),
+ 'created_at': ('image_meta', 'created_at'),
+ 'updated_at': ('image_meta', 'updated_at'),
+ 'tags': ('image_meta', 'tags'),
+ 'direct_url': ('image_meta', 'direct_url'),
+ 'min_ram': ('image_meta', 'min_ram'),
+ 'min_disk': ('image_meta', 'min_disk')
+ }
+
+ # NOTE(takashin): The reason that each field is nullable is as follows.
+ #
+ # a. It is defined as "The value might be null (JSON null data type)."
+ # in the "Show image" API (GET /v2/images/{image_id})
+ # in the glance API v2 Reference.
+ # (https://developer.openstack.org/api-ref/image/v2/index.html)
+ #
+ # * checksum
+ # * container_format
+ # * disk_format
+ # * min_disk
+ # * min_ram
+ # * name
+ # * owner
+ # * size
+ # * updated_at
+ # * virtual_size
+ #
+ # b. It is optional in the response from glance.
+ # * direct_url
+ #
+ # a. It is defined as nullable in the ImageMeta object.
+ # * created_at
+ #
+ # c. It cannot be got in the boot from volume case.
+ # See VIM_IMAGE_ATTRIBUTES in nova/utils.py.
+ #
+ # * id (not 'image_id')
+ # * visibility
+ # * protected
+ # * status
+ # * tags
+ fields = {
+ 'id': fields.UUIDField(nullable=True),
+ 'name': fields.StringField(nullable=True),
+ 'status': fields.StringField(nullable=True),
+ 'visibility': fields.StringField(nullable=True),
+ 'protected': fields.FlexibleBooleanField(nullable=True),
+ 'checksum': fields.StringField(nullable=True),
+ 'owner': fields.StringField(nullable=True),
+ 'size': fields.IntegerField(nullable=True),
+ 'virtual_size': fields.IntegerField(nullable=True),
+ 'container_format': fields.StringField(nullable=True),
+ 'disk_format': fields.StringField(nullable=True),
+ 'created_at': fields.DateTimeField(nullable=True),
+ 'updated_at': fields.DateTimeField(nullable=True),
+ 'tags': fields.ListOfStringsField(nullable=True),
+ 'direct_url': fields.StringField(nullable=True),
+ 'min_ram': fields.IntegerField(nullable=True),
+ 'min_disk': fields.IntegerField(nullable=True),
+ 'properties': fields.ObjectField('ImageMetaPropsPayload')
+ }
+
+ def __init__(self, image_meta):
+ super(ImageMetaPayload, self).__init__()
+ self.properties = ImageMetaPropsPayload(
+ image_meta_props=image_meta.properties)
+ self.populate_schema(image_meta=image_meta)
+
+
+@nova_base.NovaObjectRegistry.register_notification
+class ImageMetaPropsPayload(base.NotificationPayloadBase):
+ # Version 1.0: Initial version
+ VERSION = '1.0'
+
+ 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)
diff --git a/nova/notifications/objects/request_spec.py b/nova/notifications/objects/request_spec.py
new file mode 100644
index 0000000000..f372bafcaa
--- /dev/null
+++ b/nova/notifications/objects/request_spec.py
@@ -0,0 +1,226 @@
+# Copyright 2018 NTT Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from nova.notifications.objects import base
+from nova.notifications.objects import flavor as flavor_payload
+from nova.notifications.objects import image as image_payload
+from nova.objects import base as nova_base
+from nova.objects import fields
+
+
+@nova_base.NovaObjectRegistry.register_notification
+class RequestSpecPayload(base.NotificationPayloadBase):
+ # Version 1.0: Initial version
+ VERSION = '1.0'
+
+ SCHEMA = {
+ 'instance_uuid': ('request_spec', 'instance_uuid'),
+ 'project_id': ('request_spec', 'project_id'),
+ 'user_id': ('request_spec', 'user_id'),
+ 'availability_zone': ('request_spec', 'availability_zone'),
+ 'num_instances': ('request_spec', 'num_instances')
+ }
+
+ fields = {
+ 'instance_uuid': fields.UUIDField(),
+ 'project_id': fields.StringField(nullable=True),
+ 'user_id': fields.StringField(nullable=True),
+ 'availability_zone': fields.StringField(nullable=True),
+ 'flavor': fields.ObjectField('FlavorPayload', nullable=True),
+ 'image': fields.ObjectField('ImageMetaPayload', nullable=True),
+ 'numa_topology': fields.ObjectField('InstanceNUMATopologyPayload',
+ nullable=True),
+ 'pci_requests': fields.ObjectField('InstancePCIRequestsPayload',
+ nullable=True),
+ 'num_instances': fields.IntegerField(default=1)
+ }
+
+ def __init__(self, request_spec):
+ super(RequestSpecPayload, self).__init__()
+ self.flavor = flavor_payload.FlavorPayload(
+ request_spec.flavor) if request_spec.obj_attr_is_set(
+ 'flavor') else None
+ self.image = image_payload.ImageMetaPayload(
+ request_spec.image) if request_spec.image else None
+ if request_spec.numa_topology is not None:
+ if not request_spec.numa_topology.obj_attr_is_set('instance_uuid'):
+ request_spec.numa_topology.instance_uuid = (
+ request_spec.instance_uuid)
+ self.numa_topology = InstanceNUMATopologyPayload(
+ request_spec.numa_topology)
+ else:
+ self.numa_topology = None
+ if request_spec.pci_requests is not None:
+ if not request_spec.pci_requests.obj_attr_is_set('instance_uuid'):
+ request_spec.pci_requests.instance_uuid = (
+ request_spec.instance_uuid)
+ self.pci_requests = InstancePCIRequestsPayload(
+ request_spec.pci_requests)
+ else:
+ self.pci_requests = None
+ self.populate_schema(request_spec=request_spec)
+
+
+@nova_base.NovaObjectRegistry.register_notification
+class InstanceNUMATopologyPayload(base.NotificationPayloadBase):
+ # Version 1.0: Initial version
+ VERSION = '1.0'
+
+ SCHEMA = {
+ 'instance_uuid': ('numa_topology', 'instance_uuid'),
+ 'emulator_threads_policy': ('numa_topology',
+ 'emulator_threads_policy')
+ }
+
+ fields = {
+ 'instance_uuid': fields.UUIDField(),
+ 'cells': fields.ListOfObjectsField('InstanceNUMACellPayload'),
+ 'emulator_threads_policy': fields.CPUEmulatorThreadsPolicyField(
+ nullable=True)
+ }
+
+ def __init__(self, numa_topology):
+ super(InstanceNUMATopologyPayload, self).__init__()
+ self.cells = InstanceNUMACellPayload.from_numa_cell_list_obj(
+ numa_topology.cells)
+ self.populate_schema(numa_topology=numa_topology)
+
+
+@nova_base.NovaObjectRegistry.register_notification
+class InstanceNUMACellPayload(base.NotificationPayloadBase):
+ # Version 1.0: Initial version
+ VERSION = '1.0'
+
+ SCHEMA = {
+ 'id': ('numa_cell', 'id'),
+ 'cpuset': ('numa_cell', 'cpuset'),
+ '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'),
+ 'cpuset_reserved': ('numa_cell', 'cpuset_reserved'),
+ }
+
+ fields = {
+ 'id': fields.IntegerField(),
+ 'cpuset': fields.SetOfIntegersField(),
+ '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),
+ 'cpuset_reserved': fields.SetOfIntegersField(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
+
+
+@nova_base.NovaObjectRegistry.register_notification
+class VirtCPUTopologyPayload(base.NotificationPayloadBase):
+ # Version 1.0: Initial version
+ VERSION = '1.0'
+
+ SCHEMA = {
+ 'sockets': ('virt_cpu_topology', 'sockets'),
+ 'cores': ('virt_cpu_topology', 'cores'),
+ 'threads': ('virt_cpu_topology', 'threads'),
+ }
+
+ fields = {
+ 'sockets': fields.IntegerField(nullable=True, default=1),
+ 'cores': fields.IntegerField(nullable=True, default=1),
+ 'threads': fields.IntegerField(nullable=True, default=1),
+ }
+
+ def __init__(self, virt_cpu_topology):
+ super(VirtCPUTopologyPayload, self).__init__()
+ self.populate_schema(virt_cpu_topology=virt_cpu_topology)
+
+
+@nova_base.NovaObjectRegistry.register_notification
+class InstancePCIRequestsPayload(base.NotificationPayloadBase):
+ # Version 1.0: Initial version
+ VERSION = '1.0'
+
+ SCHEMA = {
+ 'instance_uuid': ('pci_requests', 'instance_uuid')
+ }
+
+ fields = {
+ 'instance_uuid': fields.UUIDField(),
+ 'requests': fields.ListOfObjectsField('InstancePCIRequestPayload')
+ }
+
+ def __init__(self, pci_requests):
+ super(InstancePCIRequestsPayload, self).__init__()
+ self.requests = InstancePCIRequestPayload.from_pci_request_list_obj(
+ pci_requests.requests)
+ self.populate_schema(pci_requests=pci_requests)
+
+
+@nova_base.NovaObjectRegistry.register_notification
+class InstancePCIRequestPayload(base.NotificationPayloadBase):
+ # Version 1.0: Initial version
+ VERSION = '1.0'
+
+ SCHEMA = {
+ 'count': ('pci_request', 'count'),
+ 'spec': ('pci_request', 'spec'),
+ 'alias_name': ('pci_request', 'alias_name'),
+ 'request_id': ('pci_request', 'request_id'),
+ 'numa_policy': ('pci_request', 'numa_policy')
+ }
+
+ fields = {
+ 'count': fields.IntegerField(),
+ 'spec': fields.ListOfDictOfNullableStringsField(),
+ 'alias_name': fields.StringField(nullable=True),
+ 'request_id': fields.UUIDField(nullable=True),
+ 'numa_policy': fields.PCINUMAAffinityPolicyField(nullable=True)
+ }
+
+ def __init__(self, pci_request):
+ super(InstancePCIRequestPayload, self).__init__()
+ self.populate_schema(pci_request=pci_request)
+
+ @classmethod
+ def from_pci_request_list_obj(cls, pci_request_list):
+ """Returns a list of InstancePCIRequestPayload objects
+ based on the passed list of InstancePCIRequest objects.
+ """
+ payloads = []
+ for pci_request in pci_request_list:
+ payloads.append(cls(pci_request))
+ return payloads