virt: convert hardware module to use nova.objects.ImageMeta

Convert the APIs in the nova.virt.hardware module to expect to
receive an instance of nova.objects.ImageMeta instead of a
dict.

Update the virt drivers to convert the dict into an ImageMeta
module, as a stepping stone, until they to are converted to
use ImageMeta throughout.

Change-Id: Iac034d864cd0265759aaa7c8049fafa276763cc0
This commit is contained in:
Daniel P. Berrange 2015-06-04 13:42:25 +01:00 committed by Jay Pipes
parent 8a73c0430d
commit 36d37a670e
9 changed files with 182 additions and 179 deletions

View File

@ -851,8 +851,9 @@ class API(base.Base):
block_device.properties_root_device_name(
boot_meta.get('properties', {})))
image_meta = objects.ImageMeta.from_dict(boot_meta)
numa_topology = hardware.numa_get_constraints(
instance_type, boot_meta)
instance_type, image_meta)
system_metadata = {}

View File

@ -285,8 +285,9 @@ class MoveClaim(Claim):
@property
def numa_topology(self):
image_meta = objects.ImageMeta.from_dict(self.image_meta)
return hardware.numa_get_constraints(
self.instance_type, self.image_meta)
self.instance_type, image_meta)
def _test_pci(self):
pci_requests = objects.InstancePCIRequests.\

View File

@ -243,8 +243,11 @@ class ResourceTracker(object):
instance_type = self._get_instance_type(ctxt, instance, prefix)
if image_meta is None:
image_meta = utils.get_image_from_system_metadata(
instance['system_metadata'])
image_meta = objects.ImageMeta.from_instance(instance)
# TODO(jaypipes): Remove when image_meta is always passed
# as an objects.ImageMeta
elif not isinstance(image_meta, objects.ImageMeta):
image_meta = objects.ImageMeta.from_dict(image_meta)
if (instance_type is not None and
instance_type.id == itype['id']):
@ -661,8 +664,11 @@ class ResourceTracker(object):
migration.old_instance_type_id)
if image_meta is None:
image_meta = utils.get_image_from_system_metadata(
instance['system_metadata'])
image_meta = objects.ImageMeta.from_instance(instance)
# TODO(jaypipes): Remove when image_meta is always passed
# as an objects.ImageMeta
elif not isinstance(image_meta, objects.ImageMeta):
image_meta = objects.ImageMeta.from_dict(image_meta)
if itype:
host_topology = self.compute_node.get('numa_topology')

View File

@ -219,7 +219,7 @@ class BaseTestCase(test.TestCase):
def fake_show(meh, context, id, **kwargs):
if id:
return {'id': id, 'min_disk': None, 'min_ram': None,
return {'id': id,
'name': 'fake_name',
'status': 'active',
'properties': {'kernel_id': 'fake_kernel_id',
@ -7506,15 +7506,6 @@ class ComputeAPITestCase(BaseTestCase):
@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
fake_image_props = {'status': 'active',
'name': 'fake_name',
'min_ram': None,
'id': 1,
'min_disk': None,
'properties': {'kernel_id': 'fake_kernel_id',
'something_else': 'meow',
'ramdisk_id': 'fake_ramdisk_id'}}
numa_topology = objects.InstanceNUMATopology(
cells=[objects.InstanceNUMACell(
@ -7527,7 +7518,7 @@ class ComputeAPITestCase(BaseTestCase):
self.fake_image['id'])
numa_constraints_mock.assert_called_once_with(
inst_type, fake_image_props)
inst_type, test.MatchType(objects.ImageMeta))
self.assertEqual(
numa_topology.cells[0].obj_to_primitive(),
instances[0].numa_topology.cells[0].obj_to_primitive())

View File

@ -79,8 +79,8 @@ class _FakeImageService(object):
'deleted': False,
'status': 'active',
'is_public': True,
'container_format': None,
'disk_format': None,
'container_format': 'bare',
'disk_format': 'raw',
'size': '83594576',
'properties': {'kernel_id': CONF.null_kernel,
'ramdisk_id': CONF.null_kernel}}

View File

@ -2541,21 +2541,6 @@ class LibvirtConnTestCase(test.NoDBTestCase):
self.assertEqual("tcp", cfg.devices[3].type)
self.assertEqual("tcp", cfg.devices[4].type)
def test_get_guest_config_serial_console_invalid_img_meta(self):
self.flags(enabled=True, group='serial_console')
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
instance_ref = objects.Instance(**self.test_instance)
image_meta = {}
disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,
instance_ref,
image_meta)
image_meta = {"properties": {"hw_serial_port_count": "fail"}}
self.assertRaises(
exception.ImageSerialPortNumberInvalid,
drvr._get_guest_config, instance_ref, [], image_meta, disk_info)
@mock.patch('nova.console.serial.acquire_port')
def test_get_guest_config_serial_console_through_port_rng_exhausted(
self, acquire_port):
@ -2823,24 +2808,6 @@ class LibvirtConnTestCase(test.NoDBTestCase):
self.assertEqual(cfg.devices[6].type, "vnc")
self.assertEqual(cfg.devices[7].type, "spice")
def test_invalid_watchdog_action(self):
self.flags(virt_type='kvm', group='libvirt')
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
instance_ref = objects.Instance(**self.test_instance)
image_meta = {}
disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,
instance_ref,
image_meta)
image_meta = {"properties": {"hw_watchdog_action": "something"}}
self.assertRaises(exception.InvalidWatchdogAction,
drvr._get_guest_config,
instance_ref,
[],
image_meta,
disk_info)
def test_get_guest_config_with_watchdog_action_image_meta(self):
self.flags(virt_type='kvm', group='libvirt')
@ -2993,24 +2960,6 @@ class LibvirtConnTestCase(test.NoDBTestCase):
self.assertEqual("pause", cfg.devices[7].action)
def test_unsupported_video_driver_through_image_meta(self):
self.flags(virt_type='kvm', group='libvirt')
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
instance_ref = objects.Instance(**self.test_instance)
image_meta = {}
disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,
instance_ref,
image_meta)
image_meta = {"properties": {"hw_video_model": "something"}}
self.assertRaises(exception.InvalidVideoMode,
drvr._get_guest_config,
instance_ref,
[],
image_meta,
disk_info)
def test_get_guest_config_with_video_driver_image_meta(self):
self.flags(virt_type='kvm', group='libvirt')
@ -3762,12 +3711,6 @@ class LibvirtConnTestCase(test.NoDBTestCase):
image_meta, disk_info)
self.assertNotEqual(cfg.os_cmdline, "")
image_meta = {"properties": {"os_command_line": None}}
cfg = drvr._get_guest_config(instance_ref,
_fake_network_info(self.stubs, 1),
image_meta, disk_info)
self.assertIsNotNone(cfg.os_cmdline)
def test_get_guest_config_armv7(self):
def get_host_capabilities_stub(self):
cpu = vconfig.LibvirtConfigGuestCPU()

View File

@ -356,11 +356,11 @@ class VCPUTopologyTest(test.NoDBTestCase):
]
for topo_test in testdata:
image_meta = objects.ImageMeta.from_dict(topo_test["image"])
if type(topo_test["expect"]) == tuple:
(preferred,
maximum) = hw._get_cpu_topology_constraints(
topo_test["flavor"],
topo_test["image"])
topo_test["flavor"], image_meta)
self.assertEqual(topo_test["expect"][0], preferred.sockets)
self.assertEqual(topo_test["expect"][1], preferred.cores)
@ -372,7 +372,7 @@ class VCPUTopologyTest(test.NoDBTestCase):
self.assertRaises(topo_test["expect"],
hw._get_cpu_topology_constraints,
topo_test["flavor"],
topo_test["image"])
image_meta)
def test_possible_topologies(self):
testdata = [
@ -797,9 +797,10 @@ class VCPUTopologyTest(test.NoDBTestCase):
]
for topo_test in testdata:
image_meta = objects.ImageMeta.from_dict(topo_test["image"])
topology = hw._get_desirable_cpu_topologies(
topo_test["flavor"],
topo_test["image"],
image_meta,
topo_test["allow_threads"],
topo_test.get("numa_topology"))[0]
@ -878,6 +879,30 @@ class NUMATopologyTest(test.NoDBTestCase):
id=2, cpuset=set([5, 7]), memory=512)
]),
},
{
"flavor": objects.Flavor(vcpus=8, memory_mb=2048, extra_specs={
}),
"image": {
"properties": {
"hw_numa_nodes": 3,
"hw_numa_cpus.0": "0-3",
"hw_numa_mem.0": "1024",
"hw_numa_cpus.1": "4,6",
"hw_numa_mem.1": "512",
"hw_numa_cpus.2": "5,7",
"hw_numa_mem.2": "512",
},
},
"expect": objects.InstanceNUMATopology(cells=
[
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)
]),
},
{
# Request a CPU that is out of range
# wrt vCPU count
@ -1062,18 +1087,20 @@ class NUMATopologyTest(test.NoDBTestCase):
]
for testitem in testdata:
image_meta = objects.ImageMeta.from_dict(testitem["image"])
if testitem["expect"] is None:
topology = hw.numa_get_constraints(
testitem["flavor"], testitem["image"])
testitem["flavor"], image_meta)
self.assertIsNone(topology)
elif type(testitem["expect"]) == type:
self.assertRaises(testitem["expect"],
hw.numa_get_constraints,
testitem["flavor"],
testitem["image"])
image_meta)
else:
topology = hw.numa_get_constraints(
testitem["flavor"], testitem["image"])
testitem["flavor"], image_meta)
self.assertIsNotNone(topology)
self.assertEqual(len(testitem["expect"].cells),
len(topology.cells))
for i in range(len(topology.cells)):
@ -1480,26 +1507,21 @@ class NumberOfSerialPortsTest(test.NoDBTestCase):
def test_flavor(self):
flavor = objects.Flavor(vcpus=8, memory_mb=2048,
extra_specs={"hw:serial_port_count": 3})
num_ports = hw.get_number_of_serial_ports(flavor, None)
image_meta = objects.ImageMeta.from_dict({})
num_ports = hw.get_number_of_serial_ports(flavor, image_meta)
self.assertEqual(3, num_ports)
def test_image_meta(self):
flavor = objects.Flavor(vcpus=8, memory_mb=2048, extra_specs={})
image_meta = {"properties": {"hw_serial_port_count": 2}}
image_meta = objects.ImageMeta.from_dict(
{"properties": {"hw_serial_port_count": 2}})
num_ports = hw.get_number_of_serial_ports(flavor, image_meta)
self.assertEqual(2, num_ports)
def test_flavor_invalid_value(self):
flavor = objects.Flavor(vcpus=8, memory_mb=2048,
extra_specs={"hw:serial_port_count": 'foo'})
image_meta = {"properties": {}}
self.assertRaises(exception.ImageSerialPortNumberInvalid,
hw.get_number_of_serial_ports,
flavor, image_meta)
def test_image_meta_invalid_value(self):
flavor = objects.Flavor(vcpus=8, memory_mb=2048, extra_specs={})
image_meta = {"properties": {"hw_serial_port_count": 'bar'}}
image_meta = objects.ImageMeta.from_dict({})
self.assertRaises(exception.ImageSerialPortNumberInvalid,
hw.get_number_of_serial_ports,
flavor, image_meta)
@ -1507,14 +1529,16 @@ class NumberOfSerialPortsTest(test.NoDBTestCase):
def test_image_meta_smaller_than_flavor(self):
flavor = objects.Flavor(vcpus=8, memory_mb=2048,
extra_specs={"hw:serial_port_count": 3})
image_meta = {"properties": {"hw_serial_port_count": 2}}
image_meta = objects.ImageMeta.from_dict(
{"properties": {"hw_serial_port_count": 2}})
num_ports = hw.get_number_of_serial_ports(flavor, image_meta)
self.assertEqual(2, num_ports)
def test_flavor_smaller_than_image_meta(self):
flavor = objects.Flavor(vcpus=8, memory_mb=2048,
extra_specs={"hw:serial_port_count": 3})
image_meta = {"properties": {"hw_serial_port_count": 4}}
image_meta = objects.ImageMeta.from_dict(
{"properties": {"hw_serial_port_count": 4}})
self.assertRaises(exception.ImageSerialPortNumberExceedFlavorValue,
hw.get_number_of_serial_ports,
flavor, image_meta)
@ -1707,7 +1731,7 @@ class VirtMemoryPagesTestCase(test.NoDBTestCase):
def _test_get_requested_mempages_pagesize(self, spec=None, props=None):
flavor = objects.Flavor(vcpus=16, memory_mb=2048,
extra_specs=spec or {})
image_meta = {"properties": props or {}}
image_meta = objects.ImageMeta.from_dict({"properties": props or {}})
return hw._numa_get_pagesize_constraints(flavor, image_meta)
def test_get_requested_mempages_pagesize_from_flavor_swipe(self):

View File

@ -153,7 +153,7 @@ def get_number_of_serial_ports(flavor, image_meta):
"""Get the number of serial consoles from the flavor or image
:param flavor: Flavor object to read extra specs from
:param image_meta: Image object to read image metadata from
:param image_meta: nova.objects.ImageMeta object instance
If flavor extra specs is not set, then any image meta value is permitted.
If flavour extra specs *is* set, then this provides the default serial
@ -182,10 +182,8 @@ def get_number_of_serial_ports(flavor, image_meta):
num_ports=num_ports, property=property)
return num_ports
image_meta_prop = (image_meta or {}).get('properties', {})
flavor_num_ports = get_number(flavor.extra_specs, "hw:serial_port_count")
image_num_ports = get_number(image_meta_prop, "hw_serial_port_count")
image_num_ports = image_meta.properties.get("hw_serial_port_count", None)
if (flavor_num_ports and image_num_ports) is not None:
if image_num_ports > flavor_num_ports:
@ -254,7 +252,7 @@ def _get_cpu_topology_constraints(flavor, image_meta):
"""Get the topology constraints declared in flavor or image
:param flavor: Flavor object to read extra specs from
:param image_meta: Image object to read image metadata from
:param image_meta: nova.objects.ImageMeta object instance
Gets the topology constraints from the configuration defined
in the flavor extra specs or the image metadata. In the flavor
@ -309,12 +307,10 @@ def _get_cpu_topology_constraints(flavor, image_meta):
"threads": flvmaxthreads})
# Get any customized limits from the image
maxsockets = int(image_meta.get("properties", {})
.get("hw_cpu_max_sockets", flvmaxsockets))
maxcores = int(image_meta.get("properties", {})
.get("hw_cpu_max_cores", flvmaxcores))
maxthreads = int(image_meta.get("properties", {})
.get("hw_cpu_max_threads", flvmaxthreads))
props = image_meta.properties
maxsockets = props.get("hw_cpu_max_sockets", flvmaxsockets)
maxcores = props.get("hw_cpu_max_cores", flvmaxcores)
maxthreads = props.get("hw_cpu_max_threads", flvmaxthreads)
LOG.debug("Image limits %(sockets)d:%(cores)d:%(threads)d",
{"sockets": maxsockets,
@ -354,12 +350,9 @@ def _get_cpu_topology_constraints(flavor, image_meta):
# Finally see if the image has provided a preferred
# topology to use
sockets = int(image_meta.get("properties", {})
.get("hw_cpu_sockets", -1))
cores = int(image_meta.get("properties", {})
.get("hw_cpu_cores", -1))
threads = int(image_meta.get("properties", {})
.get("hw_cpu_threads", -1))
sockets = props.get("hw_cpu_sockets", -1)
cores = props.get("hw_cpu_cores", -1)
threads = props.get("hw_cpu_threads", -1)
LOG.debug("Image pref %(sockets)d:%(cores)d:%(threads)d",
{"sockets": sockets,
@ -550,7 +543,7 @@ def _get_desirable_cpu_topologies(flavor, image_meta, allow_threads=True,
"""Get desired CPU topologies according to settings
:param flavor: Flavor object to query extra specs from
:param image_meta: ImageMeta object to query properties from
:param image_meta: nova.objects.ImageMeta object instance
:param allow_threads: if the hypervisor supports CPU threads
:param numa_topology: InstanceNUMATopology object that may contain
additional topology constraints (such as threading
@ -610,7 +603,7 @@ def get_best_cpu_topology(flavor, image_meta, allow_threads=True,
"""Get best CPU topology according to settings
:param flavor: Flavor object to query extra specs from
:param image_meta: ImageMeta object to query properties from
:param image_meta: nova.objects.ImageMeta object instance
:param allow_threads: if the hypervisor supports CPU threads
:param numa_topology: InstanceNUMATopology object that may contain
additional topology constraints (such as threading
@ -805,32 +798,11 @@ def _numa_fit_instance_cell(host_cell, instance_cell, limit_cell=None):
return instance_cell
def _numa_get_flavor_or_image_prop(flavor, image_meta, propname):
"""Return the value of propname from flavor or image
:param flavor: a Flavor object or dict of instance type information
:param image_meta: a dict of image information
:returns: a value or None
"""
flavor_val = flavor.get('extra_specs', {}).get("hw:" + propname)
image_val = (image_meta or {}).get("properties", {}).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_pagesize_constraints(flavor, image_meta):
"""Return the requested memory page size
:param flavor: a Flavor object to read extra specs from
:param image_meta: an Image object to read meta data from
:param image_meta: nova.objects.ImageMeta object instance
:raises: MemoryPagesSizeInvalid or MemoryPageSizeForbidden
:returns: a page size requested or MEMPAGES_*
@ -854,10 +826,8 @@ def _numa_get_pagesize_constraints(flavor, image_meta):
return request
image_meta_prop = (image_meta or {}).get("properties", {})
flavor_request = flavor.get('extra_specs', {}).get("hw:mem_page_size", "")
image_request = image_meta_prop.get("hw_mem_page_size", "")
image_request = image_meta.properties.get("hw_mem_page_size", "")
if not flavor_request and image_request:
raise exception.MemoryPageSizeForbidden(
@ -880,25 +850,72 @@ def _numa_get_pagesize_constraints(flavor, image_meta):
return pagesize
def _numa_get_constraints_manual(nodes, flavor, image_meta):
def _numa_get_flavor_cpu_map_list(flavor):
hw_numa_cpus = []
hw_numa_cpus_set = False
extra_specs = flavor.get("extra_specs", {})
for cellid in range(objects.ImageMetaProps.NUMA_NODES_MAX):
cpuprop = "hw:numa_cpus.%d" % cellid
if cpuprop not in extra_specs:
break
hw_numa_cpus.append(
parse_cpu_spec(extra_specs[cpuprop]))
hw_numa_cpus_set = True
if hw_numa_cpus_set:
return hw_numa_cpus
def _numa_get_cpu_map_list(flavor, image_meta):
flavor_cpu_list = _numa_get_flavor_cpu_map_list(flavor)
image_cpu_list = image_meta.properties.get("hw_numa_cpus", None)
if flavor_cpu_list is None:
return image_cpu_list
else:
if image_cpu_list is not None:
raise exception.ImageNUMATopologyForbidden(
name='hw_numa_cpus')
return flavor_cpu_list
def _numa_get_flavor_mem_map_list(flavor):
hw_numa_mem = []
hw_numa_mem_set = False
extra_specs = flavor.get("extra_specs", {})
for cellid in range(objects.ImageMetaProps.NUMA_NODES_MAX):
memprop = "hw:numa_mem.%d" % cellid
if memprop not in extra_specs:
break
hw_numa_mem.append(int(extra_specs[memprop]))
hw_numa_mem_set = True
if hw_numa_mem_set:
return hw_numa_mem
def _numa_get_mem_map_list(flavor, image_meta):
flavor_mem_list = _numa_get_flavor_mem_map_list(flavor)
image_mem_list = image_meta.properties.get("hw_numa_mem", None)
if flavor_mem_list is None:
return image_mem_list
else:
if image_mem_list is not None:
raise exception.ImageNUMATopologyForbidden(
name='hw_numa_mem')
return flavor_mem_list
def _numa_get_constraints_manual(nodes, flavor, cpu_list, mem_list):
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)
mem = mem_list[node]
cpuset = cpu_list[node]
for cpu in cpuset:
if cpu > (flavor.vcpus - 1):
@ -927,23 +944,13 @@ def _numa_get_constraints_manual(nodes, flavor, image_meta):
return objects.InstanceNUMATopology(cells=cells)
def _numa_get_constraints_auto(nodes, flavor, image_meta):
def _numa_get_constraints_auto(nodes, flavor):
if ((flavor.vcpus % nodes) > 0 or
(flavor.memory_mb % nodes) > 0):
raise exception.ImageNUMATopologyAsymmetric()
cells = []
for node in range(nodes):
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
@ -957,7 +964,7 @@ def _numa_get_constraints_auto(nodes, flavor, image_meta):
def _add_cpu_pinning_constraint(flavor, image_meta, numa_topology):
flavor_pinning = flavor.get('extra_specs', {}).get("hw:cpu_policy")
image_pinning = image_meta.get('properties', {}).get("hw_cpu_policy")
image_pinning = image_meta.properties.get("hw_cpu_policy")
if flavor_pinning == "dedicated":
requested = True
elif flavor_pinning == "shared":
@ -991,30 +998,52 @@ 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
:param image_meta: nova.objects.ImageMeta object instance
May raise exception.ImageNUMATopologyIncomplete() if the
image properties are not correctly specified, or
exception.ImageNUMATopologyForbidden if an attempt is
made to override flavor settings with image properties.
:returns: InstanceNUMATopology or None
"""
nodes = _numa_get_flavor_or_image_prop(
flavor, image_meta, "numa_nodes")
nodes = flavor.get('extra_specs', {}).get("hw:numa_nodes")
props = image_meta.properties
if nodes is not None:
if props.obj_attr_is_set("hw_numa_nodes"):
raise exception.ImageNUMATopologyForbidden(
name='hw_numa_nodes')
nodes = int(nodes)
else:
nodes = props.get("hw_numa_nodes")
pagesize = _numa_get_pagesize_constraints(
flavor, image_meta)
numa_topology = None
if nodes or pagesize:
nodes = nodes and int(nodes) or 1
# 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
nodes = nodes or 1
if auto:
cpu_list = _numa_get_cpu_map_list(flavor, image_meta)
mem_list = _numa_get_mem_map_list(flavor, image_meta)
# If one property list is specified both must be
if ((cpu_list is None and mem_list is not None) or
(cpu_list is not None and mem_list is None)):
raise exception.ImageNUMATopologyIncomplete()
# If any node has data set, all nodes must have data set
if ((cpu_list is not None and len(cpu_list) != nodes) or
(mem_list is not None and len(mem_list) != nodes)):
raise exception.ImageNUMATopologyIncomplete()
if cpu_list is None:
numa_topology = _numa_get_constraints_auto(
nodes, flavor, image_meta)
nodes, flavor)
else:
numa_topology = _numa_get_constraints_manual(
nodes, flavor, image_meta)
nodes, flavor, cpu_list, mem_list)
# We currently support same pagesize for all cells.
[setattr(c, 'pagesize', pagesize) for c in numa_topology.cells]

View File

@ -3090,15 +3090,19 @@ class LibvirtDriver(driver.ComputeDriver):
return cpu
def _get_guest_cpu_config(self, flavor, image,
def _get_guest_cpu_config(self, flavor, image_meta,
guest_cpu_numa_config, instance_numa_topology):
cpu = self._get_guest_cpu_model_config()
if cpu is None:
return None
# TODO(jaypipes): Remove when image_meta is always passed
# as an objects.ImageMeta
if not isinstance(image_meta, objects.ImageMeta):
image_meta = objects.ImageMeta.from_dict(image_meta)
topology = hardware.get_best_cpu_topology(
flavor, image, numa_topology=instance_numa_topology)
flavor, image_meta, numa_topology=instance_numa_topology)
cpu.sockets = topology.sockets
cpu.cores = topology.cores
@ -3689,6 +3693,10 @@ class LibvirtDriver(driver.ComputeDriver):
guest_arch = libvirt_utils.get_arch(image_meta)
if CONF.serial_console.enabled:
# TODO(jaypipes): Remove when image_meta is always passed
# as an objects.ImageMeta
if not isinstance(image_meta, objects.ImageMeta):
image_meta = objects.ImageMeta.from_dict(image_meta)
num_ports = hardware.get_number_of_serial_ports(
flavor, image_meta)
for port in six.moves.range(num_ports):