Return HTTP400 for multi spec pci alias if PCI in Placement

PCI in Placement never supported PCI aliases with multiple specs, i.e.
when an alias name is used in multiple alias definitions. The code
raised ValueError late and without a proper error message. Now
PciInvalidAlias with a descriptive message is raised instead.

Closes-Bug: #2102038
Change-Id: Id1407a37dc5ddad22d8dbf7d589ed998ffc2804e
This commit is contained in:
Balazs Gibizer
2025-05-27 16:48:22 +02:00
committed by Dan Smith
parent ebf5aca101
commit 0bfac5c7fe
3 changed files with 48 additions and 4 deletions

View File

@@ -121,6 +121,23 @@ _ALIAS_SCHEMA = {
}
def _validate_aliases(aliases):
"""Checks the parsed aliases for common mistakes and raise easy to parse
error messages
"""
if CONF.filter_scheduler.pci_in_placement:
alias_with_multiple_specs = [
name for name, spec in aliases.items() if len(spec[1]) > 1]
if alias_with_multiple_specs:
raise exception.PciInvalidAlias(
"The PCI alias(es) %s have multiple specs but "
"[filter_scheduler]pci_in_placement is True. The PCI in "
"Placement feature only supports one spec per alias. You can "
"assign the same resource_class to multiple [pci]device_spec "
"matchers to allow using different devices for the same alias."
% ",".join(alias_with_multiple_specs))
def _get_alias_from_config() -> Alias:
"""Parse and validate PCI aliases from the nova config.
@@ -177,6 +194,7 @@ def _get_alias_from_config() -> Alias:
except Exception as exc:
raise exception.PciInvalidAlias(reason=str(exc))
_validate_aliases(aliases)
return aliases

View File

@@ -49,7 +49,11 @@ class MultipleSpecPerAliasWithPCIInPlacementTest(
flavor_id=flavor_id,
networks=[],
)
# This is bug 2102038 as nova does not handle the internal ValueError
# and therefore returns HTTP 500 instead of returning 400 Bad Request
# with a message pointing to the unsupported alias config.
self.assertEqual(500, exc.response.status_code)
self.assertEqual(400, exc.response.status_code)
self.assertIn(
"The PCI alias(es) a-vf have multiple specs but "
"[filter_scheduler]pci_in_placement is True. The PCI in Placement "
"feature only supports one spec per alias. You can assign the "
"same resource_class to multiple [pci]device_spec matchers to "
"allow using different devices for the same alias.",
exc.response.text)

View File

@@ -120,6 +120,28 @@ class PciRequestTestCase(test.NoDBTestCase):
}])
self.assertEqual(expected_result, result['QuickAssist'])
def test_get_alias_from_config_multispec_rejected_pci_in_placement(self):
_fake_alias = jsonutils.dumps({
"name": "QuickAssist",
"capability_type": "pci",
"product_id": "4444",
"vendor_id": "8086",
"device_type": "type-PCI",
})
self.flags(pci_in_placement=True, group='filter_scheduler')
self.flags(alias=[_fake_alias1, _fake_alias], group='pci')
ex = self.assertRaises(
exception.PciInvalidAlias, request._get_alias_from_config)
self.assertEqual(
"The PCI alias(es) QuickAssist have multiple specs but "
"[filter_scheduler]pci_in_placement is True. The PCI in Placement "
"feature only supports one spec per alias. You can assign the "
"same resource_class to multiple [pci]device_spec matchers to "
"allow using different devices for the same alias.",
str(ex))
def _test_get_alias_from_config_invalid(self, alias):
self.flags(alias=[alias], group='pci')
self.assertRaises(