Throw exception if numa_nodes is not set to integer greater than 0
As [1] is abandoned, I used that patchset to create a new one. This patchset is freshened to the current master branch. This patch introduces InvalidNUMANodesNumber exception, which is thrown when trying to boot an instance with a flavor that has hw:numa_nodes=0 extra spec set. That means that NUMA nodes is set to 0, which is incorrect. [1]: https://review.openstack.org/#/c/190267 Change-Id: I6bd8f69e582c537a5fec40064638a8887a08cac4 Co-Authored-By: Karim Boumedhel <karimboumedhel@gmail.com> Closes-Bug: #1402709
This commit is contained in:
parent
b61cb28e98
commit
47d8aa5e7f
@ -689,6 +689,7 @@ class ServersController(wsgi.Controller):
|
||||
exception.ImageNUMATopologyCPUDuplicates,
|
||||
exception.ImageNUMATopologyCPUsUnassigned,
|
||||
exception.ImageNUMATopologyMemoryOutOfRange,
|
||||
exception.InvalidNUMANodesNumber,
|
||||
exception.InstanceGroupNotFound,
|
||||
exception.PciRequestAliasNotDefined,
|
||||
exception.SnapshotNotFound,
|
||||
|
@ -372,6 +372,11 @@ class InvalidStrTime(Invalid):
|
||||
msg_fmt = _("Invalid datetime string: %(reason)s")
|
||||
|
||||
|
||||
class InvalidNUMANodesNumber(Invalid):
|
||||
msg_fmt = _("The property 'numa_nodes' cannot be '%(nodes)s'. "
|
||||
"It must be a number greater than 0")
|
||||
|
||||
|
||||
class InvalidName(Invalid):
|
||||
msg_fmt = _("An invalid 'name' value was provided. "
|
||||
"The name must be: %(reason)s")
|
||||
|
@ -3255,6 +3255,14 @@ class ServersControllerCreateTest(test.TestCase):
|
||||
self.controller.create,
|
||||
self.req, body=self.body)
|
||||
|
||||
@mock.patch.object(compute_api.API, 'create',
|
||||
side_effect=exception.InvalidNUMANodesNumber(
|
||||
details=''))
|
||||
def test_create_instance_raise_invalid_numa_nodes(self, mock_create):
|
||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||
self.controller.create,
|
||||
self.req, body=self.body)
|
||||
|
||||
@mock.patch.object(compute_api.API, 'create',
|
||||
side_effect=exception.InvalidBDMFormat(details=''))
|
||||
def test_create_instance_raise_invalid_bdm_format(self, mock_create):
|
||||
|
@ -856,6 +856,36 @@ class NUMATopologyTest(test.NoDBTestCase):
|
||||
memory=2048, pagesize=2048)
|
||||
]),
|
||||
},
|
||||
{
|
||||
# a nodes number of zero should lead to an
|
||||
# exception
|
||||
"flavor": objects.Flavor(vcpus=8, memory_mb=2048, extra_specs={
|
||||
"hw:numa_nodes": 0
|
||||
}),
|
||||
"image": {
|
||||
},
|
||||
"expect": exception.InvalidNUMANodesNumber,
|
||||
},
|
||||
{
|
||||
# a negative nodes number should lead to an
|
||||
# exception
|
||||
"flavor": objects.Flavor(vcpus=8, memory_mb=2048, extra_specs={
|
||||
"hw:numa_nodes": -1
|
||||
}),
|
||||
"image": {
|
||||
},
|
||||
"expect": exception.InvalidNUMANodesNumber,
|
||||
},
|
||||
{
|
||||
# a nodes number not numeric should lead to an
|
||||
# exception
|
||||
"flavor": objects.Flavor(vcpus=8, memory_mb=2048, extra_specs={
|
||||
"hw:numa_nodes": 'x'
|
||||
}),
|
||||
"image": {
|
||||
},
|
||||
"expect": exception.InvalidNUMANodesNumber,
|
||||
},
|
||||
{
|
||||
# vcpus is not a multiple of nodes, so it
|
||||
# is an error to not provide cpu/mem mapping
|
||||
|
@ -1178,6 +1178,18 @@ def _add_cpu_pinning_constraint(flavor, image_meta, numa_topology):
|
||||
return numa_topology
|
||||
|
||||
|
||||
def _validate_numa_nodes(nodes):
|
||||
"""Validate NUMA nodes number
|
||||
|
||||
:param nodes: The number of NUMA nodes
|
||||
:raises: exception.InvalidNUMANodesNumber if the given
|
||||
parameter is not a number or less than 1
|
||||
"""
|
||||
if nodes is not None and (not strutils.is_int_like(nodes) or
|
||||
int(nodes) < 1):
|
||||
raise exception.InvalidNUMANodesNumber(nodes=nodes)
|
||||
|
||||
|
||||
# TODO(sahid): Move numa related to hardward/numa.py
|
||||
def numa_get_constraints(flavor, image_meta):
|
||||
"""Return topology related to input request
|
||||
@ -1189,6 +1201,8 @@ def numa_get_constraints(flavor, image_meta):
|
||||
image properties are not correctly specified, or
|
||||
exception.ImageNUMATopologyForbidden if an attempt is
|
||||
made to override flavor settings with image properties.
|
||||
exception.InvalidNUMANodesNumber if the number of NUMA
|
||||
nodes is less than 1 (or not an integer).
|
||||
|
||||
:returns: InstanceNUMATopology or None
|
||||
"""
|
||||
@ -1196,12 +1210,14 @@ def numa_get_constraints(flavor, image_meta):
|
||||
nodes = flavor.get('extra_specs', {}).get("hw:numa_nodes")
|
||||
props = image_meta.properties
|
||||
if nodes is not None:
|
||||
_validate_numa_nodes(nodes)
|
||||
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")
|
||||
_validate_numa_nodes(nodes)
|
||||
|
||||
pagesize = _numa_get_pagesize_constraints(
|
||||
flavor, image_meta)
|
||||
|
Loading…
Reference in New Issue
Block a user