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 (
37 ZFS_ERR_CHECKPOINT_EXISTS
,
38 ZFS_ERR_DISCARDING_CHECKPOINT
,
39 ZFS_ERR_NO_CHECKPOINT
,
40 ZFS_ERR_DEVRM_IN_PROGRESS
,
46 def lzc_create_translate_error(ret
, name
, ds_type
, props
):
49 if ret
== errno
.EINVAL
:
50 _validate_fs_name(name
)
51 raise lzc_exc
.PropertyInvalid(name
)
52 if ret
== errno
.EEXIST
:
53 raise lzc_exc
.FilesystemExists(name
)
54 if ret
== errno
.ENOENT
:
55 raise lzc_exc
.ParentNotFound(name
)
56 if ret
== ZFS_ERR_WRONG_PARENT
:
57 raise lzc_exc
.WrongParent(_fs_name(name
))
58 raise _generic_exception(ret
, name
, "Failed to create filesystem")
61 def lzc_clone_translate_error(ret
, name
, origin
, props
):
64 if ret
== errno
.EINVAL
:
65 _validate_fs_name(name
)
66 _validate_snap_name(origin
)
67 raise lzc_exc
.PropertyInvalid(name
)
68 if ret
== errno
.EXDEV
:
69 raise lzc_exc
.PoolsDiffer(name
)
70 if ret
== errno
.EEXIST
:
71 raise lzc_exc
.FilesystemExists(name
)
72 if ret
== errno
.ENOENT
:
73 if not _is_valid_snap_name(origin
):
74 raise lzc_exc
.SnapshotNameInvalid(origin
)
75 raise lzc_exc
.DatasetNotFound(name
)
76 raise _generic_exception(ret
, name
, "Failed to create clone")
79 def lzc_rollback_translate_error(ret
, name
):
82 if ret
== errno
.ESRCH
:
83 raise lzc_exc
.SnapshotNotFound(name
)
84 if ret
== errno
.EINVAL
:
85 _validate_fs_name(name
)
86 raise lzc_exc
.NameInvalid(name
)
87 if ret
== errno
.ENOENT
:
88 if not _is_valid_fs_name(name
):
89 raise lzc_exc
.NameInvalid(name
)
91 raise lzc_exc
.FilesystemNotFound(name
)
92 raise _generic_exception(ret
, name
, "Failed to rollback")
95 def lzc_rollback_to_translate_error(ret
, name
, snap
):
96 if ret
== errno
.EEXIST
:
97 raise lzc_exc
.SnapshotNotLatest(snap
)
99 lzc_rollback_translate_error(ret
, name
)
102 def lzc_snapshot_translate_errors(ret
, errlist
, snaps
, props
):
107 if ret
== errno
.EXDEV
:
108 pool_names
= iter(map(_pool_name
, snaps
))
109 pool_name
= next(pool_names
, None)
110 same_pool
= all(x
== pool_name
for x
in pool_names
)
112 return lzc_exc
.DuplicateSnapshots(name
)
114 return lzc_exc
.PoolsDiffer(name
)
115 elif ret
== errno
.EINVAL
:
116 if any(not _is_valid_snap_name(s
) for s
in snaps
):
117 return lzc_exc
.NameInvalid(name
)
118 elif any(len(s
) > MAXNAMELEN
for s
in snaps
):
119 return lzc_exc
.NameTooLong(name
)
121 return lzc_exc
.PropertyInvalid(name
)
123 if ret
== errno
.EEXIST
:
124 return lzc_exc
.SnapshotExists(name
)
125 if ret
== errno
.ENOENT
:
126 return lzc_exc
.FilesystemNotFound(name
)
127 return _generic_exception(ret
, name
, "Failed to create snapshot")
129 _handle_err_list(ret
, errlist
, snaps
, lzc_exc
.SnapshotFailure
, _map
)
132 def lzc_destroy_snaps_translate_errors(ret
, errlist
, snaps
, defer
):
137 if ret
== errno
.EEXIST
:
138 return lzc_exc
.SnapshotIsCloned(name
)
139 if ret
== errno
.ENOENT
:
140 return lzc_exc
.PoolNotFound(name
)
141 if ret
== errno
.EBUSY
:
142 return lzc_exc
.SnapshotIsHeld(name
)
143 return _generic_exception(ret
, name
, "Failed to destroy snapshot")
146 ret
, errlist
, snaps
, lzc_exc
.SnapshotDestructionFailure
, _map
)
149 def lzc_bookmark_translate_errors(ret
, errlist
, bookmarks
):
154 if ret
== errno
.EINVAL
:
156 snap
= bookmarks
[name
]
157 pool_names
= map(_pool_name
, bookmarks
.keys())
158 if not _is_valid_bmark_name(name
):
159 return lzc_exc
.BookmarkNameInvalid(name
)
160 elif not _is_valid_snap_name(snap
):
161 return lzc_exc
.SnapshotNameInvalid(snap
)
162 elif _fs_name(name
) != _fs_name(snap
):
163 return lzc_exc
.BookmarkMismatch(name
)
164 elif any(x
!= _pool_name(name
) for x
in pool_names
):
165 return lzc_exc
.PoolsDiffer(name
)
168 b
for b
in bookmarks
.keys() if not _is_valid_bmark_name(b
)]
170 return lzc_exc
.BookmarkNameInvalid(invalid_names
[0])
171 if ret
== errno
.EEXIST
:
172 return lzc_exc
.BookmarkExists(name
)
173 if ret
== errno
.ENOENT
:
174 return lzc_exc
.SnapshotNotFound(name
)
175 if ret
== errno
.ENOTSUP
:
176 return lzc_exc
.BookmarkNotSupported(name
)
177 return _generic_exception(ret
, name
, "Failed to create bookmark")
180 ret
, errlist
, bookmarks
.keys(), lzc_exc
.BookmarkFailure
, _map
)
183 def lzc_get_bookmarks_translate_error(ret
, fsname
, props
):
186 if ret
== errno
.ENOENT
:
187 raise lzc_exc
.FilesystemNotFound(fsname
)
188 raise _generic_exception(ret
, fsname
, "Failed to list bookmarks")
191 def lzc_destroy_bookmarks_translate_errors(ret
, errlist
, bookmarks
):
196 if ret
== errno
.EINVAL
:
197 return lzc_exc
.NameInvalid(name
)
198 return _generic_exception(ret
, name
, "Failed to destroy bookmark")
201 ret
, errlist
, bookmarks
, lzc_exc
.BookmarkDestructionFailure
, _map
)
204 def lzc_snaprange_space_translate_error(ret
, firstsnap
, lastsnap
):
207 if ret
== errno
.EXDEV
and firstsnap
is not None:
208 if _pool_name(firstsnap
) != _pool_name(lastsnap
):
209 raise lzc_exc
.PoolsDiffer(lastsnap
)
211 raise lzc_exc
.SnapshotMismatch(lastsnap
)
212 if ret
== errno
.EINVAL
:
213 if not _is_valid_snap_name(firstsnap
):
214 raise lzc_exc
.NameInvalid(firstsnap
)
215 elif not _is_valid_snap_name(lastsnap
):
216 raise lzc_exc
.NameInvalid(lastsnap
)
217 elif len(firstsnap
) > MAXNAMELEN
:
218 raise lzc_exc
.NameTooLong(firstsnap
)
219 elif len(lastsnap
) > MAXNAMELEN
:
220 raise lzc_exc
.NameTooLong(lastsnap
)
221 elif _pool_name(firstsnap
) != _pool_name(lastsnap
):
222 raise lzc_exc
.PoolsDiffer(lastsnap
)
224 raise lzc_exc
.SnapshotMismatch(lastsnap
)
225 if ret
== errno
.ENOENT
:
226 raise lzc_exc
.SnapshotNotFound(lastsnap
)
227 raise _generic_exception(
228 ret
, lastsnap
, "Failed to calculate space used by range of snapshots")
231 def lzc_hold_translate_errors(ret
, errlist
, holds
, fd
):
236 if ret
== errno
.EXDEV
:
237 return lzc_exc
.PoolsDiffer(name
)
238 elif ret
== errno
.EINVAL
:
240 pool_names
= map(_pool_name
, holds
.keys())
241 if not _is_valid_snap_name(name
):
242 return lzc_exc
.NameInvalid(name
)
243 elif len(name
) > MAXNAMELEN
:
244 return lzc_exc
.NameTooLong(name
)
245 elif any(x
!= _pool_name(name
) for x
in pool_names
):
246 return lzc_exc
.PoolsDiffer(name
)
249 b
for b
in holds
.keys() if not _is_valid_snap_name(b
)]
251 return lzc_exc
.NameInvalid(invalid_names
[0])
256 fs_name
= _fs_name(name
)
257 pool_name
= _pool_name(name
)
258 hold_name
= holds
[name
]
259 if ret
== errno
.ENOENT
:
260 return lzc_exc
.FilesystemNotFound(fs_name
)
261 if ret
== errno
.EEXIST
:
262 return lzc_exc
.HoldExists(name
)
263 if ret
== errno
.E2BIG
:
264 return lzc_exc
.NameTooLong(hold_name
)
265 if ret
== errno
.ENOTSUP
:
266 return lzc_exc
.FeatureNotSupported(pool_name
)
267 return _generic_exception(ret
, name
, "Failed to hold snapshot")
269 if ret
== errno
.EBADF
:
270 raise lzc_exc
.BadHoldCleanupFD()
271 _handle_err_list(ret
, errlist
, holds
.keys(), lzc_exc
.HoldFailure
, _map
)
274 def lzc_release_translate_errors(ret
, errlist
, holds
):
278 hold_list
= holds
[snap
]
279 if not isinstance(hold_list
, list):
280 raise lzc_exc
.TypeError('holds must be in a list')
283 if ret
== errno
.EXDEV
:
284 return lzc_exc
.PoolsDiffer(name
)
285 elif ret
== errno
.EINVAL
:
287 pool_names
= map(_pool_name
, holds
.keys())
288 if not _is_valid_snap_name(name
):
289 return lzc_exc
.NameInvalid(name
)
290 elif len(name
) > MAXNAMELEN
:
291 return lzc_exc
.NameTooLong(name
)
292 elif any(x
!= _pool_name(name
) for x
in pool_names
):
293 return lzc_exc
.PoolsDiffer(name
)
296 b
for b
in holds
.keys() if not _is_valid_snap_name(b
)]
298 return lzc_exc
.NameInvalid(invalid_names
[0])
299 elif ret
== errno
.ENOENT
:
300 return lzc_exc
.HoldNotFound(name
)
301 elif ret
== errno
.E2BIG
:
302 tag_list
= holds
[name
]
303 too_long_tags
= [t
for t
in tag_list
if len(t
) > MAXNAMELEN
]
304 return lzc_exc
.NameTooLong(too_long_tags
[0])
305 elif ret
== errno
.ENOTSUP
:
308 pool_name
= _pool_name(name
)
309 return lzc_exc
.FeatureNotSupported(pool_name
)
311 return _generic_exception(
312 ret
, name
, "Failed to release snapshot hold")
315 ret
, errlist
, holds
.keys(), lzc_exc
.HoldReleaseFailure
, _map
)
318 def lzc_get_holds_translate_error(ret
, snapname
):
321 if ret
== errno
.EINVAL
:
322 _validate_snap_name(snapname
)
323 if ret
== errno
.ENOENT
:
324 raise lzc_exc
.SnapshotNotFound(snapname
)
325 if ret
== errno
.ENOTSUP
:
326 raise lzc_exc
.FeatureNotSupported(_pool_name(snapname
))
327 raise _generic_exception(ret
, snapname
, "Failed to get holds on snapshot")
330 def lzc_send_translate_error(ret
, snapname
, fromsnap
, fd
, flags
):
333 if ret
== errno
.EXDEV
and fromsnap
is not None:
334 if _pool_name(fromsnap
) != _pool_name(snapname
):
335 raise lzc_exc
.PoolsDiffer(snapname
)
337 raise lzc_exc
.SnapshotMismatch(snapname
)
338 elif ret
== errno
.EINVAL
:
339 if (fromsnap
is not None and not _is_valid_snap_name(fromsnap
) and
340 not _is_valid_bmark_name(fromsnap
)):
341 raise lzc_exc
.NameInvalid(fromsnap
)
342 elif (not _is_valid_snap_name(snapname
) and
343 not _is_valid_fs_name(snapname
)):
344 raise lzc_exc
.NameInvalid(snapname
)
345 elif fromsnap
is not None and len(fromsnap
) > MAXNAMELEN
:
346 raise lzc_exc
.NameTooLong(fromsnap
)
347 elif len(snapname
) > MAXNAMELEN
:
348 raise lzc_exc
.NameTooLong(snapname
)
349 elif (fromsnap
is not None and
350 _pool_name(fromsnap
) != _pool_name(snapname
)):
351 raise lzc_exc
.PoolsDiffer(snapname
)
352 elif ret
== errno
.ENOENT
:
353 if (fromsnap
is not None and not _is_valid_snap_name(fromsnap
) and
354 not _is_valid_bmark_name(fromsnap
)):
355 raise lzc_exc
.NameInvalid(fromsnap
)
356 raise lzc_exc
.SnapshotNotFound(snapname
)
357 elif ret
== errno
.ENAMETOOLONG
:
358 if fromsnap
is not None and len(fromsnap
) > MAXNAMELEN
:
359 raise lzc_exc
.NameTooLong(fromsnap
)
361 raise lzc_exc
.NameTooLong(snapname
)
362 raise lzc_exc
.StreamIOError(ret
)
365 def lzc_send_space_translate_error(ret
, snapname
, fromsnap
):
368 if ret
== errno
.EXDEV
and fromsnap
is not None:
369 if _pool_name(fromsnap
) != _pool_name(snapname
):
370 raise lzc_exc
.PoolsDiffer(snapname
)
372 raise lzc_exc
.SnapshotMismatch(snapname
)
373 elif ret
== errno
.EINVAL
:
374 if fromsnap
is not None and not _is_valid_snap_name(fromsnap
):
375 raise lzc_exc
.NameInvalid(fromsnap
)
376 elif not _is_valid_snap_name(snapname
):
377 raise lzc_exc
.NameInvalid(snapname
)
378 elif fromsnap
is not None and len(fromsnap
) > MAXNAMELEN
:
379 raise lzc_exc
.NameTooLong(fromsnap
)
380 elif len(snapname
) > MAXNAMELEN
:
381 raise lzc_exc
.NameTooLong(snapname
)
382 elif (fromsnap
is not None and
383 _pool_name(fromsnap
) != _pool_name(snapname
)):
384 raise lzc_exc
.PoolsDiffer(snapname
)
385 elif ret
== errno
.ENOENT
and fromsnap
is not None:
386 if not _is_valid_snap_name(fromsnap
):
387 raise lzc_exc
.NameInvalid(fromsnap
)
388 if ret
== errno
.ENOENT
:
389 raise lzc_exc
.SnapshotNotFound(snapname
)
390 raise _generic_exception(
391 ret
, snapname
, "Failed to estimate backup stream size")
394 def lzc_receive_translate_errors(
395 ret
, snapname
, fd
, force
, raw
, resumable
, embedded
, origin
, properrs
398 if properrs
is not None and len(properrs
) > 0:
400 if ret
== errno
.EINVAL
:
401 return lzc_exc
.PropertyInvalid(name
)
402 return _generic_exception(ret
, name
, "Failed to set property")
404 errno
.EINVAL
, properrs
, [snapname
],
405 lzc_exc
.ReceivePropertyFailure
, _map
)
408 if ret
== errno
.EINVAL
:
409 if (not _is_valid_snap_name(snapname
) and
410 not _is_valid_fs_name(snapname
)):
411 raise lzc_exc
.NameInvalid(snapname
)
412 elif len(snapname
) > MAXNAMELEN
:
413 raise lzc_exc
.NameTooLong(snapname
)
414 elif origin
is not None and not _is_valid_snap_name(origin
):
415 raise lzc_exc
.NameInvalid(origin
)
417 raise lzc_exc
.StreamFeatureInvalid()
418 elif embedded
and not raw
:
419 raise lzc_exc
.StreamFeatureIncompatible()
421 raise lzc_exc
.BadStream()
422 if ret
== errno
.ENOENT
:
423 if not _is_valid_snap_name(snapname
):
424 raise lzc_exc
.NameInvalid(snapname
)
426 raise lzc_exc
.DatasetNotFound(snapname
)
427 if ret
== errno
.EEXIST
:
428 raise lzc_exc
.DatasetExists(snapname
)
429 if ret
== errno
.ENOTSUP
:
430 raise lzc_exc
.StreamFeatureNotSupported()
431 if ret
== errno
.ENODEV
:
432 raise lzc_exc
.StreamMismatch(_fs_name(snapname
))
433 if ret
== errno
.ETXTBSY
:
434 raise lzc_exc
.DestinationModified(_fs_name(snapname
))
435 if ret
== errno
.EBUSY
:
436 raise lzc_exc
.DatasetBusy(_fs_name(snapname
))
437 if ret
== errno
.ENOSPC
:
438 raise lzc_exc
.NoSpace(_fs_name(snapname
))
439 if ret
== errno
.EDQUOT
:
440 raise lzc_exc
.QuotaExceeded(_fs_name(snapname
))
441 if ret
== errno
.ENAMETOOLONG
:
442 raise lzc_exc
.NameTooLong(snapname
)
443 if ret
== errno
.EROFS
:
444 raise lzc_exc
.ReadOnlyPool(_pool_name(snapname
))
445 if ret
== errno
.EAGAIN
:
446 raise lzc_exc
.SuspendedPool(_pool_name(snapname
))
447 if ret
== errno
.EBADE
: # ECKSUM
448 raise lzc_exc
.BadStream()
449 if ret
== ZFS_ERR_WRONG_PARENT
:
450 raise lzc_exc
.WrongParent(_fs_name(snapname
))
452 raise lzc_exc
.StreamIOError(ret
)
455 def lzc_promote_translate_error(ret
, name
):
458 if ret
== errno
.EINVAL
:
459 _validate_fs_name(name
)
460 raise lzc_exc
.NotClone(name
)
461 if ret
== errno
.ENOTSOCK
:
462 raise lzc_exc
.NotClone(name
)
463 if ret
== errno
.ENOENT
:
464 raise lzc_exc
.FilesystemNotFound(name
)
465 if ret
== errno
.EEXIST
:
466 raise lzc_exc
.SnapshotExists(name
)
467 raise _generic_exception(ret
, name
, "Failed to promote dataset")
470 def lzc_change_key_translate_error(ret
, name
):
473 if ret
== errno
.EINVAL
:
474 _validate_fs_name(name
)
475 raise lzc_exc
.PropertyInvalid(name
)
476 if ret
== errno
.ENOENT
:
477 raise lzc_exc
.FilesystemNotFound(name
)
478 if ret
== errno
.EACCES
:
479 raise lzc_exc
.EncryptionKeyNotLoaded()
480 raise _generic_exception(ret
, name
, "Failed to change encryption key")
483 def lzc_load_key_translate_error(ret
, name
, noop
):
486 if ret
== errno
.EINVAL
:
487 _validate_fs_name(name
)
488 raise lzc_exc
.PropertyInvalid(name
)
489 if ret
== errno
.ENOENT
:
490 raise lzc_exc
.FilesystemNotFound(name
)
491 if ret
== errno
.EACCES
:
492 raise lzc_exc
.EncryptionKeyInvalid()
493 if ret
== errno
.EEXIST
:
494 raise lzc_exc
.EncryptionKeyAlreadyLoaded()
496 raise _generic_exception(ret
, name
, "Failed to load encryption key")
498 raise _generic_exception(ret
, name
, "Failed to verify encryption key")
501 def lzc_unload_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 unload encryption key")
514 def lzc_sync_translate_error(ret
, name
):
517 if ret
== errno
.ENOENT
:
518 raise lzc_exc
.PoolNotFound(name
)
519 raise _generic_exception(ret
, name
, "Failed to sync pool")
522 def lzc_reopen_translate_error(ret
, name
):
525 if ret
== errno
.ENOENT
:
526 raise lzc_exc
.PoolNotFound(name
)
527 raise _generic_exception(ret
, name
, "Failed to reopen pool")
530 def lzc_channel_program_translate_error(ret
, name
, error
):
533 if ret
== errno
.ENOENT
:
534 raise lzc_exc
.PoolNotFound(name
)
535 if ret
== errno
.ETIME
:
536 raise lzc_exc
.ZCPTimeout()
537 if ret
== errno
.ENOMEM
:
538 raise lzc_exc
.ZCPMemoryError()
539 if ret
== errno
.ENOSPC
:
540 raise lzc_exc
.ZCPSpaceError()
541 if ret
== errno
.EPERM
:
542 raise lzc_exc
.ZCPPermissionError()
543 if ret
== errno
.ECHRNG
:
544 raise lzc_exc
.ZCPRuntimeError(error
)
545 if ret
== errno
.EINVAL
:
547 raise lzc_exc
.ZCPLimitInvalid()
549 raise lzc_exc
.ZCPSyntaxError(error
)
550 raise _generic_exception(ret
, name
, "Failed to execute channel program")
553 def lzc_remap_translate_error(ret
, name
):
556 if ret
== errno
.ENOENT
:
557 raise lzc_exc
.DatasetNotFound(name
)
558 if ret
== errno
.EINVAL
:
559 _validate_fs_name(name
)
560 if ret
== errno
.ENOTSUP
:
561 return lzc_exc
.FeatureNotSupported(name
)
562 raise _generic_exception(ret
, name
, "Failed to remap dataset")
565 def lzc_pool_checkpoint_translate_error(ret
, name
, discard
=False):
568 if ret
== errno
.ENOENT
:
569 raise lzc_exc
.PoolNotFound(name
)
570 if ret
== ZFS_ERR_CHECKPOINT_EXISTS
:
571 raise lzc_exc
.CheckpointExists()
572 if ret
== ZFS_ERR_NO_CHECKPOINT
:
573 raise lzc_exc
.CheckpointNotFound()
574 if ret
== ZFS_ERR_DISCARDING_CHECKPOINT
:
575 raise lzc_exc
.CheckpointDiscarding()
576 if ret
== ZFS_ERR_DEVRM_IN_PROGRESS
:
577 raise lzc_exc
.DeviceRemovalRunning()
578 if ret
== ZFS_ERR_VDEV_TOO_BIG
:
579 raise lzc_exc
.DeviceTooBig()
581 raise _generic_exception(
582 ret
, name
, "Failed to discard pool checkpoint")
584 raise _generic_exception(ret
, name
, "Failed to create pool checkpoint")
587 def lzc_pool_checkpoint_discard_translate_error(ret
, name
):
588 lzc_pool_checkpoint_translate_error(ret
, name
, discard
=True)
591 def lzc_rename_translate_error(ret
, source
, target
):
594 if ret
== errno
.EINVAL
:
595 _validate_fs_name(source
)
596 _validate_fs_name(target
)
597 if _pool_name(source
) != _pool_name(target
):
598 raise lzc_exc
.PoolsDiffer(source
)
599 if ret
== errno
.EEXIST
:
600 raise lzc_exc
.FilesystemExists(target
)
601 if ret
== errno
.ENOENT
:
602 raise lzc_exc
.FilesystemNotFound(source
)
603 if ret
== ZFS_ERR_WRONG_PARENT
:
604 raise lzc_exc
.WrongParent(target
)
605 raise _generic_exception(ret
, source
, "Failed to rename dataset")
608 def lzc_destroy_translate_error(ret
, name
):
611 if ret
== errno
.EINVAL
:
612 _validate_fs_name(name
)
613 if ret
== errno
.ENOENT
:
614 raise lzc_exc
.FilesystemNotFound(name
)
615 raise _generic_exception(ret
, name
, "Failed to destroy dataset")
618 def lzc_inherit_prop_translate_error(ret
, name
, prop
):
621 if ret
== errno
.EINVAL
:
622 _validate_fs_name(name
)
623 raise lzc_exc
.PropertyInvalid(prop
)
624 if ret
== errno
.ENOENT
:
625 raise lzc_exc
.DatasetNotFound(name
)
626 raise _generic_exception(ret
, name
, "Failed to inherit a property")
629 def lzc_set_prop_translate_error(ret
, name
, prop
, val
):
632 if ret
== errno
.EINVAL
:
633 _validate_fs_or_snap_name(name
)
634 raise lzc_exc
.PropertyInvalid(prop
)
635 if ret
== errno
.ENOENT
:
636 raise lzc_exc
.DatasetNotFound(name
)
637 raise _generic_exception(ret
, name
, "Failed to set a property")
640 def lzc_get_props_translate_error(ret
, name
):
643 if ret
== errno
.EINVAL
:
644 _validate_fs_or_snap_name(name
)
645 if ret
== errno
.ENOENT
:
646 raise lzc_exc
.DatasetNotFound(name
)
647 raise _generic_exception(ret
, name
, "Failed to get properties")
650 def lzc_list_children_translate_error(ret
, name
):
653 if ret
== errno
.EINVAL
:
654 _validate_fs_name(name
)
655 raise _generic_exception(ret
, name
, "Error while iterating children")
658 def lzc_list_snaps_translate_error(ret
, name
):
661 if ret
== errno
.EINVAL
:
662 _validate_fs_name(name
)
663 raise _generic_exception(ret
, name
, "Error while iterating snapshots")
666 def lzc_list_translate_error(ret
, name
, opts
):
669 if ret
== errno
.ENOENT
:
670 raise lzc_exc
.DatasetNotFound(name
)
671 if ret
== errno
.EINVAL
:
672 _validate_fs_or_snap_name(name
)
673 raise _generic_exception(ret
, name
, "Error obtaining a list")
676 def _handle_err_list(ret
, errlist
, names
, exception
, mapper
):
678 Convert one or more errors from an operation into the requested exception.
680 :param int ret: the overall return code.
681 :param errlist: the dictionary that maps entity names to their specific
683 :type errlist: dict of bytes:int
684 :param names: the list of all names of the entities on which the operation
686 :param type exception: the type of the exception to raise if an error
687 occurred. The exception should be a subclass of
688 ``MultipleOperationsFailure``.
689 :param function mapper: the function that maps an error code and a name to
692 Unless ``ret`` is zero this function will raise the ``exception``.
693 If the ``errlist`` is not empty, then the compound exception will contain
694 a list of exceptions corresponding to each individual error code in the
696 Otherwise, the ``exception`` will contain a list with a single exception
697 corresponding to the ``ret`` value. If the ``names`` list contains only one
698 element, that is, the operation was attempted on a single entity, then the
699 name of that entity is passed to the ``mapper``.
700 If the operation was attempted on multiple entities, but the ``errlist``
701 is empty, then we can not know which entity caused the error and, thus,
702 ``None`` is used as a name to signify that fact.
705 Note that the ``errlist`` can contain a special element with a key of
707 That element means that there were too many errors to place on the
709 Those errors are suppressed and only their count is provided as a
710 value of the special ``N_MORE_ERRORS`` element.
715 if len(errlist
) == 0:
717 names
= list(zip(names
, range(2)))
722 errors
= [mapper(ret
, name
)]
725 suppressed_count
= errlist
.pop('N_MORE_ERRORS', 0)
728 errors
.append(mapper(err
, name
))
730 raise exception(errors
, suppressed_count
)
733 def _pool_name(name
):
735 Extract a pool name from the given dataset or bookmark name.
737 '/' separates dataset name components.
738 '@' separates a snapshot name from the rest of the dataset name.
739 '#' separates a bookmark name from the rest of the dataset name.
741 return re
.split(b
'[/@#]', name
, 1)[0]
746 Extract a dataset name from the given snapshot or bookmark name.
748 '@' separates a snapshot name from the rest of the dataset name.
749 '#' separates a bookmark name from the rest of the dataset name.
751 return re
.split(b
'[@#]', name
, 1)[0]
754 def _is_valid_name_component(component
):
755 allowed
= string
.ascii_letters
+ string
.digits
+ u
'-_.: '
756 return component
and all(x
in allowed
.encode() for x
in component
)
759 def _is_valid_fs_name(name
):
760 return name
and all(_is_valid_name_component(c
) for c
in name
.split(b
'/'))
763 def _is_valid_snap_name(name
):
764 parts
= name
.split(b
'@')
765 return (len(parts
) == 2 and _is_valid_fs_name(parts
[0]) and
766 _is_valid_name_component(parts
[1]))
769 def _is_valid_bmark_name(name
):
770 parts
= name
.split(b
'#')
771 return (len(parts
) == 2 and _is_valid_fs_name(parts
[0]) and
772 _is_valid_name_component(parts
[1]))
775 def _validate_fs_name(name
):
776 if not _is_valid_fs_name(name
):
777 raise lzc_exc
.FilesystemNameInvalid(name
)
778 elif len(name
) > MAXNAMELEN
:
779 raise lzc_exc
.NameTooLong(name
)
782 def _validate_snap_name(name
):
783 if not _is_valid_snap_name(name
):
784 raise lzc_exc
.SnapshotNameInvalid(name
)
785 elif len(name
) > MAXNAMELEN
:
786 raise lzc_exc
.NameTooLong(name
)
789 def _validate_bmark_name(name
):
790 if not _is_valid_bmark_name(name
):
791 raise lzc_exc
.BookmarkNameInvalid(name
)
792 elif len(name
) > MAXNAMELEN
:
793 raise lzc_exc
.NameTooLong(name
)
796 def _validate_fs_or_snap_name(name
):
797 if not _is_valid_fs_name(name
) and not _is_valid_snap_name(name
):
798 raise lzc_exc
.NameInvalid(name
)
799 elif len(name
) > MAXNAMELEN
:
800 raise lzc_exc
.NameTooLong(name
)
803 def _generic_exception(err
, name
, message
):
804 if err
in _error_to_exception
:
805 return _error_to_exception
[err
](name
)
807 return lzc_exc
.ZFSGenericError(err
, message
, name
)
810 _error_to_exception
= {e
.errno
: e
for e
in [
813 lzc_exc
.QuotaExceeded
,
816 lzc_exc
.ReadOnlyPool
,
817 lzc_exc
.SuspendedPool
,
819 lzc_exc
.PropertyNotSupported
,
823 # vim: softtabstop=4 tabstop=4 expandtab shiftwidth=4