Merge "libvirt: Handle silent failures to extend volume within os-brick"
This commit is contained in:
commit
99536b95bc
@ -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
|
||||||
|
@ -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,
|
||||||
|
@ -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']:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user