2 # Copyright 2015 ClusterHQ
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
18 Exceptions that can be raised by libzfs_core operations.
20 from __future__
import absolute_import
, division
, print_function
23 from ._constants
import (
27 ZFS_ERR_CHECKPOINT_EXISTS
,
28 ZFS_ERR_DISCARDING_CHECKPOINT
,
29 ZFS_ERR_NO_CHECKPOINT
,
30 ZFS_ERR_DEVRM_IN_PROGRESS
,
37 class ZFSError(Exception):
43 if self
.name
is not None:
44 return "[Errno %d] %s: '%s'" % (
45 self
.errno
, self
.message
, self
.name
)
47 return "[Errno %d] %s" % (self
.errno
, self
.message
)
50 return "%s(%r, %r)" % (
51 self
.__class
__.__name
__, self
.errno
, self
.message
)
54 class ZFSGenericError(ZFSError
):
56 def __init__(self
, errno
, name
, message
):
58 self
.message
= message
62 class ZFSInitializationFailed(ZFSError
):
63 message
= "Failed to initialize libzfs_core"
65 def __init__(self
, errno
):
69 class MultipleOperationsFailure(ZFSError
):
71 def __init__(self
, errors
, suppressed_count
):
72 # Use first of the individual error codes
73 # as an overall error code. This is more consistent.
74 self
.errno
= errors
[0].errno
76 # this many errors were encountered but not placed on the `errors` list
77 self
.suppressed_count
= suppressed_count
80 return "%s, %d errors included, %d suppressed" % (
81 ZFSError
.__str
__(self
), len(self
.errors
), self
.suppressed_count
)
84 return "%s(%r, %r, errors=%r, suppressed=%r)" % (
85 self
.__class
__.__name
__, self
.errno
, self
.message
, self
.errors
,
86 self
.suppressed_count
)
89 class DatasetNotFound(ZFSError
):
92 This exception is raised when an operation failure can be caused by a
93 missing snapshot or a missing filesystem and it is impossible to
94 distinguish between the causes.
97 message
= "Dataset not found"
99 def __init__(self
, name
):
103 class DatasetExists(ZFSError
):
106 This exception is raised when an operation failure can be caused by an
107 existing snapshot or filesystem and it is impossible to distinguish between
111 message
= "Dataset already exists"
113 def __init__(self
, name
):
117 class NotClone(ZFSError
):
119 message
= "Filesystem is not a clone, can not promote"
121 def __init__(self
, name
):
125 class FilesystemExists(DatasetExists
):
126 message
= "Filesystem already exists"
128 def __init__(self
, name
):
132 class FilesystemNotFound(DatasetNotFound
):
133 message
= "Filesystem not found"
135 def __init__(self
, name
):
139 class ParentNotFound(ZFSError
):
141 message
= "Parent not found"
143 def __init__(self
, name
):
147 class WrongParent(ZFSError
):
148 errno
= ZFS_ERR_WRONG_PARENT
149 message
= "Parent dataset is not a filesystem"
151 def __init__(self
, name
):
155 class SnapshotExists(DatasetExists
):
156 message
= "Snapshot already exists"
158 def __init__(self
, name
):
162 class SnapshotNotFound(DatasetNotFound
):
163 message
= "Snapshot not found"
165 def __init__(self
, name
):
169 class SnapshotNotLatest(ZFSError
):
171 message
= "Snapshot is not the latest"
173 def __init__(self
, name
):
177 class SnapshotIsCloned(ZFSError
):
179 message
= "Snapshot is cloned"
181 def __init__(self
, name
):
185 class SnapshotIsHeld(ZFSError
):
187 message
= "Snapshot is held"
189 def __init__(self
, name
):
193 class DuplicateSnapshots(ZFSError
):
195 message
= "Requested multiple snapshots of the same filesystem"
197 def __init__(self
, name
):
201 class SnapshotFailure(MultipleOperationsFailure
):
202 message
= "Creation of snapshot(s) failed for one or more reasons"
204 def __init__(self
, errors
, suppressed_count
):
205 super(SnapshotFailure
, self
).__init
__(errors
, suppressed_count
)
208 class SnapshotDestructionFailure(MultipleOperationsFailure
):
209 message
= "Destruction of snapshot(s) failed for one or more reasons"
211 def __init__(self
, errors
, suppressed_count
):
212 super(SnapshotDestructionFailure
, self
).__init
__(
213 errors
, suppressed_count
)
216 class BookmarkExists(ZFSError
):
218 message
= "Bookmark already exists"
220 def __init__(self
, name
):
224 class BookmarkNotFound(ZFSError
):
226 message
= "Bookmark not found"
228 def __init__(self
, name
):
232 class BookmarkMismatch(ZFSError
):
234 message
= "source is not an ancestor of the new bookmark's dataset"
236 def __init__(self
, name
):
240 class BookmarkSourceInvalid(ZFSError
):
242 message
= "Bookmark source is not a valid snapshot or existing bookmark"
244 def __init__(self
, name
):
248 class BookmarkNotSupported(ZFSError
):
249 errno
= errno
.ENOTSUP
250 message
= "Bookmark feature is not supported"
252 def __init__(self
, name
):
256 class BookmarkFailure(MultipleOperationsFailure
):
257 message
= "Creation of bookmark(s) failed for one or more reasons"
259 def __init__(self
, errors
, suppressed_count
):
260 super(BookmarkFailure
, self
).__init
__(errors
, suppressed_count
)
263 class BookmarkDestructionFailure(MultipleOperationsFailure
):
264 message
= "Destruction of bookmark(s) failed for one or more reasons"
266 def __init__(self
, errors
, suppressed_count
):
267 super(BookmarkDestructionFailure
, self
).__init
__(
268 errors
, suppressed_count
)
271 class BadHoldCleanupFD(ZFSError
):
273 message
= "Bad file descriptor as cleanup file descriptor"
276 class HoldExists(ZFSError
):
278 message
= "Hold with a given tag already exists on snapshot"
280 def __init__(self
, name
):
284 class HoldNotFound(ZFSError
):
286 message
= "Hold with a given tag does not exist on snapshot"
288 def __init__(self
, name
):
292 class HoldFailure(MultipleOperationsFailure
):
293 message
= "Placement of hold(s) failed for one or more reasons"
295 def __init__(self
, errors
, suppressed_count
):
296 super(HoldFailure
, self
).__init
__(errors
, suppressed_count
)
299 class HoldReleaseFailure(MultipleOperationsFailure
):
300 message
= "Release of hold(s) failed for one or more reasons"
302 def __init__(self
, errors
, suppressed_count
):
303 super(HoldReleaseFailure
, self
).__init
__(errors
, suppressed_count
)
306 class SnapshotMismatch(ZFSError
):
308 message
= "Snapshot is not descendant of source snapshot"
310 def __init__(self
, name
):
314 class StreamMismatch(ZFSError
):
316 message
= "Stream is not applicable to destination dataset"
318 def __init__(self
, name
):
322 class DestinationModified(ZFSError
):
323 errno
= errno
.ETXTBSY
324 message
= "Destination dataset has modifications that can not be undone"
326 def __init__(self
, name
):
330 class BadStream(ZFSError
):
332 message
= "Bad backup stream"
335 class StreamFeatureNotSupported(ZFSError
):
336 errno
= errno
.ENOTSUP
337 message
= "Stream contains unsupported feature"
340 class UnknownStreamFeature(ZFSError
):
341 errno
= errno
.ENOTSUP
342 message
= "Unknown feature requested for stream"
345 class StreamFeatureInvalid(ZFSError
):
347 message
= "Kernel modules must be upgraded to receive this stream"
350 class StreamFeatureIncompatible(ZFSError
):
352 message
= "Incompatible embedded feature with encrypted receive"
355 class StreamTruncated(ZFSError
):
356 errno
= zfs_errno
.ZFS_ERR_STREAM_TRUNCATED
357 message
= "incomplete stream"
360 class ReceivePropertyFailure(MultipleOperationsFailure
):
361 message
= "Receiving of properties failed for one or more reasons"
363 def __init__(self
, errors
, suppressed_count
):
364 super(ReceivePropertyFailure
, self
).__init
__(errors
, suppressed_count
)
367 class StreamIOError(ZFSError
):
368 message
= "I/O error while writing or reading stream"
370 def __init__(self
, errno
):
374 class ZIOError(ZFSError
):
376 message
= "I/O error"
378 def __init__(self
, name
):
382 class NoSpace(ZFSError
):
384 message
= "No space left"
386 def __init__(self
, name
):
390 class QuotaExceeded(ZFSError
):
392 message
= "Quota exceeded"
394 def __init__(self
, name
):
398 class DatasetBusy(ZFSError
):
400 message
= "Dataset is busy"
402 def __init__(self
, name
):
406 class NameTooLong(ZFSError
):
407 errno
= errno
.ENAMETOOLONG
408 message
= "Dataset name is too long"
410 def __init__(self
, name
):
414 class NameInvalid(ZFSError
):
416 message
= "Invalid name"
418 def __init__(self
, name
):
422 class SnapshotNameInvalid(NameInvalid
):
423 message
= "Invalid name for snapshot"
425 def __init__(self
, name
):
429 class FilesystemNameInvalid(NameInvalid
):
430 message
= "Invalid name for filesystem or volume"
432 def __init__(self
, name
):
436 class BookmarkNameInvalid(NameInvalid
):
437 message
= "Invalid name for bookmark"
439 def __init__(self
, name
):
443 class ReadOnlyPool(ZFSError
):
445 message
= "Pool is read-only"
447 def __init__(self
, name
):
451 class SuspendedPool(ZFSError
):
453 message
= "Pool is suspended"
455 def __init__(self
, name
):
459 class PoolNotFound(ZFSError
):
461 message
= "No such pool"
463 def __init__(self
, name
):
467 class PoolsDiffer(ZFSError
):
469 message
= "Source and target belong to different pools"
471 def __init__(self
, name
):
475 class FeatureNotSupported(ZFSError
):
476 errno
= errno
.ENOTSUP
477 message
= "Feature is not supported in this version"
479 def __init__(self
, name
):
483 class PropertyNotSupported(ZFSError
):
484 errno
= errno
.ENOTSUP
485 message
= "Property is not supported in this version"
487 def __init__(self
, name
):
491 class PropertyInvalid(ZFSError
):
493 message
= "Invalid property or property value"
495 def __init__(self
, name
):
499 class DatasetTypeInvalid(ZFSError
):
501 message
= "Specified dataset type is unknown"
503 def __init__(self
, name
):
507 class UnknownCryptCommand(ZFSError
):
509 message
= "Specified crypt command is invalid"
511 def __init__(self
, name
):
515 class EncryptionKeyNotLoaded(ZFSError
):
517 message
= "Encryption key is not currently loaded"
520 class EncryptionKeyAlreadyLoaded(ZFSError
):
522 message
= "Encryption key is already loaded"
525 class EncryptionKeyInvalid(ZFSError
):
527 message
= "Incorrect encryption key provided"
530 class ZCPError(ZFSError
):
535 class ZCPSyntaxError(ZCPError
):
537 message
= "Channel program contains syntax errors"
539 def __init__(self
, details
):
540 self
.details
= details
543 class ZCPRuntimeError(ZCPError
):
545 message
= "Channel programs encountered a runtime error"
547 def __init__(self
, details
):
548 self
.details
= details
551 class ZCPLimitInvalid(ZCPError
):
553 message
= "Channel program called with invalid limits"
556 class ZCPTimeout(ZCPError
):
558 message
= "Channel program timed out"
561 class ZCPSpaceError(ZCPError
):
563 message
= "Channel program exhausted the memory limit"
566 class ZCPMemoryError(ZCPError
):
568 message
= "Channel program return value too large"
571 class ZCPPermissionError(ZCPError
):
573 message
= "Channel programs must be run as root"
576 class CheckpointExists(ZFSError
):
577 errno
= ZFS_ERR_CHECKPOINT_EXISTS
578 message
= "Pool already has a checkpoint"
581 class CheckpointNotFound(ZFSError
):
582 errno
= ZFS_ERR_NO_CHECKPOINT
583 message
= "Pool does not have a checkpoint"
586 class CheckpointDiscarding(ZFSError
):
587 errno
= ZFS_ERR_DISCARDING_CHECKPOINT
588 message
= "Pool checkpoint is being discarded"
591 class DeviceRemovalRunning(ZFSError
):
592 errno
= ZFS_ERR_DEVRM_IN_PROGRESS
593 message
= "A vdev is currently being removed"
596 class DeviceTooBig(ZFSError
):
597 errno
= ZFS_ERR_VDEV_TOO_BIG
598 message
= "One or more top-level vdevs exceed the maximum vdev size"
601 # vim: softtabstop=4 tabstop=4 expandtab shiftwidth=4