Merge "libvirt: add configuration option for volume AIO mode"

This commit is contained in:
Zuul
2025-12-05 05:20:30 +00:00
committed by Gerrit Code Review
8 changed files with 75 additions and 3 deletions

View File

@@ -1652,6 +1652,15 @@ Possible values are:
accessed by anyone else. The Libvirt secret is public and persistent. It accessed by anyone else. The Libvirt secret is public and persistent. It
can be read by anyone with sufficient access on the host. The instance can can be read by anyone with sufficient access on the host. The instance can
be live-migrated and automatically resumed after host reboot. be live-migrated and automatically resumed after host reboot.
"""),
cfg.BoolOpt(
'use_default_aio_mode_for_volumes',
default=False,
help="""
With the NFS, FC, and iSCSI Cinder volume backends, Nova explicitly sets AIO
mode ``io=native`` in the Libvirt guest XML. Operators may set this option to
True in order to defer AIO mode selection to QEMU if forcing ``io=native`` is
not desired.
"""), """),
] ]

View File

@@ -65,6 +65,22 @@ class LibvirtFibreChannelVolumeDriverTestCase(
self.assertEqual('raw', tree.find('./driver').get('type')) self.assertEqual('raw', tree.find('./driver').get('type'))
self.assertEqual('native', tree.find('./driver').get('io')) self.assertEqual('native', tree.find('./driver').get('io'))
def test_libvirt_fibrechan_driver_get_config_default_aio_mode(self):
self.flags(use_default_aio_mode_for_volumes=True, group='libvirt')
libvirt_driver = fibrechannel.LibvirtFibreChannelVolumeDriver(
self.fake_host)
device_path = '/dev/fake-dev'
connection_info = {'data': {'device_path': device_path}}
conf = libvirt_driver.get_config(connection_info, self.disk_info)
tree = conf.format_dom()
self.assertEqual('block', tree.get('type'))
self.assertEqual(device_path, tree.find('./source').get('dev'))
self.assertEqual('raw', tree.find('./driver').get('type'))
self.assertIsNone(tree.find('./driver').get('io'))
def test_extend_volume(self): def test_extend_volume(self):
device_path = '/dev/fake-dev' device_path = '/dev/fake-dev'
connection_info = {'data': {'device_path': device_path}} connection_info = {'data': {'device_path': device_path}}

View File

@@ -45,6 +45,22 @@ class LibvirtISCSIVolumeDriverTestCase(
self.assertEqual('raw', tree.find('./driver').get('type')) self.assertEqual('raw', tree.find('./driver').get('type'))
self.assertEqual('native', tree.find('./driver').get('io')) self.assertEqual('native', tree.find('./driver').get('io'))
def test_libvirt_iscsi_driver_get_config_default_aio_mode(self):
self.flags(use_default_aio_mode_for_volumes=True, group='libvirt')
libvirt_driver = iscsi.LibvirtISCSIVolumeDriver(self.fake_host)
device_path = '/dev/fake-dev'
connection_info = {'data': {'device_path': device_path}}
conf = libvirt_driver.get_config(connection_info, self.disk_info)
tree = conf.format_dom()
self.assertEqual('block', tree.get('type'))
self.assertEqual(device_path, tree.find('./source').get('dev'))
self.assertEqual('raw', tree.find('./driver').get('type'))
self.assertIsNone(tree.find('./driver').get('io'))
@mock.patch.object(iscsi.LOG, 'warning') @mock.patch.object(iscsi.LOG, 'warning')
def test_libvirt_iscsi_driver_disconnect_volume_with_devicenotfound(self, def test_libvirt_iscsi_driver_disconnect_volume_with_devicenotfound(self,
mock_LOG_warning): mock_LOG_warning):

View File

@@ -77,6 +77,24 @@ class LibvirtNFSVolumeDriverTestCase(test_volume.LibvirtVolumeBaseTestCase):
self.assertEqual('raw', tree.find('./driver').get('type')) self.assertEqual('raw', tree.find('./driver').get('type'))
self.assertEqual('native', tree.find('./driver').get('io')) self.assertEqual('native', tree.find('./driver').get('io'))
def test_libvirt_nfs_driver_get_config_default_aio_mode(self):
self.flags(use_default_aio_mode_for_volumes=True, group='libvirt')
libvirt_driver = nfs.LibvirtNFSVolumeDriver(self.fake_host)
export_string = '192.168.1.1:/nfs/share1'
export_mnt_base = os.path.join(self.mnt_base,
utils.get_hash_str(export_string))
file_path = os.path.join(export_mnt_base, self.name)
connection_info = {'data': {'export': export_string,
'name': self.name,
'device_path': file_path}}
conf = libvirt_driver.get_config(connection_info, self.disk_info)
tree = conf.format_dom()
self._assertFileTypeEquals(tree, file_path)
self.assertEqual('raw', tree.find('./driver').get('type'))
self.assertIsNone(tree.find('./driver').get('io'))
def test_libvirt_nfs_driver_with_opts(self): def test_libvirt_nfs_driver_with_opts(self):
libvirt_driver = nfs.LibvirtNFSVolumeDriver(self.fake_host) libvirt_driver = nfs.LibvirtNFSVolumeDriver(self.fake_host)
export_string = '192.168.1.1:/nfs/share1' export_string = '192.168.1.1:/nfs/share1'

View File

@@ -45,7 +45,8 @@ class LibvirtFibreChannelVolumeDriver(libvirt_volume.LibvirtBaseVolumeDriver):
conf.source_type = "block" conf.source_type = "block"
conf.source_path = connection_info['data']['device_path'] conf.source_path = connection_info['data']['device_path']
conf.driver_io = "native" if not CONF.libvirt.use_default_aio_mode_for_volumes:
conf.driver_io = "native"
return conf return conf
def connect_volume(self, connection_info, instance): def connect_volume(self, connection_info, instance):

View File

@@ -55,7 +55,8 @@ class LibvirtISCSIVolumeDriver(libvirt_volume.LibvirtBaseVolumeDriver):
self).get_config(connection_info, disk_info) self).get_config(connection_info, disk_info)
conf.source_type = "block" conf.source_type = "block"
conf.source_path = connection_info['data']['device_path'] conf.source_path = connection_info['data']['device_path']
conf.driver_io = "native" if not CONF.libvirt.use_default_aio_mode_for_volumes:
conf.driver_io = "native"
return conf return conf
def connect_volume(self, connection_info, instance): def connect_volume(self, connection_info, instance):

View File

@@ -34,7 +34,8 @@ class LibvirtNFSVolumeDriver(fs.LibvirtMountedFileSystemVolumeDriver):
conf.source_type = 'file' conf.source_type = 'file'
conf.source_path = connection_info['data']['device_path'] conf.source_path = connection_info['data']['device_path']
conf.driver_format = connection_info['data'].get('format', 'raw') conf.driver_format = connection_info['data'].get('format', 'raw')
conf.driver_io = "native" if not CONF.libvirt.use_default_aio_mode_for_volumes:
conf.driver_io = "native"
return conf return conf
def _mount_options(self, connection_info): def _mount_options(self, connection_info):

View File

@@ -0,0 +1,10 @@
features:
- |
A new configuration option ``[libvirt]use_default_aio_mode_for_volumes``
has been added to enable use of QEMU default AIO modes for NFS, FC, and
iSCSI Cinder volumes.
By default, Nova explicitly sets AIO mode ``io=native`` in the Libvirt
guest XML for NFS, FC, and iSCSI Cinder volumes. Operators may set this
option to ``True`` in order to defer AIO mode selection to QEMU if forcing
``io=native`` is not desired.