libvirt: update logic to configure device for scsi controller

When using virtio-scsi it is possible to handle up to 256 disk but
because we do not specifically set the information about the
controller only 6 can be handled.

This commit is fixing the issue by adding the address element to the
disk configuration.

Closes-Bug: #1686116
Change-Id: I98e53b378cc99747765066001a0b51880543d2dd
This commit is contained in:
Sahid Orentino Ferdjaoui 2017-04-25 06:06:07 -04:00
parent 768d7cc0a6
commit fb343c4022
4 changed files with 61 additions and 7 deletions

View File

@ -197,7 +197,8 @@ class ImageBackendFixture(fixtures.Fixture):
self.imported_files.append((local_filename, remote_filename))
def _fake_libvirt_info(self, mock_disk, disk_bus, disk_dev, device_type,
cache_mode, extra_specs, hypervisor_version):
cache_mode, extra_specs, hypervisor_version,
disk_unit=None):
# For tests in test_virt_drivers which expect libvirt_info to be
# functional
info = config.LibvirtConfigGuestDisk()

View File

@ -3476,12 +3476,24 @@ class LibvirtConnTestCase(test.NoDBTestCase,
vconfig.LibvirtConfigGuestDisk)
self.assertEqual(cfg.devices[2].target_dev, disk)
def test_get_guest_config_with_virtio_scsi_bus(self):
def test_get_guest_config_default_with_virtio_scsi_bus(self):
self._test_get_guest_config_with_virtio_scsi_bus()
@mock.patch.object(rbd_utils.RBDDriver, 'get_mon_addrs')
@mock.patch.object(rbd_utils, 'rbd')
def test_get_guest_config_rbd_with_virtio_scsi_bus(
self, mock_rdb, mock_get_mon_addrs):
self.flags(images_type='rbd', group='libvirt')
mock_get_mon_addrs.return_value = ("host", 9876)
self._test_get_guest_config_with_virtio_scsi_bus()
def _test_get_guest_config_with_virtio_scsi_bus(self):
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
image_meta = objects.ImageMeta.from_dict({
"disk_format": "raw",
"properties": {"hw_scsi_model": "virtio-scsi"}})
"properties": {"hw_scsi_model": "virtio-scsi",
"hw_disk_bus": "scsi"}})
instance_ref = objects.Instance(**self.test_instance)
disk_info = blockinfo.get_disk_info(CONF.libvirt.virt_type,
@ -3491,8 +3503,10 @@ class LibvirtConnTestCase(test.NoDBTestCase,
cfg = drvr._get_guest_config(instance_ref, [], image_meta, disk_info)
self.assertIsInstance(cfg.devices[0],
vconfig.LibvirtConfigGuestDisk)
self.assertEqual(0, cfg.devices[0].device_addr.unit)
self.assertIsInstance(cfg.devices[1],
vconfig.LibvirtConfigGuestDisk)
self.assertEqual(1, cfg.devices[1].device_addr.unit)
self.assertIsInstance(cfg.devices[2],
vconfig.LibvirtConfigGuestController)
self.assertEqual(cfg.devices[2].model, 'virtio-scsi')

View File

@ -3582,6 +3582,7 @@ class LibvirtDriver(driver.ComputeDriver):
def _get_guest_disk_config(self, instance, name, disk_mapping, inst_type,
image_type=None):
disk_unit = None
disk = self.image_backend.by_name(instance, name, image_type)
if (name == 'disk.config' and image_type == 'rbd' and
not disk.exists()):
@ -3597,12 +3598,17 @@ class LibvirtDriver(driver.ComputeDriver):
LOG.debug('Config drive not found in RBD, falling back to the '
'instance directory', instance=instance)
disk_info = disk_mapping[name]
return disk.libvirt_info(disk_info['bus'],
if 'unit' in disk_mapping:
disk_unit = disk_mapping['unit']
disk_mapping['unit'] += 1 # Increments for the next disk added
conf = disk.libvirt_info(disk_info['bus'],
disk_info['dev'],
disk_info['type'],
self.disk_cachemode,
inst_type['extra_specs'],
self._host.get_version())
self._host.get_version(),
disk_unit=disk_unit)
return conf
def _get_guest_fs_config(self, instance, name, image_type=None):
disk = self.image_backend.by_name(instance, name, image_type)
@ -3620,6 +3626,19 @@ class LibvirtDriver(driver.ComputeDriver):
mount_rootfs = CONF.libvirt.virt_type == "lxc"
scsi_controller = self._get_scsi_controller(image_meta)
if scsi_controller and scsi_controller.model == 'virtio-scsi':
# The virtio-scsi can handle up to 256 devices but the
# optional element "address" must be defined to describe
# where the device is placed on the controller (see:
# LibvirtConfigGuestDeviceAddressDrive).
#
# Note about why it's added in disk_mapping: It's not
# possible to pass an 'int' by reference in Python, so we
# use disk_mapping as container to keep reference of the
# unit added and be able to increment it for each disk
# added.
disk_mapping['unit'] = 0
def _get_ephemeral_devices():
eph_devices = []
for idx, eph in enumerate(
@ -3729,6 +3748,7 @@ class LibvirtDriver(driver.ComputeDriver):
scsi_controller = vconfig.LibvirtConfigGuestController()
scsi_controller.type = 'scsi'
scsi_controller.model = hw_scsi_model
scsi_controller.index = 0
return scsi_controller
def _get_host_sysinfo_serial_hardware(self):

View File

@ -117,7 +117,8 @@ class Image(object):
pass
def libvirt_info(self, disk_bus, disk_dev, device_type, cache_mode,
extra_specs, hypervisor_version, boot_order=None):
extra_specs, hypervisor_version, boot_order=None,
disk_unit=None):
"""Get `LibvirtConfigGuestDisk` filled for this image.
:disk_dev: Disk bus device name
@ -143,10 +144,24 @@ class Image(object):
info.source_path = self.path
info.boot_order = boot_order
if disk_bus == 'scsi':
self.disk_scsi(info, disk_unit)
self.disk_qos(info, extra_specs)
return info
def disk_scsi(self, info, disk_unit):
# The driver is responsible to create the SCSI controller
# at index 0.
info.device_addr = vconfig.LibvirtConfigGuestDeviceAddressDrive()
info.device_addr.controller = 0
if disk_unit is not None:
# In order to allow up to 256 disks handled by one
# virtio-scsi controller, the device addr should be
# specified.
info.device_addr.unit = disk_unit
def disk_qos(self, info, extra_specs):
tune_items = ['disk_read_bytes_sec', 'disk_read_iops_sec',
'disk_write_bytes_sec', 'disk_write_iops_sec',
@ -808,7 +823,8 @@ class Rbd(Image):
self.discard_mode = CONF.libvirt.hw_disk_discard
def libvirt_info(self, disk_bus, disk_dev, device_type, cache_mode,
extra_specs, hypervisor_version, boot_order=None):
extra_specs, hypervisor_version, boot_order=None,
disk_unit=None):
"""Get `LibvirtConfigGuestDisk` filled for this image.
:disk_dev: Disk bus device name
@ -844,6 +860,9 @@ class Rbd(Image):
info.auth_secret_type = 'ceph'
info.auth_secret_uuid = CONF.libvirt.rbd_secret_uuid
if disk_bus == 'scsi':
self.disk_scsi(info, disk_unit)
self.disk_qos(info, extra_specs)
return info