Skip to content

Commit da6a2f7

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Reproduce bug 1995153" into stable/zed
2 parents 0ff35c5 + d9dfd0e commit da6a2f7

File tree

1 file changed

+109
-0
lines changed

1 file changed

+109
-0
lines changed
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# Copyright (C) 2023 Red Hat, Inc
2+
# All Rights Reserved.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
5+
# not use this file except in compliance with the License. You may obtain
6+
# a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
# License for the specific language governing permissions and limitations
14+
# under the License.
15+
16+
17+
import fixtures
18+
from unittest import mock
19+
20+
from oslo_serialization import jsonutils
21+
from oslo_utils import units
22+
23+
from nova.objects import fields
24+
from nova.tests.fixtures import libvirt as fakelibvirt
25+
from nova.tests.functional import integrated_helpers
26+
from nova.tests.functional.libvirt import base
27+
28+
29+
class Bug1995153RegressionTest(
30+
base.ServersTestBase,
31+
integrated_helpers.InstanceHelperMixin
32+
):
33+
34+
ADDITIONAL_FILTERS = ['NUMATopologyFilter', 'PciPassthroughFilter']
35+
36+
ALIAS_NAME = 'a1'
37+
PCI_DEVICE_SPEC = [jsonutils.dumps(
38+
{
39+
'vendor_id': fakelibvirt.PCI_VEND_ID,
40+
'product_id': fakelibvirt.PCI_PROD_ID,
41+
}
42+
)]
43+
# we set the numa_affinity policy to required to ensure strict affinity
44+
# between pci devices and the guest cpu and memory will be enforced.
45+
PCI_ALIAS = [jsonutils.dumps(
46+
{
47+
'vendor_id': fakelibvirt.PCI_VEND_ID,
48+
'product_id': fakelibvirt.PCI_PROD_ID,
49+
'name': ALIAS_NAME,
50+
'device_type': fields.PciDeviceType.STANDARD,
51+
'numa_policy': fields.PCINUMAAffinityPolicy.REQUIRED,
52+
}
53+
)]
54+
55+
def setUp(self):
56+
super(Bug1995153RegressionTest, self).setUp()
57+
self.flags(
58+
device_spec=self.PCI_DEVICE_SPEC,
59+
alias=self.PCI_ALIAS,
60+
group='pci'
61+
)
62+
host_manager = self.scheduler.manager.host_manager
63+
pci_filter_class = host_manager.filter_cls_map['PciPassthroughFilter']
64+
host_pass_mock = mock.Mock(wraps=pci_filter_class().host_passes)
65+
self.mock_filter = self.useFixture(fixtures.MockPatch(
66+
'nova.scheduler.filters.pci_passthrough_filter'
67+
'.PciPassthroughFilter.host_passes',
68+
side_effect=host_pass_mock)).mock
69+
70+
def test_socket_policy_bug_1995153(self):
71+
"""The numa_usage_from_instance_numa() method in hardware.py saves the
72+
host NUMAToplogy object with NUMACells that have no `socket` set. This
73+
was an omission in the original implementation of the `socket` PCI NUMA
74+
affinity policy. The consequence is that any code path that calls into
75+
numa_usage_from_instance_numa() will clobber the host NUMA topology in
76+
the database with a socket-less version. Booting an instance with NUMA
77+
toplogy will do that, for example. If then a second instance is booted
78+
with the `socket` PCI NUMA affinity policy, it will read the
79+
socket-less host NUMATopology from the database, and error out with a
80+
NotImplementedError. This is bug 1995153.
81+
"""
82+
host_info = fakelibvirt.HostInfo(
83+
cpu_nodes=2, cpu_sockets=1, cpu_cores=2, cpu_threads=2,
84+
kB_mem=(16 * units.Gi) // units.Ki)
85+
self.flags(cpu_dedicated_set='0-3', group='compute')
86+
pci_info = fakelibvirt.HostPCIDevicesInfo(num_pci=1, numa_node=1)
87+
88+
self.start_compute(host_info=host_info, pci_info=pci_info)
89+
90+
extra_spec = {
91+
'hw:cpu_policy': 'dedicated',
92+
'pci_passthrough:alias': '%s:1' % self.ALIAS_NAME,
93+
'hw:pci_numa_affinity_policy': 'socket'
94+
}
95+
# Boot a first instance with a guest NUMA topology to run the buggy
96+
# code in numa_usage_from_instance_numa() and save the socket-less host
97+
# NUMATopology to the database.
98+
self._create_server(
99+
flavor_id=self._create_flavor(
100+
extra_spec={'hw:cpu_policy': 'dedicated'}))
101+
102+
# FIXME(artom) Attempt to boot an instance with the `socket` PCI NUMA
103+
# affinity policy and observe the fireworks.
104+
flavor_id = self._create_flavor(extra_spec=extra_spec)
105+
server = self._create_server(flavor_id=flavor_id,
106+
expected_state='ERROR')
107+
self.assertIn('fault', server)
108+
self.assertIn('NotImplementedError', server['fault']['message'])
109+
self.assertTrue(self.mock_filter.called)

0 commit comments

Comments
 (0)