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
,
50 def lzc_create_translate_error(ret
, name
, ds_type
, props
):
53 if ret
== errno
.EINVAL
:
54 _validate_fs_name(name
)
55 raise lzc_exc
.PropertyInvalid(name
)
56 if ret
== errno
.EEXIST
:
57 raise lzc_exc
.FilesystemExists(name
)
58 if ret
== errno
.ENOENT
:
59 raise lzc_exc
.ParentNotFound(name
)
60 if ret
== ZFS_ERR_WRONG_PARENT
:
61 raise lzc_exc
.WrongParent(_fs_name(name
))
62 if ret
== zfs_errno
.ZFS_ERR_BADPROP
:
63 raise lzc_exc
.PropertyInvalid(name
)
64 raise _generic_exception(ret
, name
, "Failed to create filesystem")
67 def lzc_clone_translate_error(ret
, name
, origin
, props
):
70 if ret
== errno
.EINVAL
:
71 _validate_fs_name(name
)
72 _validate_snap_name(origin
)
73 raise lzc_exc
.PropertyInvalid(name
)
74 if ret
== errno
.EXDEV
:
75 raise lzc_exc
.PoolsDiffer(name
)
76 if ret
== errno
.EEXIST
:
77 raise lzc_exc
.FilesystemExists(name
)
78 if ret
== errno
.ENOENT
:
79 if not _is_valid_snap_name(origin
):
80 raise lzc_exc
.SnapshotNameInvalid(origin
)
81 raise lzc_exc
.DatasetNotFound(name
)
82 raise _generic_exception(ret
, name
, "Failed to create clone")
85 def lzc_rollback_translate_error(ret
, name
):
88 if ret
== errno
.ESRCH
:
89 raise lzc_exc
.SnapshotNotFound(name
)
90 if ret
== errno
.EINVAL
:
91 _validate_fs_name(name
)
92 raise lzc_exc
.NameInvalid(name
)
93 if ret
== errno
.ENOENT
:
94 if not _is_valid_fs_name(name
):
95 raise lzc_exc
.NameInvalid(name
)
97 raise lzc_exc
.FilesystemNotFound(name
)
98 raise _generic_exception(ret
, name
, "Failed to rollback")
101 def lzc_rollback_to_translate_error(ret
, name
, snap
):
102 if ret
== errno
.EEXIST
:
103 raise lzc_exc
.SnapshotNotLatest(snap
)
105 lzc_rollback_translate_error(ret
, name
)
108 def lzc_snapshot_translate_errors(ret
, errlist
, snaps
, props
):
113 if ret
== errno
.EXDEV
:
114 pool_names
= iter(map(_pool_name
, snaps
))
115 pool_name
= next(pool_names
, None)
116 same_pool
= all(x
== pool_name
for x
in pool_names
)
118 return lzc_exc
.DuplicateSnapshots(name
)
120 return lzc_exc
.PoolsDiffer(name
)
121 elif ret
== errno
.EINVAL
:
122 if any(not _is_valid_snap_name(s
) for s
in snaps
):
123 return lzc_exc
.NameInvalid(name
)
124 elif any(len(s
) > MAXNAMELEN
for s
in snaps
):
125 return lzc_exc
.NameTooLong(name
)
127 return lzc_exc
.PropertyInvalid(name
)
129 if ret
== errno
.EEXIST
:
130 return lzc_exc
.SnapshotExists(name
)
131 if ret
== errno
.ENOENT
:
132 return lzc_exc
.FilesystemNotFound(name
)
133 return _generic_exception(ret
, name
, "Failed to create snapshot")
135 _handle_err_list(ret
, errlist
, snaps
, lzc_exc
.SnapshotFailure
, _map
)
138 def lzc_destroy_snaps_translate_errors(ret
, errlist
, snaps
, defer
):
143 if ret
== errno
.EEXIST
:
144 return lzc_exc
.SnapshotIsCloned(name
)
145 if ret
== errno
.ENOENT
:
146 return lzc_exc
.PoolNotFound(name
)
147 if ret
== errno
.EBUSY
:
148 return lzc_exc
.SnapshotIsHeld(name
)
149 return _generic_exception(ret
, name
, "Failed to destroy snapshot")
152 ret
, errlist
, snaps
, lzc_exc
.SnapshotDestructionFailure
, _map
)
155 def lzc_bookmark_translate_errors(ret
, errlist
, bookmarks
):
161 source
= bookmarks
[name
]
162 if ret
== errno
.EINVAL
:
164 pool_names
= map(_pool_name
, bookmarks
.keys())
166 # use _validate* functions for MAXNAMELEN check
168 _validate_bmark_name(name
)
169 except lzc_exc
.ZFSError
as e
:
173 _validate_snap_name(source
)
174 source_is_snap
= True
175 except lzc_exc
.ZFSError
:
176 source_is_snap
= False
178 _validate_bmark_name(source
)
179 source_is_bmark
= True
180 except lzc_exc
.ZFSError
:
181 source_is_bmark
= False
182 if not source_is_snap
and not source_is_bmark
:
183 return lzc_exc
.BookmarkSourceInvalid(source
)
185 if any(x
!= _pool_name(name
) for x
in pool_names
):
186 return lzc_exc
.PoolsDiffer(name
)
189 b
for b
in bookmarks
.keys() if not _is_valid_bmark_name(b
)]
191 return lzc_exc
.BookmarkNameInvalid(invalid_names
[0])
192 if ret
== errno
.EEXIST
:
193 return lzc_exc
.BookmarkExists(name
)
194 if ret
== errno
.ENOENT
:
195 return lzc_exc
.SnapshotNotFound(name
)
196 if ret
== errno
.ENOTSUP
:
197 return lzc_exc
.BookmarkNotSupported(name
)
198 if ret
== zfs_errno
.ZFS_ERR_BOOKMARK_SOURCE_NOT_ANCESTOR
:
199 return lzc_exc
.BookmarkMismatch(source
)
200 return _generic_exception(ret
, name
, "Failed to create bookmark")
203 ret
, errlist
, bookmarks
.keys(), lzc_exc
.BookmarkFailure
, _map
)
206 def lzc_get_bookmarks_translate_error(ret
, fsname
, props
):
209 if ret
== errno
.ENOENT
:
210 raise lzc_exc
.FilesystemNotFound(fsname
)
211 raise _generic_exception(ret
, fsname
, "Failed to list bookmarks")
214 def lzc_destroy_bookmarks_translate_errors(ret
, errlist
, bookmarks
):
219 if ret
== errno
.EINVAL
:
220 return lzc_exc
.NameInvalid(name
)
221 return _generic_exception(ret
, name
, "Failed to destroy bookmark")
224 ret
, errlist
, bookmarks
, lzc_exc
.BookmarkDestructionFailure
, _map
)
227 def lzc_snaprange_space_translate_error(ret
, firstsnap
, lastsnap
):
230 if ret
== errno
.EXDEV
and firstsnap
is not None:
231 if _pool_name(firstsnap
) != _pool_name(lastsnap
):
232 raise lzc_exc
.PoolsDiffer(lastsnap
)
234 raise lzc_exc
.SnapshotMismatch(lastsnap
)
235 if ret
== errno
.EINVAL
:
236 if not _is_valid_snap_name(firstsnap
):
237 raise lzc_exc
.NameInvalid(firstsnap
)
238 elif not _is_valid_snap_name(lastsnap
):
239 raise lzc_exc
.NameInvalid(lastsnap
)
240 elif len(firstsnap
) > MAXNAMELEN
:
241 raise lzc_exc
.NameTooLong(firstsnap
)
242 elif len(lastsnap
) > MAXNAMELEN
:
243 raise lzc_exc
.NameTooLong(lastsnap
)
244 elif _pool_name(firstsnap
) != _pool_name(lastsnap
):
245 raise lzc_exc
.PoolsDiffer(lastsnap
)
247 raise lzc_exc
.SnapshotMismatch(lastsnap
)
248 if ret
== errno
.ENOENT
:
249 raise lzc_exc
.SnapshotNotFound(lastsnap
)
250 raise _generic_exception(
251 ret
, lastsnap
, "Failed to calculate space used by range of snapshots")
254 def lzc_hold_translate_errors(ret
, errlist
, holds
, fd
):
259 if ret
== errno
.EXDEV
:
260 return lzc_exc
.PoolsDiffer(name
)
261 elif ret
== errno
.EINVAL
:
263 pool_names
= map(_pool_name
, holds
.keys())
264 if not _is_valid_snap_name(name
):
265 return lzc_exc
.NameInvalid(name
)
266 elif len(name
) > MAXNAMELEN
:
267 return lzc_exc
.NameTooLong(name
)
268 elif any(x
!= _pool_name(name
) for x
in pool_names
):
269 return lzc_exc
.PoolsDiffer(name
)
272 b
for b
in holds
.keys() if not _is_valid_snap_name(b
)]
274 return lzc_exc
.NameInvalid(invalid_names
[0])
279 fs_name
= _fs_name(name
)
280 pool_name
= _pool_name(name
)
281 hold_name
= holds
[name
]
282 if ret
== errno
.ENOENT
:
283 return lzc_exc
.FilesystemNotFound(fs_name
)
284 if ret
== errno
.EEXIST
:
285 return lzc_exc
.HoldExists(name
)
286 if ret
== errno
.E2BIG
:
287 return lzc_exc
.NameTooLong(hold_name
)
288 if ret
== errno
.ENOTSUP
:
289 return lzc_exc
.FeatureNotSupported(pool_name
)
290 return _generic_exception(ret
, name
, "Failed to hold snapshot")
292 if ret
== errno
.EBADF
:
293 raise lzc_exc
.BadHoldCleanupFD()
294 _handle_err_list(ret
, errlist
, holds
.keys(), lzc_exc
.HoldFailure
, _map
)
297 def lzc_release_translate_errors(ret
, errlist
, holds
):
301 hold_list
= holds
[snap
]
302 if not isinstance(hold_list
, list):
303 raise lzc_exc
.TypeError('holds must be in a list')
306 if ret
== errno
.EXDEV
:
307 return lzc_exc
.PoolsDiffer(name
)
308 elif ret
== errno
.EINVAL
:
310 pool_names
= map(_pool_name
, holds
.keys())
311 if not _is_valid_snap_name(name
):
312 return lzc_exc
.NameInvalid(name
)
313 elif len(name
) > MAXNAMELEN
:
314 return lzc_exc
.NameTooLong(name
)
315 elif any(x
!= _pool_name(name
) for x
in pool_names
):
316 return lzc_exc
.PoolsDiffer(name
)
319 b
for b
in holds
.keys() if not _is_valid_snap_name(b
)]
321 return lzc_exc
.NameInvalid(invalid_names
[0])
322 elif ret
== errno
.ENOENT
:
323 return lzc_exc
.HoldNotFound(name
)
324 elif ret
== errno
.E2BIG
:
325 tag_list
= holds
[name
]
326 too_long_tags
= [t
for t
in tag_list
if len(t
) > MAXNAMELEN
]
327 return lzc_exc
.NameTooLong(too_long_tags
[0])
328 elif ret
== errno
.ENOTSUP
:
331 pool_name
= _pool_name(name
)
332 return lzc_exc
.FeatureNotSupported(pool_name
)
334 return _generic_exception(
335 ret
, name
, "Failed to release snapshot hold")
338 ret
, errlist
, holds
.keys(), lzc_exc
.HoldReleaseFailure
, _map
)
341 def lzc_get_holds_translate_error(ret
, snapname
):
344 if ret
== errno
.EINVAL
:
345 _validate_snap_name(snapname
)
346 if ret
== errno
.ENOENT
:
347 raise lzc_exc
.SnapshotNotFound(snapname
)
348 if ret
== errno
.ENOTSUP
:
349 raise lzc_exc
.FeatureNotSupported(_pool_name(snapname
))
350 raise _generic_exception(ret
, snapname
, "Failed to get holds on snapshot")
353 def lzc_send_translate_error(ret
, snapname
, fromsnap
, fd
, flags
):
356 if ret
== errno
.EXDEV
and fromsnap
is not None:
357 if _pool_name(fromsnap
) != _pool_name(snapname
):
358 raise lzc_exc
.PoolsDiffer(snapname
)
360 raise lzc_exc
.SnapshotMismatch(snapname
)
361 elif ret
== errno
.EINVAL
:
362 if (fromsnap
is not None and not _is_valid_snap_name(fromsnap
) and
363 not _is_valid_bmark_name(fromsnap
)):
364 raise lzc_exc
.NameInvalid(fromsnap
)
365 elif (not _is_valid_snap_name(snapname
) and
366 not _is_valid_fs_name(snapname
)):
367 raise lzc_exc
.NameInvalid(snapname
)
368 elif fromsnap
is not None and len(fromsnap
) > MAXNAMELEN
:
369 raise lzc_exc
.NameTooLong(fromsnap
)
370 elif len(snapname
) > MAXNAMELEN
:
371 raise lzc_exc
.NameTooLong(snapname
)
372 elif (fromsnap
is not None and
373 _pool_name(fromsnap
) != _pool_name(snapname
)):
374 raise lzc_exc
.PoolsDiffer(snapname
)
375 elif ret
== errno
.ENOENT
:
376 if (fromsnap
is not None and not _is_valid_snap_name(fromsnap
) and
377 not _is_valid_bmark_name(fromsnap
)):
378 raise lzc_exc
.NameInvalid(fromsnap
)
379 raise lzc_exc
.SnapshotNotFound(snapname
)
380 elif ret
== errno
.ENAMETOOLONG
:
381 if fromsnap
is not None and len(fromsnap
) > MAXNAMELEN
:
382 raise lzc_exc
.NameTooLong(fromsnap
)
384 raise lzc_exc
.NameTooLong(snapname
)
385 raise lzc_exc
.StreamIOError(ret
)
388 def lzc_send_space_translate_error(ret
, snapname
, fromsnap
):
391 if ret
== errno
.EXDEV
and fromsnap
is not None:
392 if _pool_name(fromsnap
) != _pool_name(snapname
):
393 raise lzc_exc
.PoolsDiffer(snapname
)
395 raise lzc_exc
.SnapshotMismatch(snapname
)
396 elif ret
== errno
.EINVAL
:
397 if fromsnap
is not None and not _is_valid_snap_name(fromsnap
):
398 raise lzc_exc
.NameInvalid(fromsnap
)
399 elif not _is_valid_snap_name(snapname
):
400 raise lzc_exc
.NameInvalid(snapname
)
401 elif fromsnap
is not None and len(fromsnap
) > MAXNAMELEN
:
402 raise lzc_exc
.NameTooLong(fromsnap
)
403 elif len(snapname
) > MAXNAMELEN
:
404 raise lzc_exc
.NameTooLong(snapname
)
405 elif (fromsnap
is not None and
406 _pool_name(fromsnap
) != _pool_name(snapname
)):
407 raise lzc_exc
.PoolsDiffer(snapname
)
408 elif ret
== errno
.ENOENT
and fromsnap
is not None:
409 if not _is_valid_snap_name(fromsnap
):
410 raise lzc_exc
.NameInvalid(fromsnap
)
411 if ret
== errno
.ENOENT
:
412 raise lzc_exc
.SnapshotNotFound(snapname
)
413 raise _generic_exception(
414 ret
, snapname
, "Failed to estimate backup stream size")
417 def lzc_receive_translate_errors(
418 ret
, snapname
, fd
, force
, raw
, resumable
, embedded
, origin
, properrs
421 if properrs
is not None and len(properrs
) > 0:
423 if ret
== errno
.EINVAL
:
424 return lzc_exc
.PropertyInvalid(name
)
425 if ret
== zfs_errno
.ZFS_ERR_BADPROP
:
426 return lzc_exc
.PropertyInvalid(name
)
427 return _generic_exception(ret
, name
, "Failed to set property")
429 errno
.EINVAL
, properrs
, [snapname
],
430 lzc_exc
.ReceivePropertyFailure
, _map
)
433 if ret
== errno
.EINVAL
:
434 if (not _is_valid_snap_name(snapname
) and
435 not _is_valid_fs_name(snapname
)):
436 raise lzc_exc
.NameInvalid(snapname
)
437 elif len(snapname
) > MAXNAMELEN
:
438 raise lzc_exc
.NameTooLong(snapname
)
439 elif origin
is not None and not _is_valid_snap_name(origin
):
440 raise lzc_exc
.NameInvalid(origin
)
442 raise lzc_exc
.StreamFeatureInvalid()
443 elif embedded
and not raw
:
444 raise lzc_exc
.StreamFeatureIncompatible()
446 raise lzc_exc
.BadStream()
447 if ret
== errno
.ENOENT
:
448 if not _is_valid_snap_name(snapname
):
449 raise lzc_exc
.NameInvalid(snapname
)
451 raise lzc_exc
.DatasetNotFound(snapname
)
452 if ret
== errno
.EEXIST
:
453 raise lzc_exc
.DatasetExists(snapname
)
454 if ret
== errno
.ENOTSUP
:
455 raise lzc_exc
.StreamFeatureNotSupported()
456 if ret
== errno
.ENODEV
:
457 raise lzc_exc
.StreamMismatch(_fs_name(snapname
))
458 if ret
== errno
.ETXTBSY
:
459 raise lzc_exc
.DestinationModified(_fs_name(snapname
))
460 if ret
== errno
.EBUSY
:
461 raise lzc_exc
.DatasetBusy(_fs_name(snapname
))
462 if ret
== errno
.ENOSPC
:
463 raise lzc_exc
.NoSpace(_fs_name(snapname
))
464 if ret
== errno
.EDQUOT
:
465 raise lzc_exc
.QuotaExceeded(_fs_name(snapname
))
466 if ret
== errno
.ENAMETOOLONG
:
467 raise lzc_exc
.NameTooLong(snapname
)
468 if ret
== errno
.EROFS
:
469 raise lzc_exc
.ReadOnlyPool(_pool_name(snapname
))
470 if ret
== errno
.EAGAIN
:
471 raise lzc_exc
.SuspendedPool(_pool_name(snapname
))
472 if ret
== errno
.EACCES
:
473 raise lzc_exc
.EncryptionKeyNotLoaded()
475 raise lzc_exc
.BadStream()
476 if ret
== ZFS_ERR_WRONG_PARENT
:
477 raise lzc_exc
.WrongParent(_fs_name(snapname
))
478 if ret
== zfs_errno
.ZFS_ERR_STREAM_TRUNCATED
:
479 raise lzc_exc
.StreamTruncated()
480 if ret
== zfs_errno
.ZFS_ERR_BADPROP
:
481 raise lzc_exc
.PropertyInvalid(snapname
)
483 raise lzc_exc
.StreamIOError(ret
)
486 def lzc_promote_translate_error(ret
, name
):
489 if ret
== errno
.EINVAL
:
490 _validate_fs_name(name
)
491 raise lzc_exc
.NotClone(name
)
492 if ret
== errno
.ENOTSOCK
:
493 raise lzc_exc
.NotClone(name
)
494 if ret
== errno
.ENOENT
:
495 raise lzc_exc
.FilesystemNotFound(name
)
496 if ret
== errno
.EEXIST
:
497 raise lzc_exc
.SnapshotExists(name
)
498 raise _generic_exception(ret
, name
, "Failed to promote dataset")
501 def lzc_change_key_translate_error(ret
, name
):
504 if ret
== errno
.EINVAL
:
505 _validate_fs_name(name
)
506 raise lzc_exc
.PropertyInvalid(name
)
507 if ret
== errno
.ENOENT
:
508 raise lzc_exc
.FilesystemNotFound(name
)
509 if ret
== errno
.EACCES
:
510 raise lzc_exc
.EncryptionKeyNotLoaded()
511 raise _generic_exception(ret
, name
, "Failed to change encryption key")
514 def lzc_load_key_translate_error(ret
, name
, noop
):
517 if ret
== errno
.EINVAL
:
518 _validate_fs_name(name
)
519 raise lzc_exc
.PropertyInvalid(name
)
520 if ret
== errno
.ENOENT
:
521 raise lzc_exc
.FilesystemNotFound(name
)
522 if ret
== errno
.EACCES
:
523 raise lzc_exc
.EncryptionKeyInvalid()
524 if ret
== errno
.EEXIST
:
525 raise lzc_exc
.EncryptionKeyAlreadyLoaded()
527 raise _generic_exception(ret
, name
, "Failed to load encryption key")
529 raise _generic_exception(ret
, name
, "Failed to verify encryption key")
532 def lzc_unload_key_translate_error(ret
, name
):
535 if ret
== errno
.EINVAL
:
536 _validate_fs_name(name
)
537 raise lzc_exc
.PropertyInvalid(name
)
538 if ret
== errno
.ENOENT
:
539 raise lzc_exc
.FilesystemNotFound(name
)
540 if ret
== errno
.EACCES
:
541 raise lzc_exc
.EncryptionKeyNotLoaded()
542 raise _generic_exception(ret
, name
, "Failed to unload encryption key")
545 def lzc_sync_translate_error(ret
, name
):
548 if ret
== errno
.ENOENT
:
549 raise lzc_exc
.PoolNotFound(name
)
550 raise _generic_exception(ret
, name
, "Failed to sync pool")
553 def lzc_reopen_translate_error(ret
, name
):
556 if ret
== errno
.ENOENT
:
557 raise lzc_exc
.PoolNotFound(name
)
558 raise _generic_exception(ret
, name
, "Failed to reopen pool")
561 def lzc_channel_program_translate_error(ret
, name
, error
):
564 if ret
== errno
.ENOENT
:
565 raise lzc_exc
.PoolNotFound(name
)
567 raise lzc_exc
.ZCPTimeout()
568 if ret
== errno
.ENOMEM
:
569 raise lzc_exc
.ZCPMemoryError()
570 if ret
== errno
.ENOSPC
:
571 raise lzc_exc
.ZCPSpaceError()
572 if ret
== errno
.EPERM
:
573 raise lzc_exc
.ZCPPermissionError()
575 raise lzc_exc
.ZCPRuntimeError(error
)
576 if ret
== errno
.EINVAL
:
578 raise lzc_exc
.ZCPLimitInvalid()
580 raise lzc_exc
.ZCPSyntaxError(error
)
581 raise _generic_exception(ret
, name
, "Failed to execute channel program")
584 def lzc_pool_checkpoint_translate_error(ret
, name
, discard
=False):
587 if ret
== errno
.ENOENT
:
588 raise lzc_exc
.PoolNotFound(name
)
589 if ret
== ZFS_ERR_CHECKPOINT_EXISTS
:
590 raise lzc_exc
.CheckpointExists()
591 if ret
== ZFS_ERR_NO_CHECKPOINT
:
592 raise lzc_exc
.CheckpointNotFound()
593 if ret
== ZFS_ERR_DISCARDING_CHECKPOINT
:
594 raise lzc_exc
.CheckpointDiscarding()
595 if ret
== ZFS_ERR_DEVRM_IN_PROGRESS
:
596 raise lzc_exc
.DeviceRemovalRunning()
597 if ret
== ZFS_ERR_VDEV_TOO_BIG
:
598 raise lzc_exc
.DeviceTooBig()
600 raise _generic_exception(
601 ret
, name
, "Failed to discard pool checkpoint")
603 raise _generic_exception(ret
, name
, "Failed to create pool checkpoint")
606 def lzc_pool_checkpoint_discard_translate_error(ret
, name
):
607 lzc_pool_checkpoint_translate_error(ret
, name
, discard
=True)
610 def lzc_rename_translate_error(ret
, source
, target
):
613 if ret
== errno
.EINVAL
:
614 _validate_fs_name(source
)
615 _validate_fs_name(target
)
616 if _pool_name(source
) != _pool_name(target
):
617 raise lzc_exc
.PoolsDiffer(source
)
618 if ret
== errno
.EEXIST
:
619 raise lzc_exc
.FilesystemExists(target
)
620 if ret
== errno
.ENOENT
:
621 raise lzc_exc
.FilesystemNotFound(source
)
622 if ret
== ZFS_ERR_WRONG_PARENT
:
623 raise lzc_exc
.WrongParent(target
)
624 raise _generic_exception(ret
, source
, "Failed to rename dataset")
627 def lzc_destroy_translate_error(ret
, name
):
630 if ret
== errno
.EINVAL
:
631 _validate_fs_name(name
)
632 if ret
== errno
.ENOENT
:
633 raise lzc_exc
.FilesystemNotFound(name
)
634 raise _generic_exception(ret
, name
, "Failed to destroy dataset")
637 def lzc_inherit_prop_translate_error(ret
, name
, prop
):
640 if ret
== errno
.EINVAL
:
641 _validate_fs_name(name
)
642 raise lzc_exc
.PropertyInvalid(prop
)
643 if ret
== errno
.ENOENT
:
644 raise lzc_exc
.DatasetNotFound(name
)
645 raise _generic_exception(ret
, name
, "Failed to inherit a property")
648 def lzc_set_prop_translate_error(ret
, name
, prop
, val
):
651 if ret
== errno
.EINVAL
:
652 _validate_fs_or_snap_name(name
)
653 raise lzc_exc
.PropertyInvalid(prop
)
654 if ret
== errno
.ENOENT
:
655 raise lzc_exc
.DatasetNotFound(name
)
656 raise _generic_exception(ret
, name
, "Failed to set a property")
659 def lzc_get_props_translate_error(ret
, name
):
662 if ret
== errno
.EINVAL
:
663 _validate_fs_or_snap_name(name
)
664 if ret
== errno
.ENOENT
:
665 raise lzc_exc
.DatasetNotFound(name
)
666 raise _generic_exception(ret
, name
, "Failed to get properties")
669 def lzc_list_children_translate_error(ret
, name
):
672 if ret
== errno
.EINVAL
:
673 _validate_fs_name(name
)
674 raise _generic_exception(ret
, name
, "Error while iterating children")
677 def lzc_list_snaps_translate_error(ret
, name
):
680 if ret
== errno
.EINVAL
:
681 _validate_fs_name(name
)
682 raise _generic_exception(ret
, name
, "Error while iterating snapshots")
685 def lzc_list_translate_error(ret
, name
, opts
):
688 if ret
== errno
.ENOENT
:
689 raise lzc_exc
.DatasetNotFound(name
)
690 if ret
== errno
.EINVAL
:
691 _validate_fs_or_snap_name(name
)
692 raise _generic_exception(ret
, name
, "Error obtaining a list")
695 def _handle_err_list(ret
, errlist
, names
, exception
, mapper
):
697 Convert one or more errors from an operation into the requested exception.
699 :param int ret: the overall return code.
700 :param errlist: the dictionary that maps entity names to their specific
702 :type errlist: dict of bytes:int
703 :param names: the list of all names of the entities on which the operation
705 :param type exception: the type of the exception to raise if an error
706 occurred. The exception should be a subclass of
707 ``MultipleOperationsFailure``.
708 :param function mapper: the function that maps an error code and a name to
711 Unless ``ret`` is zero this function will raise the ``exception``.
712 If the ``errlist`` is not empty, then the compound exception will contain
713 a list of exceptions corresponding to each individual error code in the
715 Otherwise, the ``exception`` will contain a list with a single exception
716 corresponding to the ``ret`` value. If the ``names`` list contains only one
717 element, that is, the operation was attempted on a single entity, then the
718 name of that entity is passed to the ``mapper``.
719 If the operation was attempted on multiple entities, but the ``errlist``
720 is empty, then we can not know which entity caused the error and, thus,
721 ``None`` is used as a name to signify that fact.
724 Note that the ``errlist`` can contain a special element with a key of
726 That element means that there were too many errors to place on the
728 Those errors are suppressed and only their count is provided as a
729 value of the special ``N_MORE_ERRORS`` element.
734 if len(errlist
) == 0:
736 names
= list(zip(names
, range(2)))
741 errors
= [mapper(ret
, name
)]
744 suppressed_count
= errlist
.pop('N_MORE_ERRORS', 0)
747 errors
.append(mapper(err
, name
))
749 raise exception(errors
, suppressed_count
)
752 def _pool_name(name
):
754 Extract a pool name from the given dataset or bookmark name.
756 '/' separates dataset name components.
757 '@' separates a snapshot name from the rest of the dataset name.
758 '#' separates a bookmark name from the rest of the dataset name.
760 return re
.split(b
'[/@#]', name
, 1)[0]
765 Extract a dataset name from the given snapshot or bookmark name.
767 '@' separates a snapshot name from the rest of the dataset name.
768 '#' separates a bookmark name from the rest of the dataset name.
770 return re
.split(b
'[@#]', name
, 1)[0]
773 def _is_valid_name_component(component
):
774 allowed
= string
.ascii_letters
+ string
.digits
+ u
'-_.: '
775 return component
and all(x
in allowed
.encode() for x
in component
)
778 def _is_valid_fs_name(name
):
779 return name
and all(_is_valid_name_component(c
) for c
in name
.split(b
'/'))
782 def _is_valid_snap_name(name
):
783 parts
= name
.split(b
'@')
784 return (len(parts
) == 2 and _is_valid_fs_name(parts
[0]) and
785 _is_valid_name_component(parts
[1]))
788 def _is_valid_bmark_name(name
):
789 parts
= name
.split(b
'#')
790 return (len(parts
) == 2 and _is_valid_fs_name(parts
[0]) and
791 _is_valid_name_component(parts
[1]))
794 def _validate_fs_name(name
):
795 if not _is_valid_fs_name(name
):
796 raise lzc_exc
.FilesystemNameInvalid(name
)
797 elif len(name
) > MAXNAMELEN
:
798 raise lzc_exc
.NameTooLong(name
)
801 def _validate_snap_name(name
):
802 if not _is_valid_snap_name(name
):
803 raise lzc_exc
.SnapshotNameInvalid(name
)
804 elif len(name
) > MAXNAMELEN
:
805 raise lzc_exc
.NameTooLong(name
)
808 def _validate_bmark_name(name
):
809 if not _is_valid_bmark_name(name
):
810 raise lzc_exc
.BookmarkNameInvalid(name
)
811 elif len(name
) > MAXNAMELEN
:
812 raise lzc_exc
.NameTooLong(name
)
815 def _validate_fs_or_snap_name(name
):
816 if not _is_valid_fs_name(name
) and not _is_valid_snap_name(name
):
817 raise lzc_exc
.NameInvalid(name
)
818 elif len(name
) > MAXNAMELEN
:
819 raise lzc_exc
.NameTooLong(name
)
822 def _generic_exception(err
, name
, message
):
823 if err
in _error_to_exception
:
824 return _error_to_exception
[err
](name
)
826 return lzc_exc
.ZFSGenericError(err
, message
, name
)
829 _error_to_exception
= {e
.errno
: e
for e
in [
832 lzc_exc
.QuotaExceeded
,
835 lzc_exc
.ReadOnlyPool
,
836 lzc_exc
.SuspendedPool
,
838 lzc_exc
.PropertyNotSupported
,
842 # vim: softtabstop=4 tabstop=4 expandtab shiftwidth=4