Skip empty cpu pinning and hugepages
If there is no specified hugepages or CPU pinning
distributors shouldn't be called. Also changed
initialization of custom_hugepages type.
Change-Id: Iedb819b1da7dcb3877a6a94b9e7cfb93aa949a9e
Closes-Bug: #1594443
(cherry picked from commit 661ce479a6
)
This commit is contained in:
parent
7184b2229e
commit
a6434023f1
@ -464,6 +464,10 @@ class NodeAttributesValidator(base.BasicAttributesValidator):
|
||||
|
||||
@classmethod
|
||||
def _validate_cpu_pinning(cls, node, attrs):
|
||||
if not objects.NodeAttributes.is_cpu_pinning_enabled(
|
||||
node, attributes=attrs):
|
||||
return
|
||||
|
||||
pining_info = objects.NodeAttributes.node_cpu_pinning_info(node, attrs)
|
||||
|
||||
# check that we have at least one CPU for operating system
|
||||
@ -477,6 +481,28 @@ class NodeAttributesValidator(base.BasicAttributesValidator):
|
||||
|
||||
@classmethod
|
||||
def _validate_hugepages(cls, node, attrs):
|
||||
if not objects.NodeAttributes.is_hugepages_enabled(
|
||||
node, attributes=attrs):
|
||||
return
|
||||
|
||||
hugepage_sizes = set(
|
||||
objects.NodeAttributes.total_hugepages(node, attributes=attrs)
|
||||
)
|
||||
supported_hugepages = set(
|
||||
str(page)
|
||||
for page in node.meta['numa_topology']['supported_hugepages']
|
||||
)
|
||||
|
||||
if not hugepage_sizes.issubset(supported_hugepages):
|
||||
raise errors.InvalidData(
|
||||
"Node {0} doesn't support {1} Huge Page(s), supported Huge"
|
||||
" Page(s): {2}.".format(
|
||||
node.id,
|
||||
", ".join(hugepage_sizes - supported_hugepages),
|
||||
", ".join(supported_hugepages)
|
||||
)
|
||||
)
|
||||
|
||||
try:
|
||||
objects.NodeAttributes.distribute_hugepages(node, attrs)
|
||||
except ValueError as exc:
|
||||
|
@ -1095,14 +1095,16 @@ class Node(NailgunObject):
|
||||
kernel_params += ' amd_iommu=on'
|
||||
break
|
||||
|
||||
if 'hugepages' not in kernel_params:
|
||||
if ('hugepages' not in kernel_params
|
||||
and NodeAttributes.is_hugepages_enabled(instance)):
|
||||
kernel_params += NodeAttributes.hugepages_kernel_opts(instance)
|
||||
|
||||
isolated_cpus = NodeAttributes.distribute_node_cpus(
|
||||
instance)['isolated_cpus']
|
||||
if isolated_cpus and 'isolcpus' not in kernel_params:
|
||||
kernel_params += " isolcpus={0}".format(
|
||||
",".join(six.moves.map(str, isolated_cpus)))
|
||||
if NodeAttributes.is_cpu_pinning_enabled(instance):
|
||||
isolated_cpus = NodeAttributes.distribute_node_cpus(
|
||||
instance)['isolated_cpus']
|
||||
if isolated_cpus and 'isolcpus' not in kernel_params:
|
||||
kernel_params += " isolcpus={0}".format(
|
||||
",".join(six.moves.map(str, isolated_cpus)))
|
||||
|
||||
return kernel_params
|
||||
|
||||
@ -1413,14 +1415,15 @@ class NodeAttributes(object):
|
||||
|
||||
@classmethod
|
||||
def set_default_hugepages(cls, node):
|
||||
supported_hugepages = node.meta['numa_topology']['supported_hugepages']
|
||||
hugepages = cls._safe_get_hugepages(node)
|
||||
if not hugepages:
|
||||
return
|
||||
|
||||
sizes = [x[0] for x in consts.HUGE_PAGES_SIZE_MAP]
|
||||
|
||||
for attrs in six.itervalues(hugepages):
|
||||
if attrs.get('type') == 'custom_hugepages':
|
||||
attrs['value'] = dict.fromkeys(supported_hugepages, 0)
|
||||
attrs['value'] = dict.fromkeys(sizes, 0)
|
||||
|
||||
Node.update_attributes(node, {'hugepages': hugepages})
|
||||
|
||||
@ -1457,11 +1460,6 @@ class NodeAttributes(object):
|
||||
return {'total_required_cpus': total_required_cpus,
|
||||
'components': components}
|
||||
|
||||
@classmethod
|
||||
def is_nova_cpu_pinning_enabled(cls, node):
|
||||
cpu_pinning = cls._safe_get_cpu_pinning(node)
|
||||
return 'nova' in cpu_pinning and bool(cpu_pinning['nova']['value'])
|
||||
|
||||
@staticmethod
|
||||
def pages_per_numa_node(size):
|
||||
"""Convert memory size to 2 MiB pages count.
|
||||
@ -1473,7 +1471,7 @@ class NodeAttributes(object):
|
||||
return int(math.ceil(float(size) / 2))
|
||||
|
||||
@classmethod
|
||||
def total_hugepages(cls, node):
|
||||
def total_hugepages(cls, node, attributes=None):
|
||||
"""Return total hugepages for the node
|
||||
|
||||
Iterate over hugepages attributes and sum them
|
||||
@ -1490,7 +1488,9 @@ class NodeAttributes(object):
|
||||
hugepages = collections.defaultdict(int)
|
||||
numa_count = len(node.meta['numa_topology']['numa_nodes'])
|
||||
|
||||
hugepages_attributes = cls._safe_get_hugepages(node)
|
||||
hugepages_attributes = cls._safe_get_hugepages(
|
||||
node, attributes=attributes)
|
||||
|
||||
for name, attrs in six.iteritems(hugepages_attributes):
|
||||
if attrs.get('type') == 'custom_hugepages':
|
||||
value = attrs['value']
|
||||
@ -1503,6 +1503,10 @@ class NodeAttributes(object):
|
||||
hugepages[consts.DEFAULT_HUGEPAGE_SIZE] += (
|
||||
count_per_numa_node * numa_count)
|
||||
|
||||
for size in list(hugepages):
|
||||
if not hugepages[size]:
|
||||
hugepages.pop(size)
|
||||
|
||||
return hugepages
|
||||
|
||||
@classmethod
|
||||
@ -1522,15 +1526,39 @@ class NodeAttributes(object):
|
||||
return kernel_opts
|
||||
|
||||
@classmethod
|
||||
def is_nova_hugepages_enabled(cls, node):
|
||||
hugepages = cls._safe_get_hugepages(node)
|
||||
def is_hugepages_enabled(cls, node, attributes=None):
|
||||
return (
|
||||
cls.is_nova_hugepages_enabled(node, attributes=attributes)
|
||||
or cls.is_dpdk_hugepages_enabled(node, attributes=attributes)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def is_cpu_pinning_enabled(cls, node, attributes=None):
|
||||
return (
|
||||
cls.is_nova_cpu_pinning_enabled(node, attributes=attributes)
|
||||
or cls.is_dpdk_cpu_pinning_enabled(node, attributes=attributes)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def is_dpdk_cpu_pinning_enabled(cls, node, attributes=None):
|
||||
cpu_pinning = cls._safe_get_cpu_pinning(node, attributes=attributes)
|
||||
return 'dpdk' in cpu_pinning and bool(cpu_pinning['dpdk']['value'])
|
||||
|
||||
@classmethod
|
||||
def is_nova_cpu_pinning_enabled(cls, node, attributes=None):
|
||||
cpu_pinning = cls._safe_get_cpu_pinning(node, attributes=attributes)
|
||||
return 'nova' in cpu_pinning and bool(cpu_pinning['nova']['value'])
|
||||
|
||||
@classmethod
|
||||
def is_nova_hugepages_enabled(cls, node, attributes=None):
|
||||
hugepages = cls._safe_get_hugepages(node, attributes=attributes)
|
||||
return ('nova' in hugepages and
|
||||
any(six.itervalues(hugepages['nova']['value'])))
|
||||
|
||||
@classmethod
|
||||
def is_dpdk_hugepages_enabled(cls, node):
|
||||
return int(Node.get_attributes(
|
||||
node)['hugepages']['dpdk']['value']) != 0
|
||||
def is_dpdk_hugepages_enabled(cls, node, attributes=None):
|
||||
hugepages = cls._safe_get_hugepages(node, attributes=attributes)
|
||||
return 'dpdk' in hugepages and bool(hugepages['dpdk']['value'])
|
||||
|
||||
@classmethod
|
||||
def dpdk_hugepages_attrs(cls, node):
|
||||
|
@ -584,6 +584,9 @@ class DeploymentHASerializer90(DeploymentHASerializer80):
|
||||
self.generate_node_hugepages(node, serialized_node)
|
||||
|
||||
def generate_cpu_pinning(self, node, serialized_node):
|
||||
if not objects.NodeAttributes.is_cpu_pinning_enabled(node):
|
||||
return
|
||||
|
||||
pinning_info = objects.NodeAttributes.distribute_node_cpus(node)
|
||||
cpu_pinning = pinning_info['components']
|
||||
|
||||
@ -599,6 +602,8 @@ class DeploymentHASerializer90(DeploymentHASerializer80):
|
||||
serialized_node['cpu_pinning'] = cpu_pinning
|
||||
|
||||
def generate_node_hugepages(self, node, serialized_node):
|
||||
if not objects.NodeAttributes.is_hugepages_enabled(node):
|
||||
return
|
||||
self._generate_nova_hugepages(node, serialized_node)
|
||||
self._generate_dpdk_hugepages(node, serialized_node)
|
||||
self._generate_hugepages_distribution(node, serialized_node)
|
||||
|
@ -373,7 +373,7 @@ class TestDeploymentAttributesSerialization90(
|
||||
|
||||
self.assertEqual(serialized_node['dpdk']['ovs_core_mask'], '0x2')
|
||||
self.assertEqual(serialized_node['dpdk']['ovs_pmd_core_mask'], '0x4')
|
||||
self.assertNotIn('cpu_pinning', serialized_node['nova'])
|
||||
self.assertNotIn('cpu_pinning', serialized_node.get('nova', {}))
|
||||
|
||||
node_name = objects.Node.get_slave_name(node)
|
||||
network_data = serialized_for_astute['common']['network_metadata']
|
||||
|
@ -364,7 +364,7 @@ class TestTaskDeploy90(BaseIntegrationTest):
|
||||
'type': 'puppet',
|
||||
'roles': ['compute'],
|
||||
'condition': {
|
||||
'yaql_exp': 'changedAny($.network_scheme, $.dpdk)',
|
||||
'yaql_exp': 'changedAny($.network_scheme, $.get(dpdk))',
|
||||
},
|
||||
'parameters': {},
|
||||
},
|
||||
@ -374,7 +374,7 @@ class TestTaskDeploy90(BaseIntegrationTest):
|
||||
'type': 'puppet',
|
||||
'roles': ['compute'],
|
||||
'condition': {
|
||||
'yaql_exp': 'changedAny($.network_scheme, $.dpdk)',
|
||||
'yaql_exp': 'changedAny($.network_scheme, $.get(dpdk))',
|
||||
},
|
||||
'parameters': {},
|
||||
}]
|
||||
@ -453,7 +453,7 @@ class TestTaskDeploy90AfterDeployment(BaseIntegrationTest):
|
||||
.filter_by(task_name='netconfig')\
|
||||
.update({
|
||||
'condition': {
|
||||
'yaql_exp': 'changedAny($.network_scheme, $.dpdk)',
|
||||
'yaql_exp': 'changedAny($.network_scheme, $.get(dpdk))',
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -166,7 +166,7 @@ class TestNodeAttributes(base.BaseUnitTest):
|
||||
objects.NodeAttributes.distribute_hugepages(node), expected)
|
||||
|
||||
def test_set_default_hugepages(self):
|
||||
fake_hugepages = ['0', '1', '2', '3']
|
||||
hugepages = ['2048', '1048576']
|
||||
node = mock.Mock(
|
||||
id=1,
|
||||
attributes={
|
||||
@ -177,12 +177,8 @@ class TestNodeAttributes(base.BaseUnitTest):
|
||||
}
|
||||
}
|
||||
},
|
||||
meta={
|
||||
'numa_topology': {
|
||||
'supported_hugepages': fake_hugepages,
|
||||
'numa_nodes': []}}
|
||||
)
|
||||
objects.NodeAttributes.set_default_hugepages(node)
|
||||
hugepages = node.attributes['hugepages']['nova']['value']
|
||||
for size in fake_hugepages:
|
||||
self.assertEqual(0, hugepages[size])
|
||||
nova_hugepages = node.attributes['hugepages']['nova']['value']
|
||||
for size in hugepages:
|
||||
self.assertEqual(0, nova_hugepages[size])
|
||||
|
@ -146,6 +146,30 @@ class TestNodeAttributesValidatorHugepages(BaseNodeAttributeValidatorTest):
|
||||
errors.InvalidData, 'could not require more memory than node has',
|
||||
validator, json.dumps(data), self.node, self.cluster)
|
||||
|
||||
@mock_cluster_attributes
|
||||
def test_limited_supported_hugepages(self, m_dpdk_nics):
|
||||
data = {
|
||||
'hugepages': {
|
||||
'nova': {
|
||||
'value': {
|
||||
'2048': 3,
|
||||
'1048576': 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
self.node.meta['numa_topology']['supported_hugepages'] = ['2048']
|
||||
self.assertNotRaises(errors.InvalidData, validator,
|
||||
json.dumps(data), self.node, self.cluster)
|
||||
|
||||
data['hugepages']['nova']['value']['1048576'] = 1
|
||||
self.assertRaisesWithMessageIn(
|
||||
errors.InvalidData,
|
||||
"Node 1 doesn't support 1048576 Huge Page(s),"
|
||||
" supported Huge Page(s): 2048.",
|
||||
validator, json.dumps(data), self.node, self.cluster)
|
||||
|
||||
|
||||
@mock.patch.object(objects.Node, 'dpdk_nics', return_value=[])
|
||||
class TestNodeAttributesValidatorCpuPinning(BaseNodeAttributeValidatorTest):
|
||||
|
Loading…
Reference in New Issue
Block a user