Skip to content

Commit 896db4e

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Validate [pci]alias at service startup" into stable/2025.1
2 parents 84f4d13 + b5dffed commit 896db4e

6 files changed

Lines changed: 43 additions & 12 deletions

File tree

nova/api/openstack/wsgi_app.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from nova import context
2727
from nova import exception
2828
from nova import objects
29+
from nova.pci import request
2930
from nova import service
3031
from nova import utils
3132
from nova import version
@@ -51,6 +52,11 @@ def _get_config_files(env=None):
5152

5253

5354
def _setup_service(host, name):
55+
56+
# NOTE(gibi): validate the [pci]alias config early to avoid late failures
57+
# at instance creation due to config errors.
58+
request.get_alias_from_config()
59+
5460
try:
5561
utils.raise_if_old_compute()
5662
except exception.TooOldComputeService as e:

nova/compute/manager.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1615,6 +1615,10 @@ def init_host(self, service_ref):
16151615
# if the configuration is wrong.
16161616
whitelist.Whitelist(CONF.pci.device_spec)
16171617

1618+
# NOTE(gibi): validate the [pci]alias config early to avoid late
1619+
# failures at instance lifecycle operations due to config errors.
1620+
pci_req_module.get_alias_from_config()
1621+
16181622
nova.conf.neutron.register_dynamic_opts(CONF)
16191623
# Even if only libvirt uses them, make it available for all drivers
16201624
nova.conf.devices.register_dynamic_opts(CONF)

nova/pci/request.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ def _validate_aliases(aliases):
173173
_validate_required_ids(aliases)
174174

175175

176-
def _get_alias_from_config() -> Alias:
176+
def get_alias_from_config() -> Alias:
177177
"""Parse and validate PCI aliases from the nova config.
178178
179179
:returns: A dictionary where the keys are alias names and the values are
@@ -237,7 +237,7 @@ def _translate_alias_to_requests(
237237
alias_spec: str, affinity_policy: ty.Optional[str] = None,
238238
) -> ty.List['objects.InstancePCIRequest']:
239239
"""Generate complete pci requests from pci aliases in extra_spec."""
240-
pci_aliases = _get_alias_from_config()
240+
pci_aliases = get_alias_from_config()
241241

242242
pci_requests: ty.List[objects.InstancePCIRequest] = []
243243
for name, count in [spec.split(':') for spec in alias_spec.split(',')]:

nova/tests/unit/api/openstack/test_wsgi_app.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import fixtures
1717
from oslo_config import fixture as config_fixture
18+
from oslo_serialization import jsonutils
1819
from oslotest import base
1920

2021
from nova.api.openstack import wsgi_app
@@ -127,6 +128,14 @@ def test_setup_service_version_workaround(self, mock_check_old, mock_get):
127128
group='workarounds')
128129
wsgi_app._setup_service('myhost', 'api')
129130

131+
def test_setup_service_pci_alias_validation(self):
132+
wsgi_app.CONF.set_override(
133+
'alias', jsonutils.dumps({'name': 'foo'}),
134+
group='pci')
135+
self.assertRaises(
136+
exception.PciInvalidAlias,
137+
wsgi_app._setup_service, 'myhost', 'api')
138+
130139
def test__get_config_files_empty_env(self):
131140
env = {}
132141
result = wsgi_app._get_config_files(env)

nova/tests/unit/compute/test_compute_mgr.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7025,6 +7025,18 @@ def test_init_host_pci_device_spec_validation_failure(self):
70257025
self.assertRaises(exception.PciDeviceInvalidDeviceName,
70267026
self.compute.init_host, None)
70277027

7028+
def test_init_host_pci_alias_validation_failure(self):
7029+
# Tests that we fail init_host if the pci.alias is
7030+
# configured incorrectly.
7031+
self.flags(
7032+
alias=[
7033+
jsonutils.dumps({'name': 'foo'})
7034+
],
7035+
group='pci'
7036+
)
7037+
self.assertRaises(
7038+
exception.PciInvalidAlias, self.compute.init_host, None)
7039+
70287040
@mock.patch('nova.compute.manager.ComputeManager._instance_update')
70297041
def test_error_out_instance_on_exception_not_implemented_err(self,
70307042
inst_update_mock):

nova/tests/unit/pci/test_request.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def setUp(self):
8181

8282
def test_get_alias_from_config_valid(self):
8383
self.flags(alias=[_fake_alias1], group='pci')
84-
result = request._get_alias_from_config()
84+
result = request.get_alias_from_config()
8585
expected_result = (
8686
'legacy',
8787
[{
@@ -103,7 +103,7 @@ def test_get_alias_from_config_valid_multispec(self):
103103
})
104104

105105
self.flags(alias=[_fake_alias1, _fake_alias], group='pci')
106-
result = request._get_alias_from_config()
106+
result = request.get_alias_from_config()
107107
expected_result = (
108108
'legacy',
109109
[{
@@ -133,7 +133,7 @@ def test_get_alias_from_config_multispec_rejected_pci_in_placement(self):
133133
self.flags(alias=[_fake_alias1, _fake_alias], group='pci')
134134

135135
ex = self.assertRaises(
136-
exception.PciInvalidAlias, request._get_alias_from_config)
136+
exception.PciInvalidAlias, request.get_alias_from_config)
137137
self.assertEqual(
138138
"The PCI alias(es) QuickAssist have multiple specs but "
139139
"[filter_scheduler]pci_in_placement is True. The PCI in Placement "
@@ -146,7 +146,7 @@ def _test_get_alias_from_config_invalid(self, alias):
146146
self.flags(alias=[alias], group='pci')
147147
self.assertRaises(
148148
exception.PciInvalidAlias,
149-
request._get_alias_from_config)
149+
request.get_alias_from_config)
150150

151151
def test_get_alias_from_config_invalid_device_type(self):
152152
fake_alias = jsonutils.dumps({
@@ -215,7 +215,7 @@ def test_get_alias_from_config_valid_numa_policy(self):
215215
"numa_policy": policy,
216216
})
217217
self.flags(alias=[fake_alias], group='pci')
218-
aliases = request._get_alias_from_config()
218+
aliases = request.get_alias_from_config()
219219
self.assertIsNotNone(aliases)
220220
self.assertIn("xxx", aliases)
221221
self.assertEqual(policy, aliases["xxx"][0])
@@ -228,7 +228,7 @@ def test_get_alias_from_config_valid_rc_and_traits(self):
228228
})
229229
self.flags(pci_in_placement=True, group='filter_scheduler')
230230
self.flags(alias=[fake_alias], group='pci')
231-
aliases = request._get_alias_from_config()
231+
aliases = request.get_alias_from_config()
232232
self.assertIsNotNone(aliases)
233233
self.assertIn("xxx", aliases)
234234
self.assertEqual(
@@ -256,7 +256,7 @@ def test_get_alias_from_config_conflicting_device_type(self):
256256
self.flags(alias=[fake_alias_a, fake_alias_b], group='pci')
257257
self.assertRaises(
258258
exception.PciInvalidAlias,
259-
request._get_alias_from_config)
259+
request.get_alias_from_config)
260260

261261
def test_get_alias_from_config_conflicting_numa_policy(self):
262262
"""Check behavior when numa_policy conflicts occur."""
@@ -277,7 +277,7 @@ def test_get_alias_from_config_conflicting_numa_policy(self):
277277
self.flags(alias=[fake_alias_a, fake_alias_b], group='pci')
278278
self.assertRaises(
279279
exception.PciInvalidAlias,
280-
request._get_alias_from_config)
280+
request.get_alias_from_config)
281281

282282
def test_get_alias_from_config_missing_ids(self):
283283
a1 = jsonutils.dumps({
@@ -304,7 +304,7 @@ def test_get_alias_from_config_missing_ids(self):
304304
self.flags(alias=[a1, a2, a3, a4, a5], group='pci')
305305

306306
ex = self.assertRaises(
307-
exception.PciInvalidAlias, request._get_alias_from_config)
307+
exception.PciInvalidAlias, request.get_alias_from_config)
308308
self.assertEqual(
309309
"The PCI alias(es) a1,a2,a3,a4 does not have vendor_id and "
310310
"product_id fields set.",
@@ -336,7 +336,7 @@ def test_get_alias_from_config_missing_ids_or_rc_pci_in_placement(self):
336336
self.flags(alias=[a1, a2, a3, a4, a5], group='pci')
337337

338338
ex = self.assertRaises(
339-
exception.PciInvalidAlias, request._get_alias_from_config)
339+
exception.PciInvalidAlias, request.get_alias_from_config)
340340
self.assertEqual(
341341
"The PCI alias(es) a1,a2,a3 does not have vendor_id and "
342342
"product_id fields set or resource_class field set.",

0 commit comments

Comments
 (0)