# 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.notifications.objects import server_group as server_group_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.1: Add force_hosts, force_nodes, ignore_hosts, image_meta, # instance_group, requested_destination, retry, # scheduler_hints and security_groups fields VERSION = '1.1' SCHEMA = { 'ignore_hosts': ('request_spec', 'ignore_hosts'), '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'), 'scheduler_hints': ('request_spec', 'scheduler_hints'), } 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), 'force_hosts': fields.StringField(nullable=True), 'force_nodes': fields.StringField(nullable=True), 'ignore_hosts': fields.ListOfStringsField(nullable=True), 'image_meta': fields.ObjectField('ImageMetaPayload', nullable=True), 'instance_group': fields.ObjectField('ServerGroupPayload', 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), 'requested_destination': fields.ObjectField('DestinationPayload', nullable=True), 'retry': fields.ObjectField('SchedulerRetriesPayload', nullable=True), 'scheduler_hints': fields.DictOfListOfStringsField(nullable=True), 'security_groups': fields.ListOfStringsField(), } 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 if 'requested_destination' in request_spec \ and request_spec.requested_destination: self.requested_destination = DestinationPayload( destination=request_spec.requested_destination) else: self.requested_destination = None if 'retry' in request_spec and request_spec.retry: self.retry = SchedulerRetriesPayload( retry=request_spec.retry) else: self.retry = None self.security_groups = [ sec_group.identifier for sec_group in request_spec.security_groups] if 'instance_group' in request_spec and request_spec.instance_group: self.instance_group = server_group_payload.ServerGroupPayload( group=request_spec.instance_group) else: self.instance_group = None if 'force_hosts' in request_spec and request_spec.force_hosts: self.force_hosts = request_spec.force_hosts[0] else: self.force_hosts = None if 'force_nodes' in request_spec and request_spec.force_nodes: self.force_nodes = request_spec.force_nodes[0] else: self.force_nodes = 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.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 @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.1: Added 'socket' to numa_policy field VERSION = '1.1' 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 @nova_base.NovaObjectRegistry.register_notification class DestinationPayload(base.NotificationPayloadBase): # Version 1.0: Initial version VERSION = '1.0' SCHEMA = { 'aggregates': ('destination', 'aggregates'), } fields = { 'host': fields.StringField(), 'node': fields.StringField(nullable=True), 'cell': fields.ObjectField('CellMappingPayload', nullable=True), 'aggregates': fields.ListOfStringsField(nullable=True, default=None), } def __init__(self, destination): super(DestinationPayload, self).__init__() if (destination.obj_attr_is_set('host') and destination.host is not None): self.host = destination.host if (destination.obj_attr_is_set('node') and destination.node is not None): self.node = destination.node if (destination.obj_attr_is_set('cell') and destination.cell is not None): self.cell = CellMappingPayload(destination.cell) self.populate_schema(destination=destination) @nova_base.NovaObjectRegistry.register_notification class SchedulerRetriesPayload(base.NotificationPayloadBase): # Version 1.0: Initial version VERSION = '1.0' SCHEMA = { 'num_attempts': ('retry', 'num_attempts'), } fields = { 'num_attempts': fields.IntegerField(), 'hosts': fields.ListOfStringsField(), } def __init__(self, retry): super(SchedulerRetriesPayload, self).__init__() self.hosts = [] for compute_node in retry.hosts: self.hosts.append(compute_node.hypervisor_hostname) self.populate_schema(retry=retry) @nova_base.NovaObjectRegistry.register_notification class CellMappingPayload(base.NotificationPayloadBase): # Version 1.0: Initial version # Version 2.0: Remove transport_url and database_connection fields. VERSION = '2.0' SCHEMA = { 'uuid': ('cell', 'uuid'), 'name': ('cell', 'name'), 'disabled': ('cell', 'disabled'), } fields = { 'uuid': fields.UUIDField(), 'name': fields.StringField(nullable=True), 'disabled': fields.BooleanField(default=False), } def __init__(self, cell): super(CellMappingPayload, self).__init__() self.populate_schema(cell=cell)