class ImageBusy(Error):
pass
+class ImageHasSnapshots(Error):
+ pass
+
def make_ex(ret, msg):
"""
Translate a librbd return code into an exception.
:returns: a subclass of :class:`Error`
"""
errors = {
- errno.EPERM : PermissionError,
- errno.ENOENT : ImageNotFound,
- errno.EIO : IOError,
- errno.ENOSPC : NoSpace,
- errno.EEXIST : ImageExists,
- errno.EINVAL : InvalidArgument,
- errno.EROFS : ReadOnlyImage,
- errno.EBUSY : ImageBusy,
+ errno.EPERM : PermissionError,
+ errno.ENOENT : ImageNotFound,
+ errno.EIO : IOError,
+ errno.ENOSPC : NoSpace,
+ errno.EEXIST : ImageExists,
+ errno.EINVAL : InvalidArgument,
+ errno.EROFS : ReadOnlyImage,
+ errno.EBUSY : ImageBusy,
+ errno.ENOTEMPTY : ImageHasSnapshots,
}
ret = abs(ret)
if ret in errors:
not return until every object that comprises the image has
been deleted. Note that all snapshots must be deleted before
the image can be removed. If there are snapshots left,
+ :class:`ImageHasSnapshots` is raised. If the image is still
+ open, or the watch from a crashed client has not expired,
:class:`ImageBusy` is raised.
:param ioctx: determines which RADOS pool the image is in
:type ioctx: :class:`rados.Ioctx`
:param name: the name of the image to remove
:type name: str
- :raises: :class:`ImageNotFound`, :class:`ImageBusy`
+ :raises: :class:`ImageNotFound`, :class:`ImageBusy`,
+ :class:`ImageHasSnapshots`
"""
if not isinstance(name, str):
raise TypeError('name must be a string')
from nose.tools import eq_ as eq, assert_raises
from rados import Rados
from rbd import (RBD, Image, ImageNotFound, InvalidArgument, ImageExists,
- ImageBusy)
+ ImageBusy, ImageHasSnapshots)
rados = None
def test_remove_with_snap(self):
self.image.create_snap('snap1')
- assert_raises(ImageBusy, remove_image)
+ assert_raises(ImageHasSnapshots, remove_image)
self.image.remove_snap('snap1')
+ def test_remove_with_watcher(self):
+ assert_raises(ImageBusy, remove_image)
+
def test_rollback_to_snap(self):
self.image.write('\0' * 256, 0)
self.image.create_snap('snap1')