Avoid exploding if guest refuses to detach a volume

When we run detach_volume(), the guest has to respond to the ACPI
eject request in order for us to proceed. It may not do this at all
if the volume is mounted or in-use, or may not by the time we time out
if lots of dirty data needs flushing. Right now, we let the failure
exception bubble up to our caller and we log a nasty stack trace, which
doesn't really convey the reason (and that it's an expected and
reasonable thing to happen).

Thus, this patch catches that, logs the situation at warning level and
avoids the trace.

Change-Id: I3800b466a50b1e5f5d1e8c8a963d9a6258af67ee
Closes-Bug: #1750680
This commit is contained in:
Dan Smith 2018-02-20 14:41:35 -08:00
parent 4a03e3e5d4
commit b16c0f1053
2 changed files with 22 additions and 0 deletions

View File

@ -230,6 +230,24 @@ class TestDriverBlockDevice(test.NoDBTestCase):
bdm = getattr(self, attr % name)
bdm['attachment_id'] = self.attachment_id
@mock.patch('nova.virt.block_device.LOG')
@mock.patch('os_brick.encryptors')
def test_driver_detach_passes_failed(self, enc, log):
virt = mock.MagicMock()
virt.detach_volume.side_effect = exception.DeviceDetachFailed(
device='sda', reason='because testing')
driver_bdm = self.driver_classes['volume'](self.volume_bdm)
inst = mock.MagicMock(),
vol_api = mock.MagicMock()
# Make sure we pass through DeviceDetachFailed,
# but don't log it as an exception, just a warning
self.assertRaises(exception.DeviceDetachFailed,
driver_bdm.driver_detach,
self.context, inst, vol_api, virt)
self.assertFalse(log.exception.called)
self.assertTrue(log.warning.called)
def test_no_device_raises(self):
for name, cls in self.driver_classes.items():
bdm = fake_block_device.fake_bdm_object(

View File

@ -304,6 +304,10 @@ class DriverVolumeBlockDevice(DriverBlockDevice):
'%(mp)s : %(err)s',
{'volume_id': volume_id, 'mp': mp,
'err': err}, instance=instance)
except exception.DeviceDetachFailed as err:
with excutils.save_and_reraise_exception():
LOG.warning('Guest refused to detach volume %(vol)s',
{'vol': volume_id}, instance=instance)
except Exception:
with excutils.save_and_reraise_exception():
LOG.exception('Failed to detach volume '