summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLOLi <[email protected]>2018-08-20 19:11:52 +0200
committerBrian Behlendorf <[email protected]>2018-08-20 10:11:52 -0700
commitc962fd6c4e3836be223af93b0d75d92e8ee98fb4 (patch)
treecbddbe0f17d1cd28a861d60bff72754f6b4192e2
parent34fe773e303e499e6a6e5fcd2ceeee4531579dab (diff)
pyzfs: add missing libzfs_core functions
This change adds the following libzfs_core functions to pyzfs: lzc_remap, lzc_pool_checkpoint, lzc_pool_checkpoint_discard Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: loli10K <[email protected]> Closes #7793 Closes #7800
-rw-r--r--contrib/pyzfs/libzfs_core/__init__.py6
-rw-r--r--contrib/pyzfs/libzfs_core/_constants.py7
-rw-r--r--contrib/pyzfs/libzfs_core/_error_translation.py35
-rw-r--r--contrib/pyzfs/libzfs_core/_libzfs_core.py31
-rw-r--r--contrib/pyzfs/libzfs_core/bindings/libzfs_core.py2
-rw-r--r--contrib/pyzfs/libzfs_core/exceptions.py32
-rw-r--r--contrib/pyzfs/libzfs_core/test/test_libzfs_core.py36
7 files changed, 148 insertions, 1 deletions
diff --git a/contrib/pyzfs/libzfs_core/__init__.py b/contrib/pyzfs/libzfs_core/__init__.py
index d8c0e44b0..6ad9fa129 100644
--- a/contrib/pyzfs/libzfs_core/__init__.py
+++ b/contrib/pyzfs/libzfs_core/__init__.py
@@ -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',
diff --git a/contrib/pyzfs/libzfs_core/_constants.py b/contrib/pyzfs/libzfs_core/_constants.py
index 7bffebd9c..4e1af55d7 100644
--- a/contrib/pyzfs/libzfs_core/_constants.py
+++ b/contrib/pyzfs/libzfs_core/_constants.py
@@ -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
diff --git a/contrib/pyzfs/libzfs_core/_error_translation.py b/contrib/pyzfs/libzfs_core/_error_translation.py
index fca67ea89..b9db026d7 100644
--- a/contrib/pyzfs/libzfs_core/_error_translation.py
+++ b/contrib/pyzfs/libzfs_core/_error_translation.py
@@ -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
diff --git a/contrib/pyzfs/libzfs_core/_libzfs_core.py b/contrib/pyzfs/libzfs_core/_libzfs_core.py
index ffc930812..db207bf71 100644
--- a/contrib/pyzfs/libzfs_core/_libzfs_core.py
+++ b/contrib/pyzfs/libzfs_core/_libzfs_core.py
@@ -1575,6 +1575,37 @@ def lzc_remap(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):
'''
Rename the ZFS dataset.
diff --git a/contrib/pyzfs/libzfs_core/bindings/libzfs_core.py b/contrib/pyzfs/libzfs_core/bindings/libzfs_core.py
index 55899b556..b69c8d779 100644
--- a/contrib/pyzfs/libzfs_core/bindings/libzfs_core.py
+++ b/contrib/pyzfs/libzfs_core/bindings/libzfs_core.py
@@ -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 *);
diff --git a/contrib/pyzfs/libzfs_core/exceptions.py b/contrib/pyzfs/libzfs_core/exceptions.py
index 58e1da6ec..d274b5b06 100644
--- a/contrib/pyzfs/libzfs_core/exceptions.py
+++ b/contrib/pyzfs/libzfs_core/exceptions.py
@@ -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
diff --git a/contrib/pyzfs/libzfs_core/test/test_libzfs_core.py b/contrib/pyzfs/libzfs_core/test/test_libzfs_core.py
index 111cd91f9..14303871a 100644
--- a/contrib/pyzfs/libzfs_core/test/test_libzfs_core.py
+++ b/contrib/pyzfs/libzfs_core/test/test_libzfs_core.py
@@ -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")