ZPool: adapt to new structure

main
svalouch 3 years ago
parent 89a7a98470
commit 83fcbb1053

@ -30,8 +30,9 @@ 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, pe_helper: Optional[PEHelperBase] = None,
use_pe_helper: bool = False, zfs_exe: Optional[str] = None, **kwargs) -> None:
super().__init__(metadata_namespace=metadata_namespace, pe_helper=pe_helper, use_pe_helper=use_pe_helper,
pe_helper_mode: PEHelperMode = PEHelperMode.DO_NOT_USE, zfs_exe: Optional[str] = None,
**kwargs) -> None:
super().__init__(metadata_namespace=metadata_namespace, pe_helper=pe_helper, pe_helper_mode=pe_helper_mode,
**kwargs)
self.find_executable(path=zfs_exe)

@ -1,9 +1,15 @@
'''
ZPOOL frontend API
'''
import logging
import os
import stat
from typing import Optional
from .pe_helper import PEHelperBase
from .types import PEHelperMode
log = logging.getLogger('simplezfs.zpool')
@ -20,12 +26,25 @@ class ZPool:
* Using the native API
When creating an instance of this class, select one or the other as the ``api`` argument.
**Properties and Metadata**
Please see the documentation for :class:`~simplezfs.zfs.ZFS` for native and metadata properties.
:param metadata_namespace: Default namespace
:param pe_helper: Privilege escalation (PE) helper to use for actions that require elevated privileges (root).
:param pe_helper_mode: How and when to use the PEHelper. Defaults to not using it at all.
:param kwargs: Extra arguments, ignored
'''
def __init__(self, *, metadata_namespace: Optional[str] = None, pe_helper: Optional[str] = None,
use_pe_helper: bool = False, **kwargs) -> None:
def __init__(self, *, metadata_namespace: Optional[str] = None, pe_helper: Optional[PEHelperBase] = None,
pe_helper_mode: PEHelperMode = PEHelperMode.DO_NOT_USE, **kwargs) -> None:
self.metadata_namespace = metadata_namespace
self.pe_helper = pe_helper
self.use_pe_helper = use_pe_helper
self.pe_helper_mode = pe_helper_mode
def __repr__(self) -> str:
return f'<ZPool(pe_helper="{self._pe_helper}", pe_helper_mode="{self._pe_helper_mode}")>'
@property
def metadata_namespace(self) -> Optional[str]:
@ -44,36 +63,37 @@ class ZPool:
self._metadata_namespace = namespace
@property
def pe_helper(self) -> Optional[str]:
def pe_helper(self) -> Optional[PEHelperBase]:
'''
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:
def pe_helper(self, helper: Optional[PEHelperBase]) -> 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.
Sets the privilege escalation (PE) helper. Supply ``None`` to unset it.
'''
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
self._pe_helper = helper
@property
def pe_helper_mode(self) -> PEHelperMode:
'''
Returns whether the privilege escalation (PE) helper should be used and when. If the helper has not been set,
this property evaluates to ``False``.
'''
if self._pe_helper is None:
return PEHelperMode.DO_NOT_USE
return self._pe_helper_mode
@pe_helper_mode.setter
def pe_helper_mode(self, mode: PEHelperMode) -> None:
'''
Sets the privilege escalation (PE) helper mode.
'''
self._pe_helper_mode = mode
def get_zpool(api: str = 'cli', metadata_namespace: Optional[str] = None, **kwargs) -> ZPool:
'''

@ -7,7 +7,9 @@ import logging
import shutil
from typing import Any, Dict, Optional
from .types import ZPoolHealth
from .pe_helper import PEHelperBase
from .types import PEHelperMode, ZPoolHealth
from .zpool import ZPool
log = logging.getLogger('simplezfs.zpool_cli')
@ -21,18 +23,23 @@ class ZPoolCli(ZPool):
If ``zpool_exe`` is supplied, it is assumed that it points to the path to the ``zpool(8)`` executable.
'''
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)
def __init__(self, *, metadata_namespace: Optional[str] = None, pe_helper: Optional[PEHelperBase] = None,
pe_helper_mode: PEHelperMode = PEHelperMode.DO_NOT_USE, zpool_exe: Optional[str] = None,
**kwargs) -> None:
super().__init__(metadata_namespace=metadata_namespace, pe_helper=pe_helper, pe_helper_mode=pe_helper_mode,
**kwargs)
self.find_executable(path=zpool_exe)
def __repr__(self) -> str:
return f'<ZPoolCLI(exe="{self.__exe}", pe_helper="{self._pe_helper}", pe_helper_mode="{self._pe_helper_mode}")>'
def find_executable(self, path: str = None) -> None:
'''
Tries to find the executable ``zpool``. If ``path`` points to an executable, it is used instead of relying on
the PATH to find it. It does not fall back to searching in PATH if ``path`` does not point to an exeuctable.
An exception is raised if no executable could be found.
:param path: Path to an executable to use instead of searching through $PATH.
:param path: Path to the executable, used blindly if supplied.
:raises OSError: If the executable could not be found.
'''
exe_path = path
@ -40,14 +47,14 @@ class ZPoolCli(ZPool):
exe_path = shutil.which('zpool')
if not exe_path:
raise OSError('Could not find the executable')
raise OSError('Could not find executable')
self.__exe = exe_path
@property
def executable(self) -> str:
'''
Returns the executable found by find_executable.
Returns the zpool executable that was found by find_executable.
'''
return self.__exe

@ -39,7 +39,7 @@ class TestZPoolCli:
with pytest.raises(OSError) as excinfo:
ZPoolCli()
assert 'not find the executable' in str(excinfo.value)
assert 'not find executable' in str(excinfo.value)
##########################################################################

Loading…
Cancel
Save