]> granicus.if.org Git - zfs/commitdiff
pyzfs: add missing libzfs_core functions
authorLOLi <loli10K@users.noreply.github.com>
Mon, 20 Aug 2018 17:11:52 +0000 (19:11 +0200)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Mon, 20 Aug 2018 17:11:52 +0000 (10:11 -0700)
This change adds the following libzfs_core functions to pyzfs:
lzc_remap, lzc_pool_checkpoint, lzc_pool_checkpoint_discard

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: loli10K <ezomori.nozomu@gmail.com>
Closes #7793
Closes #7800

contrib/pyzfs/libzfs_core/__init__.py
contrib/pyzfs/libzfs_core/_constants.py
contrib/pyzfs/libzfs_core/_error_translation.py
contrib/pyzfs/libzfs_core/_libzfs_core.py
contrib/pyzfs/libzfs_core/bindings/libzfs_core.py
contrib/pyzfs/libzfs_core/exceptions.py
contrib/pyzfs/libzfs_core/test/test_libzfs_core.py

index d8c0e44b0e4a19f3aab332c328b7aed769d87f09..6ad9fa1295c641fb43d1a483a95de44404385a75 100644 (file)
@@ -63,6 +63,8 @@ from ._libzfs_core import (
     lzc_get_holds,
     lzc_hold,
     lzc_load_key,
+    lzc_pool_checkpoint,
+    lzc_pool_checkpoint_discard,
     lzc_promote,
     lzc_receive,
     lzc_receive_one,
@@ -70,6 +72,7 @@ from ._libzfs_core import (
     lzc_receive_with_cmdprops,
     lzc_receive_with_header,
     lzc_release,
+    lzc_remap,
     lzc_reopen,
     lzc_rollback,
     lzc_rollback_to,
@@ -116,6 +119,8 @@ __all__ = [
     'lzc_get_holds',
     'lzc_hold',
     'lzc_load_key',
+    'lzc_pool_checkpoint',
+    'lzc_pool_checkpoint_discard',
     'lzc_promote',
     'lzc_receive',
     'lzc_receive_one',
@@ -123,6 +128,7 @@ __all__ = [
     'lzc_receive_with_cmdprops',
     'lzc_receive_with_header',
     'lzc_release',
+    'lzc_remap',
     'lzc_reopen',
     'lzc_rollback',
     'lzc_rollback_to',
index 7bffebd9cec696de3ea0366720a463c8c1d3292a..4e1af55d7b1e231a00f4deb94effcab4f579ac24 100644 (file)
@@ -57,5 +57,12 @@ zio_encrypt = enum(
     'ZIO_CRYPT_AES_192_GCM',
     'ZIO_CRYPT_AES_256_GCM'
 )
+# ZFS-specific error codes
+ZFS_ERR_CHECKPOINT_EXISTS = 1024
+ZFS_ERR_DISCARDING_CHECKPOINT = 1025
+ZFS_ERR_NO_CHECKPOINT = 1026
+ZFS_ERR_DEVRM_IN_PROGRESS = 1027
+ZFS_ERR_VDEV_TOO_BIG = 1028
+
 
 # vim: softtabstop=4 tabstop=4 expandtab shiftwidth=4
index fca67ea89f8e8a7eb6487933e431af6577b76d29..b9db026d7dcfd307f1f689fa6ab0bef1d95a295e 100644 (file)
@@ -31,7 +31,14 @@ import errno
 import re
 import string
 from . import exceptions as lzc_exc
-from ._constants import MAXNAMELEN
+from ._constants import (
+    MAXNAMELEN,
+    ZFS_ERR_CHECKPOINT_EXISTS,
+    ZFS_ERR_DISCARDING_CHECKPOINT,
+    ZFS_ERR_NO_CHECKPOINT,
+    ZFS_ERR_DEVRM_IN_PROGRESS,
+    ZFS_ERR_VDEV_TOO_BIG
+)
 
 
 def lzc_create_translate_error(ret, name, ds_type, props):
@@ -548,6 +555,32 @@ def lzc_remap_translate_error(ret, name):
     raise _generic_exception(ret, name, "Failed to remap dataset")
 
 
+def lzc_pool_checkpoint_translate_error(ret, name, discard=False):
+    if ret == 0:
+        return
+    if ret == errno.ENOENT:
+        raise lzc_exc.PoolNotFound(name)
+    if ret == ZFS_ERR_CHECKPOINT_EXISTS:
+        raise lzc_exc.CheckpointExists()
+    if ret == ZFS_ERR_NO_CHECKPOINT:
+        raise lzc_exc.CheckpointNotFound()
+    if ret == ZFS_ERR_DISCARDING_CHECKPOINT:
+        raise lzc_exc.CheckpointDiscarding()
+    if ret == ZFS_ERR_DEVRM_IN_PROGRESS:
+        raise lzc_exc.DeviceRemovalRunning()
+    if ret == ZFS_ERR_VDEV_TOO_BIG:
+        raise lzc_exc.DeviceTooBig()
+    if discard:
+        raise _generic_exception(
+            ret, name, "Failed to discard pool checkpoint")
+    else:
+        raise _generic_exception(ret, name, "Failed to create pool checkpoint")
+
+
+def lzc_pool_checkpoint_discard_translate_error(ret, name):
+    lzc_pool_checkpoint_translate_error(ret, name, discard=True)
+
+
 def lzc_rename_translate_error(ret, source, target):
     if ret == 0:
         return
index ffc93081284e3afefc69de22b8c21081d14cf175..db207bf71e1fcb144bfa5d80010e36c7a3ec8568 100644 (file)
@@ -1574,6 +1574,37 @@ def lzc_remap(name):
     errors.lzc_remap_translate_error(ret, name)
 
 
+@_uncommitted()
+def lzc_pool_checkpoint(name):
+    '''
+    Creates a checkpoint for the specified pool.
+
+    :param bytes name: the name of the pool to create a checkpoint for.
+    :raises CheckpointExists: if the pool already has a checkpoint.
+    :raises CheckpointDiscarding: if ZFS is in the middle of discarding a
+        checkpoint for this pool.
+    :raises DeviceRemovalRunning: if a vdev is currently being removed.
+    :raises DeviceTooBig: if one or more top-level vdevs exceed the maximum
+        vdev size.
+    '''
+    ret = _lib.lzc_pool_checkpoint(name)
+    errors.lzc_pool_checkpoint_translate_error(ret, name)
+
+
+@_uncommitted()
+def lzc_pool_checkpoint_discard(name):
+    '''
+    Discard the checkpoint from the specified pool.
+
+    :param bytes name: the name of the pool to discard the checkpoint from.
+    :raises CheckpointNotFound: if pool does not have a checkpoint.
+    :raises CheckpointDiscarding: if ZFS is in the middle of discarding a
+        checkpoint for this pool.
+    '''
+    ret = _lib.lzc_pool_checkpoint_discard(name)
+    errors.lzc_pool_checkpoint_discard_translate_error(ret, name)
+
+
 @_uncommitted()
 def lzc_rename(source, target):
     '''
index 55899b5565d15937f6054a5513ccc8774eb89685..b69c8d779aa861cc330b2081e687f70160ba9c22 100644 (file)
@@ -127,6 +127,8 @@ CDEF = """
     int lzc_sync(const char *, nvlist_t *, nvlist_t **);
     int lzc_unload_key(const char *);
     int lzc_remap(const char *);
+    int lzc_pool_checkpoint(const char *);
+    int lzc_pool_checkpoint_discard(const char *);
 
     int lzc_rename(const char *, const char *, nvlist_t *, char **);
     int lzc_destroy_one(const char *fsname, nvlist_t *);
index 58e1da6ec8de63e2c2ff5ece93622214ae66a9d9..d274b5b06b92cb33bb09f1a3aba6de08c5785e69 100644 (file)
@@ -19,6 +19,13 @@ Exceptions that can be raised by libzfs_core operations.
 """
 
 import errno
+from ._constants import (
+    ZFS_ERR_CHECKPOINT_EXISTS,
+    ZFS_ERR_DISCARDING_CHECKPOINT,
+    ZFS_ERR_NO_CHECKPOINT,
+    ZFS_ERR_DEVRM_IN_PROGRESS,
+    ZFS_ERR_VDEV_TOO_BIG
+)
 
 
 class ZFSError(Exception):
@@ -547,4 +554,29 @@ class ZCPPermissionError(ZCPError):
     message = "Channel programs must be run as root"
 
 
+class CheckpointExists(ZFSError):
+    errno = ZFS_ERR_CHECKPOINT_EXISTS
+    message = "Pool already has a checkpoint"
+
+
+class CheckpointNotFound(ZFSError):
+    errno = ZFS_ERR_NO_CHECKPOINT
+    message = "Pool does not have a checkpoint"
+
+
+class CheckpointDiscarding(ZFSError):
+    errno = ZFS_ERR_DISCARDING_CHECKPOINT
+    message = "Pool checkpoint is being discarded"
+
+
+class DeviceRemovalRunning(ZFSError):
+    errno = ZFS_ERR_DEVRM_IN_PROGRESS
+    message = "A vdev is currently being removed"
+
+
+class DeviceTooBig(ZFSError):
+    errno = ZFS_ERR_VDEV_TOO_BIG
+    message = "One or more top-level vdevs exceed the maximum vdev size"
+
+
 # vim: softtabstop=4 tabstop=4 expandtab shiftwidth=4
index 111cd91f93e414c726ee13d573cd8795c9ec7152..14303871a17ec8e1b330af083dc9309b6aa206b2 100644 (file)
@@ -3576,6 +3576,42 @@ zfs.sync.snapshot('""" + pool + """@zcp')
 
         lzc.lzc_remap(name)
 
+    def test_checkpoint(self):
+        pool = ZFSTest.pool.getRoot().getName()
+
+        lzc.lzc_pool_checkpoint(pool)
+
+    def test_checkpoint_missing_pool(self):
+        pool = "nonexistent"
+
+        with self.assertRaises(lzc_exc.PoolNotFound):
+            lzc.lzc_pool_checkpoint(pool)
+
+    def test_checkpoint_already_exists(self):
+        pool = ZFSTest.pool.getRoot().getName()
+
+        lzc.lzc_pool_checkpoint(pool)
+        with self.assertRaises(lzc_exc.CheckpointExists):
+            lzc.lzc_pool_checkpoint(pool)
+
+    def test_checkpoint_discard(self):
+        pool = ZFSTest.pool.getRoot().getName()
+
+        lzc.lzc_pool_checkpoint(pool)
+        lzc.lzc_pool_checkpoint_discard(pool)
+
+    def test_checkpoint_discard_missing_pool(self):
+        pool = "nonexistent"
+
+        with self.assertRaises(lzc_exc.PoolNotFound):
+            lzc.lzc_pool_checkpoint_discard(pool)
+
+    def test_checkpoint_discard_missing_checkpoint(self):
+        pool = ZFSTest.pool.getRoot().getName()
+
+        with self.assertRaises(lzc_exc.CheckpointNotFound):
+            lzc.lzc_pool_checkpoint_discard(pool)
+
     @needs_support(lzc.lzc_list_children)
     def test_list_children(self):
         name = ZFSTest.pool.makeName("fs1/fs")