Merge "libvirt: Handle silent failures to extend volume within os-brick"

This commit is contained in:
Zuul 2021-08-06 20:39:27 +00:00 committed by Gerrit Code Review
commit 99536b95bc
3 changed files with 108 additions and 32 deletions

View File

@ -272,6 +272,11 @@ class VolumeDetachFailed(Invalid):
"Reason: %(reason)s") "Reason: %(reason)s")
class VolumeExtendFailed(Invalid):
msg_fmt = _("Volume %(volume_id)s could not be extended. "
"Reason: %(reason)s")
class MultiattachNotSupportedByVirtDriver(NovaException): class MultiattachNotSupportedByVirtDriver(NovaException):
# This exception indicates the compute hosting the instance does not # This exception indicates the compute hosting the instance does not
# support multiattach volumes. This should generally be considered a # support multiattach volumes. This should generally be considered a

View File

@ -9532,8 +9532,11 @@ class LibvirtConnTestCase(test.NoDBTestCase,
instance = objects.Instance(**self.test_instance) instance = objects.Instance(**self.test_instance)
connection_info = { connection_info = {
'driver_volume_type': 'fake', 'driver_volume_type': 'fake',
'data': {'device_path': '/fake', 'data': {
'access_mode': 'rw'} 'volume_id': uuids.volume_id,
'device_path': '/fake',
'access_mode': 'rw'
}
} }
new_size = 20 * units.Gi new_size = 20 * units.Gi
@ -9561,21 +9564,55 @@ class LibvirtConnTestCase(test.NoDBTestCase,
def test_extend_volume_with_volume_driver_without_support(self): def test_extend_volume_with_volume_driver_without_support(self):
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
instance = objects.Instance(**self.test_instance) instance = objects.Instance(**self.test_instance)
connection_info = {
'driver_volume_type': 'fake',
'serial': uuids.volume_id,
'data': {
'volume_id': uuids.volume_id,
'device_path': '/fake',
'access_mode': 'rw'
}
}
with mock.patch.object(drvr, '_extend_volume', with mock.patch.object(drvr, '_extend_volume',
side_effect=NotImplementedError()): side_effect=NotImplementedError()):
connection_info = {'driver_volume_type': 'fake'}
self.assertRaises(exception.ExtendVolumeNotSupported, self.assertRaises(exception.ExtendVolumeNotSupported,
drvr.extend_volume, self.context, drvr.extend_volume, self.context,
connection_info, instance, 0) connection_info, instance, 0)
def test_extend_volume_with_new_size_none(self):
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
instance = objects.Instance(**self.test_instance)
connection_info = {
'driver_volume_type': 'fake',
'serial': uuids.volume_id,
'data': {
'volume_id': uuids.volume_id,
'device_path': '/fake',
'access_mode': 'rw'
}
}
with mock.patch.object(drvr, '_extend_volume', return_value=None):
self.assertRaises(
exception.VolumeExtendFailed,
drvr.extend_volume,
self.context,
connection_info,
instance,
0
)
def test_extend_volume_disk_not_found(self): def test_extend_volume_disk_not_found(self):
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
instance = objects.Instance(**self.test_instance) instance = objects.Instance(**self.test_instance)
connection_info = { connection_info = {
'driver_volume_type': 'fake', 'driver_volume_type': 'fake',
'data': {'device_path': '/fake', 'serial': uuids.volume_id,
'access_mode': 'rw'} 'data': {
'volume_id': uuids.volume_id,
'device_path': '/fake',
'access_mode': 'rw'
}
} }
new_size = 20 * units.Gi new_size = 20 * units.Gi
@ -9590,6 +9627,15 @@ class LibvirtConnTestCase(test.NoDBTestCase,
def test_extend_volume_with_instance_not_found(self): def test_extend_volume_with_instance_not_found(self):
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
instance = objects.Instance(**self.test_instance) instance = objects.Instance(**self.test_instance)
connection_info = {
'driver_volume_type': 'fake',
'serial': uuids.volume_id,
'data': {
'volume_id': uuids.volume_id,
'device_path': '/fake',
'access_mode': 'rw'
}
}
with test.nested( with test.nested(
mock.patch.object(host.Host, '_get_domain', mock.patch.object(host.Host, '_get_domain',
@ -9597,7 +9643,6 @@ class LibvirtConnTestCase(test.NoDBTestCase,
instance_id=instance.uuid)), instance_id=instance.uuid)),
mock.patch.object(drvr, '_extend_volume') mock.patch.object(drvr, '_extend_volume')
) as (_get_domain, _extend_volume): ) as (_get_domain, _extend_volume):
connection_info = {'driver_volume_type': 'fake'}
self.assertRaises(exception.InstanceNotFound, self.assertRaises(exception.InstanceNotFound,
drvr.extend_volume, self.context, drvr.extend_volume, self.context,
connection_info, instance, 0) connection_info, instance, 0)
@ -9607,9 +9652,14 @@ class LibvirtConnTestCase(test.NoDBTestCase,
instance = objects.Instance(**self.test_instance) instance = objects.Instance(**self.test_instance)
connection_info = { connection_info = {
'driver_volume_type': 'fake', 'driver_volume_type': 'fake',
'data': {'device_path': '/fake', 'serial': uuids.volume_id,
'access_mode': 'rw'} 'data': {
'volume_id': uuids.volume_id,
'device_path': '/fake',
'access_mode': 'rw'
}
} }
new_size = 20 * units.Gi new_size = 20 * units.Gi
guest = mock.Mock(spec=libvirt_guest.Guest) guest = mock.Mock(spec=libvirt_guest.Guest)
@ -9631,12 +9681,14 @@ class LibvirtConnTestCase(test.NoDBTestCase,
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
instance = objects.Instance(**self.test_instance) instance = objects.Instance(**self.test_instance)
connection_info = { connection_info = {
'serial': '58a84f6d-3f0c-4e19-a0af-eb657b790657', 'serial': uuids.volume_id,
'driver_volume_type': 'fake', 'driver_volume_type': 'fake',
'data': {'cluster_name': 'fake', 'data': {
'auth_enabled': False, 'cluster_name': 'fake',
'volume_id': '58a84f6d-3f0c-4e19-a0af-eb657b790657', 'auth_enabled': False,
'access_mode': 'rw'} 'volume_id': uuids.volume_id,
'access_mode': 'rw'
}
} }
new_size = 20 * units.Gi new_size = 20 * units.Gi
@ -9648,7 +9700,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
block_device.resize = mock.Mock() block_device.resize = mock.Mock()
disk = mock.Mock( disk = mock.Mock(
spec=vconfig.LibvirtConfigGuestDisk, spec=vconfig.LibvirtConfigGuestDisk,
serial='58a84f6d-3f0c-4e19-a0af-eb657b790657', serial=uuids.volume_id,
target_dev='vdb') target_dev='vdb')
guest.get_block_device = mock.Mock(return_value=block_device) guest.get_block_device = mock.Mock(return_value=block_device)
guest.get_all_disks = mock.Mock(return_value=[disk]) guest.get_all_disks = mock.Mock(return_value=[disk])
@ -9668,12 +9720,14 @@ class LibvirtConnTestCase(test.NoDBTestCase,
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
instance = objects.Instance(**self.test_instance) instance = objects.Instance(**self.test_instance)
connection_info = { connection_info = {
'serial': '58a84f6d-3f0c-4e19-a0af-eb657b790657', 'serial': uuids.volume_id,
'driver_volume_type': 'fake', 'driver_volume_type': 'fake',
'data': {'cluster_name': 'fake', 'data': {
'auth_enabled': False, 'cluster_name': 'fake',
'volume_id': '58a84f6d-3f0c-4e19-a0af-eb657b790657', 'auth_enabled': False,
'access_mode': 'rw'} 'volume_id': uuids.volume_id,
'access_mode': 'rw'
}
} }
new_size = 20 * units.Gi new_size = 20 * units.Gi
@ -9684,7 +9738,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
block_device.resize = mock.Mock() block_device.resize = mock.Mock()
disk = mock.Mock( disk = mock.Mock(
spec=vconfig.LibvirtConfigGuestDisk, spec=vconfig.LibvirtConfigGuestDisk,
serial='12345678-abcd-abcd-abcd-0123456789012', serial=uuids.different_volume_id,
target_dev='vdb') target_dev='vdb')
guest.get_block_device = mock.Mock(return_value=block_device) guest.get_block_device = mock.Mock(return_value=block_device)
guest.get_all_disks = mock.Mock(return_value=[disk]) guest.get_all_disks = mock.Mock(return_value=[disk])
@ -9709,7 +9763,9 @@ class LibvirtConnTestCase(test.NoDBTestCase,
connection_info = { connection_info = {
'serial': uuids.volume_id, 'serial': uuids.volume_id,
'driver_volume_type': 'fake', 'driver_volume_type': 'fake',
'data': {'access_mode': 'rw'} 'data': {
'access_mode': 'rw'
}
} }
disk_1 = mock.Mock(spec=vconfig.LibvirtConfigGuestDisk, disk_1 = mock.Mock(spec=vconfig.LibvirtConfigGuestDisk,
@ -9748,8 +9804,10 @@ class LibvirtConnTestCase(test.NoDBTestCase,
connection_info = { connection_info = {
'serial': uuids.volume_id, 'serial': uuids.volume_id,
'driver_volume_type': 'fake', 'driver_volume_type': 'fake',
'data': {'device_path': mock.sentinel.device_path, 'data': {
'access_mode': 'rw'} 'device_path': mock.sentinel.device_path,
'access_mode': 'rw'
}
} }
block_device = mock.Mock(spec=libvirt_guest.BlockDevice, block_device = mock.Mock(spec=libvirt_guest.BlockDevice,
@ -9786,8 +9844,10 @@ class LibvirtConnTestCase(test.NoDBTestCase,
connection_info = { connection_info = {
'serial': uuids.volume_id, 'serial': uuids.volume_id,
'driver_volume_type': 'fake', 'driver_volume_type': 'fake',
'data': {'device_path': mock.sentinel.device_path, 'data': {
'access_mode': 'rw'} 'device_path': mock.sentinel.device_path,
'access_mode': 'rw'
}
} }
block_device = mock.Mock(spec=libvirt_guest.BlockDevice, block_device = mock.Mock(spec=libvirt_guest.BlockDevice,
@ -9837,10 +9897,12 @@ class LibvirtConnTestCase(test.NoDBTestCase,
connection_info = { connection_info = {
'serial': uuids.volume_id, 'serial': uuids.volume_id,
'driver_volume_type': 'rbd', 'driver_volume_type': 'rbd',
'data': {'name': 'pool/volume', 'data': {
'auth_enabled': 'true', 'name': 'pool/volume',
'auth_username': 'username', 'auth_enabled': 'true',
'access_mode': 'rw'} 'auth_username': 'username',
'access_mode': 'rw'
}
} }
disk_1 = mock.Mock(spec=vconfig.LibvirtConfigGuestDisk, disk_1 = mock.Mock(spec=vconfig.LibvirtConfigGuestDisk,
serial=uuids.volume_id, serial=uuids.volume_id,

View File

@ -2664,9 +2664,19 @@ class LibvirtDriver(driver.ComputeDriver):
def extend_volume(self, context, connection_info, instance, def extend_volume(self, context, connection_info, instance,
requested_size): requested_size):
volume_id = driver_block_device.get_volume_id(connection_info)
try: try:
new_size = self._extend_volume(connection_info, instance, new_size = self._extend_volume(
requested_size) connection_info, instance, requested_size)
# NOTE(lyarwood): Handle cases where os-brick has ignored failures
# and returned an invalid new_size of None through the vol drivers
if new_size is None:
raise exception.VolumeExtendFailed(
volume_id=volume_id,
reason="Failure to resize underlying volume on compute."
)
except NotImplementedError: except NotImplementedError:
raise exception.ExtendVolumeNotSupported() raise exception.ExtendVolumeNotSupported()
@ -2675,7 +2685,6 @@ class LibvirtDriver(driver.ComputeDriver):
try: try:
guest = self._host.get_guest(instance) guest = self._host.get_guest(instance)
state = guest.get_power_state(self._host) state = guest.get_power_state(self._host)
volume_id = driver_block_device.get_volume_id(connection_info)
active_state = state in (power_state.RUNNING, power_state.PAUSED) active_state = state in (power_state.RUNNING, power_state.PAUSED)
if active_state: if active_state:
if 'device_path' in connection_info['data']: if 'device_path' in connection_info['data']: