# # Copyright 2015 ClusterHQ # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # """ Exceptions that can be raised by libzfs_core operations. """ from __future__ import absolute_import, division, print_function import errno from ._constants import ( ECHRNG, ECKSUM, ETIME, ZFS_ERR_CHECKPOINT_EXISTS, ZFS_ERR_DISCARDING_CHECKPOINT, ZFS_ERR_NO_CHECKPOINT, ZFS_ERR_DEVRM_IN_PROGRESS, ZFS_ERR_VDEV_TOO_BIG, ZFS_ERR_WRONG_PARENT, zfs_errno ) class ZFSError(Exception): errno = None message = None name = None def __str__(self): if self.name is not None: return "[Errno %d] %s: '%s'" % ( self.errno, self.message, self.name) else: return "[Errno %d] %s" % (self.errno, self.message) def __repr__(self): return "%s(%r, %r)" % ( self.__class__.__name__, self.errno, self.message) class ZFSGenericError(ZFSError): def __init__(self, errno, name, message): self.errno = errno self.message = message self.name = name class ZFSInitializationFailed(ZFSError): message = "Failed to initialize libzfs_core" def __init__(self, errno): self.errno = errno class MultipleOperationsFailure(ZFSError): def __init__(self, errors, suppressed_count): # Use first of the individual error codes # as an overall error code. This is more consistent. self.errno = errors[0].errno self.errors = errors # this many errors were encountered but not placed on the `errors` list self.suppressed_count = suppressed_count def __str__(self): return "%s, %d errors included, %d suppressed" % ( ZFSError.__str__(self), len(self.errors), self.suppressed_count) def __repr__(self): return "%s(%r, %r, errors=%r, suppressed=%r)" % ( self.__class__.__name__, self.errno, self.message, self.errors, self.suppressed_count) class DatasetNotFound(ZFSError): """ This exception is raised when an operation failure can be caused by a missing snapshot or a missing filesystem and it is impossible to distinguish between the causes. """ errno = errno.ENOENT message = "Dataset not found" def __init__(self, name): self.name = name class DatasetExists(ZFSError): """ This exception is raised when an operation failure can be caused by an existing snapshot or filesystem and it is impossible to distinguish between the causes. """ errno = errno.EEXIST message = "Dataset already exists" def __init__(self, name): self.name = name class NotClone(ZFSError): errno = errno.EINVAL message = "Filesystem is not a clone, can not promote" def __init__(self, name): self.name = name class FilesystemExists(DatasetExists): message = "Filesystem already exists" def __init__(self, name): self.name = name class FilesystemNotFound(DatasetNotFound): message = "Filesystem not found" def __init__(self, name): self.name = name class ParentNotFound(ZFSError): errno = errno.ENOENT message = "Parent not found" def __init__(self, name): self.name = name class WrongParent(ZFSError): errno = ZFS_ERR_WRONG_PARENT message = "Parent dataset is not a filesystem" def __init__(self, name): self.name = name class SnapshotExists(DatasetExists): message = "Snapshot already exists" def __init__(self, name): self.name = name class SnapshotNotFound(DatasetNotFound): message = "Snapshot not found" def __init__(self, name): self.name = name class SnapshotNotLatest(ZFSError): errno = errno.EEXIST message = "Snapshot is not the latest" def __init__(self, name): self.name = name class SnapshotIsCloned(ZFSError): errno = errno.EEXIST message = "Snapshot is cloned" def __init__(self, name): self.name = name class SnapshotIsHeld(ZFSError): errno = errno.EBUSY message = "Snapshot is held" def __init__(self, name): self.name = name class DuplicateSnapshots(ZFSError): errno = errno.EXDEV message = "Requested multiple snapshots of the same filesystem" def __init__(self, name): self.name = name class SnapshotFailure(MultipleOperationsFailure): message = "Creation of snapshot(s) failed for one or more reasons" def __init__(self, errors, suppressed_count): super(SnapshotFailure, self).__init__(errors, suppressed_count) class SnapshotDestructionFailure(MultipleOperationsFailure): message = "Destruction of snapshot(s) failed for one or more reasons" def __init__(self, errors, suppressed_count): super(SnapshotDestructionFailure, self).__init__( errors, suppressed_count) class BookmarkExists(ZFSError): errno = errno.EEXIST message = "Bookmark already exists" def __init__(self, name): self.name = name class BookmarkNotFound(ZFSError): errno = errno.ENOENT message = "Bookmark not found" def __init__(self, name): self.name = name class BookmarkMismatch(ZFSError): errno = errno.EINVAL message = "source is not an ancestor of the new bookmark's dataset" def __init__(self, name): self.name = name class BookmarkSourceInvalid(ZFSError): errno = errno.EINVAL message = "Bookmark source is not a valid snapshot or existing bookmark" def __init__(self, name): self.name = name class BookmarkNotSupported(ZFSError): errno = errno.ENOTSUP message = "Bookmark feature is not supported" def __init__(self, name): self.name = name class BookmarkFailure(MultipleOperationsFailure): message = "Creation of bookmark(s) failed for one or more reasons" def __init__(self, errors, suppressed_count): super(BookmarkFailure, self).__init__(errors, suppressed_count) class BookmarkDestructionFailure(MultipleOperationsFailure): message = "Destruction of bookmark(s) failed for one or more reasons" def __init__(self, errors, suppressed_count): super(BookmarkDestructionFailure, self).__init__( errors, suppressed_count) class BadHoldCleanupFD(ZFSError): errno = errno.EBADF message = "Bad file descriptor as cleanup file descriptor" class HoldExists(ZFSError): errno = errno.EEXIST message = "Hold with a given tag already exists on snapshot" def __init__(self, name): self.name = name class HoldNotFound(ZFSError): errno = errno.ENOENT message = "Hold with a given tag does not exist on snapshot" def __init__(self, name): self.name = name class HoldFailure(MultipleOperationsFailure): message = "Placement of hold(s) failed for one or more reasons" def __init__(self, errors, suppressed_count): super(HoldFailure, self).__init__(errors, suppressed_count) class HoldReleaseFailure(MultipleOperationsFailure): message = "Release of hold(s) failed for one or more reasons" def __init__(self, errors, suppressed_count): super(HoldReleaseFailure, self).__init__(errors, suppressed_count) class SnapshotMismatch(ZFSError): errno = errno.ENODEV message = "Snapshot is not descendant of source snapshot" def __init__(self, name): self.name = name class StreamMismatch(ZFSError): errno = errno.ENODEV message = "Stream is not applicable to destination dataset" def __init__(self, name): self.name = name class DestinationModified(ZFSError): errno = errno.ETXTBSY message = "Destination dataset has modifications that can not be undone" def __init__(self, name): self.name = name class BadStream(ZFSError): errno = ECKSUM message = "Bad backup stream" class StreamFeatureNotSupported(ZFSError): errno = errno.ENOTSUP message = "Stream contains unsupported feature" class UnknownStreamFeature(ZFSError): errno = errno.ENOTSUP message = "Unknown feature requested for stream" class StreamFeatureInvalid(ZFSError): errno = errno.EINVAL message = "Kernel modules must be upgraded to receive this stream" class StreamFeatureIncompatible(ZFSError): errno = errno.EINVAL message = "Incompatible embedded feature with encrypted receive" class StreamTruncated(ZFSError): errno = zfs_errno.ZFS_ERR_STREAM_TRUNCATED message = "incomplete stream" class ReceivePropertyFailure(MultipleOperationsFailure): message = "Receiving of properties failed for one or more reasons" def __init__(self, errors, suppressed_count): super(ReceivePropertyFailure, self).__init__(errors, suppressed_count) class StreamIOError(ZFSError): message = "I/O error while writing or reading stream" def __init__(self, errno): self.errno = errno class ZIOError(ZFSError): errno = errno.EIO message = "I/O error" def __init__(self, name): self.name = name class NoSpace(ZFSError): errno = errno.ENOSPC message = "No space left" def __init__(self, name): self.name = name class QuotaExceeded(ZFSError): errno = errno.EDQUOT message = "Quota exceeded" def __init__(self, name): self.name = name class DatasetBusy(ZFSError): errno = errno.EBUSY message = "Dataset is busy" def __init__(self, name): self.name = name class NameTooLong(ZFSError): errno = errno.ENAMETOOLONG message = "Dataset name is too long" def __init__(self, name): self.name = name class NameInvalid(ZFSError): errno = errno.EINVAL message = "Invalid name" def __init__(self, name): self.name = name class SnapshotNameInvalid(NameInvalid): message = "Invalid name for snapshot" def __init__(self, name): self.name = name class FilesystemNameInvalid(NameInvalid): message = "Invalid name for filesystem or volume" def __init__(self, name): self.name = name class BookmarkNameInvalid(NameInvalid): message = "Invalid name for bookmark" def __init__(self, name): self.name = name class ReadOnlyPool(ZFSError): errno = errno.EROFS message = "Pool is read-only" def __init__(self, name): self.name = name class SuspendedPool(ZFSError): errno = errno.EAGAIN message = "Pool is suspended" def __init__(self, name): self.name = name class PoolNotFound(ZFSError): errno = errno.EXDEV message = "No such pool" def __init__(self, name): self.name = name class PoolsDiffer(ZFSError): errno = errno.EXDEV message = "Source and target belong to different pools" def __init__(self, name): self.name = name class FeatureNotSupported(ZFSError): errno = errno.ENOTSUP message = "Feature is not supported in this version" def __init__(self, name): self.name = name class PropertyNotSupported(ZFSError): errno = errno.ENOTSUP message = "Property is not supported in this version" def __init__(self, name): self.name = name class PropertyInvalid(ZFSError): errno = errno.EINVAL message = "Invalid property or property value" def __init__(self, name): self.name = name class DatasetTypeInvalid(ZFSError): errno = errno.EINVAL message = "Specified dataset type is unknown" def __init__(self, name): self.name = name class UnknownCryptCommand(ZFSError): errno = errno.EINVAL message = "Specified crypt command is invalid" def __init__(self, name): self.name = name class EncryptionKeyNotLoaded(ZFSError): errno = errno.EACCES message = "Encryption key is not currently loaded" class EncryptionKeyAlreadyLoaded(ZFSError): errno = errno.EEXIST message = "Encryption key is already loaded" class EncryptionKeyInvalid(ZFSError): errno = errno.EACCES message = "Incorrect encryption key provided" class ZCPError(ZFSError): errno = None message = None class ZCPSyntaxError(ZCPError): errno = errno.EINVAL message = "Channel program contains syntax errors" def __init__(self, details): self.details = details class ZCPRuntimeError(ZCPError): errno = ECHRNG message = "Channel programs encountered a runtime error" def __init__(self, details): self.details = details class ZCPLimitInvalid(ZCPError): errno = errno.EINVAL message = "Channel program called with invalid limits" class ZCPTimeout(ZCPError): errno = ETIME message = "Channel program timed out" class ZCPSpaceError(ZCPError): errno = errno.ENOSPC message = "Channel program exhausted the memory limit" class ZCPMemoryError(ZCPError): errno = errno.ENOMEM message = "Channel program return value too large" class ZCPPermissionError(ZCPError): errno = errno.EPERM message = "Channel programs must be run as root" class CheckpointExists(ZFSError): errno = ZFS_ERR_CHECKPOINT_EXISTS message = "Pool already has a checkpoint" class CheckpointNotFound(ZFSError): errno = ZFS_ERR_NO_CHECKPOINT message = "Pool does not have a checkpoint" class CheckpointDiscarding(ZFSError): errno = ZFS_ERR_DISCARDING_CHECKPOINT message = "Pool checkpoint is being discarded" class DeviceRemovalRunning(ZFSError): errno = ZFS_ERR_DEVRM_IN_PROGRESS message = "A vdev is currently being removed" class DeviceTooBig(ZFSError): errno = ZFS_ERR_VDEV_TOO_BIG message = "One or more top-level vdevs exceed the maximum vdev size" # vim: softtabstop=4 tabstop=4 expandtab shiftwidth=4