Libvirt: Allow missing volumes during delete
When deleting an instance, libvirt driver will clear all the volumes of the instance. Ignore exception when clearing a missing volume to avoid delete instance error. Closes-Bug: 1404791 Change-Id: I8a663e8f0396bf2303642610ae1001c330159b75
This commit is contained in:
parent
10a7974b3a
commit
11fb3936a1
@ -50,10 +50,20 @@ class LvmTestCase(test.NoDBTestCase):
|
||||
self.assertRaises(exception.VolumeBDMPathNotFound,
|
||||
lvm.get_volume_size, '/dev/foo')
|
||||
|
||||
@mock.patch.object(utils, 'execute',
|
||||
side_effect=processutils.ProcessExecutionError(
|
||||
stderr=('blockdev: cannot open /dev/foo: '
|
||||
'No such file or directory')))
|
||||
def test_get_volume_size_not_found_file(self, mock_execute):
|
||||
self.assertRaises(exception.VolumeBDMPathNotFound,
|
||||
lvm.get_volume_size, '/dev/foo')
|
||||
|
||||
@mock.patch.object(libvirt_utils, 'path_exists', return_value=True)
|
||||
@mock.patch.object(utils, 'execute',
|
||||
side_effect=processutils.ProcessExecutionError(
|
||||
stderr='blockdev: i am sad in other ways'))
|
||||
def test_get_volume_size_unexpectd_error(self, mock_execute):
|
||||
def test_get_volume_size_unexpectd_error(self, mock_execute,
|
||||
mock_path_exists):
|
||||
self.assertRaises(processutils.ProcessExecutionError,
|
||||
lvm.get_volume_size, '/dev/foo')
|
||||
|
||||
@ -168,6 +178,13 @@ class LvmTestCase(test.NoDBTestCase):
|
||||
lvm.clear_volume('/dev/vd')
|
||||
self.assertEqual(expected_commands, executes)
|
||||
|
||||
@mock.patch.object(utils, 'execute',
|
||||
side_effect=processutils.ProcessExecutionError(
|
||||
stderr=('blockdev: cannot open /dev/foo: '
|
||||
'No such file or directory')))
|
||||
def test_lvm_clear_ignore_lvm_not_found(self, mock_execute):
|
||||
lvm.clear_volume('/dev/foo')
|
||||
|
||||
def test_fail_remove_all_logical_volumes(self):
|
||||
def fake_execute(*args, **kwargs):
|
||||
if 'vol2' in args:
|
||||
|
@ -19,8 +19,6 @@
|
||||
# under the License.
|
||||
#
|
||||
|
||||
import functools
|
||||
|
||||
from oslo_concurrency import processutils
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
@ -31,7 +29,6 @@ from nova import exception
|
||||
from nova.i18n import _
|
||||
from nova.i18n import _LE
|
||||
from nova.i18n import _LW
|
||||
from nova import utils as nova_utils
|
||||
from nova.virt.libvirt import utils
|
||||
|
||||
|
||||
@ -51,28 +48,6 @@ CONF.import_opt('instances_path', 'nova.compute.manager')
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@nova_utils.expects_func_args('path')
|
||||
def wrap_no_device_error(function):
|
||||
"""Wraps a method to catch exceptions related to volume BDM not found.
|
||||
|
||||
This decorator wraps a method to catch ProcessExecutionError having to do
|
||||
with a missing volume block device mapping. It translates the error to a
|
||||
VolumeBDMPathNotFound exception.
|
||||
"""
|
||||
|
||||
@functools.wraps(function)
|
||||
def decorated_function(path):
|
||||
try:
|
||||
return function(path)
|
||||
except processutils.ProcessExecutionError as e:
|
||||
if 'No such device or address' in e.stderr:
|
||||
raise exception.VolumeBDMPathNotFound(path=path)
|
||||
else:
|
||||
raise
|
||||
|
||||
return decorated_function
|
||||
|
||||
|
||||
def create_volume(vg, lv, size, sparse=False):
|
||||
"""Create LVM image.
|
||||
|
||||
@ -184,7 +159,6 @@ def volume_info(path):
|
||||
return dict(zip(*info))
|
||||
|
||||
|
||||
@wrap_no_device_error
|
||||
def get_volume_size(path):
|
||||
"""Get logical volume size in bytes.
|
||||
|
||||
@ -193,9 +167,14 @@ def get_volume_size(path):
|
||||
fails in some unexpected way.
|
||||
:raises: exception.VolumeBDMPathNotFound if the volume path does not exist.
|
||||
"""
|
||||
out, _err = utils.execute('blockdev', '--getsize64', path,
|
||||
run_as_root=True)
|
||||
|
||||
try:
|
||||
out, _err = utils.execute('blockdev', '--getsize64', path,
|
||||
run_as_root=True)
|
||||
except processutils.ProcessExecutionError:
|
||||
if not utils.path_exists(path):
|
||||
raise exception.VolumeBDMPathNotFound(path=path)
|
||||
else:
|
||||
raise
|
||||
return int(out)
|
||||
|
||||
|
||||
@ -246,7 +225,13 @@ def clear_volume(path):
|
||||
return
|
||||
|
||||
volume_clear_size = int(CONF.libvirt.volume_clear_size) * units.Mi
|
||||
volume_size = get_volume_size(path)
|
||||
|
||||
try:
|
||||
volume_size = get_volume_size(path)
|
||||
except exception.VolumeBDMPathNotFound:
|
||||
LOG.warn(_LW('ignoring missing logical volume %(path)s'),
|
||||
{'path': path})
|
||||
return
|
||||
|
||||
if volume_clear_size != 0 and volume_clear_size < volume_size:
|
||||
volume_size = volume_clear_size
|
||||
|
Loading…
Reference in New Issue
Block a user