def test_get_pci_requests_from_flavor_affinity_policy( self, mock_translate): self.flags(alias=[_fake_alias1, _fake_alias2], group='pci') flavor = {'extra_specs': {"pci_passthrough:alias": "QuickAssist:3, IntelNIC: 1"}} policy = fields.PCINUMAAffinityPolicy.PREFERRED request.get_pci_requests_from_flavor(flavor, affinity_policy=policy) mock_translate.assert_called_with(mock.ANY, affinity_policy=policy)
def test_get_pci_requests_from_flavor_including_space(self): _fake_alias4 = jsonutils.dumps({ "name": " Cirrus Logic ", "capability_type": "pci", "product_id": "0ff2", "vendor_id": "10de", "device_type": "type-PCI", }) self.flags(alias=[_fake_alias2, _fake_alias4], group='pci') expect_request = [ {'count': 4, 'spec': [{'vendor_id': '10de', 'product_id': '0ff2', 'dev_type': "type-PCI", 'capability_type': 'pci'}], 'alias_name': 'Cirrus Logic'}, {'count': 3, 'spec': [{'vendor_id': '8086', 'product_id': '1111', 'dev_type': "type-PF", 'capability_type': 'pci'}], 'alias_name': 'IntelNIC'}, ] flavor = {'extra_specs': {"pci_passthrough:alias": " Cirrus Logic : 4, IntelNIC: 3"}} requests = request.get_pci_requests_from_flavor(flavor) self.assertEqual(2, len(requests.requests)) self.assertEqual({3, 4}, {p.count for p in requests.requests}) self._verify_result(expect_request, requests.requests)
def test_get_pci_requests_from_flavor(self): self.flags(alias=[_fake_alias1], group='pci') expect_request = [ { 'count': 3, 'spec': [{ 'vendor_id': '8086', 'product_id': '4443', 'dev_type': "type-PCI", 'capability_type': 'pci', }], 'alias_name': 'QuickAssist' }, ] flavor = {'extra_specs': {'pci_passthrough:alias': 'QuickAssist:3'}} requests = request.get_pci_requests_from_flavor(flavor) self.assertEqual(1, len(requests.requests)) self.assertEqual({ 3, }, {p.count for p in requests.requests}) self._verify_result(expect_request, requests.requests)
def test_get_pci_requests_from_flavor_multiple(self): self.flags(alias=[_fake_alias1, _fake_alias2], group='pci') expect_request = [ {'count': 3, 'spec': [{'vendor_id': '8086', 'product_id': '4443', 'dev_type': "type-PCI", 'capability_type': 'pci'}], 'alias_name': 'QuickAssist'}, {'count': 1, 'spec': [{'vendor_id': '8086', 'product_id': '1111', 'dev_type': "type-PF", 'capability_type': 'pci'}], 'alias_name': 'IntelNIC'}, ] flavor = {'extra_specs': {"pci_passthrough:alias": "QuickAssist:3, IntelNIC: 1"}} requests = request.get_pci_requests_from_flavor(flavor) self.assertEqual(2, len(requests.requests)) self.assertEqual({3, 1}, {p.count for p in requests.requests}) self._verify_result(expect_request, requests.requests)
def test_get_pci_requests_from_flavor_including_space(self): self.flags(alias=[_fake_alias3, _fake_alias4], group='pci') expect_request = [ {'count': 4, 'spec': [{'vendor_id': '10de', 'product_id': '0ff2', 'dev_type': "type-PCI", 'capability_type': 'pci'}], 'alias_name': 'Cirrus Logic'}, {'count': 3, 'spec': [{'vendor_id': '8086', 'product_id': '1111', 'dev_type': "type-PF", 'capability_type': 'pci'}], 'alias_name': 'IntelNIC'}, ] flavor = {'extra_specs': {"pci_passthrough:alias": " Cirrus Logic : 4, IntelNIC: 3"}} requests = request.get_pci_requests_from_flavor(flavor) self.assertEqual(set([3, 4]), set([p.count for p in requests.requests])) self._verify_result(expect_request, requests.requests)
def test_get_pci_requests_from_flavor(self): self.flags(alias=[_fake_alias1, _fake_alias3], group='pci') expect_request = [ {'count': 3, 'spec': [{'vendor_id': '8086', 'product_id': '4443', 'dev_type': "type-PCI", 'capability_type': 'pci'}], 'alias_name': 'QuicAssist'}, {'count': 1, 'spec': [{'vendor_id': '8086', 'product_id': '1111', 'dev_type': "type-PF", 'capability_type': 'pci'}], 'alias_name': 'IntelNIC'}, ] flavor = {'extra_specs': {"pci_passthrough:alias": "QuicAssist:3, IntelNIC: 1"}} requests = request.get_pci_requests_from_flavor(flavor) self.assertEqual(set([1, 3]), set([p.count for p in requests.requests])) self._verify_result(expect_request, requests.requests)
def test_get_pci_requests_from_flavor(self): self.flags(pci_alias=[_fake_alias1, _fake_alias3]) expect_request = [ {'count': 3, 'spec': [{'vendor_id': '8086', 'product_id': '4443', 'device_type': "ACCEL", 'capability_type': 'pci'}], 'alias_name': 'QuicAssist'}, {'count': 1, 'spec': [{'vendor_id': '8086', 'product_id': '1111', 'device_type': "NIC", 'capability_type': 'pci'}], 'alias_name': 'IntelNIC'}, ] flavor = {'extra_specs': {"pci_passthrough:alias": "QuicAssist:3, IntelNIC: 1"}} requests = request.get_pci_requests_from_flavor(flavor) self.assertEqual(set([1, 3]), set([p.count for p in requests.requests])) self._verify_result(expect_request, requests.requests)
def test_get_pci_requests_from_flavor_including_space(self): self.flags(alias=[_fake_alias3, _fake_alias4], group='pci') expect_request = [ { 'count': 4, 'spec': [{ 'vendor_id': '10de', 'product_id': '0ff2', 'dev_type': "type-PCI", 'capability_type': 'pci' }], 'alias_name': 'Cirrus Logic' }, { 'count': 3, 'spec': [{ 'vendor_id': '8086', 'product_id': '1111', 'dev_type': "type-PF", 'capability_type': 'pci' }], 'alias_name': 'IntelNIC' }, ] flavor = { 'extra_specs': { "pci_passthrough:alias": " Cirrus Logic : 4, IntelNIC: 3" } } requests = request.get_pci_requests_from_flavor(flavor) self.assertEqual(set([3, 4]), set([p.count for p in requests.requests])) self._verify_result(expect_request, requests.requests)
def _move_claim(self, context, instance, new_instance_type, nodename, move_type=None, image_meta=None, limits=None, migration=None): """Indicate that resources are needed for a move to this host. Move can be either a migrate/resize, live-migrate or an evacuate/rebuild operation. :param context: security context :param instance: instance object to reserve resources for :param new_instance_type: new instance_type being resized to :param nodename: The Ironic nodename selected by the scheduler :param image_meta: instance image metadata :param move_type: move type - can be one of 'migration', 'resize', 'live-migration', 'evacuate' :param limits: Dict of oversubscription limits for memory, disk, and CPUs :param migration: A migration object if one was already created elsewhere for this operation :returns: A Claim ticket representing the reserved resources. This should be turned into finalize a resource claim or free resources after the compute operation is finished. """ image_meta = image_meta or {} if migration: self._claim_existing_migration(migration, nodename) else: migration = self._create_migration(context, instance, new_instance_type, nodename, move_type) if self.disabled(nodename): # compute_driver doesn't support resource tracking, just # generate the migration record and continue the resize: return claims.NopClaim(migration=migration) # get memory overhead required to build this instance: overhead = self.driver.estimate_instance_overhead(new_instance_type) LOG.debug( "Memory overhead for %(flavor)d MB instance; %(overhead)d " "MB", { 'flavor': new_instance_type.memory_mb, 'overhead': overhead['memory_mb'] }) LOG.debug( "Disk overhead for %(flavor)d GB instance; %(overhead)d " "GB", { 'flavor': instance.flavor.root_gb, 'overhead': overhead.get('disk_gb', 0) }) LOG.debug( "CPU overhead for %(flavor)d vCPUs instance; %(overhead)d " "vCPU(s)", { 'flavor': instance.flavor.vcpus, 'overhead': overhead.get('vcpus', 0) }) cn = self.compute_nodes[nodename] # TODO(moshele): we are recreating the pci requests even if # there was no change on resize. This will cause allocating # the old/new pci device in the resize phase. In the future # we would like to optimise this. new_pci_requests = pci_request.get_pci_requests_from_flavor( new_instance_type) new_pci_requests.instance_uuid = instance.uuid # PCI requests come from two sources: instance flavor and # SR-IOV ports. SR-IOV ports pci_request don't have an alias_name. # On resize merge the SR-IOV ports pci_requests with the new # instance flavor pci_requests. if instance.pci_requests: for request in instance.pci_requests.requests: if request.alias_name is None: new_pci_requests.requests.append(request) claim = claims.MoveClaim(context, instance, nodename, new_instance_type, image_meta, self, cn, new_pci_requests, overhead=overhead, limits=limits) claim.migration = migration claimed_pci_devices_objs = [] if self.pci_tracker: # NOTE(jaypipes): ComputeNode.pci_device_pools is set below # in _update_usage_from_instance(). claimed_pci_devices_objs = self.pci_tracker.claim_instance( context, new_pci_requests, claim.claimed_numa_topology) claimed_pci_devices = objects.PciDeviceList( objects=claimed_pci_devices_objs) # TODO(jaypipes): Move claimed_numa_topology out of the Claim's # constructor flow so the Claim constructor only tests whether # resources can be claimed, not consume the resources directly. mig_context = objects.MigrationContext( context=context, instance_uuid=instance.uuid, migration_id=migration.id, old_numa_topology=instance.numa_topology, new_numa_topology=claim.claimed_numa_topology, old_pci_devices=instance.pci_devices, new_pci_devices=claimed_pci_devices, old_pci_requests=instance.pci_requests, new_pci_requests=new_pci_requests) instance.migration_context = mig_context instance.save() # Mark the resources in-use for the resize landing on this # compute host: self._update_usage_from_migration(context, instance, migration, nodename) elevated = context.elevated() self._update(elevated, cn) return claim
def test_get_pci_requests_from_flavor_no_extra_spec(self): self.flags(alias=[_fake_alias1, _fake_alias3], group='pci') flavor = {} requests = request.get_pci_requests_from_flavor(flavor) self.assertEqual([], requests.requests)
def _move_claim(self, context, instance, new_instance_type, nodename, move_type=None, image_meta=None, limits=None, migration=None): """Indicate that resources are needed for a move to this host. Move can be either a migrate/resize, live-migrate or an evacuate/rebuild operation. :param context: security context :param instance: instance object to reserve resources for :param new_instance_type: new instance_type being resized to :param nodename: The Ironic nodename selected by the scheduler :param image_meta: instance image metadata :param move_type: move type - can be one of 'migration', 'resize', 'live-migration', 'evacuate' :param limits: Dict of oversubscription limits for memory, disk, and CPUs :param migration: A migration object if one was already created elsewhere for this operation :returns: A Claim ticket representing the reserved resources. This should be turned into finalize a resource claim or free resources after the compute operation is finished. """ image_meta = image_meta or {} if migration: self._claim_existing_migration(migration, nodename) else: migration = self._create_migration(context, instance, new_instance_type, nodename, move_type) if self.disabled(nodename): # compute_driver doesn't support resource tracking, just # generate the migration record and continue the resize: return claims.NopClaim(migration=migration) # get memory overhead required to build this instance: overhead = self.driver.estimate_instance_overhead(new_instance_type) LOG.debug("Memory overhead for %(flavor)d MB instance; %(overhead)d " "MB", {'flavor': new_instance_type.memory_mb, 'overhead': overhead['memory_mb']}) LOG.debug("Disk overhead for %(flavor)d GB instance; %(overhead)d " "GB", {'flavor': instance.flavor.root_gb, 'overhead': overhead.get('disk_gb', 0)}) LOG.debug("CPU overhead for %(flavor)d vCPUs instance; %(overhead)d " "vCPU(s)", {'flavor': instance.flavor.vcpus, 'overhead': overhead.get('vcpus', 0)}) cn = self.compute_nodes[nodename] # TODO(moshele): we are recreating the pci requests even if # there was no change on resize. This will cause allocating # the old/new pci device in the resize phase. In the future # we would like to optimise this. new_pci_requests = pci_request.get_pci_requests_from_flavor( new_instance_type) new_pci_requests.instance_uuid = instance.uuid # PCI requests come from two sources: instance flavor and # SR-IOV ports. SR-IOV ports pci_request don't have an alias_name. # On resize merge the SR-IOV ports pci_requests with the new # instance flavor pci_requests. if instance.pci_requests: for request in instance.pci_requests.requests: if request.alias_name is None: new_pci_requests.requests.append(request) claim = claims.MoveClaim(context, instance, nodename, new_instance_type, image_meta, self, cn, new_pci_requests, overhead=overhead, limits=limits) claim.migration = migration claimed_pci_devices_objs = [] if self.pci_tracker: # NOTE(jaypipes): ComputeNode.pci_device_pools is set below # in _update_usage_from_instance(). claimed_pci_devices_objs = self.pci_tracker.claim_instance( context, new_pci_requests, claim.claimed_numa_topology) claimed_pci_devices = objects.PciDeviceList( objects=claimed_pci_devices_objs) # TODO(jaypipes): Move claimed_numa_topology out of the Claim's # constructor flow so the Claim constructor only tests whether # resources can be claimed, not consume the resources directly. mig_context = objects.MigrationContext( context=context, instance_uuid=instance.uuid, migration_id=migration.id, old_numa_topology=instance.numa_topology, new_numa_topology=claim.claimed_numa_topology, old_pci_devices=instance.pci_devices, new_pci_devices=claimed_pci_devices, old_pci_requests=instance.pci_requests, new_pci_requests=new_pci_requests) instance.migration_context = mig_context instance.save() # Mark the resources in-use for the resize landing on this # compute host: self._update_usage_from_migration(context, instance, migration, nodename) elevated = context.elevated() self._update(elevated, cn) return claim
def test_get_pci_requests_from_flavor_no_extra_spec(self): self.flags(alias=[_fake_alias1, _fake_alias3], group='pci') flavor = {} requests = request.get_pci_requests_from_flavor(flavor) self.assertEqual([], requests.requests)