objects: move virt numa instance to objects
Moves VirtNUMAInstance in InstanceNUMATopology provides by objects. Change-Id: I1a93f00a390312590963a9ed50722a946d772d3b
This commit is contained in:
+1
-4
@@ -785,11 +785,8 @@ class API(base.Base):
|
||||
block_device.properties_root_device_name(
|
||||
boot_meta.get('properties', {})))
|
||||
|
||||
numa_topology = hardware.VirtNUMAInstanceTopology.get_constraints(
|
||||
numa_topology = hardware.numa_get_constraints(
|
||||
instance_type, boot_meta.get('properties', {}))
|
||||
if numa_topology is not None:
|
||||
numa_topology = objects.InstanceNUMATopology.obj_from_topology(
|
||||
numa_topology)
|
||||
|
||||
system_metadata = flavors.save_flavor_info(
|
||||
dict(), instance_type)
|
||||
|
||||
+4
-10
@@ -202,8 +202,7 @@ class Claim(NopClaim):
|
||||
|
||||
def _test_numa_topology(self, resources, limit):
|
||||
host_topology = resources.get('numa_topology')
|
||||
requested_topology = (self.numa_topology and
|
||||
self.numa_topology.topology_from_obj())
|
||||
requested_topology = self.numa_topology
|
||||
if host_topology:
|
||||
host_topology = hardware.VirtNUMAHostTopology.from_json(
|
||||
host_topology)
|
||||
@@ -215,9 +214,7 @@ class Claim(NopClaim):
|
||||
return (_("Requested instance NUMA topology cannot fit "
|
||||
"the given host NUMA topology"))
|
||||
elif instance_topology:
|
||||
self.claimed_numa_topology = (
|
||||
objects.InstanceNUMATopology.obj_from_topology(
|
||||
instance_topology))
|
||||
self.claimed_numa_topology = instance_topology
|
||||
|
||||
def _test(self, type_, unit, total, used, requested, limit):
|
||||
"""Test if the given type of resource needed for a claim can be safely
|
||||
@@ -274,11 +271,8 @@ class ResizeClaim(Claim):
|
||||
|
||||
@property
|
||||
def numa_topology(self):
|
||||
instance_topology = hardware.VirtNUMAInstanceTopology.get_constraints(
|
||||
self.instance_type, self.image_meta)
|
||||
if instance_topology:
|
||||
return objects.InstanceNUMATopology.obj_from_topology(
|
||||
instance_topology)
|
||||
return hardware.numa_get_constraints(
|
||||
self.instance_type, self.image_meta)
|
||||
|
||||
def _test_pci(self):
|
||||
pci_requests = objects.InstancePCIRequests.\
|
||||
|
||||
@@ -247,9 +247,8 @@ class ResourceTracker(object):
|
||||
instance['system_metadata'])
|
||||
|
||||
if instance_type['id'] == itype['id']:
|
||||
numa_topology = (
|
||||
hardware.VirtNUMAInstanceTopology.get_constraints(
|
||||
itype, image_meta))
|
||||
numa_topology = hardware.numa_get_constraints(
|
||||
itype, image_meta)
|
||||
usage = self._get_usage_dict(
|
||||
itype, numa_topology=numa_topology)
|
||||
if self.pci_tracker:
|
||||
@@ -603,9 +602,7 @@ class ResourceTracker(object):
|
||||
if host_topology:
|
||||
host_topology = hardware.VirtNUMAHostTopology.from_json(
|
||||
host_topology)
|
||||
numa_topology = (
|
||||
hardware.VirtNUMAInstanceTopology.get_constraints(
|
||||
itype, image_meta))
|
||||
numa_topology = hardware.numa_get_constraints(itype, image_meta)
|
||||
numa_topology = (
|
||||
hardware.VirtNUMAHostTopology.fit_instance_to_host(
|
||||
host_topology, numa_topology))
|
||||
|
||||
@@ -33,6 +33,26 @@ class InstanceNUMACell(base.NovaObject):
|
||||
'pagesize': fields.IntegerField(nullable=True),
|
||||
}
|
||||
|
||||
def _to_dict(self):
|
||||
# NOTE(sahid): Used as legacy, could be renamed in
|
||||
# _legacy_to_dict_ to the future to avoid confusing.
|
||||
return {'cpus': hardware.format_cpu_spec(self.cpuset,
|
||||
allow_ranges=False),
|
||||
'mem': {'total': self.memory},
|
||||
'id': self.id,
|
||||
'pagesize': self.pagesize}
|
||||
|
||||
@classmethod
|
||||
def _from_dict(cls, data_dict):
|
||||
# NOTE(sahid): Used as legacy, could be renamed in
|
||||
# _legacy_from_dict_ to the future to avoid confusing.
|
||||
cpuset = hardware.parse_cpu_spec(data_dict.get('cpus', ''))
|
||||
memory = data_dict.get('mem', {}).get('total', 0)
|
||||
cell_id = data_dict.get('id')
|
||||
pagesize = data_dict.get('pagesize')
|
||||
return cls(id=cell_id, cpuset=cpuset,
|
||||
memory=memory, pagesize=pagesize)
|
||||
|
||||
|
||||
class InstanceNUMATopology(base.NovaObject):
|
||||
# Version 1.0: Initial version
|
||||
@@ -48,43 +68,29 @@ class InstanceNUMATopology(base.NovaObject):
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def obj_from_db_obj(cls, instance_uuid, db_obj):
|
||||
if 'nova_object.name' in db_obj:
|
||||
obj_topology = cls.obj_from_primitive(
|
||||
jsonutils.loads(db_obj))
|
||||
def obj_from_primitive(cls, primitive):
|
||||
if 'nova_object.name' in primitive:
|
||||
obj_topology = super(InstanceNUMATopology, cls).obj_from_primitive(
|
||||
primitive)
|
||||
else:
|
||||
# NOTE(sahid): This compatibility code needs to stay until we can
|
||||
# guarantee that there are no cases of the old format stored in
|
||||
# the database (or forever, if we can never guarantee that).
|
||||
topo = hardware.VirtNUMAInstanceTopology.from_json(db_obj)
|
||||
obj_topology = cls.obj_from_topology(topo)
|
||||
obj_topology.instance_uuid = instance_uuid
|
||||
|
||||
# No benefit to store a list of changed fields
|
||||
obj_topology.obj_reset_changes()
|
||||
obj_topology = InstanceNUMATopology._from_dict(primitive)
|
||||
obj_topology.id = 0
|
||||
return obj_topology
|
||||
|
||||
@classmethod
|
||||
def obj_from_topology(cls, topology):
|
||||
if not isinstance(topology, hardware.VirtNUMAInstanceTopology):
|
||||
raise exception.ObjectActionError(action='obj_from_topology',
|
||||
reason='invalid topology class')
|
||||
if topology:
|
||||
cells = []
|
||||
for topocell in topology.cells:
|
||||
cell = InstanceNUMACell(id=topocell.id, cpuset=topocell.cpuset,
|
||||
memory=topocell.memory,
|
||||
pagesize=topocell.pagesize)
|
||||
cells.append(cell)
|
||||
return cls(cells=cells)
|
||||
def obj_from_db_obj(cls, instance_uuid, db_obj):
|
||||
primitive = jsonutils.loads(db_obj)
|
||||
obj_topology = cls.obj_from_primitive(primitive)
|
||||
|
||||
def topology_from_obj(self):
|
||||
cells = []
|
||||
for objcell in self.cells:
|
||||
cell = hardware.VirtNUMATopologyCellInstance(
|
||||
objcell.id, objcell.cpuset, objcell.memory, objcell.pagesize)
|
||||
cells.append(cell)
|
||||
return hardware.VirtNUMAInstanceTopology(cells=cells)
|
||||
if 'nova_object.name' not in db_obj:
|
||||
obj_topology.instance_uuid = instance_uuid
|
||||
# No benefit to store a list of changed fields
|
||||
obj_topology.obj_reset_changes()
|
||||
|
||||
return obj_topology
|
||||
|
||||
# TODO(ndipanov) Remove this method on the major version bump to 2.0
|
||||
@base.remotable
|
||||
@@ -123,3 +129,20 @@ class InstanceNUMATopology(base.NovaObject):
|
||||
|
||||
def _to_json(self):
|
||||
return jsonutils.dumps(self.obj_to_primitive())
|
||||
|
||||
def __len__(self):
|
||||
"""Defined so that boolean testing works the same as for lists."""
|
||||
return len(self.cells)
|
||||
|
||||
def _to_dict(self):
|
||||
# NOTE(sahid): Used as legacy, could be renamed in _legacy_to_dict_
|
||||
# in the future to avoid confusing.
|
||||
return {'cells': [cell._to_dict() for cell in self.cells]}
|
||||
|
||||
@classmethod
|
||||
def _from_dict(cls, data_dict):
|
||||
# NOTE(sahid): Used as legacy, could be renamed in _legacy_from_dict_
|
||||
# in the future to avoid confusing.
|
||||
return cls(cells=[
|
||||
InstanceNUMACell._from_dict(cell_dict)
|
||||
for cell_dict in data_dict.get('cells', [])])
|
||||
|
||||
@@ -47,7 +47,7 @@ class NUMATopologyFilter(filters.BaseHostFilter):
|
||||
if not instance_topology:
|
||||
return False
|
||||
host_state.limits['numa_topology'] = limits.to_json()
|
||||
instance['numa_topology'] = instance_topology.to_json()
|
||||
instance['numa_topology'] = instance_topology
|
||||
return True
|
||||
elif requested_topology:
|
||||
return False
|
||||
|
||||
@@ -2357,7 +2357,7 @@ class ServersControllerCreateTest(test.TestCase):
|
||||
self._check_admin_pass_missing(server)
|
||||
self.assertEqual(FAKE_UUID, server['id'])
|
||||
|
||||
@mock.patch('nova.virt.hardware.VirtNUMAInstanceTopology.get_constraints')
|
||||
@mock.patch('nova.virt.hardware.numa_get_constraints')
|
||||
def test_create_instance_numa_topology_wrong(self, numa_constraints_mock):
|
||||
numa_constraints_mock.side_effect = (
|
||||
exception.ImageNUMATopologyIncomplete)
|
||||
|
||||
@@ -73,7 +73,7 @@ class ClaimTestCase(test.NoDBTestCase):
|
||||
'id': 1, 'created_at': None, 'updated_at': None,
|
||||
'deleted_at': None, 'deleted': None,
|
||||
'instance_uuid': instance['uuid'],
|
||||
'numa_topology': numa_topology.to_json()
|
||||
'numa_topology': numa_topology._to_json()
|
||||
}
|
||||
else:
|
||||
db_numa_topology = None
|
||||
@@ -234,15 +234,15 @@ class ClaimTestCase(test.NoDBTestCase):
|
||||
self.assertFalse(self.tracker.ext_resources_handler.usage_is_itype)
|
||||
|
||||
def test_numa_topology_no_limit(self, mock_get):
|
||||
huge_instance = hardware.VirtNUMAInstanceTopology(
|
||||
cells=[hardware.VirtNUMATopologyCellInstance(
|
||||
1, set([1, 2]), 512)])
|
||||
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_fails(self, mock_get):
|
||||
huge_instance = hardware.VirtNUMAInstanceTopology(
|
||||
cells=[hardware.VirtNUMATopologyCellInstance(
|
||||
1, set([1, 2, 3, 4, 5]), 2048)])
|
||||
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),
|
||||
@@ -254,9 +254,9 @@ class ClaimTestCase(test.NoDBTestCase):
|
||||
numa_topology=huge_instance)
|
||||
|
||||
def test_numa_topology_passes(self, mock_get):
|
||||
huge_instance = hardware.VirtNUMAInstanceTopology(
|
||||
cells=[hardware.VirtNUMATopologyCellInstance(
|
||||
1, set([1, 2]), 512)])
|
||||
huge_instance = objects.InstanceNUMATopology(
|
||||
cells=[objects.InstanceNUMACell(
|
||||
id=1, cpuset=set([1, 2]), memory=512)])
|
||||
limit_topo = hardware.VirtNUMALimitTopology(
|
||||
cells=[hardware.VirtNUMATopologyCellLimit(
|
||||
1, [1, 2], 512, cpu_limit=5, memory_limit=4096),
|
||||
@@ -292,8 +292,8 @@ class ResizeClaimTestCase(ClaimTestCase):
|
||||
numa_constraint = kwargs.pop('numa_topology', None)
|
||||
if overhead is None:
|
||||
overhead = {'memory_mb': 0}
|
||||
with mock.patch.object(
|
||||
hardware.VirtNUMAInstanceTopology, 'get_constraints',
|
||||
with mock.patch(
|
||||
'nova.virt.hardware.numa_get_constraints',
|
||||
return_value=numa_constraint):
|
||||
return claims.ResizeClaim('context', self.instance, instance_type,
|
||||
{}, self.tracker, self.resources,
|
||||
|
||||
@@ -7312,7 +7312,7 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
self.compute_api.create(self.context, inst_type,
|
||||
self.fake_image['id'])
|
||||
|
||||
@mock.patch('nova.virt.hardware.VirtNUMAInstanceTopology.get_constraints')
|
||||
@mock.patch('nova.virt.hardware.numa_get_constraints')
|
||||
def test_create_with_numa_topology(self, numa_constraints_mock):
|
||||
inst_type = flavors.get_default_flavor()
|
||||
# This is what the stubbed out method will return
|
||||
@@ -7320,19 +7320,24 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
'ramdisk_id': 'fake_ramdisk_id',
|
||||
'something_else': 'meow'}
|
||||
|
||||
numa_topology = hardware.VirtNUMAInstanceTopology(
|
||||
cells=[hardware.VirtNUMATopologyCellInstance(0, set([1, 2]), 512),
|
||||
hardware.VirtNUMATopologyCellInstance(1, set([3, 4]), 512)])
|
||||
numa_topology = objects.InstanceNUMATopology(
|
||||
cells=[objects.InstanceNUMACell(
|
||||
id=0, cpuset=set([1, 2]), memory=512),
|
||||
objects.InstanceNUMACell(
|
||||
id=1, cpuset=set([3, 4]), memory=512)])
|
||||
numa_constraints_mock.return_value = numa_topology
|
||||
|
||||
instances, resv_id = self.compute_api.create(self.context, inst_type,
|
||||
self.fake_image['id'])
|
||||
|
||||
numa_constraints_mock.assert_called_once_with(
|
||||
inst_type, fake_image_props)
|
||||
self.assertThat(numa_topology._to_dict(),
|
||||
matchers.DictMatches(
|
||||
instances[0].numa_topology
|
||||
.topology_from_obj()._to_dict()))
|
||||
inst_type, fake_image_props)
|
||||
self.assertEqual(
|
||||
numa_topology.cells[0].obj_to_primitive(),
|
||||
instances[0].numa_topology.cells[0].obj_to_primitive())
|
||||
self.assertEqual(
|
||||
numa_topology.cells[1].obj_to_primitive(),
|
||||
instances[0].numa_topology.cells[1].obj_to_primitive())
|
||||
|
||||
def test_create_instance_defaults_display_name(self):
|
||||
# Verify that an instance cannot be created without a display_name.
|
||||
|
||||
@@ -292,7 +292,7 @@ class BaseTestCase(test.TestCase):
|
||||
|
||||
numa_topology = kwargs.pop('numa_topology', None)
|
||||
if numa_topology:
|
||||
extra['numa_topology'] = numa_topology.to_json()
|
||||
extra['numa_topology'] = numa_topology._to_json()
|
||||
|
||||
instance.update(kwargs)
|
||||
instance['extra'] = extra
|
||||
@@ -719,9 +719,11 @@ class TrackerExtraResourcesTestCase(BaseTrackerTestCase):
|
||||
class InstanceClaimTestCase(BaseTrackerTestCase):
|
||||
def _instance_topology(self, mem):
|
||||
mem = mem * 1024
|
||||
return hardware.VirtNUMAInstanceTopology(
|
||||
cells=[hardware.VirtNUMATopologyCellInstance(0, set([1]), mem),
|
||||
hardware.VirtNUMATopologyCellInstance(1, set([3]), mem)])
|
||||
return objects.InstanceNUMATopology(
|
||||
cells=[objects.InstanceNUMACell(
|
||||
id=0, cpuset=set([1]), memory=mem),
|
||||
objects.InstanceNUMACell(
|
||||
id=1, cpuset=set([3]), memory=mem)])
|
||||
|
||||
def _claim_topology(self, mem, cpus=1):
|
||||
if self.tracker.driver.numa_topology is None:
|
||||
|
||||
@@ -13,22 +13,24 @@
|
||||
import uuid
|
||||
|
||||
import mock
|
||||
from oslo.serialization import jsonutils
|
||||
|
||||
from nova import exception
|
||||
from nova import objects
|
||||
from nova.tests.unit.objects import test_objects
|
||||
from nova.virt import hardware
|
||||
|
||||
fake_instance_uuid = str(uuid.uuid4())
|
||||
fake_numa_topology = hardware.VirtNUMAInstanceTopology(
|
||||
cells=[hardware.VirtNUMATopologyCellInstance(
|
||||
0, set([1, 2]), 512, 2048),
|
||||
hardware.VirtNUMATopologyCellInstance(
|
||||
1, set([3, 4]), 512, 2048)])
|
||||
|
||||
fake_obj_numa_topology = objects.InstanceNUMATopology.obj_from_topology(
|
||||
fake_numa_topology)
|
||||
fake_obj_numa_topology.instance_uuid = fake_instance_uuid
|
||||
fake_obj_numa_topology = objects.InstanceNUMATopology(
|
||||
instance_uuid = fake_instance_uuid,
|
||||
cells=[
|
||||
objects.InstanceNUMACell(
|
||||
id=0, cpuset=set([1, 2]), memory=512, pagesize=2048),
|
||||
objects.InstanceNUMACell(
|
||||
id=1, cpuset=set([3, 4]), memory=512, pagesize=2048)
|
||||
])
|
||||
|
||||
fake_numa_topology = fake_obj_numa_topology._to_dict()
|
||||
|
||||
fake_db_topology = {
|
||||
'created_at': None,
|
||||
@@ -41,22 +43,20 @@ fake_db_topology = {
|
||||
}
|
||||
|
||||
fake_old_db_topology = dict(fake_db_topology) # copy
|
||||
fake_old_db_topology['numa_topology'] = fake_numa_topology.to_json()
|
||||
fake_old_db_topology['numa_topology'] = jsonutils.dumps(fake_numa_topology)
|
||||
|
||||
|
||||
class _TestInstanceNUMATopology(object):
|
||||
@mock.patch('nova.db.instance_extra_update_by_uuid')
|
||||
def test_create(self, mock_update):
|
||||
topo_obj = objects.InstanceNUMATopology.obj_from_topology(
|
||||
fake_numa_topology)
|
||||
topo_obj = fake_obj_numa_topology
|
||||
topo_obj.instance_uuid = fake_db_topology['instance_uuid']
|
||||
topo_obj.create(self.context)
|
||||
self.assertEqual(1, len(mock_update.call_args_list))
|
||||
|
||||
@mock.patch('nova.db.instance_extra_update_by_uuid')
|
||||
def test_save(self, mock_update):
|
||||
topo_obj = objects.InstanceNUMATopology.obj_from_topology(
|
||||
fake_numa_topology)
|
||||
topo_obj = fake_obj_numa_topology
|
||||
topo_obj.instance_uuid = fake_db_topology['instance_uuid']
|
||||
topo_obj._save(self.context)
|
||||
self.assertEqual(1, len(mock_update.call_args_list))
|
||||
@@ -67,8 +67,9 @@ class _TestInstanceNUMATopology(object):
|
||||
self.assertEqual(fake_db_topology['instance_uuid'],
|
||||
numa_topology.instance_uuid)
|
||||
for obj_cell, topo_cell in zip(
|
||||
numa_topology.cells, fake_numa_topology.cells):
|
||||
numa_topology.cells, fake_obj_numa_topology['cells']):
|
||||
self.assertIsInstance(obj_cell, objects.InstanceNUMACell)
|
||||
self.assertEqual(topo_cell.id, obj_cell.id)
|
||||
self.assertEqual(topo_cell.cpuset, obj_cell.cpuset)
|
||||
self.assertEqual(topo_cell.memory, obj_cell.memory)
|
||||
self.assertEqual(topo_cell.pagesize, obj_cell.pagesize)
|
||||
|
||||
@@ -29,13 +29,12 @@ class TestNUMATopologyFilter(test.NoDBTestCase):
|
||||
self.filt_cls = numa_topology_filter.NUMATopologyFilter()
|
||||
|
||||
def test_numa_topology_filter_pass(self):
|
||||
instance_topology = hardware.VirtNUMAInstanceTopology(
|
||||
cells=[hardware.VirtNUMATopologyCellInstance(0, set([1]), 512),
|
||||
hardware.VirtNUMATopologyCellInstance(1, set([3]), 512)])
|
||||
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 = (
|
||||
objects.InstanceNUMATopology.obj_from_topology(
|
||||
instance_topology))
|
||||
instance.numa_topology = instance_topology
|
||||
filter_properties = {
|
||||
'request_spec': {
|
||||
'instance_properties': jsonutils.to_primitive(
|
||||
@@ -45,13 +44,12 @@ class TestNUMATopologyFilter(test.NoDBTestCase):
|
||||
self.assertTrue(self.filt_cls.host_passes(host, filter_properties))
|
||||
|
||||
def test_numa_topology_filter_numa_instance_no_numa_host_fail(self):
|
||||
instance_topology = hardware.VirtNUMAInstanceTopology(
|
||||
cells=[hardware.VirtNUMATopologyCellInstance(0, set([1]), 512),
|
||||
hardware.VirtNUMATopologyCellInstance(1, set([3]), 512)])
|
||||
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 = (
|
||||
objects.InstanceNUMATopology.obj_from_topology(
|
||||
instance_topology))
|
||||
instance.numa_topology = instance_topology
|
||||
|
||||
filter_properties = {
|
||||
'request_spec': {
|
||||
@@ -72,14 +70,13 @@ class TestNUMATopologyFilter(test.NoDBTestCase):
|
||||
self.assertTrue(self.filt_cls.host_passes(host, filter_properties))
|
||||
|
||||
def test_numa_topology_filter_fail_fit(self):
|
||||
instance_topology = hardware.VirtNUMAInstanceTopology(
|
||||
cells=[hardware.VirtNUMATopologyCellInstance(0, set([1]), 512),
|
||||
hardware.VirtNUMATopologyCellInstance(1, set([2]), 512),
|
||||
hardware.VirtNUMATopologyCellInstance(2, set([3]), 512)])
|
||||
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)
|
||||
])
|
||||
instance = fake_instance.fake_instance_obj(mock.sentinel.ctx)
|
||||
instance.numa_topology = (
|
||||
objects.InstanceNUMATopology.obj_from_topology(
|
||||
instance_topology))
|
||||
instance.numa_topology = instance_topology
|
||||
filter_properties = {
|
||||
'request_spec': {
|
||||
'instance_properties': jsonutils.to_primitive(
|
||||
@@ -91,13 +88,13 @@ class TestNUMATopologyFilter(test.NoDBTestCase):
|
||||
def test_numa_topology_filter_fail_memory(self):
|
||||
self.flags(ram_allocation_ratio=1)
|
||||
|
||||
instance_topology = hardware.VirtNUMAInstanceTopology(
|
||||
cells=[hardware.VirtNUMATopologyCellInstance(0, set([1]), 1024),
|
||||
hardware.VirtNUMATopologyCellInstance(1, set([3]), 512)])
|
||||
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 = (
|
||||
objects.InstanceNUMATopology.obj_from_topology(
|
||||
instance_topology))
|
||||
instance.numa_topology = instance_topology
|
||||
filter_properties = {
|
||||
'request_spec': {
|
||||
'instance_properties': jsonutils.to_primitive(
|
||||
@@ -109,14 +106,12 @@ class TestNUMATopologyFilter(test.NoDBTestCase):
|
||||
def test_numa_topology_filter_fail_cpu(self):
|
||||
self.flags(cpu_allocation_ratio=1)
|
||||
|
||||
instance_topology = hardware.VirtNUMAInstanceTopology(
|
||||
cells=[hardware.VirtNUMATopologyCellInstance(0, set([1]), 512),
|
||||
hardware.VirtNUMATopologyCellInstance(
|
||||
1, set([3, 4, 5]), 512)])
|
||||
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)])
|
||||
instance = fake_instance.fake_instance_obj(mock.sentinel.ctx)
|
||||
instance.numa_topology = (
|
||||
objects.InstanceNUMATopology.obj_from_topology(
|
||||
instance_topology))
|
||||
instance.numa_topology = instance_topology
|
||||
filter_properties = {
|
||||
'request_spec': {
|
||||
'instance_properties': jsonutils.to_primitive(
|
||||
@@ -129,13 +124,12 @@ class TestNUMATopologyFilter(test.NoDBTestCase):
|
||||
self.flags(cpu_allocation_ratio=21)
|
||||
self.flags(ram_allocation_ratio=1.3)
|
||||
|
||||
instance_topology = hardware.VirtNUMAInstanceTopology(
|
||||
cells=[hardware.VirtNUMATopologyCellInstance(0, set([1]), 512),
|
||||
hardware.VirtNUMATopologyCellInstance(1, set([3]), 512)])
|
||||
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 = (
|
||||
objects.InstanceNUMATopology.obj_from_topology(
|
||||
instance_topology))
|
||||
instance.numa_topology = instance_topology
|
||||
filter_properties = {
|
||||
'request_spec': {
|
||||
'instance_properties': jsonutils.to_primitive(
|
||||
|
||||
@@ -1334,12 +1334,11 @@ class LibvirtConnTestCase(test.NoDBTestCase):
|
||||
|
||||
@mock.patch.object(objects.Flavor, 'get_by_id')
|
||||
def test_get_guest_config_non_numa_host_instance_topo(self, mock_flavor):
|
||||
instance_topology = objects.InstanceNUMATopology.obj_from_topology(
|
||||
hardware.VirtNUMAInstanceTopology(
|
||||
cells=[hardware.VirtNUMATopologyCellInstance(
|
||||
0, set([0]), 1024),
|
||||
hardware.VirtNUMATopologyCellInstance(
|
||||
1, set([2]), 1024)]))
|
||||
instance_topology = objects.InstanceNUMATopology(
|
||||
cells=[objects.InstanceNUMACell(
|
||||
id=0, cpuset=set([0]), memory=1024),
|
||||
objects.InstanceNUMACell(
|
||||
id=1, cpuset=set([2]), memory=1024)])
|
||||
instance_ref = objects.Instance(**self.test_instance)
|
||||
instance_ref.numa_topology = instance_topology
|
||||
flavor = objects.Flavor(memory_mb=2048, vcpus=2, root_gb=496,
|
||||
@@ -1378,13 +1377,11 @@ class LibvirtConnTestCase(test.NoDBTestCase):
|
||||
|
||||
@mock.patch.object(objects.Flavor, 'get_by_id')
|
||||
def test_get_guest_config_numa_host_instance_topo(self, mock_flavor):
|
||||
instance_topology = objects.InstanceNUMATopology.obj_from_topology(
|
||||
hardware.VirtNUMAInstanceTopology(
|
||||
cells=[hardware.VirtNUMATopologyCellInstance(
|
||||
0, set([0, 1]), 1024),
|
||||
hardware.VirtNUMATopologyCellInstance(
|
||||
1, set([2, 3]),
|
||||
1024)]))
|
||||
instance_topology = objects.InstanceNUMATopology(
|
||||
cells=[objects.InstanceNUMACell(
|
||||
id=0, cpuset=set([0, 1]), memory=1024),
|
||||
objects.InstanceNUMACell(
|
||||
id=1, cpuset=set([2, 3]), memory=1024)])
|
||||
instance_ref = objects.Instance(**self.test_instance)
|
||||
instance_ref.numa_topology = instance_topology
|
||||
flavor = objects.Flavor(memory_mb=2048, vcpus=2, root_gb=496,
|
||||
|
||||
@@ -23,7 +23,6 @@ from nova import exception
|
||||
from nova import objects
|
||||
from nova.objects import base as base_obj
|
||||
from nova import test
|
||||
from nova.tests.unit import matchers
|
||||
from nova.virt import hardware as hw
|
||||
|
||||
|
||||
@@ -726,12 +725,12 @@ class NUMATopologyTest(test.NoDBTestCase):
|
||||
}),
|
||||
"image": {
|
||||
},
|
||||
"expect": hw.VirtNUMAInstanceTopology(
|
||||
"expect": objects.InstanceNUMATopology(cells=
|
||||
[
|
||||
hw.VirtNUMATopologyCellInstance(
|
||||
0, set([0, 1, 2, 3]), 1024),
|
||||
hw.VirtNUMATopologyCellInstance(
|
||||
1, set([4, 5, 6, 7]), 1024),
|
||||
objects.InstanceNUMACell(
|
||||
id=0, cpuset=set([0, 1, 2, 3]), memory=1024),
|
||||
objects.InstanceNUMACell(
|
||||
id=1, cpuset=set([4, 5, 6, 7]), memory=1024),
|
||||
]),
|
||||
},
|
||||
{
|
||||
@@ -756,14 +755,14 @@ class NUMATopologyTest(test.NoDBTestCase):
|
||||
}),
|
||||
"image": {
|
||||
},
|
||||
"expect": hw.VirtNUMAInstanceTopology(
|
||||
"expect": objects.InstanceNUMATopology(cells=
|
||||
[
|
||||
hw.VirtNUMATopologyCellInstance(
|
||||
0, set([0, 1, 2, 3]), 1024),
|
||||
hw.VirtNUMATopologyCellInstance(
|
||||
1, set([4, 6]), 512),
|
||||
hw.VirtNUMATopologyCellInstance(
|
||||
2, set([5, 7]), 512),
|
||||
objects.InstanceNUMACell(
|
||||
id=0, cpuset=set([0, 1, 2, 3]), memory=1024),
|
||||
objects.InstanceNUMACell(
|
||||
id=1, cpuset=set([4, 6]), memory=512),
|
||||
objects.InstanceNUMACell(
|
||||
id=2, cpuset=set([5, 7]), memory=512),
|
||||
]),
|
||||
},
|
||||
{
|
||||
@@ -874,16 +873,16 @@ class NUMATopologyTest(test.NoDBTestCase):
|
||||
|
||||
for testitem in testdata:
|
||||
if testitem["expect"] is None:
|
||||
topology = hw.VirtNUMAInstanceTopology.get_constraints(
|
||||
topology = hw.numa_get_constraints(
|
||||
testitem["flavor"], testitem["image"])
|
||||
self.assertIsNone(topology)
|
||||
elif type(testitem["expect"]) == type:
|
||||
self.assertRaises(testitem["expect"],
|
||||
hw.VirtNUMAInstanceTopology.get_constraints,
|
||||
hw.numa_get_constraints,
|
||||
testitem["flavor"],
|
||||
testitem["image"])
|
||||
else:
|
||||
topology = hw.VirtNUMAInstanceTopology.get_constraints(
|
||||
topology = hw.numa_get_constraints(
|
||||
testitem["flavor"], testitem["image"])
|
||||
self.assertEqual(len(testitem["expect"].cells),
|
||||
len(topology.cells))
|
||||
@@ -899,13 +898,13 @@ class NUMATopologyTest(test.NoDBTestCase):
|
||||
hw.VirtNUMATopologyCellUsage(1, set([4, 6]), 512),
|
||||
hw.VirtNUMATopologyCellUsage(2, set([5, 7]), 512),
|
||||
])
|
||||
instance1 = hw.VirtNUMAInstanceTopology([
|
||||
hw.VirtNUMATopologyCellInstance(0, set([0, 1, 2]), 256),
|
||||
hw.VirtNUMATopologyCellInstance(1, set([4]), 256),
|
||||
instance1 = objects.InstanceNUMATopology(cells=[
|
||||
objects.InstanceNUMACell(id=0, cpuset=set([0, 1, 2]), memory=256),
|
||||
objects.InstanceNUMACell(id=1, cpuset=set([4]), memory=256),
|
||||
])
|
||||
instance2 = hw.VirtNUMAInstanceTopology([
|
||||
hw.VirtNUMATopologyCellInstance(0, set([0, 1]), 256),
|
||||
hw.VirtNUMATopologyCellInstance(1, set([5, 7]), 256),
|
||||
instance2 = objects.InstanceNUMATopology(cells=[
|
||||
objects.InstanceNUMACell(id=0, cpuset=set([0, 1]), memory=256),
|
||||
objects.InstanceNUMACell(id=1, cpuset=set([5, 7]), memory=256),
|
||||
])
|
||||
|
||||
hostusage = hw.VirtNUMAHostTopology.usage_from_instances(
|
||||
@@ -946,13 +945,13 @@ class NUMATopologyTest(test.NoDBTestCase):
|
||||
hw.VirtNUMATopologyCellUsage(5, set([4, 6]), 512),
|
||||
hw.VirtNUMATopologyCellUsage(6, set([5, 7]), 512),
|
||||
])
|
||||
instance1 = hw.VirtNUMAInstanceTopology([
|
||||
hw.VirtNUMATopologyCellInstance(0, set([0, 1, 2]), 256),
|
||||
hw.VirtNUMATopologyCellInstance(6, set([4]), 256),
|
||||
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 = hw.VirtNUMAInstanceTopology([
|
||||
hw.VirtNUMATopologyCellInstance(0, set([0, 1]), 256),
|
||||
hw.VirtNUMATopologyCellInstance(5, set([5, 7]), 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),
|
||||
])
|
||||
|
||||
hostusage = hw.VirtNUMAHostTopology.usage_from_instances(
|
||||
@@ -999,10 +998,10 @@ class NUMATopologyTest(test.NoDBTestCase):
|
||||
1, set([4, 6]), 512, cpu_usage=1, memory_usage=512),
|
||||
hw.VirtNUMATopologyCellUsage(2, set([5, 7]), 256),
|
||||
])
|
||||
instance1 = hw.VirtNUMAInstanceTopology([
|
||||
hw.VirtNUMATopologyCellInstance(0, set([0, 1, 2]), 512),
|
||||
hw.VirtNUMATopologyCellInstance(1, set([3]), 256),
|
||||
hw.VirtNUMATopologyCellInstance(2, set([4]), 256)])
|
||||
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(
|
||||
hosttopo, [instance1])
|
||||
@@ -1038,9 +1037,9 @@ class NUMATopologyTest(test.NoDBTestCase):
|
||||
hw.VirtNUMATopologyCellUsage(0, set([0, 1]), 512),
|
||||
hw.VirtNUMATopologyCellUsage(1, set([2, 3]), 512),
|
||||
])
|
||||
instance1 = hw.VirtNUMAInstanceTopology([
|
||||
hw.VirtNUMATopologyCellInstance(0, set([0, 1]), 256),
|
||||
hw.VirtNUMATopologyCellInstance(2, set([2]), 256),
|
||||
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(
|
||||
@@ -1061,10 +1060,6 @@ class NUMATopologyTest(test.NoDBTestCase):
|
||||
self.assertEqual(hostusage.cells[1].cpu_usage, 0)
|
||||
self.assertEqual(hostusage.cells[1].memory_usage, 0)
|
||||
|
||||
def _test_to_dict(self, cell_or_topo, expected):
|
||||
got = cell_or_topo._to_dict()
|
||||
self.assertThat(expected, matchers.DictMatches(got))
|
||||
|
||||
def assertNUMACellMatches(self, expected_cell, got_cell):
|
||||
attrs = ('cpuset', 'memory', 'id')
|
||||
if isinstance(expected_cell, hw.VirtNUMAHostTopology):
|
||||
@@ -1074,104 +1069,6 @@ class NUMATopologyTest(test.NoDBTestCase):
|
||||
self.assertEqual(getattr(expected_cell, attr),
|
||||
getattr(got_cell, attr))
|
||||
|
||||
def _test_cell_from_dict(self, data_dict, expected_cell):
|
||||
cell_class = expected_cell.__class__
|
||||
got_cell = cell_class._from_dict(data_dict)
|
||||
self.assertNUMACellMatches(expected_cell, got_cell)
|
||||
|
||||
def _test_topo_from_dict(self, data_dict, expected_topo):
|
||||
got_topo = expected_topo.__class__._from_dict(
|
||||
data_dict)
|
||||
for got_cell, expected_cell in zip(
|
||||
got_topo.cells, expected_topo.cells):
|
||||
self.assertNUMACellMatches(expected_cell, got_cell)
|
||||
|
||||
def test_numa_cell_dict(self):
|
||||
cell = hw.VirtNUMATopologyCellInstance(1, set([1, 2]), 512)
|
||||
cell_dict = {'cpus': '1,2',
|
||||
'mem': {'total': 512},
|
||||
'id': 1,
|
||||
'pagesize': None}
|
||||
self._test_to_dict(cell, cell_dict)
|
||||
self._test_cell_from_dict(cell_dict, cell)
|
||||
|
||||
def test_numa_cell_pagesize_dict(self):
|
||||
cell = hw.VirtNUMATopologyCellInstance(
|
||||
1, set([1, 2]), 512, 2048)
|
||||
cell_dict = {'cpus': '1,2',
|
||||
'mem': {'total': 512},
|
||||
'id': 1,
|
||||
'pagesize': 2048}
|
||||
self._test_to_dict(cell, cell_dict)
|
||||
self._test_cell_from_dict(cell_dict, cell)
|
||||
|
||||
def test_numa_limit_cell_dict(self):
|
||||
cell = hw.VirtNUMATopologyCellLimit(1, set([1, 2]), 512, 4, 2048)
|
||||
cell_dict = {'cpus': '1,2', 'cpu_limit': 4,
|
||||
'mem': {'total': 512, 'limit': 2048},
|
||||
'id': 1}
|
||||
self._test_to_dict(cell, cell_dict)
|
||||
self._test_cell_from_dict(cell_dict, cell)
|
||||
|
||||
def test_numa_cell_usage_dict(self):
|
||||
cell = hw.VirtNUMATopologyCellUsage(1, set([1, 2]), 512)
|
||||
cell_dict = {'cpus': '1,2', 'cpu_usage': 0,
|
||||
'mem': {'total': 512, 'used': 0},
|
||||
'id': 1}
|
||||
self._test_to_dict(cell, cell_dict)
|
||||
self._test_cell_from_dict(cell_dict, cell)
|
||||
|
||||
def test_numa_instance_topo_dict(self):
|
||||
topo = hw.VirtNUMAInstanceTopology(
|
||||
cells=[
|
||||
hw.VirtNUMATopologyCellInstance(1, set([1, 2]), 1024),
|
||||
hw.VirtNUMATopologyCellInstance(2, set([3, 4]), 1024)])
|
||||
topo_dict = {'cells': [
|
||||
{'cpus': '1,2',
|
||||
'mem': {'total': 1024},
|
||||
'id': 1,
|
||||
'pagesize': None},
|
||||
{'cpus': '3,4',
|
||||
'mem': {'total': 1024},
|
||||
'id': 2,
|
||||
'pagesize': None}]}
|
||||
self._test_to_dict(topo, topo_dict)
|
||||
self._test_topo_from_dict(topo_dict, topo)
|
||||
|
||||
def test_numa_limits_topo_dict(self):
|
||||
topo = hw.VirtNUMALimitTopology(
|
||||
cells=[
|
||||
hw.VirtNUMATopologyCellLimit(
|
||||
1, set([1, 2]), 1024, 4, 2048),
|
||||
hw.VirtNUMATopologyCellLimit(
|
||||
2, set([3, 4]), 1024, 4, 2048)])
|
||||
topo_dict = {'cells': [
|
||||
{'cpus': '1,2', 'cpu_limit': 4,
|
||||
'mem': {'total': 1024, 'limit': 2048},
|
||||
'id': 1},
|
||||
{'cpus': '3,4', 'cpu_limit': 4,
|
||||
'mem': {'total': 1024, 'limit': 2048},
|
||||
'id': 2}]}
|
||||
self._test_to_dict(topo, topo_dict)
|
||||
self._test_topo_from_dict(topo_dict, topo)
|
||||
|
||||
def test_numa_topo_dict_with_usage(self):
|
||||
topo = hw.VirtNUMAHostTopology(
|
||||
cells=[
|
||||
hw.VirtNUMATopologyCellUsage(
|
||||
1, set([1, 2]), 1024),
|
||||
hw.VirtNUMATopologyCellUsage(
|
||||
2, set([3, 4]), 1024)])
|
||||
topo_dict = {'cells': [
|
||||
{'cpus': '1,2', 'cpu_usage': 0,
|
||||
'mem': {'total': 1024, 'used': 0},
|
||||
'id': 1},
|
||||
{'cpus': '3,4', 'cpu_usage': 0,
|
||||
'mem': {'total': 1024, 'used': 0},
|
||||
'id': 2}]}
|
||||
self._test_to_dict(topo, topo_dict)
|
||||
self._test_topo_from_dict(topo_dict, topo)
|
||||
|
||||
def test_json(self):
|
||||
expected = hw.VirtNUMAHostTopology(
|
||||
cells=[
|
||||
@@ -1188,10 +1085,10 @@ 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)
|
||||
instance_cell = hw.VirtNUMATopologyCellInstance(
|
||||
None, set([1, 2]), 1024)
|
||||
instance_cell = objects.InstanceNUMACell(
|
||||
id=0, cpuset=set([1, 2]), memory=1024)
|
||||
fitted_cell = host_cell.fit_instance_cell(host_cell, instance_cell)
|
||||
self.assertIsInstance(fitted_cell, hw.VirtNUMATopologyCellInstance)
|
||||
self.assertIsInstance(fitted_cell, objects.InstanceNUMACell)
|
||||
self.assertEqual(host_cell.id, fitted_cell.id)
|
||||
|
||||
def test_fit_instance_cell_success_w_limit(self):
|
||||
@@ -1201,11 +1098,11 @@ class VirtNUMATopologyCellUsageTestCase(test.NoDBTestCase):
|
||||
limit_cell = hw.VirtNUMATopologyCellLimit(
|
||||
4, set([1, 2]), 1024,
|
||||
cpu_limit=4, memory_limit=2048)
|
||||
instance_cell = hw.VirtNUMATopologyCellInstance(
|
||||
None, set([1, 2]), 1024)
|
||||
instance_cell = objects.InstanceNUMACell(
|
||||
id=0, cpuset=set([1, 2]), memory=1024)
|
||||
fitted_cell = host_cell.fit_instance_cell(
|
||||
host_cell, instance_cell, limit_cell=limit_cell)
|
||||
self.assertIsInstance(fitted_cell, hw.VirtNUMATopologyCellInstance)
|
||||
self.assertIsInstance(fitted_cell, objects.InstanceNUMACell)
|
||||
self.assertEqual(host_cell.id, fitted_cell.id)
|
||||
|
||||
def test_fit_instance_cell_self_overcommit(self):
|
||||
@@ -1213,8 +1110,8 @@ class VirtNUMATopologyCellUsageTestCase(test.NoDBTestCase):
|
||||
limit_cell = hw.VirtNUMATopologyCellLimit(
|
||||
4, set([1, 2]), 1024,
|
||||
cpu_limit=4, memory_limit=2048)
|
||||
instance_cell = hw.VirtNUMATopologyCellInstance(
|
||||
None, set([1, 2, 3]), 4096)
|
||||
instance_cell = objects.InstanceNUMACell(
|
||||
id=0, cpuset=set([1, 2, 3]), memory=4096)
|
||||
fitted_cell = host_cell.fit_instance_cell(
|
||||
host_cell, instance_cell, limit_cell=limit_cell)
|
||||
self.assertIsNone(fitted_cell)
|
||||
@@ -1226,14 +1123,14 @@ class VirtNUMATopologyCellUsageTestCase(test.NoDBTestCase):
|
||||
limit_cell = hw.VirtNUMATopologyCellLimit(
|
||||
4, set([1, 2]), 1024,
|
||||
cpu_limit=4, memory_limit=2048)
|
||||
instance_cell = hw.VirtNUMATopologyCellInstance(
|
||||
None, set([1, 2]), 4096)
|
||||
instance_cell = objects.InstanceNUMACell(
|
||||
id=0, cpuset=set([1, 2]), memory=4096)
|
||||
fitted_cell = host_cell.fit_instance_cell(
|
||||
host_cell, instance_cell, limit_cell=limit_cell)
|
||||
self.assertIsNone(fitted_cell)
|
||||
|
||||
instance_cell = hw.VirtNUMATopologyCellInstance(
|
||||
None, set([1, 2, 3, 4, 5]), 1024)
|
||||
instance_cell = objects.InstanceNUMACell(
|
||||
id=0, cpuset=set([1, 2, 3, 4, 5]), memory=1024)
|
||||
fitted_cell = host_cell.fit_instance_cell(
|
||||
host_cell, instance_cell, limit_cell=limit_cell)
|
||||
self.assertIsNone(fitted_cell)
|
||||
@@ -1261,33 +1158,33 @@ class VirtNUMAHostTopologyTestCase(test.NoDBTestCase):
|
||||
2, set([3, 4]), 2048,
|
||||
cpu_limit=4, memory_limit=3072)])
|
||||
|
||||
self.instance1 = hw.VirtNUMAInstanceTopology(
|
||||
self.instance1 = objects.InstanceNUMATopology(
|
||||
cells=[
|
||||
hw.VirtNUMATopologyCellInstance(
|
||||
None, set([1, 2]), 2048)])
|
||||
self.instance2 = hw.VirtNUMAInstanceTopology(
|
||||
objects.InstanceNUMACell(
|
||||
id=0, cpuset=set([1, 2]), memory=2048)])
|
||||
self.instance2 = objects.InstanceNUMATopology(
|
||||
cells=[
|
||||
hw.VirtNUMATopologyCellInstance(
|
||||
None, set([1, 2, 3, 4]), 1024)])
|
||||
self.instance3 = hw.VirtNUMAInstanceTopology(
|
||||
objects.InstanceNUMACell(
|
||||
id=0, cpuset=set([1, 2, 3, 4]), memory=1024)])
|
||||
self.instance3 = objects.InstanceNUMATopology(
|
||||
cells=[
|
||||
hw.VirtNUMATopologyCellInstance(
|
||||
None, set([1, 2]), 1024)])
|
||||
objects.InstanceNUMACell(
|
||||
id=0, cpuset=set([1, 2]), memory=1024)])
|
||||
|
||||
def test_get_fitting_success_no_limits(self):
|
||||
fitted_instance1 = hw.VirtNUMAHostTopology.fit_instance_to_host(
|
||||
self.host, self.instance1)
|
||||
self.assertIsInstance(fitted_instance1, hw.VirtNUMAInstanceTopology)
|
||||
self.assertIsInstance(fitted_instance1, objects.InstanceNUMATopology)
|
||||
self.host = hw.VirtNUMAHostTopology.usage_from_instances(self.host,
|
||||
[fitted_instance1])
|
||||
fitted_instance2 = hw.VirtNUMAHostTopology.fit_instance_to_host(
|
||||
self.host, self.instance3)
|
||||
self.assertIsInstance(fitted_instance2, hw.VirtNUMAInstanceTopology)
|
||||
self.assertIsInstance(fitted_instance2, objects.InstanceNUMATopology)
|
||||
|
||||
def test_get_fitting_success_limits(self):
|
||||
fitted_instance = hw.VirtNUMAHostTopology.fit_instance_to_host(
|
||||
self.host, self.instance3, self.limits)
|
||||
self.assertIsInstance(fitted_instance, hw.VirtNUMAInstanceTopology)
|
||||
self.assertIsInstance(fitted_instance, objects.InstanceNUMATopology)
|
||||
self.assertEqual(1, fitted_instance.cells[0].id)
|
||||
|
||||
def test_get_fitting_fails_no_limits(self):
|
||||
@@ -1298,7 +1195,7 @@ class VirtNUMAHostTopologyTestCase(test.NoDBTestCase):
|
||||
def test_get_fitting_culmulative_fails_limits(self):
|
||||
fitted_instance1 = hw.VirtNUMAHostTopology.fit_instance_to_host(
|
||||
self.host, self.instance1, self.limits)
|
||||
self.assertIsInstance(fitted_instance1, hw.VirtNUMAInstanceTopology)
|
||||
self.assertIsInstance(fitted_instance1, objects.InstanceNUMATopology)
|
||||
self.assertEqual(1, fitted_instance1.cells[0].id)
|
||||
self.host = hw.VirtNUMAHostTopology.usage_from_instances(self.host,
|
||||
[fitted_instance1])
|
||||
@@ -1309,13 +1206,13 @@ class VirtNUMAHostTopologyTestCase(test.NoDBTestCase):
|
||||
def test_get_fitting_culmulative_success_limits(self):
|
||||
fitted_instance1 = hw.VirtNUMAHostTopology.fit_instance_to_host(
|
||||
self.host, self.instance1, self.limits)
|
||||
self.assertIsInstance(fitted_instance1, hw.VirtNUMAInstanceTopology)
|
||||
self.assertIsInstance(fitted_instance1, objects.InstanceNUMATopology)
|
||||
self.assertEqual(1, fitted_instance1.cells[0].id)
|
||||
self.host = hw.VirtNUMAHostTopology.usage_from_instances(self.host,
|
||||
[fitted_instance1])
|
||||
fitted_instance2 = hw.VirtNUMAHostTopology.fit_instance_to_host(
|
||||
self.host, self.instance3, self.limits)
|
||||
self.assertIsInstance(fitted_instance2, hw.VirtNUMAInstanceTopology)
|
||||
self.assertIsInstance(fitted_instance2, objects.InstanceNUMATopology)
|
||||
self.assertEqual(2, fitted_instance2.cells[0].id)
|
||||
|
||||
|
||||
@@ -1370,9 +1267,13 @@ class HelperMethodsTestCase(test.NoDBTestCase):
|
||||
hw.VirtNUMATopologyCellUsage(0, set([0, 1]), 512),
|
||||
hw.VirtNUMATopologyCellUsage(1, set([2, 3]), 512),
|
||||
])
|
||||
self.instancetopo = hw.VirtNUMAInstanceTopology([
|
||||
hw.VirtNUMATopologyCellInstance(0, set([0, 1]), 256),
|
||||
hw.VirtNUMATopologyCellInstance(1, set([2]), 256),
|
||||
self.instancetopo = objects.InstanceNUMATopology(
|
||||
instance_uuid='fake-uuid',
|
||||
cells=[
|
||||
objects.InstanceNUMACell(
|
||||
id=0, cpuset=set([0, 1]), memory=256, pagesize=2048),
|
||||
objects.InstanceNUMACell(
|
||||
id=1, cpuset=set([2]), memory=256, pagesize=2048),
|
||||
])
|
||||
self.context = context.RequestContext('fake-user',
|
||||
'fake-project')
|
||||
@@ -1385,7 +1286,7 @@ class HelperMethodsTestCase(test.NoDBTestCase):
|
||||
|
||||
def test_dicts_json(self):
|
||||
host = {'numa_topology': self.hosttopo.to_json()}
|
||||
instance = {'numa_topology': self.instancetopo.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)
|
||||
@@ -1393,7 +1294,16 @@ class HelperMethodsTestCase(test.NoDBTestCase):
|
||||
|
||||
def test_dicts_instance_json(self):
|
||||
host = {'numa_topology': self.hosttopo}
|
||||
instance = {'numa_topology': self.instancetopo.to_json()}
|
||||
instance = {'numa_topology': self.instancetopo._to_json()}
|
||||
|
||||
res = hw.get_host_numa_usage_from_instance(host, instance)
|
||||
self.assertIsInstance(res, hw.VirtNUMAHostTopology)
|
||||
self._check_usage(res)
|
||||
|
||||
def test_dicts_instance_json_old(self):
|
||||
host = {'numa_topology': self.hosttopo}
|
||||
instance = {'numa_topology':
|
||||
jsonutils.dumps(self.instancetopo._to_dict())}
|
||||
|
||||
res = hw.get_host_numa_usage_from_instance(host, instance)
|
||||
self.assertIsInstance(res, hw.VirtNUMAHostTopology)
|
||||
@@ -1409,7 +1319,7 @@ class HelperMethodsTestCase(test.NoDBTestCase):
|
||||
|
||||
def test_object_host_instance_json(self):
|
||||
host = objects.ComputeNode(numa_topology=self.hosttopo.to_json())
|
||||
instance = {'numa_topology': self.instancetopo.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)
|
||||
@@ -1449,8 +1359,7 @@ class HelperMethodsTestCase(test.NoDBTestCase):
|
||||
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=objects.InstanceNUMATopology.obj_from_topology(
|
||||
self.instancetopo))
|
||||
numa_topology=self.instancetopo)
|
||||
# NOTE (ndipanov): This emulates scheduler.utils.build_request_spec
|
||||
# We can remove this test once we no longer use that method.
|
||||
instance_raw = jsonutils.to_primitive(
|
||||
@@ -1465,7 +1374,7 @@ class HelperMethodsTestCase(test.NoDBTestCase):
|
||||
obj.numa_topology = self.hosttopo.to_json()
|
||||
|
||||
host = Host()
|
||||
instance = {'numa_topology': self.instancetopo.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)
|
||||
@@ -1488,23 +1397,9 @@ class VirtMemoryPagesTestCase(test.NoDBTestCase):
|
||||
self.assertEqual(1024, pages.total)
|
||||
self.assertEqual(512, pages.used)
|
||||
|
||||
def test_virt_pages_topology_to_dict(self):
|
||||
pages = hw.VirtPagesTopology(4, 1024, 512)
|
||||
self.assertEqual({'size_kb': 4,
|
||||
'total': 1024,
|
||||
'used': 512}, pages.to_dict())
|
||||
|
||||
def test_virt_pages_topology_from_dict(self):
|
||||
pages = hw.VirtPagesTopology.from_dict({'size_kb': 4,
|
||||
'total': 1024,
|
||||
'used': 512})
|
||||
self.assertEqual(4, pages.size_kb)
|
||||
self.assertEqual(1024, pages.total)
|
||||
self.assertEqual(512, pages.used)
|
||||
|
||||
def test_cell_instance_pagesize(self):
|
||||
cell = hw.VirtNUMATopologyCellInstance(
|
||||
0, set([0]), 1024, 2048)
|
||||
cell = objects.InstanceNUMACell(
|
||||
id=0, cpuset=set([0]), memory=1024, pagesize=2048)
|
||||
|
||||
self.assertEqual(0, cell.id)
|
||||
self.assertEqual(set([0]), cell.cpuset)
|
||||
|
||||
+141
-169
@@ -609,40 +609,6 @@ class VirtNUMATopologyCell(object):
|
||||
return cls(cell_id, cpuset, memory)
|
||||
|
||||
|
||||
class VirtNUMATopologyCellInstance(VirtNUMATopologyCell):
|
||||
"""Class for reporting NUMA resources in an iinstance cell."""
|
||||
|
||||
def __init__(self, id, cpuset, memory, pagesize=None):
|
||||
"""Create a new NUMA Cell Instance
|
||||
|
||||
:param id: integer identifier of cell
|
||||
:param cpuset: set containing list of CPU indexes
|
||||
:param memory: RAM measured in Mib
|
||||
:param pagesize: measured in Kib
|
||||
|
||||
:returns: a new NUMA cell instance object
|
||||
"""
|
||||
|
||||
super(VirtNUMATopologyCellInstance, self).__init__(
|
||||
id, cpuset, memory)
|
||||
|
||||
self.pagesize = pagesize
|
||||
|
||||
def _to_dict(self):
|
||||
return {'cpus': format_cpu_spec(self.cpuset, allow_ranges=False),
|
||||
'mem': {'total': self.memory},
|
||||
'id': self.id,
|
||||
'pagesize': self.pagesize}
|
||||
|
||||
@classmethod
|
||||
def _from_dict(cls, data_dict):
|
||||
cpuset = parse_cpu_spec(data_dict.get('cpus', ''))
|
||||
memory = data_dict.get('mem', {}).get('total', 0)
|
||||
cell_id = data_dict.get('id')
|
||||
pagesize = data_dict.get('pagesize')
|
||||
return cls(cell_id, cpuset, memory, pagesize)
|
||||
|
||||
|
||||
class VirtNUMATopologyCellLimit(VirtNUMATopologyCell):
|
||||
def __init__(self, id, cpuset, memory, cpu_limit, memory_limit):
|
||||
"""Create a new NUMA Cell with usage
|
||||
@@ -729,7 +695,7 @@ class VirtNUMATopologyCellUsage(VirtNUMATopologyCell):
|
||||
: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 VirtNUMATopologyCellInstance with the id set to that of
|
||||
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
|
||||
@@ -746,9 +712,9 @@ class VirtNUMATopologyCellUsage(VirtNUMATopologyCell):
|
||||
if (memory_usage > limit_cell.memory_limit or
|
||||
cpu_usage > limit_cell.cpu_limit):
|
||||
return None
|
||||
return VirtNUMATopologyCellInstance(
|
||||
host_cell.id, instance_cell.cpuset, instance_cell.memory,
|
||||
pagesize=instance_cell.pagesize)
|
||||
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()
|
||||
@@ -809,124 +775,124 @@ class VirtNUMATopology(object):
|
||||
return cls._from_dict(jsonutils.loads(json_string))
|
||||
|
||||
|
||||
class VirtNUMAInstanceTopology(VirtNUMATopology):
|
||||
"""Class to represent the topology configured for a guest
|
||||
instance. It provides helper APIs to determine configuration
|
||||
from the metadata specified against the flavour and or
|
||||
disk image
|
||||
def _numa_get_flavor_or_image_prop(flavor, image_meta, propname):
|
||||
flavor_val = flavor.get('extra_specs', {}).get("hw:" + propname)
|
||||
image_val = image_meta.get("hw_" + propname)
|
||||
|
||||
if flavor_val is not None:
|
||||
if image_val is not None:
|
||||
raise exception.ImageNUMATopologyForbidden(
|
||||
name='hw_' + propname)
|
||||
|
||||
return flavor_val
|
||||
else:
|
||||
return image_val
|
||||
|
||||
|
||||
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 _numa_get_constraints_auto(nodes, flavor, image_meta):
|
||||
if ((flavor['vcpus'] % nodes) > 0 or
|
||||
(flavor['memory_mb'] % nodes) > 0):
|
||||
raise exception.ImageNUMATopologyAsymmetric()
|
||||
|
||||
cells = []
|
||||
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 not expecting any properties set, so
|
||||
# raise an error if there are any
|
||||
if cpus is not None or mem is not None:
|
||||
raise exception.ImageNUMATopologyIncomplete()
|
||||
|
||||
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)
|
||||
|
||||
|
||||
# TODO(sahid): Move numa related to hardward/numa.py
|
||||
def numa_get_constraints(flavor, image_meta):
|
||||
"""Return topology related to input request
|
||||
|
||||
:param flavor: Flavor object to read extra specs from
|
||||
:param image_meta: Image object to read image metadata from
|
||||
|
||||
:returns: InstanceNUMATopology or None
|
||||
"""
|
||||
nodes = _numa_get_flavor_or_image_prop(
|
||||
flavor, image_meta, "numa_nodes")
|
||||
|
||||
cell_class = VirtNUMATopologyCellInstance
|
||||
if nodes is None:
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def _get_flavor_or_image_prop(flavor, image_meta, propname):
|
||||
flavor_val = flavor.get('extra_specs', {}).get("hw:" + propname)
|
||||
image_val = image_meta.get("hw_" + propname)
|
||||
nodes = int(nodes)
|
||||
|
||||
if flavor_val is not None:
|
||||
if image_val is not None:
|
||||
raise exception.ImageNUMATopologyForbidden(
|
||||
name='hw_' + propname)
|
||||
# We'll pick what path to go down based on whether
|
||||
# anything is set for the first node. Both paths
|
||||
# have logic to cope with inconsistent property usage
|
||||
auto = _numa_get_flavor_or_image_prop(
|
||||
flavor, image_meta, "numa_cpus.0") is None
|
||||
|
||||
return flavor_val
|
||||
else:
|
||||
return image_val
|
||||
|
||||
@classmethod
|
||||
def _get_constraints_manual(cls, nodes, flavor, image_meta):
|
||||
cells = []
|
||||
totalmem = 0
|
||||
|
||||
availcpus = set(range(flavor['vcpus']))
|
||||
|
||||
for node in range(nodes):
|
||||
cpus = cls._get_flavor_or_image_prop(
|
||||
flavor, image_meta, "numa_cpus.%d" % node)
|
||||
mem = cls._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(cls.cell_class(node, cpuset, 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 cls(cells)
|
||||
|
||||
@classmethod
|
||||
def _get_constraints_auto(cls, nodes, flavor, image_meta):
|
||||
if ((flavor['vcpus'] % nodes) > 0 or
|
||||
(flavor['memory_mb'] % nodes) > 0):
|
||||
raise exception.ImageNUMATopologyAsymmetric()
|
||||
|
||||
cells = []
|
||||
for node in range(nodes):
|
||||
cpus = cls._get_flavor_or_image_prop(
|
||||
flavor, image_meta, "numa_cpus.%d" % node)
|
||||
mem = cls._get_flavor_or_image_prop(
|
||||
flavor, image_meta, "numa_mem.%d" % node)
|
||||
|
||||
# We're not expecting any properties set, so
|
||||
# raise an error if there are any
|
||||
if cpus is not None or mem is not None:
|
||||
raise exception.ImageNUMATopologyIncomplete()
|
||||
|
||||
ncpus = int(flavor['vcpus'] / nodes)
|
||||
mem = int(flavor['memory_mb'] / nodes)
|
||||
start = node * ncpus
|
||||
cpuset = set(range(start, start + ncpus))
|
||||
|
||||
cells.append(cls.cell_class(node, cpuset, mem))
|
||||
|
||||
return cls(cells)
|
||||
|
||||
@classmethod
|
||||
def get_constraints(cls, flavor, image_meta):
|
||||
nodes = cls._get_flavor_or_image_prop(
|
||||
flavor, image_meta, "numa_nodes")
|
||||
|
||||
if nodes is None:
|
||||
return None
|
||||
|
||||
nodes = int(nodes)
|
||||
|
||||
# We'll pick what path to go down based on whether
|
||||
# anything is set for the first node. Both paths
|
||||
# have logic to cope with inconsistent property usage
|
||||
auto = cls._get_flavor_or_image_prop(
|
||||
flavor, image_meta, "numa_cpus.0") is None
|
||||
|
||||
if auto:
|
||||
return cls._get_constraints_auto(
|
||||
nodes, flavor, image_meta)
|
||||
else:
|
||||
return cls._get_constraints_manual(
|
||||
nodes, flavor, image_meta)
|
||||
if auto:
|
||||
return _numa_get_constraints_auto(
|
||||
nodes, flavor, image_meta)
|
||||
else:
|
||||
return _numa_get_constraints_manual(
|
||||
nodes, flavor, image_meta)
|
||||
|
||||
|
||||
class VirtNUMALimitTopology(VirtNUMATopology):
|
||||
@@ -952,13 +918,13 @@ class VirtNUMAHostTopology(VirtNUMATopology):
|
||||
"""Fit the instance topology onto the host topology given the limits
|
||||
|
||||
:param host_topology: VirtNUMAHostTopology object to fit an instance on
|
||||
:param instance_topology: VirtNUMAInstanceTopology object to be fitted
|
||||
: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
|
||||
VirtNUMAInstanceTopology with it's cell ids set to host cell id's of
|
||||
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
|
||||
@@ -985,14 +951,14 @@ class VirtNUMAHostTopology(VirtNUMATopology):
|
||||
break
|
||||
cells.append(got_cell)
|
||||
if len(cells) == len(host_cell_perm):
|
||||
return VirtNUMAInstanceTopology(cells=cells)
|
||||
return objects.InstanceNUMATopology(cells=cells)
|
||||
|
||||
@classmethod
|
||||
def usage_from_instances(cls, host, instances, free=False):
|
||||
"""Get host topology usage
|
||||
|
||||
:param host: VirtNUMAHostTopology with usage information
|
||||
:param instances: list of VirtNUMAInstanceTopology
|
||||
: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
|
||||
@@ -1053,26 +1019,32 @@ def instance_topology_from_instance(instance):
|
||||
|
||||
if instance_numa_topology:
|
||||
if isinstance(instance_numa_topology, six.string_types):
|
||||
instance_numa_topology = VirtNUMAInstanceTopology.from_json(
|
||||
instance_numa_topology)
|
||||
instance_numa_topology = (
|
||||
objects.InstanceNUMATopology.obj_from_primitive(
|
||||
jsonutils.loads(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.
|
||||
# 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 = [VirtNUMATopologyCellInstance(cell['id'],
|
||||
set(cell['cpuset']),
|
||||
cell['memory'],
|
||||
cell.get('pagesize'))
|
||||
cells = [objects.InstanceNUMACell(
|
||||
id=cell['id'],
|
||||
cpuset=set(cell['cpuset']),
|
||||
memory=cell['memory'],
|
||||
pagesize=cell.get('pagesize'))
|
||||
for cell in dict_cells]
|
||||
instance_numa_topology = VirtNUMAInstanceTopology(cells=cells)
|
||||
instance_numa_topology = objects.InstanceNUMATopology(
|
||||
cells=cells)
|
||||
|
||||
return instance_numa_topology
|
||||
|
||||
|
||||
Reference in New Issue
Block a user