objects: move numa host and cell to objects
To continue objectification of numa, this commit move numa host/cell related to objects. Change-Id: I9fbc3ed6d9bd74840e42586faa9951d9672691c1
This commit is contained in:
parent
e18809359b
commit
57f6db96d5
|
@ -204,10 +204,10 @@ class Claim(NopClaim):
|
|||
host_topology = resources.get('numa_topology')
|
||||
requested_topology = self.numa_topology
|
||||
if host_topology:
|
||||
host_topology = hardware.VirtNUMAHostTopology.from_json(
|
||||
host_topology = objects.NUMATopology.obj_from_db_obj(
|
||||
host_topology)
|
||||
instance_topology = (
|
||||
hardware.VirtNUMAHostTopology.fit_instance_to_host(
|
||||
hardware.numa_fit_instance_to_host(
|
||||
host_topology, requested_topology,
|
||||
limits_topology=limit))
|
||||
if requested_topology and not instance_topology:
|
||||
|
|
|
@ -600,11 +600,11 @@ class ResourceTracker(object):
|
|||
if itype:
|
||||
host_topology = resources.get('numa_topology')
|
||||
if host_topology:
|
||||
host_topology = hardware.VirtNUMAHostTopology.from_json(
|
||||
host_topology = objects.NUMATopology.obj_from_db_obj(
|
||||
host_topology)
|
||||
numa_topology = hardware.numa_get_constraints(itype, image_meta)
|
||||
numa_topology = (
|
||||
hardware.VirtNUMAHostTopology.fit_instance_to_host(
|
||||
hardware.numa_fit_instance_to_host(
|
||||
host_topology, numa_topology))
|
||||
usage = self._get_usage_dict(
|
||||
itype, numa_topology=numa_topology)
|
||||
|
|
|
@ -132,7 +132,7 @@ class ComputeNode(BASE, NovaBase):
|
|||
stats = Column(Text, default='{}')
|
||||
|
||||
# json-encoded dict that contains NUMA topology as generated by
|
||||
# nova.virt.hardware.VirtNUMAHostTopology.to_json()
|
||||
# objects.NUMATopoloogy._to_json()
|
||||
numa_topology = Column(Text)
|
||||
|
||||
|
||||
|
|
|
@ -80,6 +80,11 @@ class NUMATopology(base.NovaObject):
|
|||
def _to_json(self):
|
||||
return jsonutils.dumps(self.obj_to_primitive())
|
||||
|
||||
@classmethod
|
||||
def obj_from_db_obj(cls, db_obj):
|
||||
return cls.obj_from_primitive(
|
||||
jsonutils.loads(db_obj))
|
||||
|
||||
def __len__(self):
|
||||
"""Defined so that boolean testing works the same as for lists."""
|
||||
return len(self.cells)
|
||||
|
|
|
@ -40,8 +40,7 @@ class NUMATopologyFilter(filters.BaseHostFilter):
|
|||
cell.id, cell.cpuset, cell.memory,
|
||||
max_cell_cpu, max_cell_memory))
|
||||
limits = hardware.VirtNUMALimitTopology(cells=limit_cells)
|
||||
instance_topology = (
|
||||
hardware.VirtNUMAHostTopology.fit_instance_to_host(
|
||||
instance_topology = (hardware.numa_fit_instance_to_host(
|
||||
host_topology, requested_topology,
|
||||
limits_topology=limits))
|
||||
if not instance_topology:
|
||||
|
|
|
@ -121,10 +121,12 @@ class ClaimTestCase(test.NoDBTestCase):
|
|||
'free_disk_gb': 20,
|
||||
'vcpus': 2,
|
||||
'vcpus_used': 0,
|
||||
'numa_topology': hardware.VirtNUMAHostTopology(
|
||||
cells=[hardware.VirtNUMATopologyCellUsage(1, [1, 2], 512),
|
||||
hardware.VirtNUMATopologyCellUsage(2, [3, 4], 512)]
|
||||
).to_json()
|
||||
'numa_topology': objects.NUMATopology(
|
||||
cells=[objects.NUMACell(id=1, cpuset=set([1, 2]), memory=512,
|
||||
memory_usage=0, cpu_usage=0),
|
||||
objects.NUMACell(id=2, cpuset=set([3, 4]), memory=512,
|
||||
memory_usage=0, cpu_usage=0)]
|
||||
)._to_json()
|
||||
}
|
||||
if values:
|
||||
resources.update(values)
|
||||
|
|
|
@ -44,9 +44,11 @@ FAKE_VIRT_MEMORY_MB = 5
|
|||
FAKE_VIRT_MEMORY_OVERHEAD = 1
|
||||
FAKE_VIRT_MEMORY_WITH_OVERHEAD = (
|
||||
FAKE_VIRT_MEMORY_MB + FAKE_VIRT_MEMORY_OVERHEAD)
|
||||
FAKE_VIRT_NUMA_TOPOLOGY = hardware.VirtNUMAHostTopology(
|
||||
cells=[hardware.VirtNUMATopologyCellUsage(0, set([1, 2]), 3072),
|
||||
hardware.VirtNUMATopologyCellUsage(1, set([3, 4]), 3072)])
|
||||
FAKE_VIRT_NUMA_TOPOLOGY = objects.NUMATopology(
|
||||
cells=[objects.NUMACell(id=0, cpuset=set([1, 2]), memory=3072,
|
||||
cpu_usage=0, memory_usage=0),
|
||||
objects.NUMACell(id=1, cpuset=set([3, 4]), memory=3072,
|
||||
cpu_usage=0, memory_usage=0)])
|
||||
FAKE_VIRT_NUMA_TOPOLOGY_OVERHEAD = hardware.VirtNUMALimitTopology(
|
||||
cells=[hardware.VirtNUMATopologyCellLimit(
|
||||
0, set([1, 2]), 3072, 4, 10240),
|
||||
|
@ -121,7 +123,7 @@ class FakeVirtDriver(driver.ComputeDriver):
|
|||
'hypervisor_hostname': 'fakehost',
|
||||
'cpu_info': '',
|
||||
'numa_topology': (
|
||||
self.numa_topology.to_json() if self.numa_topology else None),
|
||||
self.numa_topology._to_json() if self.numa_topology else None),
|
||||
}
|
||||
if self.pci_support:
|
||||
d['pci_passthrough_devices'] = jsonutils.dumps(self.pci_devices)
|
||||
|
@ -585,7 +587,7 @@ class BaseTrackerTestCase(BaseTestCase):
|
|||
|
||||
if field == 'numa_topology':
|
||||
self.assertEqualNUMAHostTopology(
|
||||
value, hardware.VirtNUMAHostTopology.from_json(x))
|
||||
value, objects.NUMATopology.obj_from_db_obj(x))
|
||||
else:
|
||||
self.assertEqual(value, x)
|
||||
|
||||
|
@ -729,12 +731,12 @@ class InstanceClaimTestCase(BaseTrackerTestCase):
|
|||
if self.tracker.driver.numa_topology is None:
|
||||
return None
|
||||
mem = mem * 1024
|
||||
return hardware.VirtNUMAHostTopology(
|
||||
cells=[hardware.VirtNUMATopologyCellUsage(
|
||||
0, set([1, 2]), 3072, cpu_usage=cpus,
|
||||
return objects.NUMATopology(
|
||||
cells=[objects.NUMACell(
|
||||
id=0, cpuset=set([1, 2]), memory=3072, cpu_usage=cpus,
|
||||
memory_usage=mem),
|
||||
hardware.VirtNUMATopologyCellUsage(
|
||||
1, set([3, 4]), 3072, cpu_usage=cpus,
|
||||
objects.NUMACell(
|
||||
id=1, cpuset=set([3, 4]), memory=3072, cpu_usage=cpus,
|
||||
memory_usage=mem)])
|
||||
|
||||
@mock.patch('nova.objects.InstancePCIRequests.get_by_instance_uuid',
|
||||
|
@ -792,7 +794,7 @@ class InstanceClaimTestCase(BaseTrackerTestCase):
|
|||
self.assertEqual(FAKE_VIRT_MEMORY_MB - claim_mem_total,
|
||||
self.compute["free_ram_mb"])
|
||||
self.assertEqualNUMAHostTopology(
|
||||
claim_topology, hardware.VirtNUMAHostTopology.from_json(
|
||||
claim_topology, objects.NUMATopology.obj_from_db_obj(
|
||||
self.compute['numa_topology']))
|
||||
|
||||
self.assertEqual(FAKE_VIRT_LOCAL_GB, self.compute["local_gb"])
|
||||
|
@ -817,7 +819,7 @@ class InstanceClaimTestCase(BaseTrackerTestCase):
|
|||
self.assertEqual(FAKE_VIRT_MEMORY_MB - claim_mem_total,
|
||||
self.compute['free_ram_mb'])
|
||||
self.assertEqualNUMAHostTopology(
|
||||
claim_topology, hardware.VirtNUMAHostTopology.from_json(
|
||||
claim_topology, objects.NUMATopology.obj_from_db_obj(
|
||||
self.compute['numa_topology']))
|
||||
|
||||
self.assertEqual(claim_disk, self.compute['local_gb_used'])
|
||||
|
@ -845,7 +847,7 @@ class InstanceClaimTestCase(BaseTrackerTestCase):
|
|||
self.assertEqual(FAKE_VIRT_MEMORY_MB - claim_mem_total,
|
||||
self.compute["free_ram_mb"])
|
||||
self.assertEqualNUMAHostTopology(
|
||||
claim_topology, hardware.VirtNUMAHostTopology.from_json(
|
||||
claim_topology, objects.NUMATopology.obj_from_db_obj(
|
||||
self.compute['numa_topology']))
|
||||
|
||||
self.assertEqual(claim_disk, self.compute["local_gb_used"])
|
||||
|
@ -858,7 +860,7 @@ class InstanceClaimTestCase(BaseTrackerTestCase):
|
|||
self.assertEqual(FAKE_VIRT_MEMORY_MB, self.compute["free_ram_mb"])
|
||||
self.assertEqualNUMAHostTopology(
|
||||
FAKE_VIRT_NUMA_TOPOLOGY,
|
||||
hardware.VirtNUMAHostTopology.from_json(
|
||||
objects.NUMATopology.obj_from_db_obj(
|
||||
self.compute['numa_topology']))
|
||||
|
||||
self.assertEqual(0, self.compute["local_gb_used"])
|
||||
|
@ -887,7 +889,7 @@ class InstanceClaimTestCase(BaseTrackerTestCase):
|
|||
self.tracker.compute_node['memory_mb_used'])
|
||||
self.assertEqualNUMAHostTopology(
|
||||
claim_topology,
|
||||
hardware.VirtNUMAHostTopology.from_json(
|
||||
objects.NUMATopology.obj_from_db_obj(
|
||||
self.compute['numa_topology']))
|
||||
self.assertEqual(root_gb * 2,
|
||||
self.tracker.compute_node['local_gb_used'])
|
||||
|
@ -919,7 +921,7 @@ class InstanceClaimTestCase(BaseTrackerTestCase):
|
|||
|
||||
self.assertEqualNUMAHostTopology(
|
||||
claim_topology,
|
||||
hardware.VirtNUMAHostTopology.from_json(
|
||||
objects.NUMATopology.obj_from_db_obj(
|
||||
self.compute['numa_topology']))
|
||||
|
||||
@mock.patch('nova.objects.InstancePCIRequests.get_by_instance_uuid',
|
||||
|
@ -939,7 +941,7 @@ class InstanceClaimTestCase(BaseTrackerTestCase):
|
|||
self.assertEqual(0, self.compute['local_gb_used'])
|
||||
self.assertEqualNUMAHostTopology(
|
||||
FAKE_VIRT_NUMA_TOPOLOGY,
|
||||
hardware.VirtNUMAHostTopology.from_json(
|
||||
objects.NUMATopology.obj_from_db_obj(
|
||||
self.compute['numa_topology']))
|
||||
|
||||
@mock.patch('nova.objects.InstancePCIRequests.get_by_instance_uuid',
|
||||
|
@ -962,7 +964,7 @@ class InstanceClaimTestCase(BaseTrackerTestCase):
|
|||
self.compute['memory_mb_used'])
|
||||
self.assertEqualNUMAHostTopology(
|
||||
claim_topology,
|
||||
hardware.VirtNUMAHostTopology.from_json(
|
||||
objects.NUMATopology.obj_from_db_obj(
|
||||
self.compute['numa_topology']))
|
||||
self.assertEqual(flavor['root_gb'] + flavor['ephemeral_gb'],
|
||||
self.compute['local_gb_used'])
|
||||
|
@ -978,7 +980,7 @@ class InstanceClaimTestCase(BaseTrackerTestCase):
|
|||
self.compute['memory_mb_used'])
|
||||
self.assertEqualNUMAHostTopology(
|
||||
claim_topology,
|
||||
hardware.VirtNUMAHostTopology.from_json(
|
||||
objects.NUMATopology.obj_from_db_obj(
|
||||
self.compute['numa_topology']))
|
||||
self.assertEqual(flavor['root_gb'] + flavor['ephemeral_gb'],
|
||||
self.compute['local_gb_used'])
|
||||
|
|
|
@ -18,11 +18,11 @@ from oslo.utils import timeutils
|
|||
|
||||
from nova import db
|
||||
from nova import exception
|
||||
from nova import objects
|
||||
from nova.objects import compute_node
|
||||
from nova.objects import hv_spec
|
||||
from nova.objects import service
|
||||
from nova.tests.unit.objects import test_objects
|
||||
from nova.virt import hardware
|
||||
|
||||
NOW = timeutils.utcnow().replace(microsecond=0)
|
||||
fake_stats = {'num_foo': '10'}
|
||||
|
@ -30,10 +30,12 @@ fake_stats_db_format = jsonutils.dumps(fake_stats)
|
|||
# host_ip is coerced from a string to an IPAddress
|
||||
# but needs to be converted to a string for the database format
|
||||
fake_host_ip = '127.0.0.1'
|
||||
fake_numa_topology = hardware.VirtNUMAHostTopology(
|
||||
cells=[hardware.VirtNUMATopologyCellUsage(0, set([1, 2]), 512),
|
||||
hardware.VirtNUMATopologyCellUsage(1, set([3, 4]), 512)])
|
||||
fake_numa_topology_db_format = fake_numa_topology.to_json()
|
||||
fake_numa_topology = objects.NUMATopology(
|
||||
cells=[objects.NUMACell(id=0, cpuset=set([1, 2]), memory=512,
|
||||
cpu_usage=0, memory_usage=0),
|
||||
objects.NUMACell(id=1, cpuset=set([3, 4]), memory=512,
|
||||
cpu_usage=0, memory_usage=0)])
|
||||
fake_numa_topology_db_format = fake_numa_topology._to_json()
|
||||
fake_hv_spec = hv_spec.HVSpec(arch='foo', hv_type='bar', vm_mode='foobar')
|
||||
fake_supported_hv_specs = [fake_hv_spec]
|
||||
# for backward compatibility, each supported instance object
|
||||
|
|
|
@ -21,15 +21,17 @@ from oslo.serialization import jsonutils
|
|||
|
||||
from nova.compute import vm_states
|
||||
from nova import db
|
||||
from nova import objects
|
||||
from nova.scheduler import filter_scheduler
|
||||
from nova.scheduler import host_manager
|
||||
from nova.virt import hardware
|
||||
|
||||
NUMA_TOPOLOGY = hardware.VirtNUMAHostTopology(
|
||||
cells=[hardware.VirtNUMATopologyCellUsage(
|
||||
0, set([1, 2]), 512),
|
||||
hardware.VirtNUMATopologyCellUsage(
|
||||
1, set([3, 4]), 512)])
|
||||
NUMA_TOPOLOGY = objects.NUMATopology(
|
||||
cells=[objects.NUMACell(
|
||||
id=0, cpuset=set([1, 2]), memory=512,
|
||||
cpu_usage=0, memory_usage=0),
|
||||
objects.NUMACell(
|
||||
id=1, cpuset=set([3, 4]), memory=512,
|
||||
cpu_usage=0, memory_usage=0)])
|
||||
|
||||
COMPUTE_NODES = [
|
||||
dict(id=1, local_gb=1024, memory_mb=1024, vcpus=1,
|
||||
|
@ -49,7 +51,7 @@ COMPUTE_NODES = [
|
|||
free_disk_gb=3072, local_gb_used=0, updated_at=None,
|
||||
service=dict(host='host3', disabled=False),
|
||||
hypervisor_hostname='node3', host_ip='127.0.0.1',
|
||||
hypervisor_version=0, numa_topology=NUMA_TOPOLOGY.to_json()),
|
||||
hypervisor_version=0, numa_topology=NUMA_TOPOLOGY._to_json()),
|
||||
dict(id=4, local_gb=8192, memory_mb=8192, vcpus=8,
|
||||
disk_available_least=8192, free_ram_mb=8192, vcpus_used=0,
|
||||
free_disk_gb=8888, local_gb_used=0, updated_at=None,
|
||||
|
|
|
@ -26,13 +26,13 @@ from nova.compute import vm_states
|
|||
from nova import db
|
||||
from nova import exception
|
||||
from nova.i18n import _LW
|
||||
from nova import objects
|
||||
from nova.scheduler import filters
|
||||
from nova.scheduler import host_manager
|
||||
from nova import test
|
||||
from nova.tests.unit import matchers
|
||||
from nova.tests.unit.scheduler import fakes
|
||||
from nova import utils
|
||||
from nova.virt import hardware
|
||||
|
||||
|
||||
class FakeFilterClass1(filters.BaseHostFilter):
|
||||
|
@ -319,7 +319,7 @@ class HostManagerTestCase(test.NoDBTestCase):
|
|||
self.assertEqual(host_states_map[('host3', 'node3')].free_disk_mb,
|
||||
3145728)
|
||||
self.assertThat(
|
||||
hardware.VirtNUMAHostTopology.from_json(
|
||||
objects.NUMATopology.obj_from_db_obj(
|
||||
host_states_map[('host3', 'node3')].numa_topology
|
||||
)._to_dict(),
|
||||
matchers.DictMatches(fakes.NUMA_TOPOLOGY._to_dict()))
|
||||
|
@ -532,7 +532,7 @@ class HostStateTestCase(test.NoDBTestCase):
|
|||
local_gb_used=0, free_ram_mb=0, vcpus=0, vcpus_used=0,
|
||||
updated_at=None, host_ip='127.0.0.1',
|
||||
hypervisor_version=hyper_ver_int,
|
||||
numa_topology=fakes.NUMA_TOPOLOGY.to_json())
|
||||
numa_topology=fakes.NUMA_TOPOLOGY._to_json())
|
||||
host = host_manager.HostState("fakehost", "fakenode")
|
||||
host.update_from_compute_node(compute)
|
||||
|
||||
|
|
|
@ -10594,11 +10594,13 @@ class HostStateTestCase(test.NoDBTestCase):
|
|||
"vendor_id": '8086',
|
||||
"dev_type": 'type-PF',
|
||||
"phys_function": None}]
|
||||
numa_topology = hardware.VirtNUMAHostTopology(
|
||||
cells=[hardware.VirtNUMATopologyCellUsage(
|
||||
1, set([1, 2]), 1024),
|
||||
hardware.VirtNUMATopologyCellUsage(
|
||||
2, set([3, 4]), 1024)])
|
||||
numa_topology = objects.NUMATopology(
|
||||
cells=[objects.NUMACell(
|
||||
id=1, cpuset=set([1, 2]), memory=1024,
|
||||
cpu_usage=0, memory_usage=0),
|
||||
objects.NUMACell(
|
||||
id=2, cpuset=set([3, 4]), memory=1024,
|
||||
cpu_usage=0, memory_usage=0)])
|
||||
|
||||
class FakeConnection(libvirt_driver.LibvirtDriver):
|
||||
"""Fake connection object."""
|
||||
|
@ -10676,7 +10678,7 @@ class HostStateTestCase(test.NoDBTestCase):
|
|||
self.assertEqual(stats["disk_available_least"], 80)
|
||||
self.assertEqual(jsonutils.loads(stats["pci_passthrough_devices"]),
|
||||
HostStateTestCase.pci_devices)
|
||||
self.assertThat(hardware.VirtNUMAHostTopology.from_json(
|
||||
self.assertThat(objects.NUMATopology.obj_from_db_obj(
|
||||
stats['numa_topology'])._to_dict(),
|
||||
matchers.DictMatches(
|
||||
HostStateTestCase.numa_topology._to_dict()))
|
||||
|
|
|
@ -893,10 +893,13 @@ class NUMATopologyTest(test.NoDBTestCase):
|
|||
topology.cells[i].memory)
|
||||
|
||||
def test_host_usage_contiguous(self):
|
||||
hosttopo = hw.VirtNUMAHostTopology([
|
||||
hw.VirtNUMATopologyCellUsage(0, set([0, 1, 2, 3]), 1024),
|
||||
hw.VirtNUMATopologyCellUsage(1, set([4, 6]), 512),
|
||||
hw.VirtNUMATopologyCellUsage(2, set([5, 7]), 512),
|
||||
hosttopo = objects.NUMATopology(cells=[
|
||||
objects.NUMACell(id=0, cpuset=set([0, 1, 2, 3]), memory=1024,
|
||||
cpu_usage=0, memory_usage=0),
|
||||
objects.NUMACell(id=1, cpuset=set([4, 6]), memory=512,
|
||||
cpu_usage=0, memory_usage=0),
|
||||
objects.NUMACell(id=2, cpuset=set([5, 7]), memory=512,
|
||||
cpu_usage=0, memory_usage=0),
|
||||
])
|
||||
instance1 = objects.InstanceNUMATopology(cells=[
|
||||
objects.InstanceNUMACell(id=0, cpuset=set([0, 1, 2]), memory=256),
|
||||
|
@ -907,13 +910,12 @@ class NUMATopologyTest(test.NoDBTestCase):
|
|||
objects.InstanceNUMACell(id=1, cpuset=set([5, 7]), memory=256),
|
||||
])
|
||||
|
||||
hostusage = hw.VirtNUMAHostTopology.usage_from_instances(
|
||||
hostusage = hw.numa_usage_from_instances(
|
||||
hosttopo, [instance1, instance2])
|
||||
|
||||
self.assertEqual(len(hosttopo), len(hostusage))
|
||||
|
||||
self.assertIsInstance(hostusage.cells[0],
|
||||
hw.VirtNUMATopologyCellUsage)
|
||||
self.assertIsInstance(hostusage.cells[0], objects.NUMACell)
|
||||
self.assertEqual(hosttopo.cells[0].cpuset,
|
||||
hostusage.cells[0].cpuset)
|
||||
self.assertEqual(hosttopo.cells[0].memory,
|
||||
|
@ -921,8 +923,7 @@ class NUMATopologyTest(test.NoDBTestCase):
|
|||
self.assertEqual(hostusage.cells[0].cpu_usage, 5)
|
||||
self.assertEqual(hostusage.cells[0].memory_usage, 512)
|
||||
|
||||
self.assertIsInstance(hostusage.cells[1],
|
||||
hw.VirtNUMATopologyCellUsage)
|
||||
self.assertIsInstance(hostusage.cells[1], objects.NUMACell)
|
||||
self.assertEqual(hosttopo.cells[1].cpuset,
|
||||
hostusage.cells[1].cpuset)
|
||||
self.assertEqual(hosttopo.cells[1].memory,
|
||||
|
@ -930,8 +931,7 @@ class NUMATopologyTest(test.NoDBTestCase):
|
|||
self.assertEqual(hostusage.cells[1].cpu_usage, 3)
|
||||
self.assertEqual(hostusage.cells[1].memory_usage, 512)
|
||||
|
||||
self.assertIsInstance(hostusage.cells[2],
|
||||
hw.VirtNUMATopologyCellUsage)
|
||||
self.assertIsInstance(hostusage.cells[2], objects.NUMACell)
|
||||
self.assertEqual(hosttopo.cells[2].cpuset,
|
||||
hostusage.cells[2].cpuset)
|
||||
self.assertEqual(hosttopo.cells[2].memory,
|
||||
|
@ -940,27 +940,31 @@ class NUMATopologyTest(test.NoDBTestCase):
|
|||
self.assertEqual(hostusage.cells[2].memory_usage, 0)
|
||||
|
||||
def test_host_usage_sparse(self):
|
||||
hosttopo = hw.VirtNUMAHostTopology([
|
||||
hw.VirtNUMATopologyCellUsage(0, set([0, 1, 2, 3]), 1024),
|
||||
hw.VirtNUMATopologyCellUsage(5, set([4, 6]), 512),
|
||||
hw.VirtNUMATopologyCellUsage(6, set([5, 7]), 512),
|
||||
hosttopo = objects.NUMATopology(cells=[
|
||||
objects.NUMACell(id=0, cpuset=set([0, 1, 2, 3]), memory=1024,
|
||||
cpu_usage=0, memory_usage=0),
|
||||
objects.NUMACell(id=5, cpuset=set([4, 6]), memory=512,
|
||||
cpu_usage=0, memory_usage=0),
|
||||
objects.NUMACell(id=6, cpuset=set([5, 7]), memory=512,
|
||||
cpu_usage=0, memory_usage=0),
|
||||
])
|
||||
instance1 = objects.InstanceNUMATopology(cells=[
|
||||
objects.InstanceNUMACell(id=0, cpuset=set([0, 1, 2]), memory=256),
|
||||
objects.InstanceNUMACell(id=6, cpuset=set([4]), memory=256),
|
||||
])
|
||||
instance2 = objects.InstanceNUMATopology(cells=[
|
||||
objects.InstanceNUMACell(id=0, cpuset=set([0, 1]), memory=256),
|
||||
objects.InstanceNUMACell(id=5, cpuset=set([5, 7]), memory=256),
|
||||
objects.InstanceNUMACell(id=0, cpuset=set([0, 1]), memory=256,
|
||||
cpu_usage=0, memory_usage=0),
|
||||
objects.InstanceNUMACell(id=5, cpuset=set([5, 7]), memory=256,
|
||||
cpu_usage=0, memory_usage=0),
|
||||
])
|
||||
|
||||
hostusage = hw.VirtNUMAHostTopology.usage_from_instances(
|
||||
hostusage = hw.numa_usage_from_instances(
|
||||
hosttopo, [instance1, instance2])
|
||||
|
||||
self.assertEqual(len(hosttopo), len(hostusage))
|
||||
|
||||
self.assertIsInstance(hostusage.cells[0],
|
||||
hw.VirtNUMATopologyCellUsage)
|
||||
self.assertIsInstance(hostusage.cells[0], objects.NUMACell)
|
||||
self.assertEqual(hosttopo.cells[0].id,
|
||||
hostusage.cells[0].id)
|
||||
self.assertEqual(hosttopo.cells[0].cpuset,
|
||||
|
@ -970,8 +974,7 @@ class NUMATopologyTest(test.NoDBTestCase):
|
|||
self.assertEqual(hostusage.cells[0].cpu_usage, 5)
|
||||
self.assertEqual(hostusage.cells[0].memory_usage, 512)
|
||||
|
||||
self.assertIsInstance(hostusage.cells[1],
|
||||
hw.VirtNUMATopologyCellUsage)
|
||||
self.assertIsInstance(hostusage.cells[1], objects.NUMACell)
|
||||
self.assertEqual(hosttopo.cells[1].id,
|
||||
hostusage.cells[1].id)
|
||||
self.assertEqual(hosttopo.cells[1].cpuset,
|
||||
|
@ -981,8 +984,7 @@ class NUMATopologyTest(test.NoDBTestCase):
|
|||
self.assertEqual(hostusage.cells[1].cpu_usage, 2)
|
||||
self.assertEqual(hostusage.cells[1].memory_usage, 256)
|
||||
|
||||
self.assertIsInstance(hostusage.cells[2],
|
||||
hw.VirtNUMATopologyCellUsage)
|
||||
self.assertIsInstance(hostusage.cells[2], objects.NUMACell)
|
||||
self.assertEqual(hosttopo.cells[2].cpuset,
|
||||
hostusage.cells[2].cpuset)
|
||||
self.assertEqual(hosttopo.cells[2].memory,
|
||||
|
@ -991,37 +993,35 @@ class NUMATopologyTest(test.NoDBTestCase):
|
|||
self.assertEqual(hostusage.cells[2].memory_usage, 256)
|
||||
|
||||
def test_host_usage_culmulative_with_free(self):
|
||||
hosttopo = hw.VirtNUMAHostTopology([
|
||||
hw.VirtNUMATopologyCellUsage(
|
||||
0, set([0, 1, 2, 3]), 1024, cpu_usage=2, memory_usage=512),
|
||||
hw.VirtNUMATopologyCellUsage(
|
||||
1, set([4, 6]), 512, cpu_usage=1, memory_usage=512),
|
||||
hw.VirtNUMATopologyCellUsage(2, set([5, 7]), 256),
|
||||
hosttopo = objects.NUMATopology(cells=[
|
||||
objects.NUMACell(id=0, cpuset=set([0, 1, 2, 3]), memory=1024,
|
||||
cpu_usage=2, memory_usage=512),
|
||||
objects.NUMACell(id=1, cpuset=set([4, 6]), memory=512,
|
||||
cpu_usage=1, memory_usage=512),
|
||||
objects.NUMACell(id=2, cpuset=set([5, 7]), memory=256,
|
||||
cpu_usage=0, memory_usage=0),
|
||||
])
|
||||
instance1 = objects.InstanceNUMATopology(cells=[
|
||||
objects.InstanceNUMACell(id=0, cpuset=set([0, 1, 2]), memory=512),
|
||||
objects.InstanceNUMACell(id=1, cpuset=set([3]), memory=256),
|
||||
objects.InstanceNUMACell(id=2, cpuset=set([4]), memory=256)])
|
||||
|
||||
hostusage = hw.VirtNUMAHostTopology.usage_from_instances(
|
||||
hostusage = hw.numa_usage_from_instances(
|
||||
hosttopo, [instance1])
|
||||
self.assertIsInstance(hostusage.cells[0],
|
||||
hw.VirtNUMATopologyCellUsage)
|
||||
self.assertIsInstance(hostusage.cells[0], objects.NUMACell)
|
||||
self.assertEqual(hostusage.cells[0].cpu_usage, 5)
|
||||
self.assertEqual(hostusage.cells[0].memory_usage, 1024)
|
||||
|
||||
self.assertIsInstance(hostusage.cells[1],
|
||||
hw.VirtNUMATopologyCellUsage)
|
||||
self.assertIsInstance(hostusage.cells[1], objects.NUMACell)
|
||||
self.assertEqual(hostusage.cells[1].cpu_usage, 2)
|
||||
self.assertEqual(hostusage.cells[1].memory_usage, 768)
|
||||
|
||||
self.assertIsInstance(hostusage.cells[2],
|
||||
hw.VirtNUMATopologyCellUsage)
|
||||
self.assertIsInstance(hostusage.cells[2], objects.NUMACell)
|
||||
self.assertEqual(hostusage.cells[2].cpu_usage, 1)
|
||||
self.assertEqual(hostusage.cells[2].memory_usage, 256)
|
||||
|
||||
# Test freeing of resources
|
||||
hostusage = hw.VirtNUMAHostTopology.usage_from_instances(
|
||||
hostusage = hw.numa_usage_from_instances(
|
||||
hostusage, [instance1], free=True)
|
||||
self.assertEqual(hostusage.cells[0].cpu_usage, 2)
|
||||
self.assertEqual(hostusage.cells[0].memory_usage, 512)
|
||||
|
@ -1033,27 +1033,29 @@ class NUMATopologyTest(test.NoDBTestCase):
|
|||
self.assertEqual(hostusage.cells[2].memory_usage, 0)
|
||||
|
||||
def test_topo_usage_none(self):
|
||||
hosttopo = hw.VirtNUMAHostTopology([
|
||||
hw.VirtNUMATopologyCellUsage(0, set([0, 1]), 512),
|
||||
hw.VirtNUMATopologyCellUsage(1, set([2, 3]), 512),
|
||||
hosttopo = objects.NUMATopology(cells=[
|
||||
objects.NUMACell(id=0, cpuset=set([0, 1]), memory=512,
|
||||
cpu_usage=0, memory_usage=0),
|
||||
objects.NUMACell(id=1, cpuset=set([2, 3]), memory=512,
|
||||
cpu_usage=0, memory_usage=0),
|
||||
])
|
||||
instance1 = objects.InstanceNUMATopology(cells=[
|
||||
objects.InstanceNUMACell(id=0, cpuset=set([0, 1]), memory=256),
|
||||
objects.InstanceNUMACell(id=2, cpuset=set([2]), memory=256),
|
||||
])
|
||||
|
||||
hostusage = hw.VirtNUMAHostTopology.usage_from_instances(
|
||||
hostusage = hw.numa_usage_from_instances(
|
||||
None, [instance1])
|
||||
self.assertIsNone(hostusage)
|
||||
|
||||
hostusage = hw.VirtNUMAHostTopology.usage_from_instances(
|
||||
hostusage = hw.numa_usage_from_instances(
|
||||
hosttopo, [])
|
||||
self.assertEqual(hostusage.cells[0].cpu_usage, 0)
|
||||
self.assertEqual(hostusage.cells[0].memory_usage, 0)
|
||||
self.assertEqual(hostusage.cells[1].cpu_usage, 0)
|
||||
self.assertEqual(hostusage.cells[1].memory_usage, 0)
|
||||
|
||||
hostusage = hw.VirtNUMAHostTopology.usage_from_instances(
|
||||
hostusage = hw.numa_usage_from_instances(
|
||||
hosttopo, None)
|
||||
self.assertEqual(hostusage.cells[0].cpu_usage, 0)
|
||||
self.assertEqual(hostusage.cells[0].memory_usage, 0)
|
||||
|
@ -1062,7 +1064,7 @@ class NUMATopologyTest(test.NoDBTestCase):
|
|||
|
||||
def assertNUMACellMatches(self, expected_cell, got_cell):
|
||||
attrs = ('cpuset', 'memory', 'id')
|
||||
if isinstance(expected_cell, hw.VirtNUMAHostTopology):
|
||||
if isinstance(expected_cell, objects.NUMATopology):
|
||||
attrs += ('cpu_usage', 'memory_usage')
|
||||
|
||||
for attr in attrs:
|
||||
|
@ -1070,13 +1072,13 @@ class NUMATopologyTest(test.NoDBTestCase):
|
|||
getattr(got_cell, attr))
|
||||
|
||||
def test_json(self):
|
||||
expected = hw.VirtNUMAHostTopology(
|
||||
expected = objects.NUMATopology(
|
||||
cells=[
|
||||
hw.VirtNUMATopologyCellUsage(
|
||||
1, set([1, 2]), 1024),
|
||||
hw.VirtNUMATopologyCellUsage(
|
||||
2, set([3, 4]), 1024)])
|
||||
got = hw.VirtNUMAHostTopology.from_json(expected.to_json())
|
||||
objects.NUMACell(id=1, cpuset=set([1, 2]), memory=1024,
|
||||
cpu_usage=0, memory_usage=0),
|
||||
objects.NUMACell(id=2, cpuset=set([3, 4]), memory=1024,
|
||||
cpu_usage=0, memory_usage=0)])
|
||||
got = objects.NUMATopology.obj_from_db_obj(expected._to_json())
|
||||
|
||||
for exp_cell, got_cell in zip(expected.cells, got.cells):
|
||||
self.assertNUMACellMatches(exp_cell, got_cell)
|
||||
|
@ -1084,54 +1086,56 @@ class NUMATopologyTest(test.NoDBTestCase):
|
|||
|
||||
class VirtNUMATopologyCellUsageTestCase(test.NoDBTestCase):
|
||||
def test_fit_instance_cell_success_no_limit(self):
|
||||
host_cell = hw.VirtNUMATopologyCellUsage(4, set([1, 2]), 1024)
|
||||
host_cell = objects.NUMACell(id=4, cpuset=set([1, 2]), memory=1024,
|
||||
cpu_usage=0, memory_usage=0)
|
||||
instance_cell = objects.InstanceNUMACell(
|
||||
id=0, cpuset=set([1, 2]), memory=1024)
|
||||
fitted_cell = host_cell.fit_instance_cell(host_cell, instance_cell)
|
||||
fitted_cell = hw._numa_fit_instance_cell(host_cell, instance_cell)
|
||||
self.assertIsInstance(fitted_cell, objects.InstanceNUMACell)
|
||||
self.assertEqual(host_cell.id, fitted_cell.id)
|
||||
|
||||
def test_fit_instance_cell_success_w_limit(self):
|
||||
host_cell = hw.VirtNUMATopologyCellUsage(4, set([1, 2]), 1024,
|
||||
host_cell = objects.NUMACell(id=4, cpuset=set([1, 2]), memory=1024,
|
||||
cpu_usage=2,
|
||||
memory_usage=1024)
|
||||
limit_cell = hw.VirtNUMATopologyCellLimit(
|
||||
4, set([1, 2]), 1024,
|
||||
4, cpuset=set([1, 2]), memory=1024,
|
||||
cpu_limit=4, memory_limit=2048)
|
||||
instance_cell = objects.InstanceNUMACell(
|
||||
id=0, cpuset=set([1, 2]), memory=1024)
|
||||
fitted_cell = host_cell.fit_instance_cell(
|
||||
fitted_cell = hw._numa_fit_instance_cell(
|
||||
host_cell, instance_cell, limit_cell=limit_cell)
|
||||
self.assertIsInstance(fitted_cell, objects.InstanceNUMACell)
|
||||
self.assertEqual(host_cell.id, fitted_cell.id)
|
||||
|
||||
def test_fit_instance_cell_self_overcommit(self):
|
||||
host_cell = hw.VirtNUMATopologyCellUsage(4, set([1, 2]), 1024)
|
||||
host_cell = objects.NUMACell(id=4, cpuset=set([1, 2]), memory=1024,
|
||||
cpu_usage=0, memory_usage=0)
|
||||
limit_cell = hw.VirtNUMATopologyCellLimit(
|
||||
4, set([1, 2]), 1024,
|
||||
4, cpuset=set([1, 2]), memory=1024,
|
||||
cpu_limit=4, memory_limit=2048)
|
||||
instance_cell = objects.InstanceNUMACell(
|
||||
id=0, cpuset=set([1, 2, 3]), memory=4096)
|
||||
fitted_cell = host_cell.fit_instance_cell(
|
||||
fitted_cell = hw._numa_fit_instance_cell(
|
||||
host_cell, instance_cell, limit_cell=limit_cell)
|
||||
self.assertIsNone(fitted_cell)
|
||||
|
||||
def test_fit_instance_cell_fail_w_limit(self):
|
||||
host_cell = hw.VirtNUMATopologyCellUsage(4, set([1, 2]), 1024,
|
||||
host_cell = objects.NUMACell(id=4, cpuset=set([1, 2]), memory=1024,
|
||||
cpu_usage=2,
|
||||
memory_usage=1024)
|
||||
limit_cell = hw.VirtNUMATopologyCellLimit(
|
||||
4, set([1, 2]), 1024,
|
||||
4, cpuset=set([1, 2]), memory=1024,
|
||||
cpu_limit=4, memory_limit=2048)
|
||||
instance_cell = objects.InstanceNUMACell(
|
||||
id=0, cpuset=set([1, 2]), memory=4096)
|
||||
fitted_cell = host_cell.fit_instance_cell(
|
||||
fitted_cell = hw._numa_fit_instance_cell(
|
||||
host_cell, instance_cell, limit_cell=limit_cell)
|
||||
self.assertIsNone(fitted_cell)
|
||||
|
||||
instance_cell = objects.InstanceNUMACell(
|
||||
id=0, cpuset=set([1, 2, 3, 4, 5]), memory=1024)
|
||||
fitted_cell = host_cell.fit_instance_cell(
|
||||
fitted_cell = hw._numa_fit_instance_cell(
|
||||
host_cell, instance_cell, limit_cell=limit_cell)
|
||||
self.assertIsNone(fitted_cell)
|
||||
|
||||
|
@ -1140,22 +1144,20 @@ class VirtNUMAHostTopologyTestCase(test.NoDBTestCase):
|
|||
def setUp(self):
|
||||
super(VirtNUMAHostTopologyTestCase, self).setUp()
|
||||
|
||||
self.host = hw.VirtNUMAHostTopology(
|
||||
self.host = objects.NUMATopology(
|
||||
cells=[
|
||||
hw.VirtNUMATopologyCellUsage(
|
||||
1, set([1, 2]), 2048,
|
||||
objects.NUMACell(id=1, cpuset=set([1, 2]), memory=2048,
|
||||
cpu_usage=2, memory_usage=2048),
|
||||
hw.VirtNUMATopologyCellUsage(
|
||||
2, set([3, 4]), 2048,
|
||||
objects.NUMACell(id=2, cpuset=set([3, 4]), memory=2048,
|
||||
cpu_usage=2, memory_usage=2048)])
|
||||
|
||||
self.limits = hw.VirtNUMALimitTopology(
|
||||
cells=[
|
||||
hw.VirtNUMATopologyCellLimit(
|
||||
1, set([1, 2]), 2048,
|
||||
1, cpuset=set([1, 2]), memory=2048,
|
||||
cpu_limit=4, memory_limit=4096),
|
||||
hw.VirtNUMATopologyCellLimit(
|
||||
2, set([3, 4]), 2048,
|
||||
2, cpuset=set([3, 4]), memory=2048,
|
||||
cpu_limit=4, memory_limit=3072)])
|
||||
|
||||
self.instance1 = objects.InstanceNUMATopology(
|
||||
|
@ -1172,45 +1174,45 @@ class VirtNUMAHostTopologyTestCase(test.NoDBTestCase):
|
|||
id=0, cpuset=set([1, 2]), memory=1024)])
|
||||
|
||||
def test_get_fitting_success_no_limits(self):
|
||||
fitted_instance1 = hw.VirtNUMAHostTopology.fit_instance_to_host(
|
||||
fitted_instance1 = hw.numa_fit_instance_to_host(
|
||||
self.host, self.instance1)
|
||||
self.assertIsInstance(fitted_instance1, objects.InstanceNUMATopology)
|
||||
self.host = hw.VirtNUMAHostTopology.usage_from_instances(self.host,
|
||||
self.host = hw.numa_usage_from_instances(self.host,
|
||||
[fitted_instance1])
|
||||
fitted_instance2 = hw.VirtNUMAHostTopology.fit_instance_to_host(
|
||||
fitted_instance2 = hw.numa_fit_instance_to_host(
|
||||
self.host, self.instance3)
|
||||
self.assertIsInstance(fitted_instance2, objects.InstanceNUMATopology)
|
||||
|
||||
def test_get_fitting_success_limits(self):
|
||||
fitted_instance = hw.VirtNUMAHostTopology.fit_instance_to_host(
|
||||
fitted_instance = hw.numa_fit_instance_to_host(
|
||||
self.host, self.instance3, self.limits)
|
||||
self.assertIsInstance(fitted_instance, objects.InstanceNUMATopology)
|
||||
self.assertEqual(1, fitted_instance.cells[0].id)
|
||||
|
||||
def test_get_fitting_fails_no_limits(self):
|
||||
fitted_instance = hw.VirtNUMAHostTopology.fit_instance_to_host(
|
||||
fitted_instance = hw.numa_fit_instance_to_host(
|
||||
self.host, self.instance2, self.limits)
|
||||
self.assertIsNone(fitted_instance)
|
||||
|
||||
def test_get_fitting_culmulative_fails_limits(self):
|
||||
fitted_instance1 = hw.VirtNUMAHostTopology.fit_instance_to_host(
|
||||
fitted_instance1 = hw.numa_fit_instance_to_host(
|
||||
self.host, self.instance1, self.limits)
|
||||
self.assertIsInstance(fitted_instance1, objects.InstanceNUMATopology)
|
||||
self.assertEqual(1, fitted_instance1.cells[0].id)
|
||||
self.host = hw.VirtNUMAHostTopology.usage_from_instances(self.host,
|
||||
self.host = hw.numa_usage_from_instances(self.host,
|
||||
[fitted_instance1])
|
||||
fitted_instance2 = hw.VirtNUMAHostTopology.fit_instance_to_host(
|
||||
fitted_instance2 = hw.numa_fit_instance_to_host(
|
||||
self.host, self.instance1, self.limits)
|
||||
self.assertIsNone(fitted_instance2)
|
||||
|
||||
def test_get_fitting_culmulative_success_limits(self):
|
||||
fitted_instance1 = hw.VirtNUMAHostTopology.fit_instance_to_host(
|
||||
fitted_instance1 = hw.numa_fit_instance_to_host(
|
||||
self.host, self.instance1, self.limits)
|
||||
self.assertIsInstance(fitted_instance1, objects.InstanceNUMATopology)
|
||||
self.assertEqual(1, fitted_instance1.cells[0].id)
|
||||
self.host = hw.VirtNUMAHostTopology.usage_from_instances(self.host,
|
||||
self.host = hw.numa_usage_from_instances(self.host,
|
||||
[fitted_instance1])
|
||||
fitted_instance2 = hw.VirtNUMAHostTopology.fit_instance_to_host(
|
||||
fitted_instance2 = hw.numa_fit_instance_to_host(
|
||||
self.host, self.instance3, self.limits)
|
||||
self.assertIsInstance(fitted_instance2, objects.InstanceNUMATopology)
|
||||
self.assertEqual(2, fitted_instance2.cells[0].id)
|
||||
|
@ -1263,9 +1265,11 @@ class NumberOfSerialPortsTest(test.NoDBTestCase):
|
|||
class HelperMethodsTestCase(test.NoDBTestCase):
|
||||
def setUp(self):
|
||||
super(HelperMethodsTestCase, self).setUp()
|
||||
self.hosttopo = hw.VirtNUMAHostTopology([
|
||||
hw.VirtNUMATopologyCellUsage(0, set([0, 1]), 512),
|
||||
hw.VirtNUMATopologyCellUsage(1, set([2, 3]), 512),
|
||||
self.hosttopo = objects.NUMATopology(cells=[
|
||||
objects.NUMACell(id=0, cpuset=set([0, 1]), memory=512,
|
||||
memory_usage=0, cpu_usage=0),
|
||||
objects.NUMACell(id=1, cpuset=set([2, 3]), memory=512,
|
||||
memory_usage=0, cpu_usage=0),
|
||||
])
|
||||
self.instancetopo = objects.InstanceNUMATopology(
|
||||
instance_uuid='fake-uuid',
|
||||
|
@ -1285,19 +1289,19 @@ class HelperMethodsTestCase(test.NoDBTestCase):
|
|||
self.assertEqual(256, host_usage.cells[1].memory_usage)
|
||||
|
||||
def test_dicts_json(self):
|
||||
host = {'numa_topology': self.hosttopo.to_json()}
|
||||
host = {'numa_topology': self.hosttopo._to_json()}
|
||||
instance = {'numa_topology': self.instancetopo._to_json()}
|
||||
|
||||
res = hw.get_host_numa_usage_from_instance(host, instance)
|
||||
self.assertIsInstance(res, six.string_types)
|
||||
self._check_usage(hw.VirtNUMAHostTopology.from_json(res))
|
||||
self._check_usage(objects.NUMATopology.obj_from_db_obj(res))
|
||||
|
||||
def test_dicts_instance_json(self):
|
||||
host = {'numa_topology': self.hosttopo}
|
||||
instance = {'numa_topology': self.instancetopo._to_json()}
|
||||
|
||||
res = hw.get_host_numa_usage_from_instance(host, instance)
|
||||
self.assertIsInstance(res, hw.VirtNUMAHostTopology)
|
||||
self.assertIsInstance(res, objects.NUMATopology)
|
||||
self._check_usage(res)
|
||||
|
||||
def test_dicts_instance_json_old(self):
|
||||
|
@ -1306,35 +1310,44 @@ class HelperMethodsTestCase(test.NoDBTestCase):
|
|||
jsonutils.dumps(self.instancetopo._to_dict())}
|
||||
|
||||
res = hw.get_host_numa_usage_from_instance(host, instance)
|
||||
self.assertIsInstance(res, hw.VirtNUMAHostTopology)
|
||||
self.assertIsInstance(res, objects.NUMATopology)
|
||||
self._check_usage(res)
|
||||
|
||||
def test_dicts_host_json(self):
|
||||
host = {'numa_topology': self.hosttopo.to_json()}
|
||||
host = {'numa_topology': self.hosttopo._to_json()}
|
||||
instance = {'numa_topology': self.instancetopo}
|
||||
|
||||
res = hw.get_host_numa_usage_from_instance(host, instance)
|
||||
self.assertIsInstance(res, six.string_types)
|
||||
self._check_usage(hw.VirtNUMAHostTopology.from_json(res))
|
||||
self._check_usage(objects.NUMATopology.obj_from_db_obj(res))
|
||||
|
||||
def test_dicts_host_json_old(self):
|
||||
host = {'numa_topology': jsonutils.dumps(
|
||||
self.hosttopo._to_dict())}
|
||||
instance = {'numa_topology': self.instancetopo}
|
||||
|
||||
res = hw.get_host_numa_usage_from_instance(host, instance)
|
||||
self.assertIsInstance(res, six.string_types)
|
||||
self._check_usage(objects.NUMATopology.obj_from_db_obj(res))
|
||||
|
||||
def test_object_host_instance_json(self):
|
||||
host = objects.ComputeNode(numa_topology=self.hosttopo.to_json())
|
||||
host = objects.ComputeNode(numa_topology=self.hosttopo._to_json())
|
||||
instance = {'numa_topology': self.instancetopo._to_json()}
|
||||
|
||||
res = hw.get_host_numa_usage_from_instance(host, instance)
|
||||
self.assertIsInstance(res, six.string_types)
|
||||
self._check_usage(hw.VirtNUMAHostTopology.from_json(res))
|
||||
self._check_usage(objects.NUMATopology.obj_from_db_obj(res))
|
||||
|
||||
def test_object_host_instance(self):
|
||||
host = objects.ComputeNode(numa_topology=self.hosttopo.to_json())
|
||||
host = objects.ComputeNode(numa_topology=self.hosttopo._to_json())
|
||||
instance = {'numa_topology': self.instancetopo}
|
||||
|
||||
res = hw.get_host_numa_usage_from_instance(host, instance)
|
||||
self.assertIsInstance(res, six.string_types)
|
||||
self._check_usage(hw.VirtNUMAHostTopology.from_json(res))
|
||||
self._check_usage(objects.NUMATopology.obj_from_db_obj(res))
|
||||
|
||||
def test_instance_with_fetch(self):
|
||||
host = objects.ComputeNode(numa_topology=self.hosttopo.to_json())
|
||||
host = objects.ComputeNode(numa_topology=self.hosttopo._to_json())
|
||||
fake_uuid = str(uuid.uuid4())
|
||||
instance = {'uuid': fake_uuid}
|
||||
|
||||
|
@ -1345,7 +1358,7 @@ class HelperMethodsTestCase(test.NoDBTestCase):
|
|||
self.assertTrue(get_mock.called)
|
||||
|
||||
def test_object_instance_with_load(self):
|
||||
host = objects.ComputeNode(numa_topology=self.hosttopo.to_json())
|
||||
host = objects.ComputeNode(numa_topology=self.hosttopo._to_json())
|
||||
fake_uuid = str(uuid.uuid4())
|
||||
instance = objects.Instance(context=self.context, uuid=fake_uuid)
|
||||
|
||||
|
@ -1356,7 +1369,7 @@ class HelperMethodsTestCase(test.NoDBTestCase):
|
|||
self.assertTrue(get_mock.called)
|
||||
|
||||
def test_instance_serialized_by_build_request_spec(self):
|
||||
host = objects.ComputeNode(numa_topology=self.hosttopo.to_json())
|
||||
host = objects.ComputeNode(numa_topology=self.hosttopo._to_json())
|
||||
fake_uuid = str(uuid.uuid4())
|
||||
instance = objects.Instance(context=self.context, id=1, uuid=fake_uuid,
|
||||
numa_topology=self.instancetopo)
|
||||
|
@ -1366,27 +1379,27 @@ class HelperMethodsTestCase(test.NoDBTestCase):
|
|||
base_obj.obj_to_primitive(instance))
|
||||
res = hw.get_host_numa_usage_from_instance(host, instance_raw)
|
||||
self.assertIsInstance(res, six.string_types)
|
||||
self._check_usage(hw.VirtNUMAHostTopology.from_json(res))
|
||||
self._check_usage(objects.NUMATopology.obj_from_db_obj(res))
|
||||
|
||||
def test_attr_host(self):
|
||||
class Host(object):
|
||||
def __init__(obj):
|
||||
obj.numa_topology = self.hosttopo.to_json()
|
||||
obj.numa_topology = self.hosttopo._to_json()
|
||||
|
||||
host = Host()
|
||||
instance = {'numa_topology': self.instancetopo._to_json()}
|
||||
|
||||
res = hw.get_host_numa_usage_from_instance(host, instance)
|
||||
self.assertIsInstance(res, six.string_types)
|
||||
self._check_usage(hw.VirtNUMAHostTopology.from_json(res))
|
||||
self._check_usage(objects.NUMATopology.obj_from_db_obj(res))
|
||||
|
||||
def test_never_serialize_result(self):
|
||||
host = {'numa_topology': self.hosttopo.to_json()}
|
||||
host = {'numa_topology': self.hosttopo._to_json()}
|
||||
instance = {'numa_topology': self.instancetopo}
|
||||
|
||||
res = hw.get_host_numa_usage_from_instance(host, instance,
|
||||
never_serialize_result=True)
|
||||
self.assertIsInstance(res, hw.VirtNUMAHostTopology)
|
||||
self.assertIsInstance(res, objects.NUMATopology)
|
||||
self._check_usage(res)
|
||||
|
||||
|
||||
|
|
|
@ -652,84 +652,34 @@ class VirtNUMATopologyCellLimit(VirtNUMATopologyCell):
|
|||
return cls(cell_id, cpuset, memory, cpu_limit, memory_limit)
|
||||
|
||||
|
||||
class VirtNUMATopologyCellUsage(VirtNUMATopologyCell):
|
||||
"""Class for reporting NUMA resources and usage in a cell
|
||||
def _numa_fit_instance_cell(host_cell, instance_cell, limit_cell=None):
|
||||
"""Check if a instance cell can fit and set it's cell id
|
||||
|
||||
The VirtNUMATopologyCellUsage class specializes
|
||||
VirtNUMATopologyCell to include information about the
|
||||
utilization of hardware resources in a NUMA cell.
|
||||
:param host_cell: host cell to fit the instance cell onto
|
||||
:param instance_cell: instance cell we want to fit
|
||||
:param limit_cell: cell with limits of the host_cell if any
|
||||
|
||||
Make sure we can fit the instance cell onto a host cell and if so,
|
||||
return a new objects.InstanceNUMACell with the id set to that of
|
||||
the host, or None if the cell exceeds the limits of the host
|
||||
|
||||
:returns: a new instance cell or None
|
||||
"""
|
||||
# NOTE (ndipanov): do not allow an instance to overcommit against
|
||||
# itself on any NUMA cell
|
||||
if (instance_cell.memory > host_cell.memory or
|
||||
len(instance_cell.cpuset) > len(host_cell.cpuset)):
|
||||
return None
|
||||
|
||||
def __init__(self, id, cpuset, memory, cpu_usage=0, memory_usage=0):
|
||||
"""Create a new NUMA Cell with usage
|
||||
|
||||
:param id: integer identifier of cell
|
||||
:param cpuset: set containing list of CPU indexes
|
||||
:param memory: RAM measured in MiB
|
||||
:param cpu_usage: number of CPUs allocated
|
||||
:param memory_usage: RAM allocated in MiB
|
||||
|
||||
Creates a new NUMA cell object to record the hardware
|
||||
resources and utilization. The number of CPUs specified
|
||||
by the @cpu_usage parameter may be larger than the number
|
||||
of bits set in @cpuset if CPU overcommit is used. Likewise
|
||||
the amount of RAM specified by the @memory_usage parameter
|
||||
may be larger than the available RAM in @memory if RAM
|
||||
overcommit is used.
|
||||
|
||||
:returns: a new NUMA cell object
|
||||
"""
|
||||
|
||||
super(VirtNUMATopologyCellUsage, self).__init__(
|
||||
id, cpuset, memory)
|
||||
|
||||
self.cpu_usage = cpu_usage
|
||||
self.memory_usage = memory_usage
|
||||
|
||||
@classmethod
|
||||
def fit_instance_cell(cls, host_cell, instance_cell, limit_cell=None):
|
||||
"""Check if a instance cell can fit and set it's cell id
|
||||
|
||||
:param host_cell: host cell to fit the instance cell onto
|
||||
:param instance_cell: instance cell we want to fit
|
||||
:param limit_cell: cell with limits of the host_cell if any
|
||||
|
||||
Make sure we can fit the instance cell onto a host cell and if so,
|
||||
return a new objects.InstanceNUMACell with the id set to that of
|
||||
the host, or None if the cell exceeds the limits of the host
|
||||
|
||||
:returns: a new instance cell or None
|
||||
"""
|
||||
# NOTE (ndipanov): do not allow an instance to overcommit against
|
||||
# itself on any NUMA cell
|
||||
if (instance_cell.memory > host_cell.memory or
|
||||
len(instance_cell.cpuset) > len(host_cell.cpuset)):
|
||||
if limit_cell:
|
||||
memory_usage = host_cell.memory_usage + instance_cell.memory
|
||||
cpu_usage = host_cell.cpu_usage + len(instance_cell.cpuset)
|
||||
if (memory_usage > limit_cell.memory_limit or
|
||||
cpu_usage > limit_cell.cpu_limit):
|
||||
return None
|
||||
|
||||
if limit_cell:
|
||||
memory_usage = host_cell.memory_usage + instance_cell.memory
|
||||
cpu_usage = host_cell.cpu_usage + len(instance_cell.cpuset)
|
||||
if (memory_usage > limit_cell.memory_limit or
|
||||
cpu_usage > limit_cell.cpu_limit):
|
||||
return None
|
||||
return objects.InstanceNUMACell(
|
||||
id=host_cell.id, cpuset=instance_cell.cpuset,
|
||||
memory=instance_cell.memory)
|
||||
|
||||
def _to_dict(self):
|
||||
data_dict = super(VirtNUMATopologyCellUsage, self)._to_dict()
|
||||
data_dict['mem']['used'] = self.memory_usage
|
||||
data_dict['cpu_usage'] = self.cpu_usage
|
||||
return data_dict
|
||||
|
||||
@classmethod
|
||||
def _from_dict(cls, data_dict):
|
||||
cpuset = parse_cpu_spec(data_dict.get('cpus', ''))
|
||||
cpu_usage = data_dict.get('cpu_usage', 0)
|
||||
memory = data_dict.get('mem', {}).get('total', 0)
|
||||
memory_usage = data_dict.get('mem', {}).get('used', 0)
|
||||
cell_id = data_dict.get('id')
|
||||
return cls(cell_id, cpuset, memory, cpu_usage, memory_usage)
|
||||
return objects.InstanceNUMACell(
|
||||
id=host_cell.id, cpuset=instance_cell.cpuset,
|
||||
memory=instance_cell.memory)
|
||||
|
||||
|
||||
class VirtNUMATopology(object):
|
||||
|
@ -903,93 +853,83 @@ class VirtNUMALimitTopology(VirtNUMATopology):
|
|||
cell_class = VirtNUMATopologyCellLimit
|
||||
|
||||
|
||||
class VirtNUMAHostTopology(VirtNUMATopology):
|
||||
def numa_fit_instance_to_host(
|
||||
host_topology, instance_topology, limits_topology=None):
|
||||
"""Fit the instance topology onto the host topology given the limits
|
||||
|
||||
"""Class represents the NUMA configuration and utilization
|
||||
of a compute node. As well as exposing the overall topology
|
||||
it tracks the utilization of the resources by guest instances
|
||||
:param host_topology: objects.NUMATopology 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 _numa_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 = _numa_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 numa_usage_from_instances(host, instances, free=False):
|
||||
"""Get host topology usage
|
||||
|
||||
:param host: objects.NUMATopology with usage information
|
||||
:param instances: list of objects.InstanceNUMATopology
|
||||
:param free: If True usage of the host will be decreased
|
||||
|
||||
Sum the usage from all @instances to report the overall
|
||||
host topology usage
|
||||
|
||||
:returns: objects.NUMATopology including usage information
|
||||
"""
|
||||
|
||||
cell_class = VirtNUMATopologyCellUsage
|
||||
if host is None:
|
||||
return
|
||||
|
||||
@classmethod
|
||||
def fit_instance_to_host(cls, host_topology, instance_topology,
|
||||
limits_topology=None):
|
||||
"""Fit the instance topology onto the host topology given the limits
|
||||
instances = instances or []
|
||||
cells = []
|
||||
sign = -1 if free else 1
|
||||
for hostcell in host.cells:
|
||||
memory_usage = hostcell.memory_usage
|
||||
cpu_usage = hostcell.cpu_usage
|
||||
for instance in instances:
|
||||
for instancecell in instance.cells:
|
||||
if instancecell.id == hostcell.id:
|
||||
memory_usage = (
|
||||
memory_usage + sign * instancecell.memory)
|
||||
cpu_usage = cpu_usage + sign * len(instancecell.cpuset)
|
||||
|
||||
: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
|
||||
cell = objects.NUMACell(
|
||||
id=hostcell.id, cpuset=hostcell.cpuset, memory=hostcell.memory,
|
||||
cpu_usage=max(0, cpu_usage), memory_usage=max(0, memory_usage))
|
||||
|
||||
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)
|
||||
cells.append(cell)
|
||||
|
||||
@classmethod
|
||||
def usage_from_instances(cls, host, instances, free=False):
|
||||
"""Get host topology usage
|
||||
|
||||
:param host: VirtNUMAHostTopology with usage information
|
||||
:param instances: list of objects.InstanceNUMATopology
|
||||
:param free: If True usage of the host will be decreased
|
||||
|
||||
Sum the usage from all @instances to report the overall
|
||||
host topology usage
|
||||
|
||||
:returns: VirtNUMAHostTopology including usage information
|
||||
"""
|
||||
|
||||
if host is None:
|
||||
return
|
||||
|
||||
instances = instances or []
|
||||
cells = []
|
||||
sign = -1 if free else 1
|
||||
for hostcell in host.cells:
|
||||
memory_usage = hostcell.memory_usage
|
||||
cpu_usage = hostcell.cpu_usage
|
||||
for instance in instances:
|
||||
for instancecell in instance.cells:
|
||||
if instancecell.id == hostcell.id:
|
||||
memory_usage = (
|
||||
memory_usage + sign * instancecell.memory)
|
||||
cpu_usage = cpu_usage + sign * len(instancecell.cpuset)
|
||||
|
||||
cell = cls.cell_class(
|
||||
hostcell.id, hostcell.cpuset, hostcell.memory,
|
||||
max(0, cpu_usage), max(0, memory_usage))
|
||||
|
||||
cells.append(cell)
|
||||
|
||||
return cls(cells)
|
||||
return objects.NUMATopology(cells=cells)
|
||||
|
||||
|
||||
# TODO(ndipanov): Remove when all code paths are using objects
|
||||
|
@ -1055,7 +995,7 @@ def host_topology_and_format_from_host(host):
|
|||
|
||||
Since we may get a host as either a dict, a db object, or an actual
|
||||
ComputeNode object, or an instance of HostState class, this makes sure we
|
||||
get beck either None, or an instance of VirtNUMAHostTopology class.
|
||||
get beck either None, or an instance of objects.NUMATopology class.
|
||||
|
||||
:returns: A two-tuple, first element is the topology itself or None, second
|
||||
is a boolean set to True if topology was in json format.
|
||||
|
@ -1069,7 +1009,9 @@ def host_topology_and_format_from_host(host):
|
|||
if host_numa_topology is not None and isinstance(
|
||||
host_numa_topology, six.string_types):
|
||||
was_json = True
|
||||
host_numa_topology = VirtNUMAHostTopology.from_json(host_numa_topology)
|
||||
|
||||
host_numa_topology = (objects.NUMATopology.obj_from_db_obj(
|
||||
host_numa_topology))
|
||||
|
||||
return host_numa_topology, was_json
|
||||
|
||||
|
@ -1091,10 +1033,10 @@ def get_host_numa_usage_from_instance(host, instance, free=False,
|
|||
:param free: if True the the returned topology will have it's usage
|
||||
decreased instead.
|
||||
:param never_serialize_result: if True result will always be an instance of
|
||||
VirtNUMAHostTopology class.
|
||||
objects.NUMATopology class.
|
||||
|
||||
:returns: numa_usage in the format it was on the host or
|
||||
VirtNUMAHostTopology instance if never_serialize_result was True
|
||||
objects.NUMATopology instance if never_serialize_result was True
|
||||
"""
|
||||
instance_numa_topology = instance_topology_from_instance(instance)
|
||||
if instance_numa_topology:
|
||||
|
@ -1104,11 +1046,11 @@ def get_host_numa_usage_from_instance(host, instance, free=False,
|
|||
host)
|
||||
|
||||
updated_numa_topology = (
|
||||
VirtNUMAHostTopology.usage_from_instances(
|
||||
host_numa_topology, instance_numa_topology, free=free))
|
||||
numa_usage_from_instances(
|
||||
host_numa_topology, instance_numa_topology, free=free))
|
||||
|
||||
if updated_numa_topology is not None:
|
||||
if jsonify_result and not never_serialize_result:
|
||||
updated_numa_topology = updated_numa_topology.to_json()
|
||||
updated_numa_topology = updated_numa_topology._to_json()
|
||||
|
||||
return updated_numa_topology
|
||||
|
|
|
@ -4912,11 +4912,13 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
if topology is None or not topology.cells:
|
||||
return
|
||||
|
||||
topology = hardware.VirtNUMAHostTopology(
|
||||
cells=[hardware.VirtNUMATopologyCellUsage(
|
||||
cell.id, set(cpu.id for cpu in cell.cpus),
|
||||
cell.memory / units.Ki)
|
||||
for cell in topology.cells])
|
||||
topology = objects.NUMATopology(
|
||||
cells=[objects.NUMACell(
|
||||
id=cell.id,
|
||||
cpuset=set(cpu.id for cpu in cell.cpus),
|
||||
memory=cell.memory / units.Ki,
|
||||
cpu_usage=0, memory_usage=0)
|
||||
for cell in topology.cells])
|
||||
|
||||
allowed_cpus = hardware.get_vcpu_pin_set()
|
||||
if allowed_cpus:
|
||||
|
@ -5046,7 +5048,7 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
|
||||
numa_topology = self._get_host_numa_topology()
|
||||
if numa_topology:
|
||||
data['numa_topology'] = numa_topology.to_json()
|
||||
data['numa_topology'] = numa_topology._to_json()
|
||||
else:
|
||||
data['numa_topology'] = None
|
||||
|
||||
|
|
Loading…
Reference in New Issue