Fix invalid pointer access in trace_dbuf.h
[zfs.git] / contrib / pyzfs / libzfs_core / _error_translation.py
blob26676db398c51a3e3d37924910151ac1f0354a1a
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.
17 """
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.
28 """
29 from __future__ import absolute_import, division, print_function
31 import errno
32 import re
33 import string
34 from . import exceptions as lzc_exc
35 from ._constants import (
36 ECHRNG,
37 ECKSUM,
38 ETIME,
39 MAXNAMELEN,
40 ZFS_ERR_CHECKPOINT_EXISTS,
41 ZFS_ERR_DISCARDING_CHECKPOINT,
42 ZFS_ERR_NO_CHECKPOINT,
43 ZFS_ERR_DEVRM_IN_PROGRESS,
44 ZFS_ERR_VDEV_TOO_BIG,
45 ZFS_ERR_WRONG_PARENT,
46 zfs_errno
50 def lzc_create_translate_error(ret, name, ds_type, props):
51 if ret == 0:
52 return
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):
68 if ret == 0:
69 return
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):
86 if ret == 0:
87 return
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)
96 else:
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)
104 else:
105 lzc_rollback_translate_error(ret, name)
108 def lzc_snapshot_translate_errors(ret, errlist, snaps, props):
109 if ret == 0:
110 return
112 def _map(ret, name):
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)
117 if same_pool:
118 return lzc_exc.DuplicateSnapshots(name)
119 else:
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)
126 else:
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):
139 if ret == 0:
140 return
142 def _map(ret, name):
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")
151 _handle_err_list(
152 ret, errlist, snaps, lzc_exc.SnapshotDestructionFailure, _map)
155 def lzc_bookmark_translate_errors(ret, errlist, bookmarks):
157 if ret == 0:
158 return
160 def _map(ret, name):
161 source = bookmarks[name]
162 if ret == errno.EINVAL:
163 if name:
164 pool_names = map(_pool_name, bookmarks.keys())
166 # use _validate* functions for MAXNAMELEN check
167 try:
168 _validate_bmark_name(name)
169 except lzc_exc.ZFSError as e:
170 return e
172 try:
173 _validate_snap_name(source)
174 source_is_snap = True
175 except lzc_exc.ZFSError:
176 source_is_snap = False
177 try:
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)
187 else:
188 invalid_names = [
189 b for b in bookmarks.keys() if not _is_valid_bmark_name(b)]
190 if invalid_names:
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")
202 _handle_err_list(
203 ret, errlist, bookmarks.keys(), lzc_exc.BookmarkFailure, _map)
206 def lzc_get_bookmarks_translate_error(ret, fsname, props):
207 if ret == 0:
208 return
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):
215 if ret == 0:
216 return
218 def _map(ret, name):
219 if ret == errno.EINVAL:
220 return lzc_exc.NameInvalid(name)
221 return _generic_exception(ret, name, "Failed to destroy bookmark")
223 _handle_err_list(
224 ret, errlist, bookmarks, lzc_exc.BookmarkDestructionFailure, _map)
227 def lzc_snaprange_space_translate_error(ret, firstsnap, lastsnap):
228 if ret == 0:
229 return
230 if ret == errno.EXDEV and firstsnap is not None:
231 if _pool_name(firstsnap) != _pool_name(lastsnap):
232 raise lzc_exc.PoolsDiffer(lastsnap)
233 else:
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)
246 else:
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):
255 if ret == 0:
256 return
258 def _map(ret, name):
259 if ret == errno.EXDEV:
260 return lzc_exc.PoolsDiffer(name)
261 elif ret == errno.EINVAL:
262 if name:
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)
270 else:
271 invalid_names = [
272 b for b in holds.keys() if not _is_valid_snap_name(b)]
273 if invalid_names:
274 return lzc_exc.NameInvalid(invalid_names[0])
275 fs_name = None
276 hold_name = None
277 pool_name = None
278 if name is not None:
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):
298 if ret == 0:
299 return
300 for snap in holds:
301 hold_list = holds[snap]
302 if not isinstance(hold_list, list):
303 raise lzc_exc.TypeError('holds must be in a list')
305 def _map(ret, name):
306 if ret == errno.EXDEV:
307 return lzc_exc.PoolsDiffer(name)
308 elif ret == errno.EINVAL:
309 if name:
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)
317 else:
318 invalid_names = [
319 b for b in holds.keys() if not _is_valid_snap_name(b)]
320 if invalid_names:
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:
329 pool_name = None
330 if name is not None:
331 pool_name = _pool_name(name)
332 return lzc_exc.FeatureNotSupported(pool_name)
333 else:
334 return _generic_exception(
335 ret, name, "Failed to release snapshot hold")
337 _handle_err_list(
338 ret, errlist, holds.keys(), lzc_exc.HoldReleaseFailure, _map)
341 def lzc_get_holds_translate_error(ret, snapname):
342 if ret == 0:
343 return
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):
354 if ret == 0:
355 return
356 if ret == errno.EXDEV and fromsnap is not None:
357 if _pool_name(fromsnap) != _pool_name(snapname):
358 raise lzc_exc.PoolsDiffer(snapname)
359 else:
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)
383 else:
384 raise lzc_exc.NameTooLong(snapname)
385 raise lzc_exc.StreamIOError(ret)
388 def lzc_send_space_translate_error(ret, snapname, fromsnap):
389 if ret == 0:
390 return
391 if ret == errno.EXDEV and fromsnap is not None:
392 if _pool_name(fromsnap) != _pool_name(snapname):
393 raise lzc_exc.PoolsDiffer(snapname)
394 else:
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
420 if ret == 0:
421 if properrs is not None and len(properrs) > 0:
422 def _map(ret, name):
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")
428 _handle_err_list(
429 errno.EINVAL, properrs, [snapname],
430 lzc_exc.ReceivePropertyFailure, _map)
431 else:
432 return
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)
441 elif resumable:
442 raise lzc_exc.StreamFeatureInvalid()
443 elif embedded and not raw:
444 raise lzc_exc.StreamFeatureIncompatible()
445 else:
446 raise lzc_exc.BadStream()
447 if ret == errno.ENOENT:
448 if not _is_valid_snap_name(snapname):
449 raise lzc_exc.NameInvalid(snapname)
450 else:
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()
474 if ret == ECKSUM:
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):
487 if ret == 0:
488 return
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):
502 if ret == 0:
503 return
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):
515 if ret == 0:
516 return
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()
526 if noop:
527 raise _generic_exception(ret, name, "Failed to load encryption key")
528 else:
529 raise _generic_exception(ret, name, "Failed to verify encryption key")
532 def lzc_unload_key_translate_error(ret, name):
533 if ret == 0:
534 return
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):
546 if ret == 0:
547 return
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):
554 if ret == 0:
555 return
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):
562 if ret == 0:
563 return
564 if ret == errno.ENOENT:
565 raise lzc_exc.PoolNotFound(name)
566 if ret == ETIME:
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()
574 if ret == ECHRNG:
575 raise lzc_exc.ZCPRuntimeError(error)
576 if ret == errno.EINVAL:
577 if error is None:
578 raise lzc_exc.ZCPLimitInvalid()
579 else:
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):
585 if ret == 0:
586 return
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()
599 if discard:
600 raise _generic_exception(
601 ret, name, "Failed to discard pool checkpoint")
602 else:
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):
611 if ret == 0:
612 return
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):
628 if ret == 0:
629 return
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):
638 if ret == 0:
639 return
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):
649 if ret == 0:
650 return
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):
660 if ret == 0:
661 return
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):
670 if ret == 0:
671 return
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):
678 if ret == 0:
679 return
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):
686 if ret == 0:
687 return
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
701 error codes.
702 :type errlist: dict of bytes:int
703 :param names: the list of all names of the entities on which the operation
704 was attempted.
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
709 a Python exception.
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
714 ``errlist``.
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.
723 .. note::
724 Note that the ``errlist`` can contain a special element with a key of
725 "N_MORE_ERRORS".
726 That element means that there were too many errors to place on the
727 ``errlist``.
728 Those errors are suppressed and only their count is provided as a
729 value of the special ``N_MORE_ERRORS`` element.
731 if ret == 0:
732 return
734 if len(errlist) == 0:
735 suppressed_count = 0
736 names = list(zip(names, range(2)))
737 if len(names) == 1:
738 name, _ = names[0]
739 else:
740 name = None
741 errors = [mapper(ret, name)]
742 else:
743 errors = []
744 suppressed_count = errlist.pop('N_MORE_ERRORS', 0)
745 for name in errlist:
746 err = errlist[name]
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]
763 def _fs_name(name):
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)
825 else:
826 return lzc_exc.ZFSGenericError(err, message, name)
829 _error_to_exception = {e.errno: e for e in [
830 lzc_exc.ZIOError,
831 lzc_exc.NoSpace,
832 lzc_exc.QuotaExceeded,
833 lzc_exc.DatasetBusy,
834 lzc_exc.NameTooLong,
835 lzc_exc.ReadOnlyPool,
836 lzc_exc.SuspendedPool,
837 lzc_exc.PoolsDiffer,
838 lzc_exc.PropertyNotSupported,
842 # vim: softtabstop=4 tabstop=4 expandtab shiftwidth=4