Skip to content

Commit 6d6b8b4

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "hardware: Invert order of NUMA topology generation"
2 parents bc784a1 + eedac34 commit 6d6b8b4

File tree

1 file changed

+74
-49
lines changed

1 file changed

+74
-49
lines changed

nova/virt/hardware.py

Lines changed: 74 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1575,9 +1575,20 @@ def get_cpu_thread_policy_constraint(
15751575
return policy
15761576

15771577

1578-
def _get_numa_topology_auto(nodes, flavor):
1579-
if ((flavor.vcpus % nodes) > 0 or
1580-
(flavor.memory_mb % nodes) > 0):
1578+
def _get_numa_topology_auto(
1579+
nodes: int,
1580+
flavor: 'objects.Flavor',
1581+
) -> 'objects.InstanceNUMATopology':
1582+
"""Generate a NUMA topology automatically based on CPUs and memory.
1583+
1584+
This is "automatic" because there's no user-provided per-node configuration
1585+
here - it's all auto-generated based on the number of nodes.
1586+
1587+
:param nodes: The number of nodes required in the generated topology.
1588+
:param flavor: The flavor used for the instance, from which to extract the
1589+
CPU and memory count.
1590+
"""
1591+
if (flavor.vcpus % nodes) > 0 or (flavor.memory_mb % nodes) > 0:
15811592
raise exception.ImageNUMATopologyAsymmetric()
15821593

15831594
cells = []
@@ -1593,7 +1604,23 @@ def _get_numa_topology_auto(nodes, flavor):
15931604
return objects.InstanceNUMATopology(cells=cells)
15941605

15951606

1596-
def _get_numa_topology_manual(nodes, flavor, cpu_list, mem_list):
1607+
def _get_numa_topology_manual(
1608+
nodes: int,
1609+
flavor: 'objects.Flavor',
1610+
cpu_list: ty.List[ty.Set[int]],
1611+
mem_list: ty.List[int],
1612+
) -> 'objects.InstanceNUMATopology':
1613+
"""Generate a NUMA topology based on user-provided NUMA topology hints.
1614+
1615+
:param nodes: The number of nodes required in the generated topology.
1616+
:param flavor: The flavor used for the instance, from which to extract the
1617+
CPU and memory count.
1618+
:param cpu_list: A list of sets of ints; each set in the list corresponds
1619+
to the set of guest cores to assign to NUMA node $index.
1620+
:param mem_list: A list of ints; each int corresponds to the amount of
1621+
memory to assign to NUMA node $index.
1622+
:returns: The generated instance NUMA topology.
1623+
"""
15971624
cells = []
15981625
totalmem = 0
15991626

@@ -1810,36 +1837,6 @@ def numa_get_constraints(flavor, image_meta):
18101837
and implicitly requested resources of hyperthreading traits
18111838
:returns: objects.InstanceNUMATopology, or None
18121839
"""
1813-
numa_topology = None
1814-
1815-
nodes = _get_numa_node_count_constraint(flavor, image_meta)
1816-
pagesize = _get_numa_pagesize_constraint(flavor, image_meta)
1817-
vpmems = get_vpmems(flavor)
1818-
1819-
if nodes or pagesize or vpmems:
1820-
nodes = nodes or 1
1821-
1822-
cpu_list = _get_numa_cpu_constraint(flavor, image_meta)
1823-
mem_list = _get_numa_mem_constraint(flavor, image_meta)
1824-
1825-
if cpu_list is None and mem_list is None:
1826-
numa_topology = _get_numa_topology_auto(
1827-
nodes, flavor)
1828-
elif cpu_list is not None and mem_list is not None:
1829-
# If any node has data set, all nodes must have data set
1830-
if len(cpu_list) != nodes or len(mem_list) != nodes:
1831-
raise exception.ImageNUMATopologyIncomplete()
1832-
1833-
numa_topology = _get_numa_topology_manual(
1834-
nodes, flavor, cpu_list, mem_list
1835-
)
1836-
else:
1837-
# If one property list is specified both must be
1838-
raise exception.ImageNUMATopologyIncomplete()
1839-
1840-
# We currently support same pagesize for all cells.
1841-
for c in numa_topology.cells:
1842-
setattr(c, 'pagesize', pagesize)
18431840

18441841
cpu_policy = get_cpu_policy_constraint(flavor, image_meta)
18451842
cpu_thread_policy = get_cpu_thread_policy_constraint(flavor, image_meta)
@@ -1912,23 +1909,51 @@ def numa_get_constraints(flavor, image_meta):
19121909
if rt_mask:
19131910
raise exception.RealtimeConfigurationInvalid()
19141911

1915-
return numa_topology
1912+
nodes = _get_numa_node_count_constraint(flavor, image_meta)
1913+
pagesize = _get_numa_pagesize_constraint(flavor, image_meta)
1914+
vpmems = get_vpmems(flavor)
19161915

1917-
if numa_topology:
1918-
for cell in numa_topology.cells:
1919-
cell.cpu_policy = cpu_policy
1920-
cell.cpu_thread_policy = cpu_thread_policy
1921-
else:
1922-
single_cell = objects.InstanceNUMACell(
1923-
id=0,
1924-
cpuset=set(range(flavor.vcpus)),
1925-
memory=flavor.memory_mb,
1926-
cpu_policy=cpu_policy,
1927-
cpu_thread_policy=cpu_thread_policy)
1928-
numa_topology = objects.InstanceNUMATopology(cells=[single_cell])
1929-
1930-
if emu_threads_policy:
1916+
# NOTE(stephenfin): There are currently four things that will configure a
1917+
# NUMA topology for an instance:
1918+
#
1919+
# - The user explicitly requesting one
1920+
# - The use of CPU pinning
1921+
# - The use of hugepages
1922+
# - The use of vPMEM
1923+
if nodes or pagesize or vpmems or cpu_policy in (
1924+
fields.CPUAllocationPolicy.DEDICATED,
1925+
):
1926+
nodes = nodes or 1
1927+
1928+
cpu_list = _get_numa_cpu_constraint(flavor, image_meta)
1929+
mem_list = _get_numa_mem_constraint(flavor, image_meta)
1930+
1931+
if cpu_list is None and mem_list is None:
1932+
numa_topology = _get_numa_topology_auto(nodes, flavor)
1933+
elif cpu_list is not None and mem_list is not None:
1934+
# If any node has data set, all nodes must have data set
1935+
if len(cpu_list) != nodes or len(mem_list) != nodes:
1936+
raise exception.ImageNUMATopologyIncomplete()
1937+
1938+
numa_topology = _get_numa_topology_manual(
1939+
nodes, flavor, cpu_list, mem_list
1940+
)
1941+
else:
1942+
# If one property list is specified both must be
1943+
raise exception.ImageNUMATopologyIncomplete()
1944+
1945+
# We currently support the same pagesize, CPU policy and CPU thread
1946+
# policy for all cells, but these are still stored on a per-cell
1947+
# basis :(
1948+
for c in numa_topology.cells:
1949+
setattr(c, 'pagesize', pagesize)
1950+
setattr(c, 'cpu_policy', cpu_policy)
1951+
setattr(c, 'cpu_thread_policy', cpu_thread_policy)
1952+
1953+
# ...but emulator threads policy is not \o/
19311954
numa_topology.emulator_threads_policy = emu_threads_policy
1955+
else:
1956+
numa_topology = None
19321957

19331958
return numa_topology
19341959

0 commit comments

Comments
 (0)