Fix blockio generation for LUN volumes
QEMU's scsi-block device driver does not support physical_block_size
and logical_block_size properties. When Cinder reports disk geometry
for LUN volumes, Nova was incorrectly including a <blockio> element
in the libvirt XML, causing QEMU to fail with:
Property 'scsi-block.physical_block_size' not found
This fix adds a check to skip blockio generation when source_device
is 'lun', following the existing pattern used for serial at line 1356.
Generated-By: claude-code (Claude Opus 4.5)
Closes-Bug: #2127196
Change-Id: Idf87e936edd97aac719222942c9842a9aca4c270
Signed-off-by: Sean Mooney <work@seanmooney.info>
This commit is contained in:
26
nova/tests/fixtures/libvirt.py
vendored
26
nova/tests/fixtures/libvirt.py
vendored
@@ -921,6 +921,13 @@ def _parse_disk_info(element):
|
||||
if alias is not None:
|
||||
disk_info['alias'] = alias.get('name')
|
||||
|
||||
blockio = element.find('./blockio')
|
||||
if blockio is not None:
|
||||
disk_info['blockio_logical_block_size'] = blockio.get(
|
||||
'logical_block_size')
|
||||
disk_info['blockio_physical_block_size'] = blockio.get(
|
||||
'physical_block_size')
|
||||
|
||||
return disk_info
|
||||
|
||||
|
||||
@@ -1570,7 +1577,24 @@ class Domain(object):
|
||||
</source>"""
|
||||
strformat += """
|
||||
<target dev='%(target_dev)s' bus='%(target_bus)s'/>
|
||||
<address type='drive' controller='0' bus='0' unit='0'/>
|
||||
<address type='drive' controller='0' bus='0' unit='0'/>"""
|
||||
|
||||
# Add blockio if present
|
||||
if 'blockio_logical_block_size' in disk or \
|
||||
'blockio_physical_block_size' in disk:
|
||||
blockio_attrs = []
|
||||
if disk.get('blockio_logical_block_size'):
|
||||
blockio_attrs.append(
|
||||
"logical_block_size='%s'" %
|
||||
disk['blockio_logical_block_size'])
|
||||
if disk.get('blockio_physical_block_size'):
|
||||
blockio_attrs.append(
|
||||
"physical_block_size='%s'" %
|
||||
disk['blockio_physical_block_size'])
|
||||
strformat += """
|
||||
<blockio %s/>""" % ' '.join(blockio_attrs)
|
||||
|
||||
strformat += """
|
||||
</disk>"""
|
||||
disks += strformat % dict(source_attr=source_attr, **disk)
|
||||
filesystems = ''
|
||||
|
||||
125
nova/tests/functional/regressions/test_bug_2127196.py
Normal file
125
nova/tests/functional/regressions/test_bug_2127196.py
Normal file
@@ -0,0 +1,125 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""Regression test for bug 2127196.
|
||||
|
||||
https://bugs.launchpad.net/nova/+bug/2127196
|
||||
|
||||
When Cinder reports disk geometry (logical/physical block size) for LUN
|
||||
volumes, Nova incorrectly includes a <blockio> element in the libvirt XML.
|
||||
QEMU's scsi-block device driver (used for device="lun") does not support
|
||||
these properties, causing QEMU to fail with:
|
||||
|
||||
Property 'scsi-block.physical_block_size' not found
|
||||
|
||||
The fix ensures that <blockio> is not generated for LUN devices.
|
||||
"""
|
||||
|
||||
from lxml import etree
|
||||
from oslo_utils.fixture import uuidsentinel as uuids
|
||||
|
||||
import fixtures
|
||||
|
||||
from nova.tests.fixtures import cinder as cinder_fixture
|
||||
from nova.tests.fixtures import libvirt as fakelibvirt
|
||||
from nova.tests.functional import integrated_helpers
|
||||
from nova.tests.functional.libvirt import base
|
||||
|
||||
|
||||
class CinderFixtureWithLunBlockSize(cinder_fixture.CinderFixture):
|
||||
"""CinderFixture that provides a LUN volume with block size info."""
|
||||
|
||||
# Volume ID for a LUN volume with block size info
|
||||
LUN_VOLUME_WITH_BLOCKSIZE = uuids.lun_volume_with_blocksize
|
||||
|
||||
def __init__(self, test, az='nova'):
|
||||
super().__init__(test, az)
|
||||
# Add connection_info for the LUN volume that includes block size
|
||||
self.VOLUME_CONNECTION_INFO[self.LUN_VOLUME_WITH_BLOCKSIZE] = {
|
||||
'driver_volume_type': 'iscsi',
|
||||
'data': {
|
||||
'target_lun': '1',
|
||||
'logical_block_size': '512',
|
||||
'physical_block_size': '512',
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TestLunVolumeBlockio(
|
||||
base.ServersTestBase,
|
||||
integrated_helpers.InstanceHelperMixin
|
||||
):
|
||||
"""Regression test for bug 2127196.
|
||||
|
||||
Tests that blockio is not generated for LUN volumes even when Cinder
|
||||
provides block size information.
|
||||
"""
|
||||
|
||||
microversion = 'latest'
|
||||
ADMIN_API = True
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.cinder = self.useFixture(CinderFixtureWithLunBlockSize(self))
|
||||
self.useFixture(fixtures.MockPatch(
|
||||
'nova.compute.manager.ComputeVirtAPI.wait_for_instance_event'))
|
||||
self.start_compute(
|
||||
hostname='compute1',
|
||||
host_info=fakelibvirt.HostInfo(
|
||||
cpu_nodes=1, cpu_sockets=1, cpu_cores=4, cpu_threads=1))
|
||||
|
||||
def _get_xml_element(self, xml, xpath):
|
||||
"""Get element from XML using xpath."""
|
||||
xml_doc = etree.fromstring(xml.encode('utf-8'))
|
||||
element = xml_doc.find(xpath)
|
||||
return element
|
||||
|
||||
def test_lun_volume_no_blockio(self):
|
||||
"""Test that blockio is not included for LUN volumes.
|
||||
|
||||
When Cinder reports block size information for a LUN volume,
|
||||
Nova should NOT include <blockio> in the libvirt XML because
|
||||
QEMU's scsi-block driver does not support these properties.
|
||||
"""
|
||||
# Build a server with a LUN volume as the boot device
|
||||
server = self._build_server(image_uuid='', networks='none')
|
||||
server['block_device_mapping_v2'] = [{
|
||||
'boot_index': 0,
|
||||
'uuid': CinderFixtureWithLunBlockSize.LUN_VOLUME_WITH_BLOCKSIZE,
|
||||
'source_type': 'volume',
|
||||
'destination_type': 'volume',
|
||||
'device_type': 'lun',
|
||||
'disk_bus': 'scsi',
|
||||
}]
|
||||
|
||||
created_server = self.api.post_server({'server': server})
|
||||
self._wait_for_state_change(created_server, 'ACTIVE')
|
||||
|
||||
# Get the libvirt XML
|
||||
conn = self.computes['compute1'].driver._host.get_connection()
|
||||
dom = conn.lookupByUUIDString(created_server['id'])
|
||||
xml = dom.XMLDesc(0)
|
||||
|
||||
# Find the disk element for the LUN volume
|
||||
xml_doc = etree.fromstring(xml.encode('utf-8'))
|
||||
disk = xml_doc.find('.//disk[@device="lun"]')
|
||||
self.assertIsNotNone(
|
||||
disk, "Expected to find a disk with device='lun' in the XML")
|
||||
|
||||
# Verify that blockio is NOT present for the LUN device
|
||||
# This is the correct behavior after the fix
|
||||
blockio = disk.find('blockio')
|
||||
self.assertIsNone(
|
||||
blockio,
|
||||
"Bug 2127196: blockio should NOT be present for LUN devices "
|
||||
"because QEMU's scsi-block driver does not support "
|
||||
"physical_block_size and logical_block_size properties")
|
||||
@@ -1159,6 +1159,31 @@ class LibvirtConfigGuestDiskTest(LibvirtConfigBaseTest):
|
||||
<target bus="scsi" dev="/dev/sda"/>
|
||||
</disk>""")
|
||||
|
||||
def test_config_block_lun_no_blockio(self):
|
||||
"""Test that blockio is not generated for LUN devices (bug 2127196).
|
||||
|
||||
QEMU's scsi-block device driver does not support physical_block_size
|
||||
and logical_block_size properties, so blockio must not be included
|
||||
in the XML when source_device is 'lun'.
|
||||
"""
|
||||
obj = config.LibvirtConfigGuestDisk()
|
||||
obj.source_type = "block"
|
||||
obj.source_path = "/tmp/hello"
|
||||
obj.source_device = "lun"
|
||||
obj.driver_name = "qemu"
|
||||
obj.target_dev = "/dev/sda"
|
||||
obj.target_bus = "scsi"
|
||||
obj.logical_block_size = "512"
|
||||
obj.physical_block_size = "512"
|
||||
|
||||
xml = obj.to_xml()
|
||||
self.assertXmlEqual(xml, """
|
||||
<disk type="block" device="lun">
|
||||
<driver name="qemu"/>
|
||||
<source dev="/tmp/hello"/>
|
||||
<target bus="scsi" dev="/dev/sda"/>
|
||||
</disk>""")
|
||||
|
||||
def test_config_block_parse(self):
|
||||
xml = """<disk type="block" device="cdrom">
|
||||
<driver name="qemu"/>
|
||||
|
||||
@@ -206,6 +206,36 @@ class LibvirtVolumeTestCase(LibvirtISCSIVolumeBaseTestCase):
|
||||
self.assertEqual('4096', blockio.get('logical_block_size'))
|
||||
self.assertEqual('4096', blockio.get('physical_block_size'))
|
||||
|
||||
def test_libvirt_volume_driver_blockio_not_for_lun(self):
|
||||
"""Test blockio is not set for LUN devices (bug 2127196).
|
||||
|
||||
QEMU's scsi-block device driver does not support physical_block_size
|
||||
and logical_block_size properties, so blockio must not be included
|
||||
when device type is 'lun'.
|
||||
"""
|
||||
libvirt_driver = volume.LibvirtVolumeDriver(self.fake_host)
|
||||
connection_info = {
|
||||
'driver_volume_type': 'fake',
|
||||
'data': {
|
||||
'device_path': '/foo',
|
||||
'logical_block_size': '4096',
|
||||
'physical_block_size': '4096',
|
||||
},
|
||||
'serial': 'fake_serial',
|
||||
}
|
||||
disk_info = {
|
||||
"bus": "scsi",
|
||||
"dev": "sda",
|
||||
"type": "lun",
|
||||
}
|
||||
conf = libvirt_driver.get_config(connection_info, disk_info)
|
||||
tree = conf.format_dom()
|
||||
self.assertEqual('lun', tree.get('device'))
|
||||
# blockio should NOT be present for LUN devices
|
||||
self.assertIsNone(tree.find('./blockio'))
|
||||
# serial should also NOT be present for LUN devices
|
||||
self.assertIsNone(tree.find('./serial'))
|
||||
|
||||
def test_libvirt_volume_driver_iotune(self):
|
||||
libvirt_driver = volume.LibvirtVolumeDriver(self.fake_host)
|
||||
connection_info = {
|
||||
|
||||
@@ -1359,8 +1359,12 @@ class LibvirtConfigGuestDisk(LibvirtConfigGuestDevice):
|
||||
self._format_iotune(dev)
|
||||
|
||||
# Block size tuning
|
||||
if (self.logical_block_size is not None or
|
||||
self.physical_block_size is not None):
|
||||
# NOTE(bug 2127196): Block size properties are not supported for
|
||||
# device='lun' because QEMU's scsi-block driver does not support
|
||||
# physical_block_size and logical_block_size properties.
|
||||
if (self.source_device != 'lun' and
|
||||
(self.logical_block_size is not None or
|
||||
self.physical_block_size is not None)):
|
||||
|
||||
blockio = etree.Element("blockio")
|
||||
if self.logical_block_size is not None:
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
fixes:
|
||||
- |
|
||||
`Bug 2127196`_ is fixed where Nova incorrectly generated a ``<blockio>``
|
||||
element in libvirt XML for LUN volumes when Cinder reported disk geometry
|
||||
(logical and physical block size). QEMU's ``scsi-block`` device driver
|
||||
does not support ``physical_block_size`` and ``logical_block_size``
|
||||
properties, causing instance spawn to fail with the error
|
||||
``Property 'scsi-block.physical_block_size' not found``.
|
||||
The ``<blockio>`` element is now omitted for LUN devices.
|
||||
|
||||
.. _Bug 2127196: https://bugs.launchpad.net/nova/+bug/2127196
|
||||
Reference in New Issue
Block a user