hardware: fix memory check usage for small/large pages

When huge pages are requested, we need to examine the host cell's
specific huge page amounts, not the amount of physical memory
associated with the host NUMA node.

Also when no pagesize is requested we should consider to compute
memory usage based on small pages since the amount of physical memory
available may also include some large pages.

The unit-tests has been updated to pass correct NUMACell mempages
information since the check is not done based on the pages available
on host. Also that the test 'test_host_usage_contiguous' to reflect to
correct update of pages availalbes on hist based on instance usage.

Closes-bug: #1734204
Change-Id: I5f5c621f2f0fa1bc18ee9a97d17085107a5dee53
Signed-off-by: Sahid Orentino Ferdjaoui <sahid.ferdjaoui@redhat.com>
(cherry picked from commit 8241deee19)
This commit is contained in:
Sahid Orentino Ferdjaoui
2018-01-09 06:46:03 -05:00
committed by sahid
parent 43f6f7479c
commit 5e69018038
3 changed files with 236 additions and 106 deletions

View File

@@ -1017,14 +1017,52 @@ def _numa_fit_instance_cell(host_cell, instance_cell, limit_cell=None,
"""
LOG.debug('Attempting to fit instance cell %(cell)s on host_cell '
'%(host_cell)s', {'cell': instance_cell, 'host_cell': host_cell})
# NOTE (ndipanov): do not allow an instance to overcommit against
# itself on any NUMA cell
if instance_cell.memory > host_cell.memory:
LOG.debug('Not enough host cell memory to fit instance cell. '
'Required: %(required)d, actual: %(actual)d',
{'required': instance_cell.memory,
'actual': host_cell.memory})
return
if 'pagesize' in instance_cell and instance_cell.pagesize:
# The instance has requested a page size. Verify that the requested
# size is valid and that there are available pages of that size on the
# host.
pagesize = _numa_cell_supports_pagesize_request(
host_cell, instance_cell)
if not pagesize:
LOG.debug('Host does not support requested memory pagesize. '
'Requested: %d kB', instance_cell.pagesize)
return
LOG.debug('Selected memory pagesize: %(selected_mem_pagesize)d kB. '
'Requested memory pagesize: %(requested_mem_pagesize)d '
'(small = -1, large = -2, any = -3)',
{'selected_mem_pagesize': pagesize,
'requested_mem_pagesize': instance_cell.pagesize})
instance_cell.pagesize = pagesize
else:
# The instance provides a NUMA topology but does not define any
# particular page size for its memory.
if host_cell.mempages:
# The host supports explicit page sizes. Use the smallest
# available page size.
pagesize = _get_smallest_pagesize(host_cell)
LOG.debug('No specific pagesize requested for instance, '
'selectionned pagesize: %d', pagesize)
if not host_cell.can_fit_hugepages(
pagesize, instance_cell.memory * units.Ki):
LOG.debug('Not enough available memory to schedule instance '
'with pagesize %(pagesize)d. Required: '
'%(required)s, available: %(available)s, total: '
'%(total)s.',
{'required': instance_cell.memory,
'available': host_cell.avail_memory,
'total': host_cell.memory,
'pagesize': pagesize})
return
else:
# NOTE (ndipanov): do not allow an instance to overcommit against
# itself on any NUMA cell
if instance_cell.memory > host_cell.memory:
LOG.debug('Not enough host cell memory to fit instance cell. '
'Required: %(required)d, actual: %(actual)d',
{'required': instance_cell.memory,
'actual': host_cell.memory})
return
if len(instance_cell.cpuset) + cpuset_reserved > len(host_cell.cpuset):
LOG.debug('Not enough host cell CPUs to fit instance cell. Required: '
@@ -1064,22 +1102,7 @@ def _numa_fit_instance_cell(host_cell, instance_cell, limit_cell=None,
{'usage': cpu_usage, 'limit': cpu_limit})
return
pagesize = None
if instance_cell.pagesize:
pagesize = _numa_cell_supports_pagesize_request(
host_cell, instance_cell)
if not pagesize:
LOG.debug('Host does not support requested memory pagesize. '
'Requested: %d kB', instance_cell.pagesize)
return
LOG.debug('Selected memory pagesize: %(selected_mem_pagesize)d kB. '
'Requested memory pagesize: %(requested_mem_pagesize)d '
'(small = -1, large = -2, any = -3)',
{'selected_mem_pagesize': pagesize,
'requested_mem_pagesize': instance_cell.pagesize})
instance_cell.id = host_cell.id
instance_cell.pagesize = pagesize
return instance_cell
@@ -1743,10 +1766,22 @@ def numa_get_reserved_huge_pages():
return bucket
def _get_smallest_pagesize(hostcell):
"""Returns the smallest available page size based o hostcell"""
avail_pagesize = [page.size_kb for page in hostcell.mempages]
avail_pagesize.sort()
return avail_pagesize[0]
def _numa_pagesize_usage_from_cell(hostcell, instancecell, sign):
if 'pagesize' in instancecell and instancecell.pagesize:
pagesize = instancecell.pagesize
else:
pagesize = _get_smallest_pagesize(hostcell)
topo = []
for pages in hostcell.mempages:
if pages.size_kb == instancecell.pagesize:
if pages.size_kb == pagesize:
topo.append(objects.NUMAPagesTopology(
size_kb=pages.size_kb,
total=pages.total,
@@ -1811,9 +1846,9 @@ def numa_usage_from_instances(host, instances, free=False):
# guest NUMA node 0.
cpu_usage += sign * len(instancecell.cpuset_reserved)
if instancecell.pagesize and instancecell.pagesize > 0:
newcell.mempages = _numa_pagesize_usage_from_cell(
newcell, instancecell, sign)
# Compute mempages usage
newcell.mempages = _numa_pagesize_usage_from_cell(
newcell, instancecell, sign)
if instance.cpu_pinning_requested:
pinned_cpus = set(instancecell.cpu_pinning.values())