rename mount helper to privilege escalation helper

The helper will be used to (u)mount, but also create filesets and change existing mountpoint settings.
main
svalouch 5 years ago
parent f79f0ce6b2
commit af941f9913

@ -52,11 +52,15 @@ class ZFS:
parameter for the get/set functions is used.
:param metadata_namespace: Default namespace
:param pe_helper: Privilege escalation (PE) helper to use for actions that require elevated privileges (root).
:param use_pe_helper: Whether to use the PE helper for creating and (u)mounting.#
:param kwargs: Extra arguments, ignored
'''
def __init__(self, *, metadata_namespace: Optional[str] = None, mount_helper: Optional[str] = None, **kwargs) -> None:
def __init__(self, *, metadata_namespace: Optional[str] = None, pe_helper: Optional[str] = None,
use_pe_helper: bool = False, **kwargs) -> None:
self.metadata_namespace = metadata_namespace
self.mount_helper = mount_helper
self.pe_helper = pe_helper
self.use_pe_helper = use_pe_helper
@property
def metadata_namespace(self) -> Optional[str]:
@ -75,35 +79,49 @@ class ZFS:
self._metadata_namespace = namespace
@property
def mount_helper(self) -> Optional[str]:
def pe_helper(self) -> Optional[str]:
'''
Returns the mount_helper, which may be None if not set.
Returns the pe_helper, which may be None if not set.
'''
return self._mount_helper
return self._pe_helper
@mount_helper.setter
def mount_helper(self, helper: Optional[str]) -> None:
@pe_helper.setter
def pe_helper(self, helper: Optional[str]) -> None:
'''
Sets the mount helper. Some basic checks for existance and executablility are performed, but these are not
sufficient for secure operation and are provided to aid the user in configuring the library.
Sets the privilege escalation (PE) helper. Some basic checks for existance and executablility are performed,
but these are not sufficient for secure operation and are provided to aid the user in configuring the library.
:note: This method does not follow symlinks.
:raises FileNotFoundError: if the script can't be found or is not executable.
'''
if helper is None:
log.debug('Mount helper is None')
self._mount_helper = None
log.debug('PE helper is None')
self._pe_helper = None
else:
candidate = helper.strip()
mode = os.lstat(candidate).st_mode
if not stat.S_ISREG(mode):
raise FileNotFoundError('Mount helper must be a file')
raise FileNotFoundError('PE helper must be a file')
if not os.access(candidate, os.X_OK):
raise FileNotFoundError('Mount helper must be executable')
log.debug(f'Setting mount helper to "{candidate}"')
self._mount_helper = candidate
raise FileNotFoundError('PE helper must be executable')
log.debug(f'Setting privilege escalation helper to "{candidate}"')
self._pe_helper = candidate
@property
def use_pe_helper(self) -> bool:
'''
Returns whether the privilege escalation (PE) helper should be used.
'''
return self._use_pe_helper
@use_pe_helper.setter
def use_pe_helper(self, use: bool) -> None:
'''
Enable or disable using the privilege escalation (PE) helper.
'''
self._use_pe_helper = use
def dataset_exists(self, name: str) -> bool:
'''
@ -130,6 +148,20 @@ class ZFS:
'''
raise NotImplementedError(f'{self} has not implemented this function')
def set_mountpoint(self, fileset: str, mountpoint: str, *, use_pe_helper: bool = False) -> None:
'''
Sets or changes the mountpoint property of a fileset. While this can be achieved using the generic function
:func:`~ZFS.set_property`, it allows for using the privilege escalation (PE) helper if so desired.
:param fileset: The fileset to modify.
:param mountpoint: The new value for the ``mountpoint`` property.
:param use_pe_helper: Overwrite the default for using the privilege escalation (PE) helper for this task.
:raises DatasetNotFound: if the fileset could not be found.
:raises ValidationError: if validating the parameters failed.
'''
real_use_pe_helper = use_pe_helper if use_pe_helper is not None else self.use_pe_helper
raise NotImplementedError(f'not implemented yet')
def set_property(self, dataset: str, key: str, value: str, *, metadata: bool = False, overwrite_metadata_namespace: Optional[str] = None) -> None:
'''
Sets the ``value`` of the native property ``key``. By default, only native properties can be set. If

@ -28,7 +28,8 @@ class ZFSCli(ZFS):
If ``zfs_exe`` is supplied, it is assumed that it points to the path of the ``zfs(8)`` executable.
'''
def __init__(self, *, metadata_namespace: Optional[str] = None, zfs_exe: Optional[str] = None, **kwargs) -> None:
def __init__(self, *, metadata_namespace: Optional[str] = None, pe_helper: Optional[str] = None,
use_pe_helper: bool = False, zfs_exe: Optional[str] = None, **kwargs) -> None:
super().__init__(metadata_namespace=metadata_namespace)
self.find_executable(path=zfs_exe)

@ -18,7 +18,8 @@ class ZFSNative(ZFS):
:class:`~zfs.zfs.ZFS`. It is recommended to use :func:`~zfs.zfs.get_zfs` to obtain an instance, using ``native``
as api.
'''
def __init__(self, *, metadata_namespace: Optional[str] = None, **kwargs) -> None:
def __init__(self, *, metadata_namespace: Optional[str] = None, pe_helper: Optional[str] = None,
use_pe_helper: bool = False, **kwargs) -> None:
super().__init__(metadata_namespace=metadata_namespace)
def set_property(self, dataset: str, key: str, value: str, *, metadata: bool = False, overwrite_metadata_namespace: Optional[str] = None) -> None:

@ -1,7 +1,13 @@
import logging
import os
import stat
from typing import Optional
log = logging.getLogger('simplezfs.zpool')
class ZPool:
'''
ZPool interface class. This API generally covers only the zpool(8) tool, for zfs(8) please see class :class:`~ZFS`.
@ -15,8 +21,11 @@ class ZPool:
When creating an instance of this class, select one or the other as the ``api`` argument.
'''
def __init__(self, *, metadata_namespace: Optional[str] = None, **kwargs) -> None:
def __init__(self, *, metadata_namespace: Optional[str] = None, pe_helper: Optional[str] = None,
use_pe_helper: bool = False, **kwargs) -> None:
self.metadata_namespace = metadata_namespace
self.pe_helper = pe_helper
self.use_pe_helper = use_pe_helper
@property
def metadata_namespace(self) -> Optional[str]:
@ -34,6 +43,37 @@ class ZPool:
'''
self._metadata_namespace = namespace
@property
def pe_helper(self) -> Optional[str]:
'''
Returns the pe_helper, which may be None if not set.
'''
return self._pe_helper
@pe_helper.setter
def pe_helper(self, helper: Optional[str]) -> None:
'''
Sets the privilege escalation (PE) helper. Some basic checks for existance and executability are performed,
but these are not sufficient for secure operation and are provided to aid the user in configuring the library.
:note: This method does not follow symlinks.
:raises FileNotFoundError: if the helper can't be found or is not executable.
'''
if helper is None:
log.debug('PE helper is None')
self._pe_helper = None
else:
candidate = helper.strip()
mode = os.lstat(candidate).st_mode
if not stat.S_ISREG(mode):
raise FileNotFoundError('PE helper must be a file')
if not os.access(candidate, os.X_OK):
raise FileNotFoundError('PE helper must be executable')
log.debug(f'Setting privilege escalation helper to "{candidate}"')
self._pe_helper = candidate
def get_zpool(api: str = 'cli', metadata_namespace: Optional[str] = None, **kwargs) -> ZPool:
'''

@ -15,8 +15,9 @@ log = logging.getLogger('zfs.zpool_cli')
class ZPoolCli(ZPool):
def __init__(self, *, metadata_namespace: Optional[str] = None, zpool_exe: Optional[str] = None, **kwargs) -> None:
super().__init__(metadata_namespace=metadata_namespace)
def __init__(self, *, metadata_namespace: Optional[str] = None, pe_helper: Optional[str] = None,
use_pe_helper: bool = False, zpool_exe: Optional[str] = None, **kwargs) -> None:
super().__init__(metadata_namespace=metadata_namespace, pe_helper=pe_helper, use_pe_helper=use_pe_helper)
self.find_executable(path=zpool_exe)
def find_executable(self, path: str = None) -> None:

@ -9,5 +9,6 @@ from .zpool import ZPool
class ZPoolNative(ZPool):
def __init__(self, *, metadata_namespace: Optional[str] = None, **kwargs) -> None:
super().__init__(metadata_namespace=metadata_namespace)
def __init__(self, *, metadata_namespace: Optional[str] = None, pe_helper: Optional[str] = None,
use_pe_helper: bool = False, **kwargs) -> None:
super().__init__(metadata_namespace=metadata_namespace, pe_helper=pe_helper, use_pe_helper=use_pe_helper)

Loading…
Cancel
Save