def _numa_get_constraints_auto(nodes, flavor): if ((flavor.vcpus % nodes) > 0 or (flavor.memory_mb % nodes) > 0): raise exception.ImageNUMATopologyAsymmetric() cells = [] for node in range(nodes): ncpus = int(flavor.vcpus / nodes) mem = int(flavor.memory_mb / nodes) start = node * ncpus cpuset = set(range(start, start + ncpus)) cells.append( objects.InstanceNUMACell(id=node, cpuset=cpuset, memory=mem)) return objects.InstanceNUMATopology(cells=cells)
def test_numa_topology_filter_pass_set_limit(self): instance_topology = objects.InstanceNUMATopology( cells=[objects.InstanceNUMACell(id=0, cpuset=set([1]), memory=512), objects.InstanceNUMACell(id=1, cpuset=set([3]), memory=512) ]) spec_obj = self._get_spec_obj(numa_topology=instance_topology) host = fakes.FakeHostState('host1', 'node1', {'numa_topology': fakes.NUMA_TOPOLOGY, 'pci_stats': None, 'cpu_allocation_ratio': 21, 'ram_allocation_ratio': 1.3}) self.assertTrue(self.filt_cls.host_passes(host, spec_obj)) limits = host.limits['numa_topology'] self.assertEqual(limits.cpu_allocation_ratio, 21) self.assertEqual(limits.ram_allocation_ratio, 1.3)
def test_numa_topology_filter_pass(self): instance_topology = objects.InstanceNUMATopology( cells=[objects.InstanceNUMACell(id=0, cpuset=set([1]), memory=512), objects.InstanceNUMACell(id=1, cpuset=set([3]), memory=512) ]) instance = fake_instance.fake_instance_obj(mock.sentinel.ctx) instance.numa_topology = instance_topology filter_properties = { 'request_spec': { 'instance_properties': jsonutils.to_primitive( obj_base.obj_to_primitive(instance))}} host = fakes.FakeHostState('host1', 'node1', {'numa_topology': fakes.NUMA_TOPOLOGY, 'pci_stats': None}) self.assertTrue(self.filt_cls.host_passes(host, filter_properties))
def test_numa_topology_filter_fail_networks(self): host = self._get_fake_host_state_with_networks() instance_topology = objects.InstanceNUMATopology(cells=[ objects.InstanceNUMACell(id=0, cpuset=set([1]), memory=512) ]) # this should fail because the networks are affined to different host # NUMA nodes but our guest only has a single NUMA node network_metadata = objects.NetworkMetadata(physnets=set(['foo']), tunneled=True) spec_obj = self._get_spec_obj(numa_topology=instance_topology, network_metadata=network_metadata) self.assertFalse(self.filt_cls.host_passes(host, spec_obj))
def test_numa_topology_filter_fail_fit(self): instance_topology = objects.InstanceNUMATopology(cells=[ objects.InstanceNUMACell(id=0, cpuset=set([1]), memory=512), objects.InstanceNUMACell(id=1, cpuset=set([2]), memory=512), objects.InstanceNUMACell(id=2, cpuset=set([3]), memory=512) ]) spec_obj = self._get_spec_obj(numa_topology=instance_topology) host = fakes.FakeHostState( 'host1', 'node1', { 'numa_topology': fakes.NUMA_TOPOLOGY, 'pci_stats': None, 'cpu_allocation_ratio': 16.0, 'ram_allocation_ratio': 1.5 }) self.assertFalse(self.filt_cls.host_passes(host, spec_obj))
def test_numa_topology_fails(self, mock_get): huge_instance = objects.InstanceNUMATopology(cells=[ objects.InstanceNUMACell( id=1, cpuset=set([1, 2, 3, 4, 5]), memory=2048) ]) limit_topo = hardware.VirtNUMALimitTopology(cells=[ hardware.VirtNUMATopologyCellLimit( 1, [1, 2], 512, cpu_limit=2, memory_limit=512), hardware.VirtNUMATopologyCellLimit( 1, [3, 4], 512, cpu_limit=2, memory_limit=512) ]) self.assertRaises(exception.ComputeResourcesUnavailable, self._claim, limits={'numa_topology': limit_topo.to_json()}, numa_topology=huge_instance)
def instance_topology_from_instance(instance): """Convenience method for getting the numa_topology out of instances Since we may get an Instance as either a dict, a db object, or an actual Instance object, this makes sure we get beck either None, or an instance of objects.InstanceNUMATopology class. """ if isinstance(instance, objects.Instance): # NOTE (ndipanov): This may cause a lazy-load of the attribute instance_numa_topology = instance.numa_topology else: if 'numa_topology' in instance: instance_numa_topology = instance['numa_topology'] elif 'uuid' in instance: try: instance_numa_topology = ( objects.InstanceNUMATopology.get_by_instance_uuid( context.get_admin_context(), instance['uuid']) ) except exception.NumaTopologyNotFound: instance_numa_topology = None else: instance_numa_topology = None if instance_numa_topology: if isinstance(instance_numa_topology, six.string_types): instance_numa_topology = VirtNUMAInstanceTopology.from_json( instance_numa_topology) elif isinstance(instance_numa_topology, dict): # NOTE (ndipanov): A horrible hack so that we can use this in the # scheduler, since the InstanceNUMATopology object is serialized # raw using the obj_base.obj_to_primitive, (which is buggy and will # give us a dict with a list of InstanceNUMACell objects), and then # passed to jsonutils.to_primitive, which will make a dict out of # those objects. All of this is done by # scheduler.utils.build_request_spec called in the conductor. # # Remove when request_spec is a proper object itself! dict_cells = instance_numa_topology.get('cells') if dict_cells: cells = [objects.InstanceNUMACell(id=cell['id'], cpuset=set(cell['cpuset']), memory=cell['memory']) for cell in dict_cells] instance_numa_topology = ( objects.InstanceNUMATopology(cells=cells)) return instance_numa_topology
def test_numa_topology_filter_fail_cpu(self): instance_topology = objects.InstanceNUMATopology(cells=[ objects.InstanceNUMACell(id=0, cpuset=set([1]), memory=512), objects.InstanceNUMACell(id=1, cpuset=set([3, 4, 5]), memory=512) ]) spec_obj = objects.RequestSpec(numa_topology=instance_topology, pci_requests=None, instance_uuid=str(uuid.uuid4())) host = fakes.FakeHostState( 'host1', 'node1', { 'numa_topology': fakes.NUMA_TOPOLOGY, 'pci_stats': None, 'cpu_allocation_ratio': 1, 'ram_allocation_ratio': 1.5 }) self.assertFalse(self.filt_cls.host_passes(host, spec_obj))
def _do_test_numa_topology_filter_cpu_policy( self, numa_topology, cpu_policy, cpu_thread_policy, passes, mock_pinning_requested): instance_topology = objects.InstanceNUMATopology( cells=[objects.InstanceNUMACell(id=0, cpuset=set([1]), memory=512), objects.InstanceNUMACell(id=1, cpuset=set([3]), memory=512) ]) spec_obj = objects.RequestSpec(numa_topology=instance_topology, pci_requests=None, instance_uuid=uuids.fake) extra_specs = [ {}, { 'hw:cpu_policy': cpu_policy, 'hw:cpu_thread_policy': cpu_thread_policy, } ] image_props = [ {}, { 'hw_cpu_policy': cpu_policy, 'hw_cpu_thread_policy': cpu_thread_policy, } ] host = fakes.FakeHostState('host1', 'node1', { 'numa_topology': numa_topology, 'pci_stats': None, 'cpu_allocation_ratio': 1, 'ram_allocation_ratio': 1.5}) assertion = self.assertTrue if passes else self.assertFalse # test combinations of image properties and extra specs for specs, props in itertools.product(extra_specs, image_props): # ...except for the one where no policy is specified if specs == props == {}: continue fake_flavor = objects.Flavor(memory_mb=1024, extra_specs=specs) fake_image_props = objects.ImageMetaProps(**props) fake_image = objects.ImageMeta(properties=fake_image_props) spec_obj.image = fake_image spec_obj.flavor = fake_flavor assertion(self.filt_cls.host_passes(host, spec_obj)) self.assertIsNone(spec_obj.numa_topology.cells[0].cpu_pinning)
def setUp(self): super(ServerTopologyPolicyTest, self).setUp() self.controller = server_topology.ServerTopologyController() self.req = fakes.HTTPRequest.blank('', version='2.78') self.mock_get = self.useFixture( fixtures.MockPatch('nova.api.openstack.common.get_instance')).mock self.instance = fake_instance.fake_instance_obj( self.project_member_context, id=1, uuid=uuids.fake_id, project_id=self.project_id, vm_state=vm_states.ACTIVE) self.mock_get.return_value = self.instance self.instance.numa_topology = objects.InstanceNUMATopology( instance_uuid = self.instance.uuid, cells=[objects.InstanceNUMACell( node=0, memory=1024, pagesize=4, id=123, cpu_topology=None, cpu_pinning={}, cpuset=set([0, 1]), pcpuset=set())]) # Check that system reader or and server owner is able to get # the server topology. self.system_reader_or_owner_authorized_contexts = [ self.legacy_admin_context, self.system_admin_context, self.project_admin_context, self.project_member_context, self.project_reader_context, self.project_foo_context, self.system_member_context, self.system_reader_context] # Check that non-stem reader/owner is not able to get # the server topology. self.system_reader_or_owner_unauthorized_contexts = [ self.system_foo_context, self.other_project_member_context, self.other_project_reader_context, ] # Check that system reader is able to get the server topology # host information. self.system_reader_authorized_contexts = [ self.legacy_admin_context, self.system_admin_context, self.project_admin_context, self.system_member_context, self.system_reader_context] # Check that non-system reader is not able to get the server topology # host information. self.system_reader_unauthorized_contexts = [ self.system_foo_context, self.project_member_context, self.other_project_member_context, self.project_foo_context, self.project_reader_context, self.other_project_reader_context ]
def test_pci_claim_instance_with_numa(self, mock_get): fake_db_dev_3 = dict(fake_db_dev_1, id=4, address='0000:00:00.4') fake_devs_numa = copy.deepcopy(fake_db_devs) fake_devs_numa.append(fake_db_dev_3) self.tracker = manager.PciDevTracker(1) self.tracker._set_hvdevs(fake_devs_numa) pci_requests = copy.deepcopy(fake_pci_requests)[:1] pci_requests[0]['count'] = 2 self._create_pci_requests_object(mock_get, pci_requests) self.inst.numa_topology = objects.InstanceNUMATopology(cells=[ objects.InstanceNUMACell(id=1, cpuset=set([1, 2]), memory=512) ]) self.tracker.claim_instance(None, self.inst) free_devs = self.tracker.pci_stats.get_free_devs() self.assertEqual(2, len(free_devs)) self.assertEqual('v1', free_devs[0].vendor_id) self.assertEqual('v1', free_devs[1].vendor_id)
def test_cpuset_reserved(self): topology = objects.InstanceNUMATopology( instance_uuid=fake_instance_uuid, cells=[ objects.InstanceNUMACell(id=0, cpuset=set([1, 2]), memory=512, pagesize=2048, cpuset_reserved=set([3, 7])), objects.InstanceNUMACell(id=1, cpuset=set([3, 4]), memory=512, pagesize=2048, cpuset_reserved=set([9, 12])) ]) self.assertEqual(set([3, 7]), topology.cells[0].cpuset_reserved) self.assertEqual(set([9, 12]), topology.cells[1].cpuset_reserved)
def test_numa_topology_filter_fail_mempages(self): instance_topology = objects.InstanceNUMATopology(cells=[ objects.InstanceNUMACell( id=0, cpuset=set([3]), memory=128, pagesize=8), objects.InstanceNUMACell( id=1, cpuset=set([1]), memory=128, pagesize=16) ]) spec_obj = self._get_spec_obj(numa_topology=instance_topology) host = fakes.FakeHostState( 'host1', 'node1', { 'numa_topology': fakes.NUMA_TOPOLOGY, 'hypervisor_type': fakes.HYPERVISOR_TYPE, 'pci_stats': None, 'cpu_allocation_ratio': 16.0, 'ram_allocation_ratio': 1.5 }) self.assertFalse(self.filt_cls.host_passes(host, spec_obj))
def _numa_get_constraints_manual(nodes, flavor, image_meta): cells = [] totalmem = 0 availcpus = set(range(flavor['vcpus'])) for node in range(nodes): cpus = _numa_get_flavor_or_image_prop( flavor, image_meta, "numa_cpus.%d" % node) mem = _numa_get_flavor_or_image_prop( flavor, image_meta, "numa_mem.%d" % node) # We're expecting both properties set, so # raise an error if either is missing if cpus is None or mem is None: raise exception.ImageNUMATopologyIncomplete() mem = int(mem) cpuset = parse_cpu_spec(cpus) for cpu in cpuset: if cpu > (flavor['vcpus'] - 1): raise exception.ImageNUMATopologyCPUOutOfRange( cpunum=cpu, cpumax=(flavor['vcpus'] - 1)) if cpu not in availcpus: raise exception.ImageNUMATopologyCPUDuplicates( cpunum=cpu) availcpus.remove(cpu) cells.append(objects.InstanceNUMACell( id=node, cpuset=cpuset, memory=mem)) totalmem = totalmem + mem if availcpus: raise exception.ImageNUMATopologyCPUsUnassigned( cpuset=str(availcpus)) if totalmem != flavor['memory_mb']: raise exception.ImageNUMATopologyMemoryOutOfRange( memsize=totalmem, memtotal=flavor['memory_mb']) return objects.InstanceNUMATopology(cells=cells)
def test_stat_consumption_from_instance_pci(self): inst_topology = objects.InstanceNUMATopology( cells = [objects.InstanceNUMACell( cpuset=set([0]), memory=512, id=0)]) fake_requests = [{'request_id': 'fake_request1', 'count': 1, 'spec': [{'vendor_id': '8086'}]}] fake_requests_obj = objects.InstancePCIRequests( requests=[objects.InstancePCIRequest(**r) for r in fake_requests], instance_uuid='fake-uuid') instance = objects.Instance(root_gb=0, ephemeral_gb=0, memory_mb=512, vcpus=1, project_id='12345', vm_state=vm_states.BUILDING, task_state=task_states.SCHEDULING, os_type='Linux', uuid='fake-uuid', numa_topology=inst_topology, pci_requests=fake_requests_obj, id = 1243) req_spec = sched_utils.build_request_spec(None, None, [instance], objects.Flavor( root_gb=0, ephemeral_gb=0, memory_mb=1024, vcpus=1)) host = host_manager.HostState("fakehost", "fakenode") self.assertIsNone(host.updated) host.pci_stats = pci_stats.PciDeviceStats( [objects.PciDevicePool(vendor_id='8086', product_id='15ed', numa_node=1, count=1)]) host.numa_topology = fakes.NUMA_TOPOLOGY host.consume_from_instance(req_spec['instance_properties']) self.assertIsInstance(req_spec['instance_properties']['numa_topology'], objects.InstanceNUMATopology) self.assertEqual(512, host.numa_topology.cells[1].memory_usage) self.assertEqual(1, host.numa_topology.cells[1].cpu_usage) self.assertEqual(0, len(host.pci_stats.pools)) self.assertIsNotNone(host.updated)
def test_numa_topology_filter_fail_memory(self): self.flags(ram_allocation_ratio=1) instance_topology = objects.InstanceNUMATopology(cells=[ objects.InstanceNUMACell(id=0, cpuset=set([1]), memory=1024), objects.InstanceNUMACell(id=1, cpuset=set([3]), memory=512) ]) instance = fake_instance.fake_instance_obj(mock.sentinel.ctx) instance.numa_topology = instance_topology filter_properties = { 'request_spec': { 'instance_properties': jsonutils.to_primitive(obj_base.obj_to_primitive(instance)) } } host = fakes.FakeHostState('host1', 'node1', {'numa_topology': fakes.NUMA_TOPOLOGY}) self.assertFalse(self.filt_cls.host_passes(host, filter_properties))
def test_create_migration_context(self, mock_get): numa_topology = objects.InstanceNUMATopology( cells=[objects.InstanceNUMACell( id=1, cpuset=set([1, 2]), memory=512)]) self.instance.numa_topology = None claim = self._claim(numa_topology=numa_topology) migration = objects.Migration(context=self.context, id=42) claim.migration = migration fake_mig_context = mock.Mock(spec=objects.MigrationContext) with mock.patch('nova.objects.MigrationContext', return_value=fake_mig_context) as ctxt_mock: claim.create_migration_context() ctxt_mock.assert_called_once_with( context=self.context, instance_uuid=self.instance.uuid, migration_id=42, old_numa_topology=None, new_numa_topology=mock.ANY) self.assertIsInstance(ctxt_mock.call_args[1]['new_numa_topology'], objects.InstanceNUMATopology) self.assertEqual(migration, claim.migration)
def instance(self): inst = objects.Instance.get_by_uuid(self._context, self.instance_uuid, expected_attrs=['system_metadata']) sys_meta = inst.system_metadata numa_topology = jsonutils.loads(sys_meta.get('new_numa_topo', '{}')) if numa_topology and numa_topology.get('cells'): cells = [] for cell in numa_topology['cells']: cells.append( objects.InstanceNUMACell(id=cell['id'], cpuset=set(cell['cpuset']), memory=cell['memory'], pagesize=cell.get('pagesize'))) format_inst_numa = objects.InstanceNUMATopology( cells=cells, instance_uuid=inst.uuid) inst.numa_topology = format_inst_numa return inst
def test_cpu_policy(self): cpu_policy = fields.CPUAllocationPolicy.SHARED topology = objects.InstanceNUMATopology( instance_uuid=fake_instance_uuid, cells=[ objects.InstanceNUMACell( cpuset=set([0, 1, 2, 3]), cpu_pinning=None, cpu_policy=cpu_policy, ), objects.InstanceNUMACell( cpuset=set([4, 5, 6, 7]), cpu_pinning=None, cpu_policy=cpu_policy, ), ], ) self.assertEqual(cpu_policy, topology.cpu_policy)
def test_numa_topology_filter_pass_networks(self): host = self._get_fake_host_state_with_networks() instance_topology = objects.InstanceNUMATopology(cells=[ objects.InstanceNUMACell(id=0, cpuset=set([1]), memory=512), objects.InstanceNUMACell(id=1, cpuset=set([3]), memory=512)]) network_metadata = objects.NetworkMetadata( physnets=set(['foo']), tunneled=False) spec_obj = self._get_spec_obj(numa_topology=instance_topology, network_metadata=network_metadata) self.assertTrue(self.filt_cls.host_passes(host, spec_obj)) # this should pass because while the networks are affined to different # host NUMA nodes, our guest itself has multiple NUMA nodes network_metadata = objects.NetworkMetadata( physnets=set(['foo', 'bar']), tunneled=True) spec_obj = self._get_spec_obj(numa_topology=instance_topology, network_metadata=network_metadata) self.assertTrue(self.filt_cls.host_passes(host, spec_obj))
def test_cpu_policy__error(self): """Ensure we raise an error if cells have different values.""" topology = objects.InstanceNUMATopology( instance_uuid=fake_instance_uuid, cells=[ objects.InstanceNUMACell( cpuset=set([0, 1, 2, 3]), cpu_pinning=None, cpu_policy=None, ), objects.InstanceNUMACell( cpuset=set([4, 5, 6, 7]), cpu_pinning=None, cpu_policy=fields.CPUAllocationPolicy.SHARED ), ], ) with testtools.ExpectedException(exception.InternalError): topology.cpu_policy
def test_pci_claim_instance_with_numa(self): fake_pci_3 = dict(fake_pci_1, address='0000:00:00.4') fake_devs_numa = copy.deepcopy(fake_pci_devs) fake_devs_numa.append(fake_pci_3) self.tracker = manager.PciDevTracker( mock.sentinel.context, objects.ComputeNode(id=1, numa_topology=None)) self.tracker._set_hvdevs(copy.deepcopy(fake_devs_numa)) pci_requests = copy.deepcopy(fake_pci_requests)[:1] pci_requests[0]['count'] = 2 pci_requests_obj = self._create_pci_requests_object(pci_requests) self.inst.numa_topology = objects.InstanceNUMATopology(cells=[ objects.InstanceNUMACell(id=1, cpuset=set([1, 2]), memory=512) ]) self.tracker.claim_instance(mock.sentinel.context, pci_requests_obj, self.inst.numa_topology) free_devs = self.tracker.pci_stats.get_free_devs() self.assertEqual(2, len(free_devs)) self.assertEqual('v1', free_devs[0].vendor_id) self.assertEqual('v1', free_devs[1].vendor_id)
def test_claim_fails_page_size_not_called(self): instance_type = self._fake_instance_type() instance = self._fake_instance() # This topology cannot fit in self.resources (see _fake_resources()) numa_topology = objects.InstanceNUMATopology(cells=[ objects.InstanceNUMACell(id=1, cpuset=set([1, 2, 3]), memory=1024) ]) with test.nested( mock.patch('nova.virt.hardware.numa_get_constraints', return_value=numa_topology), mock.patch( 'nova.compute.claims.MoveClaim._test_live_migration_page_size' )) as (mock_test_numa, mock_test_page_size): self.assertRaisesRegex( exception.ComputeResourcesUnavailable, 'Requested instance NUMA topology', claims.MoveClaim, self.context, instance, _NODENAME, instance_type, {}, self.tracker, self.resources, self.empty_requests, objects.Migration(migration_type='live-migration'), None) mock_test_page_size.assert_not_called()
def test_numa_topology_with_pci(self, mock_get): dev_dict = { 'compute_node_id': 1, 'address': 'a', 'product_id': 'p', 'vendor_id': 'v', 'numa_node': 1, 'status': 'available'} self.tracker.new_pci_tracker() self.tracker.pci_tracker.set_hvdevs([dev_dict]) request = objects.InstancePCIRequest(count=1, spec=[{'vendor_id': 'v', 'product_id': 'p'}]) mock_get.return_value = objects.InstancePCIRequests( requests=[request]) huge_instance = objects.InstanceNUMATopology( cells=[objects.InstanceNUMACell( id=1, cpuset=set([1, 2]), memory=512)]) self._claim(numa_topology= huge_instance)
def test_numa_topology_with_pci_fail(self, mock_get_by_instance): dev_dict = { 'compute_node_id': 1, 'address': 'a', 'product_id': 'p', 'vendor_id': 'v', 'numa_node': 1, 'dev_type': 'type-PCI', 'parent_addr': 'a1', 'status': 'available' } dev_dict2 = { 'compute_node_id': 1, 'address': 'a', 'product_id': 'p', 'vendor_id': 'v', 'numa_node': 2, 'dev_type': 'type-PCI', 'parent_addr': 'a1', 'status': 'available' } self.tracker.new_pci_tracker() self.tracker.pci_tracker._set_hvdevs([dev_dict, dev_dict2]) request = objects.InstancePCIRequest(count=2, spec=[{ 'vendor_id': 'v', 'product_id': 'p' }]) requests = objects.InstancePCIRequests(requests=[request]) mock_get_by_instance.return_value = requests huge_instance = objects.InstanceNUMATopology(cells=[ objects.InstanceNUMACell( id=1, cpuset=set([1, 2]), pcpuset=set(), memory=512) ]) self.assertRaises(exception.ComputeResourcesUnavailable, self._claim, requests=requests, numa_topology=huge_instance)
def get_cpu_at_live_migration(self, context, instance, network_info, block_migration, migrate_data): # should check mem is ok self.test_mem_in_resource_tracker(context, instance) bind_info, instance_numa, _ = sched_utils.get_inst_cpu_bind_info( instance, self.host, network_info=network_info) if instance_numa and instance_numa['cells'][0].get('mem'): numa_id = instance_numa['cells'][0]['id'] else: numa_id = None # check live migration record has already created migrate_data['cpu'] = bind_info migrate_data['numa'] = numa_id self._create_live_migration_record( context, instance, block_migration, migrate_data) if instance_numa and instance_numa['cells'][0].get('mem'): cells = [] for cell in instance_numa['cells']: cells.append(objects.InstanceNUMACell( id=cell['id'], cpuset=set(cell['cpuset']), memory=cell['mem']['total'], pagesize=cell.get('pagesize'))) format_inst_numa = objects.InstanceNUMATopology( cells=cells, instance_uuid=instance['uuid']) sys_meta = instance.system_metadata sys_meta['new_numa_topo'] = jsonutils.dumps(format_inst_numa) sys_meta['new_bind_info'] = jsonutils.dumps(bind_info) instance.system_metadata = sys_meta instance.save() instance.numa_topology = format_inst_numa # trigger update_resource self._update_usage_from_instance(context, self.compute_node, instance) # if necessary elevated = context.elevated() # persist changes to the compute node: self._update(elevated, self.compute_node) return migrate_data
def test_numa_topology_filter_pass_set_limit(self): self.flags(cpu_allocation_ratio=21) self.flags(ram_allocation_ratio=1.3) instance_topology = objects.InstanceNUMATopology( cells=[objects.InstanceNUMACell(id=0, cpuset=set([1]), memory=512), objects.InstanceNUMACell(id=1, cpuset=set([3]), memory=512) ]) instance = fake_instance.fake_instance_obj(mock.sentinel.ctx) instance.numa_topology = instance_topology filter_properties = { 'request_spec': { 'instance_properties': jsonutils.to_primitive( obj_base.obj_to_primitive(instance))}} host = fakes.FakeHostState('host1', 'node1', {'numa_topology': fakes.NUMA_TOPOLOGY, 'pci_stats': None}) self.assertTrue(self.filt_cls.host_passes(host, filter_properties)) limits = host.limits['numa_topology'] self.assertEqual(limits.cpu_allocation_ratio, 21) self.assertEqual(limits.ram_allocation_ratio, 1.3)
def fit_instance_to_host(cls, host_topology, instance_topology, limits_topology=None): """Fit the instance topology onto the host topology given the limits :param host_topology: VirtNUMAHostTopology object to fit an instance on :param instance_topology: objects.InstanceNUMATopology to be fitted :param limits_topology: VirtNUMALimitTopology that defines limits Given a host and instance topology and optionally limits - this method will attempt to fit instance cells onto all permutations of host cells by calling the fit_instance_cell method, and return a new InstanceNUMATopology with it's cell ids set to host cell id's of the first successful permutation, or None. """ if (not (host_topology and instance_topology) or len(host_topology) < len(instance_topology)): return else: if limits_topology is None: limits_topology_cells = itertools.repeat( None, len(host_topology)) else: limits_topology_cells = limits_topology.cells # TODO(ndipanov): We may want to sort permutations differently # depending on whether we want packing/spreading over NUMA nodes for host_cell_perm in itertools.permutations( zip(host_topology.cells, limits_topology_cells), len(instance_topology)): cells = [] for (host_cell, limit_cell), instance_cell in zip( host_cell_perm, instance_topology.cells): got_cell = cls.cell_class.fit_instance_cell( host_cell, instance_cell, limit_cell) if got_cell is None: break cells.append(got_cell) if len(cells) == len(host_cell_perm): return objects.InstanceNUMATopology(cells=cells)
def _test_core_bind(self, context, instance, resource_tracker): LOG.debug("get instance cpu bind info in _test_core_bind") filter_properties = {} inst_extra = objects.HuaweiInstanceExtra.get_by_instance_uuid( context, instance.uuid) if inst_extra: scheduler_hints = jsonutils.loads(inst_extra.scheduler_hints or '{}') stats = jsonutils.loads(inst_extra.stats or '{}') else: scheduler_hints = {} stats = {} filter_properties['scheduler_hints'] = scheduler_hints filter_properties['stats'] = stats pci_requests = objects.InstancePCIRequests.get_by_instance_uuid( context, instance['uuid']) if pci_requests: filter_properties['pci_requests'] = pci_requests bind_info, instance_numa, enable_ht = sched_utils.get_inst_cpu_bind_info( instance, resource_tracker.host, filter_properties=filter_properties) sched_utils.update_cpu_bind_info_to_db(bind_info, instance.uuid, instance_numa) if instance_numa and instance_numa['cells'][0].get('is_huawei'): cells = [] for cell in instance_numa['cells']: cells.append( objects.InstanceNUMACell(id=cell['id'], cpuset=set(cell['cpuset']), memory=cell['mem']['total'], pagesize=cell.get('pagesize'))) format_inst_numa = objects.InstanceNUMATopology(cells=cells) self.claimed_numa_topology = format_inst_numa self.instance['numa_topology'] = format_inst_numa
def test_stat_consumption_from_instance_pci(self): inst_topology = objects.InstanceNUMATopology( cells = [objects.InstanceNUMACell( cpuset=set([0]), memory=512, id=0)]) fake_requests = [{'request_id': 'fake_request1', 'count': 1, 'spec': [{'vendor_id': '8086'}]}] fake_requests_obj = objects.InstancePCIRequests( requests=[objects.InstancePCIRequest(**r) for r in fake_requests], instance_uuid='fake-uuid') req_spec = objects.RequestSpec( instance_uuid='fake-uuid', project_id='12345', numa_topology=inst_topology, pci_requests=fake_requests_obj, flavor=objects.Flavor(root_gb=0, ephemeral_gb=0, memory_mb=512, vcpus=1)) host = host_manager.HostState("fakehost", "fakenode") self.assertIsNone(host.updated) host.pci_stats = pci_stats.PciDeviceStats( [objects.PciDevicePool(vendor_id='8086', product_id='15ed', numa_node=1, count=1)]) host.numa_topology = fakes.NUMA_TOPOLOGY host.consume_from_request(req_spec) self.assertIsInstance(req_spec.numa_topology, objects.InstanceNUMATopology) self.assertEqual(512, host.numa_topology.cells[1].memory_usage) self.assertEqual(1, host.numa_topology.cells[1].cpu_usage) self.assertEqual(0, len(host.pci_stats.pools)) self.assertIsNotNone(host.updated)