Skip to content

Commit fa10c6e

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "libvirt: Register defaults for undefined hw image properties"
2 parents f9ca5db + 7ecdfb6 commit fa10c6e

File tree

4 files changed

+681
-95
lines changed

4 files changed

+681
-95
lines changed
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
2+
# not use this file except in compliance with the License. You may obtain
3+
# a copy of the License at
4+
#
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10+
# License for the specific language governing permissions and limitations
11+
# under the License.
12+
13+
import datetime
14+
from unittest import mock
15+
16+
from oslo_utils.fixture import uuidsentinel as uuids
17+
18+
from nova import context as nova_context
19+
from nova import objects
20+
from nova import test
21+
from nova.tests.functional.libvirt import base
22+
from nova.virt.libvirt import driver as libvirt_driver
23+
24+
25+
class LibvirtDeviceBusMigration(base.ServersTestBase):
26+
27+
microversion = 'latest'
28+
# needed for move operations
29+
ADMIN_API = True
30+
31+
def setUp(self):
32+
super().setUp()
33+
self.context = nova_context.get_admin_context()
34+
self.compute_hostname = self.start_compute()
35+
self.compute = self.computes[self.compute_hostname]
36+
37+
def _unset_stashed_image_properties(self, server_id, properties):
38+
instance = objects.Instance.get_by_uuid(self.context, server_id)
39+
for p in properties:
40+
instance.system_metadata.pop(f'image_{p}')
41+
instance.save()
42+
43+
def _assert_stashed_image_properties(self, server_id, properties):
44+
instance = objects.Instance.get_by_uuid(self.context, server_id)
45+
for p, value in properties.items():
46+
self.assertEqual(instance.system_metadata.get(f'image_{p}'), value)
47+
48+
def _assert_stashed_image_properties_persist(self, server, properties):
49+
# Assert the stashed properties persist across a host reboot
50+
self.restart_compute_service(self.compute)
51+
self._assert_stashed_image_properties(server['id'], properties)
52+
53+
# Assert the stashed properties persist across a guest reboot
54+
self._reboot_server(server, hard=True)
55+
self._assert_stashed_image_properties(server['id'], properties)
56+
57+
# Assert the stashed properties persist across a migration
58+
if 'other_compute' not in self.computes:
59+
self.start_compute('other_compute')
60+
# TODO(stephenfin): The mock of 'migrate_disk_and_power_off' should
61+
# probably be less...dumb
62+
with mock.patch(
63+
'nova.virt.libvirt.driver.LibvirtDriver'
64+
'.migrate_disk_and_power_off', return_value='{}',
65+
):
66+
self._migrate_server(server)
67+
self._confirm_resize(server)
68+
self._assert_stashed_image_properties(server['id'], properties)
69+
70+
def test_default_image_property_registration(self):
71+
"""Assert that the defaults for various hw image properties don't
72+
change over the lifecycle of an instance.
73+
"""
74+
default_image_properties = {
75+
'hw_machine_type': 'pc',
76+
'hw_cdrom_bus': 'ide',
77+
'hw_disk_bus': 'virtio',
78+
'hw_input_bus': 'usb',
79+
'hw_pointer_model': 'usbtablet',
80+
'hw_video_model': 'virtio',
81+
'hw_vif_model': 'virtio',
82+
}
83+
84+
server = self._create_server(networks='none')
85+
self._assert_stashed_image_properties(
86+
server['id'], default_image_properties)
87+
88+
# Unset the defaults here to ensure that init_host resets them
89+
# when the compute restarts the libvirt driver
90+
self._unset_stashed_image_properties(
91+
server['id'], libvirt_driver.REGISTER_IMAGE_PROPERTY_DEFAULTS)
92+
93+
# Assert the defaults persist across a host reboot, guest reboot, and
94+
# guest migration
95+
self._assert_stashed_image_properties_persist(
96+
server, default_image_properties)
97+
98+
def test_non_default_image_property_registration(self):
99+
"""Assert that non-default values for various hw image properties
100+
don't change over the lifecycle of an instance.
101+
"""
102+
non_default_image_properties = {
103+
'hw_machine_type': 'q35',
104+
'hw_cdrom_bus': 'sata',
105+
'hw_disk_bus': 'sata',
106+
'hw_input_bus': 'virtio',
107+
'hw_video_model': 'qxl',
108+
'hw_vif_model': 'e1000',
109+
}
110+
self.glance.create(
111+
None,
112+
{
113+
'id': uuids.hw_bus_model_image_uuid,
114+
'name': 'hw_bus_model_image',
115+
'created_at': datetime.datetime(2011, 1, 1, 1, 2, 3),
116+
'updated_at': datetime.datetime(2011, 1, 1, 1, 2, 3),
117+
'deleted_at': None,
118+
'deleted': False,
119+
'status': 'active',
120+
'is_public': False,
121+
'container_format': 'bare',
122+
'disk_format': 'qcow2',
123+
'size': '74185822',
124+
'min_ram': 0,
125+
'min_disk': 0,
126+
'protected': False,
127+
'visibility': 'public',
128+
'tags': [],
129+
'properties': non_default_image_properties,
130+
}
131+
)
132+
server = self._create_server(
133+
networks='none', image_uuid=uuids.hw_bus_model_image_uuid)
134+
self._assert_stashed_image_properties(
135+
server['id'], non_default_image_properties)
136+
137+
# Assert the non defaults persist across a host reboot, guest reboot,
138+
# and guest migration
139+
self._assert_stashed_image_properties_persist(
140+
server, non_default_image_properties)
141+
142+
def test_default_image_property_persists_across_osinfo_changes(self):
143+
# Create a server with default image properties
144+
default_image_properties = {
145+
'hw_vif_model': 'virtio',
146+
'hw_disk_bus': 'virtio',
147+
}
148+
server = self._create_server(networks='none')
149+
self._assert_stashed_image_properties(
150+
server['id'], default_image_properties)
151+
152+
with test.nested(
153+
mock.patch('nova.virt.osinfo.HardwareProperties.network_model',
154+
new=mock.PropertyMock()),
155+
mock.patch('nova.virt.osinfo.HardwareProperties.disk_model',
156+
new=mock.PropertyMock())
157+
) as (mock_nw_model, mock_disk_model):
158+
# osinfo returning new things
159+
mock_nw_model.return_value = 'e1000'
160+
mock_disk_model.return_value = 'sata'
161+
162+
# Assert the defaults persist across a host reboot, guest reboot,
163+
# and guest migration
164+
self._assert_stashed_image_properties_persist(
165+
server, default_image_properties)
166+
167+
def test_default_image_property_persists_across_host_flag_changes(self):
168+
# Set the default to ps2 via host flag
169+
self.flags(pointer_model='ps2mouse')
170+
# Restart compute to pick up ps2 setting, which means the guest will
171+
# not get a prescribed pointer device
172+
self.restart_compute_service(self.compute)
173+
174+
# Create a server with default image properties
175+
default_image_properties1 = {
176+
'hw_pointer_model': None,
177+
'hw_input_bus': None,
178+
}
179+
server1 = self._create_server(networks='none')
180+
self._assert_stashed_image_properties(
181+
server1['id'], default_image_properties1)
182+
183+
# Assert the defaults persist across a host flag change
184+
self.flags(pointer_model='usbtablet')
185+
# Restart compute to pick up usb setting
186+
self.restart_compute_service(self.compute)
187+
self._assert_stashed_image_properties(
188+
server1['id'], default_image_properties1)
189+
190+
# Assert the defaults persist across a host reboot, guest reboot, and
191+
# guest migration
192+
self._assert_stashed_image_properties_persist(
193+
server1, default_image_properties1)
194+
195+
# Create a server with new default image properties since the host flag
196+
# change
197+
default_image_properties2 = {
198+
'hw_pointer_model': 'usbtablet',
199+
'hw_input_bus': 'usb',
200+
}
201+
server2 = self._create_server(networks='none')
202+
self._assert_stashed_image_properties(
203+
server2['id'], default_image_properties2)
204+
205+
# Assert the defaults persist across a host reboot, guest reboot, and
206+
# guest migration
207+
self._assert_stashed_image_properties_persist(
208+
server2, default_image_properties2)
209+
210+
# Finally, try changing the host flag again to None. Note that it is
211+
# not possible for a user to specify None for this option:
212+
# https://bugs.launchpad.net/nova/+bug/1866106
213+
self.flags(pointer_model=None)
214+
# Restart compute to pick up None setting
215+
self.restart_compute_service(self.compute)
216+
self._assert_stashed_image_properties(
217+
server1['id'], default_image_properties1)
218+
self._assert_stashed_image_properties(
219+
server2['id'], default_image_properties2)
220+
221+
# Create a server since the host flag change to None. The defaults
222+
# should be the same as for ps2mouse
223+
server3 = self._create_server(networks='none')
224+
self._assert_stashed_image_properties(
225+
server3['id'], default_image_properties1)
226+
227+
# Assert the defaults persist across a host reboot, guest reboot, and
228+
# guest migration for server1, server2, and server3
229+
self._assert_stashed_image_properties_persist(
230+
server1, default_image_properties1)
231+
self._assert_stashed_image_properties_persist(
232+
server2, default_image_properties2)
233+
self._assert_stashed_image_properties_persist(
234+
server3, default_image_properties1)

0 commit comments

Comments
 (0)