Merge "Support setting block size for block devices"

This commit is contained in:
Jenkins 2013-08-09 22:58:58 +00:00 committed by Gerrit Code Review
commit 3c83737896
6 changed files with 123 additions and 2 deletions

View File

@ -1863,6 +1863,39 @@ class LibvirtConnTestCase(test.TestCase):
{"name": "fake-instance"},
"/dev/sda")
def test_attach_blockio_invalid_hypervisor(self):
self.flags(libvirt_type='fake_type')
self.create_fake_libvirt_mock()
libvirt_driver.LibvirtDriver._conn.lookupByName = self.fake_lookup
self.mox.ReplayAll()
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
self.assertRaises(exception.InvalidHypervisorType,
conn.attach_volume,
{"driver_volume_type": "fake",
"data": {"logical_block_size": "4096",
"physical_block_size": "4096"}
},
{"name": "fake-instance"},
"/dev/sda")
def test_attach_blockio_invalid_version(self):
def get_lib_version_stub():
return (0 * 1000 * 1000) + (9 * 1000) + 8
self.flags(libvirt_type='qemu')
self.create_fake_libvirt_mock()
libvirt_driver.LibvirtDriver._conn.lookupByName = self.fake_lookup
self.mox.ReplayAll()
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
self.stubs.Set(self.conn, "getLibVersion", get_lib_version_stub)
self.assertRaises(exception.Invalid,
conn.attach_volume,
{"driver_volume_type": "fake",
"data": {"logical_block_size": "4096",
"physical_block_size": "4096"}
},
{"name": "fake-instance"},
"/dev/sda")
def test_multi_nic(self):
instance_data = dict(self.test_instance)
network_info = _fake_network_info(self.stubs, 2)

View File

@ -546,6 +546,23 @@ class LibvirtConfigGuestDiskTest(LibvirtConfigBaseTest):
</iotune>
</disk>""")
def test_config_blockio(self):
obj = config.LibvirtConfigGuestDisk()
obj.source_type = "file"
obj.source_path = "/tmp/hello"
obj.target_dev = "/dev/hda"
obj.target_bus = "ide"
obj.logical_block_size = "4096"
obj.physical_block_size = "4096"
xml = obj.to_xml()
self.assertXmlEqual("""
<disk type="file" device="disk">
<source file="/tmp/hello"/>
<target bus="ide" dev="/dev/hda"/>
<blockio logical_block_size="4096" physical_block_size="4096"/>
</disk>""", xml)
class LibvirtConfigGuestFilesysTest(LibvirtConfigBaseTest):

View File

@ -97,8 +97,31 @@ class LibvirtVolumeTestCase(test.TestCase):
}
conf = libvirt_driver.connect_volume(connection_info, self.disk_info)
tree = conf.format_dom()
self.assertEqual(tree.get('type'), 'block')
self.assertEqual(tree.find('./serial').text, 'fake_serial')
self.assertEqual('block', tree.get('type'))
self.assertEqual('fake_serial', tree.find('./serial').text)
self.assertEqual(None, tree.find('./blockio'))
def test_libvirt_volume_driver_blockio(self):
libvirt_driver = volume.LibvirtVolumeDriver(self.fake_conn)
connection_info = {
'driver_volume_type': 'fake',
'data': {
'device_path': '/foo',
'logical_block_size': '4096',
'physical_block_size': '4096',
},
'serial': 'fake_serial',
}
disk_info = {
"bus": "virtio",
"dev": "vde",
"type": "disk",
}
conf = libvirt_driver.connect_volume(connection_info, disk_info)
tree = conf.format_dom()
blockio = tree.find('./blockio')
self.assertEqual('4096', blockio.get('logical_block_size'))
self.assertEqual('4096', blockio.get('physical_block_size'))
def iscsi_connection(self, volume, location, iqn):
return {

View File

@ -476,6 +476,8 @@ class LibvirtConfigGuestDisk(LibvirtConfigGuestDevice):
self.disk_write_iops_sec = None
self.disk_total_bytes_sec = None
self.disk_total_iops_sec = None
self.logical_block_size = None
self.physical_block_size = None
def format_dom(self):
dev = super(LibvirtConfigGuestDisk, self).format_dom()
@ -556,6 +558,20 @@ class LibvirtConfigGuestDisk(LibvirtConfigGuestDevice):
if len(iotune) > 0:
dev.append(iotune)
# Block size tuning
if (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:
blockio.set('logical_block_size', self.logical_block_size)
if self.physical_block_size is not None:
blockio.set('physical_block_size', self.physical_block_size)
dev.append(blockio)
return dev

View File

@ -291,6 +291,8 @@ MIN_LIBVIRT_CLOSE_CALLBACK_VERSION = (1, 0, 1)
REQ_HYPERVISOR_LIVESNAPSHOT = "QEMU"
MIN_LIBVIRT_LIVESNAPSHOT_VERSION = (1, 0, 0)
MIN_QEMU_LIVESNAPSHOT_VERSION = (1, 3, 0)
# block size tuning requirements
MIN_LIBVIRT_BLOCKIO_VERSION = (0, 10, 2)
def libvirt_error_handler(context, err):
@ -1007,6 +1009,27 @@ class LibvirtDriver(driver.ComputeDriver):
disk_dev),
'type': 'disk',
}
# Note(cfb): If the volume has a custom block size, check that
# that we are using QEMU/KVM and libvirt >= 0.10.2. The
# prescence of a block size is considered mandatory by
# cinder so we fail if we can't honor the request.
data = {}
if ('data' in connection_info):
data = connection_info['data']
if ('logical_block_size' in data or 'physical_block_size' in data):
if CONF.libvirt_type != "kvm" and CONF.libvirt_type != "qemu":
msg = _("Volume sets block size, but the current "
"libvirt hypervisor '%s' does not support custom "
"block size") % CONF.libvirt_type
raise exception.InvalidHypervisorType(msg)
if not self.has_min_version(MIN_LIBVIRT_BLOCKIO_VERSION):
ver = ".".join([str(x) for x in MIN_LIBVIRT_BLOCKIO_VERSION])
msg = _("Volume sets block size, but libvirt '%s' or later is "
"required.") % ver
raise exception.Invalid(msg)
conf = self.volume_driver_method('connect_volume',
connection_info,
disk_info)

View File

@ -99,6 +99,15 @@ class LibvirtBaseVolumeDriver(object):
conf.target_dev = disk_info['dev']
conf.target_bus = disk_info['bus']
conf.serial = connection_info.get('serial')
# Support for block size tuning
data = {}
if 'data' in connection_info:
data = connection_info['data']
if 'logical_block_size' in data:
conf.logical_block_size = data['logical_block_size']
if 'physical_block_size' in data:
conf.physical_block_size = data['physical_block_size']
return conf
def disconnect_volume(self, connection_info, disk_dev):