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
,
33 ZFS_ERR_RAIDZ_EXPAND_IN_PROGRESS
,
38 class ZFSError(Exception):
44 if self
.name
is not None:
45 return "[Errno %d] %s: '%s'" % (
46 self
.errno
, self
.message
, self
.name
)
48 return "[Errno %d] %s" % (self
.errno
, self
.message
)
51 return "%s(%r, %r)" % (
52 self
.__class
__.__name
__, self
.errno
, self
.message
)
55 class ZFSGenericError(ZFSError
):
57 def __init__(self
, errno
, name
, message
):
59 self
.message
= message
63 class ZFSInitializationFailed(ZFSError
):
64 message
= "Failed to initialize libzfs_core"
66 def __init__(self
, errno
):
70 class MultipleOperationsFailure(ZFSError
):
72 def __init__(self
, errors
, suppressed_count
):
73 # Use first of the individual error codes
74 # as an overall error code. This is more consistent.
75 self
.errno
= errors
[0].errno
77 # this many errors were encountered but not placed on the `errors` list
78 self
.suppressed_count
= suppressed_count
81 return "%s, %d errors included, %d suppressed" % (
82 ZFSError
.__str
__(self
), len(self
.errors
), self
.suppressed_count
)
85 return "%s(%r, %r, errors=%r, suppressed=%r)" % (
86 self
.__class
__.__name
__, self
.errno
, self
.message
, self
.errors
,
87 self
.suppressed_count
)
90 class DatasetNotFound(ZFSError
):
93 This exception is raised when an operation failure can be caused by a
94 missing snapshot or a missing filesystem and it is impossible to
95 distinguish between the causes.
98 message
= "Dataset not found"
100 def __init__(self
, name
):
104 class DatasetExists(ZFSError
):
107 This exception is raised when an operation failure can be caused by an
108 existing snapshot or filesystem and it is impossible to distinguish between
112 message
= "Dataset already exists"
114 def __init__(self
, name
):
118 class NotClone(ZFSError
):
120 message
= "Filesystem is not a clone, can not promote"
122 def __init__(self
, name
):
126 class FilesystemExists(DatasetExists
):
127 message
= "Filesystem already exists"
129 def __init__(self
, name
):
133 class FilesystemNotFound(DatasetNotFound
):
134 message
= "Filesystem not found"
136 def __init__(self
, name
):
140 class ParentNotFound(ZFSError
):
142 message
= "Parent not found"
144 def __init__(self
, name
):
148 class WrongParent(ZFSError
):
149 errno
= ZFS_ERR_WRONG_PARENT
150 message
= "Parent dataset is not a filesystem"
152 def __init__(self
, name
):
156 class SnapshotExists(DatasetExists
):
157 message
= "Snapshot already exists"
159 def __init__(self
, name
):
163 class SnapshotNotFound(DatasetNotFound
):
164 message
= "Snapshot not found"
166 def __init__(self
, name
):
170 class SnapshotNotLatest(ZFSError
):
172 message
= "Snapshot is not the latest"
174 def __init__(self
, name
):
178 class SnapshotIsCloned(ZFSError
):
180 message
= "Snapshot is cloned"
182 def __init__(self
, name
):
186 class SnapshotIsHeld(ZFSError
):
188 message
= "Snapshot is held"
190 def __init__(self
, name
):
194 class DuplicateSnapshots(ZFSError
):
196 message
= "Requested multiple snapshots of the same filesystem"
198 def __init__(self
, name
):
202 class SnapshotFailure(MultipleOperationsFailure
):
203 message
= "Creation of snapshot(s) failed for one or more reasons"
205 def __init__(self
, errors
, suppressed_count
):
206 super(SnapshotFailure
, self
).__init
__(errors
, suppressed_count
)
209 class SnapshotDestructionFailure(MultipleOperationsFailure
):
210 message
= "Destruction of snapshot(s) failed for one or more reasons"
212 def __init__(self
, errors
, suppressed_count
):
213 super(SnapshotDestructionFailure
, self
).__init
__(
214 errors
, suppressed_count
)
217 class BookmarkExists(ZFSError
):
219 message
= "Bookmark already exists"
221 def __init__(self
, name
):
225 class BookmarkNotFound(ZFSError
):
227 message
= "Bookmark not found"
229 def __init__(self
, name
):
233 class BookmarkMismatch(ZFSError
):
235 message
= "source is not an ancestor of the new bookmark's dataset"
237 def __init__(self
, name
):
241 class BookmarkSourceInvalid(ZFSError
):
243 message
= "Bookmark source is not a valid snapshot or existing bookmark"
245 def __init__(self
, name
):
249 class BookmarkNotSupported(ZFSError
):
250 errno
= errno
.ENOTSUP
251 message
= "Bookmark feature is not supported"
253 def __init__(self
, name
):
257 class BookmarkFailure(MultipleOperationsFailure
):
258 message
= "Creation of bookmark(s) failed for one or more reasons"
260 def __init__(self
, errors
, suppressed_count
):
261 super(BookmarkFailure
, self
).__init
__(errors
, suppressed_count
)
264 class BookmarkDestructionFailure(MultipleOperationsFailure
):
265 message
= "Destruction of bookmark(s) failed for one or more reasons"
267 def __init__(self
, errors
, suppressed_count
):
268 super(BookmarkDestructionFailure
, self
).__init
__(
269 errors
, suppressed_count
)
272 class BadHoldCleanupFD(ZFSError
):
274 message
= "Bad file descriptor as cleanup file descriptor"
277 class HoldExists(ZFSError
):
279 message
= "Hold with a given tag already exists on snapshot"
281 def __init__(self
, name
):
285 class HoldNotFound(ZFSError
):
287 message
= "Hold with a given tag does not exist on snapshot"
289 def __init__(self
, name
):
293 class HoldFailure(MultipleOperationsFailure
):
294 message
= "Placement of hold(s) failed for one or more reasons"
296 def __init__(self
, errors
, suppressed_count
):
297 super(HoldFailure
, self
).__init
__(errors
, suppressed_count
)
300 class HoldReleaseFailure(MultipleOperationsFailure
):
301 message
= "Release of hold(s) failed for one or more reasons"
303 def __init__(self
, errors
, suppressed_count
):
304 super(HoldReleaseFailure
, self
).__init
__(errors
, suppressed_count
)
307 class SnapshotMismatch(ZFSError
):
309 message
= "Snapshot is not descendant of source snapshot"
311 def __init__(self
, name
):
315 class StreamMismatch(ZFSError
):
317 message
= "Stream is not applicable to destination dataset"
319 def __init__(self
, name
):
323 class DestinationModified(ZFSError
):
324 errno
= errno
.ETXTBSY
325 message
= "Destination dataset has modifications that can not be undone"
327 def __init__(self
, name
):
331 class BadStream(ZFSError
):
333 message
= "Bad backup stream"
336 class StreamFeatureNotSupported(ZFSError
):
337 errno
= errno
.ENOTSUP
338 message
= "Stream contains unsupported feature"
341 class UnknownStreamFeature(ZFSError
):
342 errno
= errno
.ENOTSUP
343 message
= "Unknown feature requested for stream"
346 class StreamFeatureInvalid(ZFSError
):
348 message
= "Kernel modules must be upgraded to receive this stream"
351 class StreamFeatureIncompatible(ZFSError
):
353 message
= "Incompatible embedded feature with encrypted receive"
356 class StreamTruncated(ZFSError
):
357 errno
= zfs_errno
.ZFS_ERR_STREAM_TRUNCATED
358 message
= "incomplete stream"
361 class ReceivePropertyFailure(MultipleOperationsFailure
):
362 message
= "Receiving of properties failed for one or more reasons"
364 def __init__(self
, errors
, suppressed_count
):
365 super(ReceivePropertyFailure
, self
).__init
__(errors
, suppressed_count
)
368 class StreamIOError(ZFSError
):
369 message
= "I/O error while writing or reading stream"
371 def __init__(self
, errno
):
375 class ZIOError(ZFSError
):
377 message
= "I/O error"
379 def __init__(self
, name
):
383 class NoSpace(ZFSError
):
385 message
= "No space left"
387 def __init__(self
, name
):
391 class QuotaExceeded(ZFSError
):
393 message
= "Quota exceeded"
395 def __init__(self
, name
):
399 class DatasetBusy(ZFSError
):
401 message
= "Dataset is busy"
403 def __init__(self
, name
):
407 class NameTooLong(ZFSError
):
408 errno
= errno
.ENAMETOOLONG
409 message
= "Dataset name is too long"
411 def __init__(self
, name
):
415 class NameInvalid(ZFSError
):
417 message
= "Invalid name"
419 def __init__(self
, name
):
423 class SnapshotNameInvalid(NameInvalid
):
424 message
= "Invalid name for snapshot"
426 def __init__(self
, name
):
430 class FilesystemNameInvalid(NameInvalid
):
431 message
= "Invalid name for filesystem or volume"
433 def __init__(self
, name
):
437 class BookmarkNameInvalid(NameInvalid
):
438 message
= "Invalid name for bookmark"
440 def __init__(self
, name
):
444 class ReadOnlyPool(ZFSError
):
446 message
= "Pool is read-only"
448 def __init__(self
, name
):
452 class SuspendedPool(ZFSError
):
454 message
= "Pool is suspended"
456 def __init__(self
, name
):
460 class PoolNotFound(ZFSError
):
462 message
= "No such pool"
464 def __init__(self
, name
):
468 class PoolsDiffer(ZFSError
):
470 message
= "Source and target belong to different pools"
472 def __init__(self
, name
):
476 class FeatureNotSupported(ZFSError
):
477 errno
= errno
.ENOTSUP
478 message
= "Feature is not supported in this version"
480 def __init__(self
, name
):
484 class PropertyNotSupported(ZFSError
):
485 errno
= errno
.ENOTSUP
486 message
= "Property is not supported in this version"
488 def __init__(self
, name
):
492 class PropertyInvalid(ZFSError
):
494 message
= "Invalid property or property value"
496 def __init__(self
, name
):
500 class DatasetTypeInvalid(ZFSError
):
502 message
= "Specified dataset type is unknown"
504 def __init__(self
, name
):
508 class UnknownCryptCommand(ZFSError
):
510 message
= "Specified crypt command is invalid"
512 def __init__(self
, name
):
516 class EncryptionKeyNotLoaded(ZFSError
):
518 message
= "Encryption key is not currently loaded"
521 class EncryptionKeyAlreadyLoaded(ZFSError
):
523 message
= "Encryption key is already loaded"
526 class EncryptionKeyInvalid(ZFSError
):
528 message
= "Incorrect encryption key provided"
531 class ZCPError(ZFSError
):
536 class ZCPSyntaxError(ZCPError
):
538 message
= "Channel program contains syntax errors"
540 def __init__(self
, details
):
541 self
.details
= details
544 class ZCPRuntimeError(ZCPError
):
546 message
= "Channel programs encountered a runtime error"
548 def __init__(self
, details
):
549 self
.details
= details
552 class ZCPLimitInvalid(ZCPError
):
554 message
= "Channel program called with invalid limits"
557 class ZCPTimeout(ZCPError
):
559 message
= "Channel program timed out"
562 class ZCPSpaceError(ZCPError
):
564 message
= "Channel program exhausted the memory limit"
567 class ZCPMemoryError(ZCPError
):
569 message
= "Channel program return value too large"
572 class ZCPPermissionError(ZCPError
):
574 message
= "Channel programs must be run as root"
577 class CheckpointExists(ZFSError
):
578 errno
= ZFS_ERR_CHECKPOINT_EXISTS
579 message
= "Pool already has a checkpoint"
582 class CheckpointNotFound(ZFSError
):
583 errno
= ZFS_ERR_NO_CHECKPOINT
584 message
= "Pool does not have a checkpoint"
587 class CheckpointDiscarding(ZFSError
):
588 errno
= ZFS_ERR_DISCARDING_CHECKPOINT
589 message
= "Pool checkpoint is being discarded"
592 class DeviceRemovalRunning(ZFSError
):
593 errno
= ZFS_ERR_DEVRM_IN_PROGRESS
594 message
= "A vdev is currently being removed"
597 class DeviceTooBig(ZFSError
):
598 errno
= ZFS_ERR_VDEV_TOO_BIG
599 message
= "One or more top-level vdevs exceed the maximum vdev size"
602 class RaidzExpansionRunning(ZFSError
):
603 errno
= ZFS_ERR_RAIDZ_EXPAND_IN_PROGRESS
604 message
= "A raidz device is currently expanding"
607 # vim: softtabstop=4 tabstop=4 expandtab shiftwidth=4