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 Helper routines for converting ``errno`` style error codes from C functions
19 to Python exceptions defined by `libzfs_core` API.
21 The conversion heavily depends on the context of the error: the attempted
22 operation and the input parameters. For this reason, there is a conversion
23 routine for each `libzfs_core` interface function. The conversion routines
24 have the return code as a parameter as well as all the parameters of the
25 corresponding interface functions.
27 The parameters and exceptions are documented in the `libzfs_core` interfaces.
29 from __future__
import absolute_import
, division
, print_function
34 from . import exceptions
as lzc_exc
35 from ._constants
import (
40 ZFS_ERR_CHECKPOINT_EXISTS
,
41 ZFS_ERR_DISCARDING_CHECKPOINT
,
42 ZFS_ERR_NO_CHECKPOINT
,
43 ZFS_ERR_DEVRM_IN_PROGRESS
,
46 ZFS_ERR_RAIDZ_EXPAND_IN_PROGRESS
,
51 def lzc_create_translate_error(ret
, name
, ds_type
, props
):
54 if ret
== errno
.EINVAL
:
55 _validate_fs_name(name
)
56 raise lzc_exc
.PropertyInvalid(name
)
57 if ret
== errno
.EEXIST
:
58 raise lzc_exc
.FilesystemExists(name
)
59 if ret
== errno
.ENOENT
:
60 raise lzc_exc
.ParentNotFound(name
)
61 if ret
== ZFS_ERR_WRONG_PARENT
:
62 raise lzc_exc
.WrongParent(_fs_name(name
))
63 if ret
== zfs_errno
.ZFS_ERR_BADPROP
:
64 raise lzc_exc
.PropertyInvalid(name
)
65 raise _generic_exception(ret
, name
, "Failed to create filesystem")
68 def lzc_clone_translate_error(ret
, name
, origin
, props
):
71 if ret
== errno
.EINVAL
:
72 _validate_fs_name(name
)
73 _validate_snap_name(origin
)
74 raise lzc_exc
.PropertyInvalid(name
)
75 if ret
== errno
.EXDEV
:
76 raise lzc_exc
.PoolsDiffer(name
)
77 if ret
== errno
.EEXIST
:
78 raise lzc_exc
.FilesystemExists(name
)
79 if ret
== errno
.ENOENT
:
80 if not _is_valid_snap_name(origin
):
81 raise lzc_exc
.SnapshotNameInvalid(origin
)
82 raise lzc_exc
.DatasetNotFound(name
)
83 raise _generic_exception(ret
, name
, "Failed to create clone")
86 def lzc_rollback_translate_error(ret
, name
):
89 if ret
== errno
.ESRCH
:
90 raise lzc_exc
.SnapshotNotFound(name
)
91 if ret
== errno
.EINVAL
:
92 _validate_fs_name(name
)
93 raise lzc_exc
.NameInvalid(name
)
94 if ret
== errno
.ENOENT
:
95 if not _is_valid_fs_name(name
):
96 raise lzc_exc
.NameInvalid(name
)
98 raise lzc_exc
.FilesystemNotFound(name
)
99 raise _generic_exception(ret
, name
, "Failed to rollback")
102 def lzc_rollback_to_translate_error(ret
, name
, snap
):
103 if ret
== errno
.EEXIST
:
104 raise lzc_exc
.SnapshotNotLatest(snap
)
106 lzc_rollback_translate_error(ret
, name
)
109 def lzc_snapshot_translate_errors(ret
, errlist
, snaps
, props
):
114 if ret
== errno
.EXDEV
:
115 pool_names
= iter(map(_pool_name
, snaps
))
116 pool_name
= next(pool_names
, None)
117 same_pool
= all(x
== pool_name
for x
in pool_names
)
119 return lzc_exc
.DuplicateSnapshots(name
)
121 return lzc_exc
.PoolsDiffer(name
)
122 elif ret
== errno
.EINVAL
:
123 if any(not _is_valid_snap_name(s
) for s
in snaps
):
124 return lzc_exc
.NameInvalid(name
)
125 elif any(len(s
) > MAXNAMELEN
for s
in snaps
):
126 return lzc_exc
.NameTooLong(name
)
128 return lzc_exc
.PropertyInvalid(name
)
130 if ret
== errno
.EEXIST
:
131 return lzc_exc
.SnapshotExists(name
)
132 if ret
== errno
.ENOENT
:
133 return lzc_exc
.FilesystemNotFound(name
)
134 return _generic_exception(ret
, name
, "Failed to create snapshot")
136 _handle_err_list(ret
, errlist
, snaps
, lzc_exc
.SnapshotFailure
, _map
)
139 def lzc_destroy_snaps_translate_errors(ret
, errlist
, snaps
, defer
):
144 if ret
== errno
.EEXIST
:
145 return lzc_exc
.SnapshotIsCloned(name
)
146 if ret
== errno
.ENOENT
:
147 return lzc_exc
.PoolNotFound(name
)
148 if ret
== errno
.EBUSY
:
149 return lzc_exc
.SnapshotIsHeld(name
)
150 return _generic_exception(ret
, name
, "Failed to destroy snapshot")
153 ret
, errlist
, snaps
, lzc_exc
.SnapshotDestructionFailure
, _map
)
156 def lzc_bookmark_translate_errors(ret
, errlist
, bookmarks
):
162 source
= bookmarks
[name
]
163 if ret
== errno
.EINVAL
:
165 pool_names
= map(_pool_name
, bookmarks
.keys())
167 # use _validate* functions for MAXNAMELEN check
169 _validate_bmark_name(name
)
170 except lzc_exc
.ZFSError
as e
:
174 _validate_snap_name(source
)
175 source_is_snap
= True
176 except lzc_exc
.ZFSError
:
177 source_is_snap
= False
179 _validate_bmark_name(source
)
180 source_is_bmark
= True
181 except lzc_exc
.ZFSError
:
182 source_is_bmark
= False
183 if not source_is_snap
and not source_is_bmark
:
184 return lzc_exc
.BookmarkSourceInvalid(source
)
186 if any(x
!= _pool_name(name
) for x
in pool_names
):
187 return lzc_exc
.PoolsDiffer(name
)
190 b
for b
in bookmarks
.keys() if not _is_valid_bmark_name(b
)]
192 return lzc_exc
.BookmarkNameInvalid(invalid_names
[0])
193 if ret
== errno
.EEXIST
:
194 return lzc_exc
.BookmarkExists(name
)
195 if ret
== errno
.ENOENT
:
196 return lzc_exc
.SnapshotNotFound(name
)
197 if ret
== errno
.ENOTSUP
:
198 return lzc_exc
.BookmarkNotSupported(name
)
199 if ret
== zfs_errno
.ZFS_ERR_BOOKMARK_SOURCE_NOT_ANCESTOR
:
200 return lzc_exc
.BookmarkMismatch(source
)
201 return _generic_exception(ret
, name
, "Failed to create bookmark")
204 ret
, errlist
, bookmarks
.keys(), lzc_exc
.BookmarkFailure
, _map
)
207 def lzc_get_bookmarks_translate_error(ret
, fsname
, props
):
210 if ret
== errno
.ENOENT
:
211 raise lzc_exc
.FilesystemNotFound(fsname
)
212 raise _generic_exception(ret
, fsname
, "Failed to list bookmarks")
215 def lzc_destroy_bookmarks_translate_errors(ret
, errlist
, bookmarks
):
220 if ret
== errno
.EINVAL
:
221 return lzc_exc
.NameInvalid(name
)
222 return _generic_exception(ret
, name
, "Failed to destroy bookmark")
225 ret
, errlist
, bookmarks
, lzc_exc
.BookmarkDestructionFailure
, _map
)
228 def lzc_snaprange_space_translate_error(ret
, firstsnap
, lastsnap
):
231 if ret
== errno
.EXDEV
and firstsnap
is not None:
232 if _pool_name(firstsnap
) != _pool_name(lastsnap
):
233 raise lzc_exc
.PoolsDiffer(lastsnap
)
235 raise lzc_exc
.SnapshotMismatch(lastsnap
)
236 if ret
== errno
.EINVAL
:
237 if not _is_valid_snap_name(firstsnap
):
238 raise lzc_exc
.NameInvalid(firstsnap
)
239 elif not _is_valid_snap_name(lastsnap
):
240 raise lzc_exc
.NameInvalid(lastsnap
)
241 elif len(firstsnap
) > MAXNAMELEN
:
242 raise lzc_exc
.NameTooLong(firstsnap
)
243 elif len(lastsnap
) > MAXNAMELEN
:
244 raise lzc_exc
.NameTooLong(lastsnap
)
245 elif _pool_name(firstsnap
) != _pool_name(lastsnap
):
246 raise lzc_exc
.PoolsDiffer(lastsnap
)
248 raise lzc_exc
.SnapshotMismatch(lastsnap
)
249 if ret
== errno
.ENOENT
:
250 raise lzc_exc
.SnapshotNotFound(lastsnap
)
251 raise _generic_exception(
252 ret
, lastsnap
, "Failed to calculate space used by range of snapshots")
255 def lzc_hold_translate_errors(ret
, errlist
, holds
, fd
):
260 if ret
== errno
.EXDEV
:
261 return lzc_exc
.PoolsDiffer(name
)
262 elif ret
== errno
.EINVAL
:
264 pool_names
= map(_pool_name
, holds
.keys())
265 if not _is_valid_snap_name(name
):
266 return lzc_exc
.NameInvalid(name
)
267 elif len(name
) > MAXNAMELEN
:
268 return lzc_exc
.NameTooLong(name
)
269 elif any(x
!= _pool_name(name
) for x
in pool_names
):
270 return lzc_exc
.PoolsDiffer(name
)
273 b
for b
in holds
.keys() if not _is_valid_snap_name(b
)]
275 return lzc_exc
.NameInvalid(invalid_names
[0])
280 fs_name
= _fs_name(name
)
281 pool_name
= _pool_name(name
)
282 hold_name
= holds
[name
]
283 if ret
== errno
.ENOENT
:
284 return lzc_exc
.FilesystemNotFound(fs_name
)
285 if ret
== errno
.EEXIST
:
286 return lzc_exc
.HoldExists(name
)
287 if ret
== errno
.E2BIG
:
288 return lzc_exc
.NameTooLong(hold_name
)
289 if ret
== errno
.ENOTSUP
:
290 return lzc_exc
.FeatureNotSupported(pool_name
)
291 return _generic_exception(ret
, name
, "Failed to hold snapshot")
293 if ret
== errno
.EBADF
:
294 raise lzc_exc
.BadHoldCleanupFD()
295 _handle_err_list(ret
, errlist
, holds
.keys(), lzc_exc
.HoldFailure
, _map
)
298 def lzc_release_translate_errors(ret
, errlist
, holds
):
302 hold_list
= holds
[snap
]
303 if not isinstance(hold_list
, list):
304 raise lzc_exc
.TypeError('holds must be in a list')
307 if ret
== errno
.EXDEV
:
308 return lzc_exc
.PoolsDiffer(name
)
309 elif ret
== errno
.EINVAL
:
311 pool_names
= map(_pool_name
, holds
.keys())
312 if not _is_valid_snap_name(name
):
313 return lzc_exc
.NameInvalid(name
)
314 elif len(name
) > MAXNAMELEN
:
315 return lzc_exc
.NameTooLong(name
)
316 elif any(x
!= _pool_name(name
) for x
in pool_names
):
317 return lzc_exc
.PoolsDiffer(name
)
320 b
for b
in holds
.keys() if not _is_valid_snap_name(b
)]
322 return lzc_exc
.NameInvalid(invalid_names
[0])
323 elif ret
== errno
.ENOENT
:
324 return lzc_exc
.HoldNotFound(name
)
325 elif ret
== errno
.E2BIG
:
326 tag_list
= holds
[name
]
327 too_long_tags
= [t
for t
in tag_list
if len(t
) > MAXNAMELEN
]
328 return lzc_exc
.NameTooLong(too_long_tags
[0])
329 elif ret
== errno
.ENOTSUP
:
332 pool_name
= _pool_name(name
)
333 return lzc_exc
.FeatureNotSupported(pool_name
)
335 return _generic_exception(
336 ret
, name
, "Failed to release snapshot hold")
339 ret
, errlist
, holds
.keys(), lzc_exc
.HoldReleaseFailure
, _map
)
342 def lzc_get_holds_translate_error(ret
, snapname
):
345 if ret
== errno
.EINVAL
:
346 _validate_snap_name(snapname
)
347 if ret
== errno
.ENOENT
:
348 raise lzc_exc
.SnapshotNotFound(snapname
)
349 if ret
== errno
.ENOTSUP
:
350 raise lzc_exc
.FeatureNotSupported(_pool_name(snapname
))
351 raise _generic_exception(ret
, snapname
, "Failed to get holds on snapshot")
354 def lzc_send_translate_error(ret
, snapname
, fromsnap
, fd
, flags
):
357 if ret
== errno
.EXDEV
and fromsnap
is not None:
358 if _pool_name(fromsnap
) != _pool_name(snapname
):
359 raise lzc_exc
.PoolsDiffer(snapname
)
361 raise lzc_exc
.SnapshotMismatch(snapname
)
362 elif ret
== errno
.EINVAL
:
363 if (fromsnap
is not None and not _is_valid_snap_name(fromsnap
) and
364 not _is_valid_bmark_name(fromsnap
)):
365 raise lzc_exc
.NameInvalid(fromsnap
)
366 elif (not _is_valid_snap_name(snapname
) and
367 not _is_valid_fs_name(snapname
)):
368 raise lzc_exc
.NameInvalid(snapname
)
369 elif fromsnap
is not None and len(fromsnap
) > MAXNAMELEN
:
370 raise lzc_exc
.NameTooLong(fromsnap
)
371 elif len(snapname
) > MAXNAMELEN
:
372 raise lzc_exc
.NameTooLong(snapname
)
373 elif (fromsnap
is not None and
374 _pool_name(fromsnap
) != _pool_name(snapname
)):
375 raise lzc_exc
.PoolsDiffer(snapname
)
376 elif ret
== errno
.ENOENT
:
377 if (fromsnap
is not None and not _is_valid_snap_name(fromsnap
) and
378 not _is_valid_bmark_name(fromsnap
)):
379 raise lzc_exc
.NameInvalid(fromsnap
)
380 raise lzc_exc
.SnapshotNotFound(snapname
)
381 elif ret
== errno
.ENAMETOOLONG
:
382 if fromsnap
is not None and len(fromsnap
) > MAXNAMELEN
:
383 raise lzc_exc
.NameTooLong(fromsnap
)
385 raise lzc_exc
.NameTooLong(snapname
)
386 raise lzc_exc
.StreamIOError(ret
)
389 def lzc_send_space_translate_error(ret
, snapname
, fromsnap
):
392 if ret
== errno
.EXDEV
and fromsnap
is not None:
393 if _pool_name(fromsnap
) != _pool_name(snapname
):
394 raise lzc_exc
.PoolsDiffer(snapname
)
396 raise lzc_exc
.SnapshotMismatch(snapname
)
397 elif ret
== errno
.EINVAL
:
398 if fromsnap
is not None and not _is_valid_snap_name(fromsnap
):
399 raise lzc_exc
.NameInvalid(fromsnap
)
400 elif not _is_valid_snap_name(snapname
):
401 raise lzc_exc
.NameInvalid(snapname
)
402 elif fromsnap
is not None and len(fromsnap
) > MAXNAMELEN
:
403 raise lzc_exc
.NameTooLong(fromsnap
)
404 elif len(snapname
) > MAXNAMELEN
:
405 raise lzc_exc
.NameTooLong(snapname
)
406 elif (fromsnap
is not None and
407 _pool_name(fromsnap
) != _pool_name(snapname
)):
408 raise lzc_exc
.PoolsDiffer(snapname
)
409 elif ret
== errno
.ENOENT
and fromsnap
is not None:
410 if not _is_valid_snap_name(fromsnap
):
411 raise lzc_exc
.NameInvalid(fromsnap
)
412 if ret
== errno
.ENOENT
:
413 raise lzc_exc
.SnapshotNotFound(snapname
)
414 raise _generic_exception(
415 ret
, snapname
, "Failed to estimate backup stream size")
418 def lzc_receive_translate_errors(
419 ret
, snapname
, fd
, force
, raw
, resumable
, embedded
, origin
, properrs
422 if properrs
is not None and len(properrs
) > 0:
424 if ret
== errno
.EINVAL
:
425 return lzc_exc
.PropertyInvalid(name
)
426 if ret
== zfs_errno
.ZFS_ERR_BADPROP
:
427 return lzc_exc
.PropertyInvalid(name
)
428 return _generic_exception(ret
, name
, "Failed to set property")
430 errno
.EINVAL
, properrs
, [snapname
],
431 lzc_exc
.ReceivePropertyFailure
, _map
)
434 if ret
== errno
.EINVAL
:
435 if (not _is_valid_snap_name(snapname
) and
436 not _is_valid_fs_name(snapname
)):
437 raise lzc_exc
.NameInvalid(snapname
)
438 elif len(snapname
) > MAXNAMELEN
:
439 raise lzc_exc
.NameTooLong(snapname
)
440 elif origin
is not None and not _is_valid_snap_name(origin
):
441 raise lzc_exc
.NameInvalid(origin
)
443 raise lzc_exc
.StreamFeatureInvalid()
444 elif embedded
and not raw
:
445 raise lzc_exc
.StreamFeatureIncompatible()
447 raise lzc_exc
.BadStream()
448 if ret
== errno
.ENOENT
:
449 if not _is_valid_snap_name(snapname
):
450 raise lzc_exc
.NameInvalid(snapname
)
452 raise lzc_exc
.DatasetNotFound(snapname
)
453 if ret
== errno
.EEXIST
:
454 raise lzc_exc
.DatasetExists(snapname
)
455 if ret
== errno
.ENOTSUP
:
456 raise lzc_exc
.StreamFeatureNotSupported()
457 if ret
== errno
.ENODEV
:
458 raise lzc_exc
.StreamMismatch(_fs_name(snapname
))
459 if ret
== errno
.ETXTBSY
:
460 raise lzc_exc
.DestinationModified(_fs_name(snapname
))
461 if ret
== errno
.EBUSY
:
462 raise lzc_exc
.DatasetBusy(_fs_name(snapname
))
463 if ret
== errno
.ENOSPC
:
464 raise lzc_exc
.NoSpace(_fs_name(snapname
))
465 if ret
== errno
.EDQUOT
:
466 raise lzc_exc
.QuotaExceeded(_fs_name(snapname
))
467 if ret
== errno
.ENAMETOOLONG
:
468 raise lzc_exc
.NameTooLong(snapname
)
469 if ret
== errno
.EROFS
:
470 raise lzc_exc
.ReadOnlyPool(_pool_name(snapname
))
471 if ret
== errno
.EAGAIN
:
472 raise lzc_exc
.SuspendedPool(_pool_name(snapname
))
473 if ret
== errno
.EACCES
:
474 raise lzc_exc
.EncryptionKeyNotLoaded()
476 raise lzc_exc
.BadStream()
477 if ret
== ZFS_ERR_WRONG_PARENT
:
478 raise lzc_exc
.WrongParent(_fs_name(snapname
))
479 if ret
== zfs_errno
.ZFS_ERR_STREAM_TRUNCATED
:
480 raise lzc_exc
.StreamTruncated()
481 if ret
== zfs_errno
.ZFS_ERR_BADPROP
:
482 raise lzc_exc
.PropertyInvalid(snapname
)
484 raise lzc_exc
.StreamIOError(ret
)
487 def lzc_promote_translate_error(ret
, name
):
490 if ret
== errno
.EINVAL
:
491 _validate_fs_name(name
)
492 raise lzc_exc
.NotClone(name
)
493 if ret
== errno
.ENOTSOCK
:
494 raise lzc_exc
.NotClone(name
)
495 if ret
== errno
.ENOENT
:
496 raise lzc_exc
.FilesystemNotFound(name
)
497 if ret
== errno
.EEXIST
:
498 raise lzc_exc
.SnapshotExists(name
)
499 raise _generic_exception(ret
, name
, "Failed to promote dataset")
502 def lzc_change_key_translate_error(ret
, name
):
505 if ret
== errno
.EINVAL
:
506 _validate_fs_name(name
)
507 raise lzc_exc
.PropertyInvalid(name
)
508 if ret
== errno
.ENOENT
:
509 raise lzc_exc
.FilesystemNotFound(name
)
510 if ret
== errno
.EACCES
:
511 raise lzc_exc
.EncryptionKeyNotLoaded()
512 raise _generic_exception(ret
, name
, "Failed to change encryption key")
515 def lzc_load_key_translate_error(ret
, name
, noop
):
518 if ret
== errno
.EINVAL
:
519 _validate_fs_name(name
)
520 raise lzc_exc
.PropertyInvalid(name
)
521 if ret
== errno
.ENOENT
:
522 raise lzc_exc
.FilesystemNotFound(name
)
523 if ret
== errno
.EACCES
:
524 raise lzc_exc
.EncryptionKeyInvalid()
525 if ret
== errno
.EEXIST
:
526 raise lzc_exc
.EncryptionKeyAlreadyLoaded()
528 raise _generic_exception(ret
, name
, "Failed to load encryption key")
530 raise _generic_exception(ret
, name
, "Failed to verify encryption key")
533 def lzc_unload_key_translate_error(ret
, name
):
536 if ret
== errno
.EINVAL
:
537 _validate_fs_name(name
)
538 raise lzc_exc
.PropertyInvalid(name
)
539 if ret
== errno
.ENOENT
:
540 raise lzc_exc
.FilesystemNotFound(name
)
541 if ret
== errno
.EACCES
:
542 raise lzc_exc
.EncryptionKeyNotLoaded()
543 raise _generic_exception(ret
, name
, "Failed to unload encryption key")
546 def lzc_sync_translate_error(ret
, name
):
549 if ret
== errno
.ENOENT
:
550 raise lzc_exc
.PoolNotFound(name
)
551 raise _generic_exception(ret
, name
, "Failed to sync pool")
554 def lzc_reopen_translate_error(ret
, name
):
557 if ret
== errno
.ENOENT
:
558 raise lzc_exc
.PoolNotFound(name
)
559 raise _generic_exception(ret
, name
, "Failed to reopen pool")
562 def lzc_channel_program_translate_error(ret
, name
, error
):
565 if ret
== errno
.ENOENT
:
566 raise lzc_exc
.PoolNotFound(name
)
568 raise lzc_exc
.ZCPTimeout()
569 if ret
== errno
.ENOMEM
:
570 raise lzc_exc
.ZCPMemoryError()
571 if ret
== errno
.ENOSPC
:
572 raise lzc_exc
.ZCPSpaceError()
573 if ret
== errno
.EPERM
:
574 raise lzc_exc
.ZCPPermissionError()
576 raise lzc_exc
.ZCPRuntimeError(error
)
577 if ret
== errno
.EINVAL
:
579 raise lzc_exc
.ZCPLimitInvalid()
581 raise lzc_exc
.ZCPSyntaxError(error
)
582 raise _generic_exception(ret
, name
, "Failed to execute channel program")
585 def lzc_pool_checkpoint_translate_error(ret
, name
, discard
=False):
588 if ret
== errno
.ENOENT
:
589 raise lzc_exc
.PoolNotFound(name
)
590 if ret
== ZFS_ERR_CHECKPOINT_EXISTS
:
591 raise lzc_exc
.CheckpointExists()
592 if ret
== ZFS_ERR_NO_CHECKPOINT
:
593 raise lzc_exc
.CheckpointNotFound()
594 if ret
== ZFS_ERR_DISCARDING_CHECKPOINT
:
595 raise lzc_exc
.CheckpointDiscarding()
596 if ret
== ZFS_ERR_DEVRM_IN_PROGRESS
:
597 raise lzc_exc
.DeviceRemovalRunning()
598 if ret
== ZFS_ERR_VDEV_TOO_BIG
:
599 raise lzc_exc
.DeviceTooBig()
600 if ret
== ZFS_ERR_RAIDZ_EXPAND_IN_PROGRESS
:
601 raise lzc_exc
.RaidzExpansionRunning()
603 raise _generic_exception(
604 ret
, name
, "Failed to discard pool checkpoint")
606 raise _generic_exception(ret
, name
, "Failed to create pool checkpoint")
609 def lzc_pool_checkpoint_discard_translate_error(ret
, name
):
610 lzc_pool_checkpoint_translate_error(ret
, name
, discard
=True)
613 def lzc_rename_translate_error(ret
, source
, target
):
616 if ret
== errno
.EINVAL
:
617 _validate_fs_name(source
)
618 _validate_fs_name(target
)
619 if _pool_name(source
) != _pool_name(target
):
620 raise lzc_exc
.PoolsDiffer(source
)
621 if ret
== errno
.EEXIST
:
622 raise lzc_exc
.FilesystemExists(target
)
623 if ret
== errno
.ENOENT
:
624 raise lzc_exc
.FilesystemNotFound(source
)
625 if ret
== ZFS_ERR_WRONG_PARENT
:
626 raise lzc_exc
.WrongParent(target
)
627 raise _generic_exception(ret
, source
, "Failed to rename dataset")
630 def lzc_destroy_translate_error(ret
, name
):
633 if ret
== errno
.EINVAL
:
634 _validate_fs_name(name
)
635 if ret
== errno
.ENOENT
:
636 raise lzc_exc
.FilesystemNotFound(name
)
637 raise _generic_exception(ret
, name
, "Failed to destroy dataset")
640 def lzc_inherit_prop_translate_error(ret
, name
, prop
):
643 if ret
== errno
.EINVAL
:
644 _validate_fs_name(name
)
645 raise lzc_exc
.PropertyInvalid(prop
)
646 if ret
== errno
.ENOENT
:
647 raise lzc_exc
.DatasetNotFound(name
)
648 raise _generic_exception(ret
, name
, "Failed to inherit a property")
651 def lzc_set_prop_translate_error(ret
, name
, prop
, val
):
654 if ret
== errno
.EINVAL
:
655 _validate_fs_or_snap_name(name
)
656 raise lzc_exc
.PropertyInvalid(prop
)
657 if ret
== errno
.ENOENT
:
658 raise lzc_exc
.DatasetNotFound(name
)
659 raise _generic_exception(ret
, name
, "Failed to set a property")
662 def lzc_get_props_translate_error(ret
, name
):
665 if ret
== errno
.EINVAL
:
666 _validate_fs_or_snap_name(name
)
667 if ret
== errno
.ENOENT
:
668 raise lzc_exc
.DatasetNotFound(name
)
669 raise _generic_exception(ret
, name
, "Failed to get properties")
672 def lzc_list_children_translate_error(ret
, name
):
675 if ret
== errno
.EINVAL
:
676 _validate_fs_name(name
)
677 raise _generic_exception(ret
, name
, "Error while iterating children")
680 def lzc_list_snaps_translate_error(ret
, name
):
683 if ret
== errno
.EINVAL
:
684 _validate_fs_name(name
)
685 raise _generic_exception(ret
, name
, "Error while iterating snapshots")
688 def lzc_list_translate_error(ret
, name
, opts
):
691 if ret
== errno
.ENOENT
:
692 raise lzc_exc
.DatasetNotFound(name
)
693 if ret
== errno
.EINVAL
:
694 _validate_fs_or_snap_name(name
)
695 raise _generic_exception(ret
, name
, "Error obtaining a list")
698 def _handle_err_list(ret
, errlist
, names
, exception
, mapper
):
700 Convert one or more errors from an operation into the requested exception.
702 :param int ret: the overall return code.
703 :param errlist: the dictionary that maps entity names to their specific
705 :type errlist: dict of bytes:int
706 :param names: the list of all names of the entities on which the operation
708 :param type exception: the type of the exception to raise if an error
709 occurred. The exception should be a subclass of
710 ``MultipleOperationsFailure``.
711 :param function mapper: the function that maps an error code and a name to
714 Unless ``ret`` is zero this function will raise the ``exception``.
715 If the ``errlist`` is not empty, then the compound exception will contain
716 a list of exceptions corresponding to each individual error code in the
718 Otherwise, the ``exception`` will contain a list with a single exception
719 corresponding to the ``ret`` value. If the ``names`` list contains only one
720 element, that is, the operation was attempted on a single entity, then the
721 name of that entity is passed to the ``mapper``.
722 If the operation was attempted on multiple entities, but the ``errlist``
723 is empty, then we can not know which entity caused the error and, thus,
724 ``None`` is used as a name to signify that fact.
727 Note that the ``errlist`` can contain a special element with a key of
729 That element means that there were too many errors to place on the
731 Those errors are suppressed and only their count is provided as a
732 value of the special ``N_MORE_ERRORS`` element.
737 if len(errlist
) == 0:
739 names
= list(zip(names
, range(2)))
744 errors
= [mapper(ret
, name
)]
747 suppressed_count
= errlist
.pop('N_MORE_ERRORS', 0)
750 errors
.append(mapper(err
, name
))
752 raise exception(errors
, suppressed_count
)
755 def _pool_name(name
):
757 Extract a pool name from the given dataset or bookmark name.
759 '/' separates dataset name components.
760 '@' separates a snapshot name from the rest of the dataset name.
761 '#' separates a bookmark name from the rest of the dataset name.
763 return re
.split(b
'[/@#]', name
, 1)[0]
768 Extract a dataset name from the given snapshot or bookmark name.
770 '@' separates a snapshot name from the rest of the dataset name.
771 '#' separates a bookmark name from the rest of the dataset name.
773 return re
.split(b
'[@#]', name
, 1)[0]
776 def _is_valid_name_component(component
):
777 allowed
= string
.ascii_letters
+ string
.digits
+ u
'-_.: '
778 return component
and all(x
in allowed
.encode() for x
in component
)
781 def _is_valid_fs_name(name
):
782 return name
and all(_is_valid_name_component(c
) for c
in name
.split(b
'/'))
785 def _is_valid_snap_name(name
):
786 parts
= name
.split(b
'@')
787 return (len(parts
) == 2 and _is_valid_fs_name(parts
[0]) and
788 _is_valid_name_component(parts
[1]))
791 def _is_valid_bmark_name(name
):
792 parts
= name
.split(b
'#')
793 return (len(parts
) == 2 and _is_valid_fs_name(parts
[0]) and
794 _is_valid_name_component(parts
[1]))
797 def _validate_fs_name(name
):
798 if not _is_valid_fs_name(name
):
799 raise lzc_exc
.FilesystemNameInvalid(name
)
800 elif len(name
) > MAXNAMELEN
:
801 raise lzc_exc
.NameTooLong(name
)
804 def _validate_snap_name(name
):
805 if not _is_valid_snap_name(name
):
806 raise lzc_exc
.SnapshotNameInvalid(name
)
807 elif len(name
) > MAXNAMELEN
:
808 raise lzc_exc
.NameTooLong(name
)
811 def _validate_bmark_name(name
):
812 if not _is_valid_bmark_name(name
):
813 raise lzc_exc
.BookmarkNameInvalid(name
)
814 elif len(name
) > MAXNAMELEN
:
815 raise lzc_exc
.NameTooLong(name
)
818 def _validate_fs_or_snap_name(name
):
819 if not _is_valid_fs_name(name
) and not _is_valid_snap_name(name
):
820 raise lzc_exc
.NameInvalid(name
)
821 elif len(name
) > MAXNAMELEN
:
822 raise lzc_exc
.NameTooLong(name
)
825 def _generic_exception(err
, name
, message
):
826 if err
in _error_to_exception
:
827 return _error_to_exception
[err
](name
)
829 return lzc_exc
.ZFSGenericError(err
, message
, name
)
832 _error_to_exception
= {e
.errno
: e
for e
in [
835 lzc_exc
.QuotaExceeded
,
838 lzc_exc
.ReadOnlyPool
,
839 lzc_exc
.SuspendedPool
,
841 lzc_exc
.PropertyNotSupported
,
845 # vim: softtabstop=4 tabstop=4 expandtab shiftwidth=4