Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libzfs_core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

Maximum length of any ZFS name.
'''
from __future__ import unicode_literals

from ._constants import (
MAXNAMELEN,
Expand Down
1 change: 1 addition & 0 deletions libzfs_core/_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""
Important `libzfs_core` constants.
"""
from __future__ import unicode_literals

#: Maximum length of any ZFS name.
MAXNAMELEN = 255
Expand Down
26 changes: 14 additions & 12 deletions libzfs_core/_error_translation.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@

The parameters and exceptions are documented in the `libzfs_core` interfaces.
"""
from __future__ import unicode_literals

from builtins import map
import errno
import re
import string
Expand Down Expand Up @@ -74,7 +76,7 @@ def lzc_snapshot_translate_errors(ret, errlist, snaps, props):

def _map(ret, name):
if ret == errno.EXDEV:
pool_names = map(_pool_name, snaps)
pool_names = list(map(_pool_name, snaps))
same_pool = all(x == pool_names[0] for x in pool_names)
if same_pool:
return lzc_exc.DuplicateSnapshots(name)
Expand Down Expand Up @@ -121,7 +123,7 @@ def _map(ret, name):
if ret == errno.EINVAL:
if name:
snap = bookmarks[name]
pool_names = map(_pool_name, bookmarks.keys())
pool_names = list(map(_pool_name, list(bookmarks.keys())))
if not _is_valid_bmark_name(name):
return lzc_exc.BookmarkNameInvalid(name)
elif not _is_valid_snap_name(snap):
Expand All @@ -131,7 +133,7 @@ def _map(ret, name):
elif any(x != _pool_name(name) for x in pool_names):
return lzc_exc.PoolsDiffer(name)
else:
invalid_names = [b for b in bookmarks.keys() if not _is_valid_bmark_name(b)]
invalid_names = [b for b in list(bookmarks.keys()) if not _is_valid_bmark_name(b)]
if invalid_names:
return lzc_exc.BookmarkNameInvalid(invalid_names[0])
if ret == errno.EEXIST:
Expand All @@ -142,7 +144,7 @@ def _map(ret, name):
return lzc_exc.BookmarkNotSupported(name)
return _generic_exception(ret, name, "Failed to create bookmark")

_handle_err_list(ret, errlist, bookmarks.keys(), lzc_exc.BookmarkFailure, _map)
_handle_err_list(ret, errlist, list(bookmarks.keys()), lzc_exc.BookmarkFailure, _map)


def lzc_get_bookmarks_translate_error(ret, fsname, props):
Expand Down Expand Up @@ -200,15 +202,15 @@ def _map(ret, name):
return lzc_exc.PoolsDiffer(name)
elif ret == errno.EINVAL:
if name:
pool_names = map(_pool_name, holds.keys())
pool_names = list(map(_pool_name, list(holds.keys())))
if not _is_valid_snap_name(name):
return lzc_exc.NameInvalid(name)
elif len(name) > MAXNAMELEN:
return lzc_exc.NameTooLong(name)
elif any(x != _pool_name(name) for x in pool_names):
return lzc_exc.PoolsDiffer(name)
else:
invalid_names = [b for b in holds.keys() if not _is_valid_snap_name(b)]
invalid_names = [b for b in list(holds.keys()) if not _is_valid_snap_name(b)]
if invalid_names:
return lzc_exc.NameInvalid(invalid_names[0])
fs_name = None
Expand All @@ -230,13 +232,13 @@ def _map(ret, name):

if ret == errno.EBADF:
raise lzc_exc.BadHoldCleanupFD()
_handle_err_list(ret, errlist, holds.keys(), lzc_exc.HoldFailure, _map)
_handle_err_list(ret, errlist, list(holds.keys()), lzc_exc.HoldFailure, _map)


def lzc_release_translate_errors(ret, errlist, holds):
if ret == 0:
return
for _, hold_list in holds.iteritems():
for _, hold_list in holds.items():
if not isinstance(hold_list, list):
raise lzc_exc.TypeError('holds must be in a list')

Expand All @@ -245,15 +247,15 @@ def _map(ret, name):
return lzc_exc.PoolsDiffer(name)
elif ret == errno.EINVAL:
if name:
pool_names = map(_pool_name, holds.keys())
pool_names = list(map(_pool_name, list(holds.keys())))
if not _is_valid_snap_name(name):
return lzc_exc.NameInvalid(name)
elif len(name) > MAXNAMELEN:
return lzc_exc.NameTooLong(name)
elif any(x != _pool_name(name) for x in pool_names):
return lzc_exc.PoolsDiffer(name)
else:
invalid_names = [b for b in holds.keys() if not _is_valid_snap_name(b)]
invalid_names = [b for b in list(holds.keys()) if not _is_valid_snap_name(b)]
if invalid_names:
return lzc_exc.NameInvalid(invalid_names[0])
elif ret == errno.ENOENT:
Expand All @@ -270,7 +272,7 @@ def _map(ret, name):
else:
return _generic_exception(ret, name, "Failed to release snapshot hold")

_handle_err_list(ret, errlist, holds.keys(), lzc_exc.HoldReleaseFailure, _map)
_handle_err_list(ret, errlist, list(holds.keys()), lzc_exc.HoldReleaseFailure, _map)


def lzc_get_holds_translate_error(ret, snapname):
Expand Down Expand Up @@ -525,7 +527,7 @@ def _handle_err_list(ret, errlist, names, exception, mapper):
else:
errors = []
suppressed_count = errlist.pop('N_MORE_ERRORS', 0)
for name, err in errlist.iteritems():
for name, err in errlist.items():
errors.append(mapper(err, name))

raise exception(errors, suppressed_count)
Expand Down
59 changes: 36 additions & 23 deletions libzfs_core/_libzfs_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,32 @@
are directly returned. Error conditions are signalled by exceptions
rather than by integer error codes.
"""
from __future__ import unicode_literals

import errno
import functools
import fcntl
import functools
import os
import struct
import threading
from . import exceptions

from builtins import next
from builtins import object
from builtins import str

from . import _error_translation as errors
from .bindings import libzfs_core
from . import exceptions
from ._constants import MAXNAMELEN
from .ctypes import int32_t
from ._nvlist import nvlist_in, nvlist_out
from .bindings import libzfs_core
from .ctypes import int32_t


def _b(s):
if isinstance(s, str):
return s.encode()
else:
return s


def lzc_create(name, ds_type='zfs', props=None):
Expand Down Expand Up @@ -54,7 +67,7 @@ def lzc_create(name, ds_type='zfs', props=None):
else:
raise exceptions.DatasetTypeInvalid(ds_type)
nvlist = nvlist_in(props)
ret = _lib.lzc_create(name, ds_type, nvlist)
ret = _lib.lzc_create(_b(name), ds_type, nvlist)
errors.lzc_create_translate_error(ret, name, ds_type, props)


Expand Down Expand Up @@ -88,7 +101,7 @@ def lzc_clone(name, origin, props=None):
if props is None:
props = {}
nvlist = nvlist_in(props)
ret = _lib.lzc_clone(name, origin, nvlist)
ret = _lib.lzc_clone(_b(name), _b(origin), nvlist)
errors.lzc_clone_translate_error(ret, name, origin, props)


Expand All @@ -107,7 +120,7 @@ def lzc_rollback(name):
'''
# Account for terminating NUL in C strings.
snapnamep = _ffi.new('char[]', MAXNAMELEN + 1)
ret = _lib.lzc_rollback(name, snapnamep, MAXNAMELEN + 1)
ret = _lib.lzc_rollback(_b(name), snapnamep, MAXNAMELEN + 1)
errors.lzc_rollback_translate_error(ret, name)
return _ffi.string(snapnamep)

Expand Down Expand Up @@ -270,7 +283,7 @@ def lzc_get_bookmarks(fsname, props=None):
props_dict = {name: None for name in props}
nvlist = nvlist_in(props_dict)
with nvlist_out(bmarks) as bmarks_nvlist:
ret = _lib.lzc_get_bookmarks(fsname, nvlist, bmarks_nvlist)
ret = _lib.lzc_get_bookmarks(_b(fsname), nvlist, bmarks_nvlist)
errors.lzc_get_bookmarks_translate_error(ret, fsname, props)
return bmarks

Expand Down Expand Up @@ -330,7 +343,7 @@ def lzc_snaprange_space(firstsnap, lastsnap):
In that case ``lzc_snaprange_space`` calculates space used by the snapshot.
'''
valp = _ffi.new('uint64_t *')
ret = _lib.lzc_snaprange_space(firstsnap, lastsnap, valp)
ret = _lib.lzc_snaprange_space(_b(firstsnap), _b(lastsnap), valp)
errors.lzc_snaprange_space_translate_error(ret, firstsnap, lastsnap)
return int(valp[0])

Expand Down Expand Up @@ -376,8 +389,8 @@ def lzc_hold(holds, fd=None):
errors.lzc_hold_translate_errors(ret, errlist, holds, fd)
# If there is no error (no exception raised by _handleErrList), but errlist
# is not empty, then it contains missing snapshots.
assert all(x == errno.ENOENT for x in errlist.itervalues())
return errlist.keys()
assert all(x == errno.ENOENT for x in errlist.values())
return list(errlist.keys())


def lzc_release(holds):
Expand Down Expand Up @@ -411,7 +424,7 @@ def lzc_release(holds):
'''
errlist = {}
holds_dict = {}
for snap, hold_list in holds.iteritems():
for snap, hold_list in holds.items():
if not isinstance(hold_list, list):
raise TypeError('holds must be in a list')
holds_dict[snap] = {hold: None for hold in hold_list}
Expand All @@ -421,8 +434,8 @@ def lzc_release(holds):
errors.lzc_release_translate_errors(ret, errlist, holds)
# If there is no error (no exception raised by _handleErrList), but errlist
# is not empty, then it contains missing snapshots and tags.
assert all(x == errno.ENOENT for x in errlist.itervalues())
return errlist.keys()
assert all(x == errno.ENOENT for x in errlist.values())
return list(errlist.keys())


def lzc_get_holds(snapname):
Expand All @@ -436,7 +449,7 @@ def lzc_get_holds(snapname):
'''
holds = {}
with nvlist_out(holds) as nvlist:
ret = _lib.lzc_get_holds(snapname, nvlist)
ret = _lib.lzc_get_holds(_b(snapname), nvlist)
errors.lzc_get_holds_translate_error(ret, snapname)
return holds

Expand Down Expand Up @@ -514,7 +527,7 @@ def lzc_send(snapname, fromsnap, fd, flags=None):
raise exceptions.UnknownStreamFeature(flag)
c_flags |= c_flag

ret = _lib.lzc_send(snapname, c_fromsnap, fd, c_flags)
ret = _lib.lzc_send(_b(snapname), _b(c_fromsnap), fd, c_flags)
errors.lzc_send_translate_error(ret, snapname, fromsnap, fd, flags)


Expand Down Expand Up @@ -546,7 +559,7 @@ def lzc_send_space(snapname, fromsnap=None):
else:
c_fromsnap = _ffi.NULL
valp = _ffi.new('uint64_t *')
ret = _lib.lzc_send_space(snapname, c_fromsnap, valp)
ret = _lib.lzc_send_space(_b(snapname), _b(c_fromsnap), valp)
errors.lzc_send_space_translate_error(ret, snapname, fromsnap)
return int(valp[0])

Expand Down Expand Up @@ -645,7 +658,7 @@ def lzc_receive(snapname, fd, force=False, origin=None, props=None):
if props is None:
props = {}
nvlist = nvlist_in(props)
ret = _lib.lzc_receive(snapname, nvlist, c_origin, force, fd)
ret = _lib.lzc_receive(_b(snapname), nvlist, _b(c_origin), force, fd)
errors.lzc_receive_translate_error(ret, snapname, fd, force, origin, props)


Expand All @@ -664,7 +677,7 @@ def lzc_exists(name):
.. note::
``lzc_exists`` can not be used to check for existence of bookmarks.
'''
ret = _lib.lzc_exists(name)
ret = _lib.lzc_exists(_b(name))
return bool(ret)


Expand Down Expand Up @@ -751,8 +764,8 @@ def lzc_rename(source, target):
'''
Rename the ZFS dataset.

:param source name: the current name of the dataset to rename.
:param target name: the new name of the dataset.
:param bytes source: the current name of the dataset to rename.
:param bytes target: the new name of the dataset.
:raises NameInvalid: if either the source or target name is invalid.
:raises NameTooLong: if either the source or target name is too long.
:raises NameTooLong: if a snapshot of the source would get a too long
Expand Down Expand Up @@ -1025,9 +1038,9 @@ def lzc_get_props(name):
mountpoint_val = '/' + name
else:
mountpoint_val = None
result = {k: v['value'] for k, v in result.iteritems()}
result = {k: v['value'] for k, v in result.items()}
if 'clones' in result:
result['clones'] = result['clones'].keys()
result['clones'] = list(result['clones'].keys())
if mountpoint_val is not None:
result['mountpoint'] = mountpoint_val
return result
Expand Down
18 changes: 16 additions & 2 deletions libzfs_core/_nvlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,15 @@
- a value can be a list of dictionaries that adhere to this format
- all elements of a list value must be of the same type
"""
from __future__ import unicode_literals

import numbers
from collections import namedtuple
from contextlib import contextmanager

from builtins import range
from builtins import str

from .bindings import libnvpair
from .ctypes import _type_to_suffix

Expand Down Expand Up @@ -174,6 +179,11 @@ def _is_integer(x):
for string in array:
c_array.append(_ffi.new('char[]', string))
ret = _lib.nvlist_add_string_array(nvlist, key, c_array, len(c_array))
elif isinstance(specimen, str):
c_array = []
for string in array:
c_array.append(_ffi.new('char[]', string.encode()))
ret = _lib.nvlist_add_string_array(nvlist, key, c_array, len(c_array))
elif isinstance(specimen, bool):
ret = _lib.nvlist_add_boolean_array(nvlist, key, array, len(array))
elif isinstance(specimen, numbers.Integral):
Expand Down Expand Up @@ -228,16 +238,20 @@ def _nvlist_to_dict(nvlist, props):


def _dict_to_nvlist(props, nvlist):
for k, v in props.items():
if not isinstance(k, bytes):
for k, v in list(props.items()):
if not (isinstance(k, bytes) or isinstance(k, str)):
raise TypeError('Unsupported key type ' + type(k).__name__)
if isinstance(k, str):
k = k.encode()
ret = 0
if isinstance(v, dict):
ret = _lib.nvlist_add_nvlist(nvlist, k, nvlist_in(v))
elif isinstance(v, list):
_nvlist_add_array(nvlist, k, v)
elif isinstance(v, bytes):
ret = _lib.nvlist_add_string(nvlist, k, v)
elif isinstance(v, str):
ret = _lib.nvlist_add_string(nvlist, k, v.encode())
elif isinstance(v, bool):
ret = _lib.nvlist_add_boolean_value(nvlist, k, v)
elif v is None:
Expand Down
2 changes: 2 additions & 0 deletions libzfs_core/bindings/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
`libzfs_core` uses. The modules expose CFFI objects required
to make calls to functions in the libraries.
"""
from __future__ import unicode_literals

from builtins import object
import threading
import importlib

Expand Down
1 change: 1 addition & 0 deletions libzfs_core/bindings/libnvpair.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""
Python bindings for ``libnvpair``.
"""
from __future__ import unicode_literals

CDEF = """
typedef ... nvlist_t;
Expand Down
1 change: 1 addition & 0 deletions libzfs_core/bindings/libzfs_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""
Python bindings for ``libzfs_core``.
"""
from __future__ import unicode_literals

CDEF = """
enum lzc_send_flags {
Expand Down
1 change: 1 addition & 0 deletions libzfs_core/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""
Exceptions that can be raised by libzfs_core operations.
"""
from __future__ import unicode_literals

import errno

Expand Down
Loading