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 6 years ago
parent f79f0ce6b2
commit af941f9913

@ -52,11 +52,15 @@ class ZFS:
parameter for the get/set functions is used. parameter for the get/set functions is used.
:param metadata_namespace: Default namespace :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 :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.metadata_namespace = metadata_namespace
self.mount_helper = mount_helper self.pe_helper = pe_helper
self.use_pe_helper = use_pe_helper
@property @property
def metadata_namespace(self) -> Optional[str]: def metadata_namespace(self) -> Optional[str]:
@ -75,35 +79,49 @@ class ZFS:
self._metadata_namespace = namespace self._metadata_namespace = namespace
@property @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 @pe_helper.setter
def mount_helper(self, helper: Optional[str]) -> None: 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 Sets the privilege escalation (PE) helper. Some basic checks for existance and executablility are performed,
sufficient for secure operation and are provided to aid the user in configuring the library. 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. :note: This method does not follow symlinks.
:raises FileNotFoundError: if the script can't be found or is not executable. :raises FileNotFoundError: if the script can't be found or is not executable.
''' '''
if helper is None: if helper is None:
log.debug('Mount helper is None') log.debug('PE helper is None')
self._mount_helper = None self._pe_helper = None
else: else:
candidate = helper.strip() candidate = helper.strip()
mode = os.lstat(candidate).st_mode mode = os.lstat(candidate).st_mode
if not stat.S_ISREG(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): if not os.access(candidate, os.X_OK):
raise FileNotFoundError('Mount helper must be executable') raise FileNotFoundError('PE helper must be executable')
log.debug(f'Setting mount helper to "{candidate}"') log.debug(f'Setting privilege escalation helper to "{candidate}"')
self._mount_helper = 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: def dataset_exists(self, name: str) -> bool:
''' '''
@ -130,6 +148,20 @@ class ZFS:
''' '''
raise NotImplementedError(f'{self} has not implemented this function') 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: 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 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. 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) super().__init__(metadata_namespace=metadata_namespace)
self.find_executable(path=zfs_exe) 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`` :class:`~zfs.zfs.ZFS`. It is recommended to use :func:`~zfs.zfs.get_zfs` to obtain an instance, using ``native``
as api. 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) 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: 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 from typing import Optional
log = logging.getLogger('simplezfs.zpool')
class ZPool: class ZPool:
''' '''
ZPool interface class. This API generally covers only the zpool(8) tool, for zfs(8) please see class :class:`~ZFS`. 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. 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.metadata_namespace = metadata_namespace
self.pe_helper = pe_helper
self.use_pe_helper = use_pe_helper
@property @property
def metadata_namespace(self) -> Optional[str]: def metadata_namespace(self) -> Optional[str]:
@ -34,6 +43,37 @@ class ZPool:
''' '''
self._metadata_namespace = namespace 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: 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): class ZPoolCli(ZPool):
def __init__(self, *, metadata_namespace: Optional[str] = None, zpool_exe: Optional[str] = None, **kwargs) -> None: def __init__(self, *, metadata_namespace: Optional[str] = None, pe_helper: Optional[str] = None,
super().__init__(metadata_namespace=metadata_namespace) 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) self.find_executable(path=zpool_exe)
def find_executable(self, path: str = None) -> None: def find_executable(self, path: str = None) -> None:

@ -9,5 +9,6 @@ from .zpool import ZPool
class ZPoolNative(ZPool): class ZPoolNative(ZPool):
def __init__(self, *, metadata_namespace: Optional[str] = None, **kwargs) -> None: def __init__(self, *, metadata_namespace: Optional[str] = None, pe_helper: Optional[str] = None,
super().__init__(metadata_namespace=metadata_namespace) 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