|
|
@ -1,9 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
ZPOOL frontend API
|
|
|
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
|
|
import logging
|
|
|
|
import logging
|
|
|
|
import os
|
|
|
|
import os
|
|
|
|
import stat
|
|
|
|
import stat
|
|
|
|
from typing import Optional
|
|
|
|
from typing import Optional
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from .pe_helper import PEHelperBase
|
|
|
|
|
|
|
|
from .types import PEHelperMode
|
|
|
|
|
|
|
|
|
|
|
|
log = logging.getLogger('simplezfs.zpool')
|
|
|
|
log = logging.getLogger('simplezfs.zpool')
|
|
|
|
|
|
|
|
|
|
|
@ -20,12 +26,25 @@ class ZPool:
|
|
|
|
* Using the native API
|
|
|
|
* Using the native API
|
|
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**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,
|
|
|
|
def __init__(self, *, metadata_namespace: Optional[str] = None, pe_helper: Optional[PEHelperBase] = None,
|
|
|
|
use_pe_helper: bool = False, **kwargs) -> None:
|
|
|
|
pe_helper_mode: PEHelperMode = PEHelperMode.DO_NOT_USE, **kwargs) -> None:
|
|
|
|
self.metadata_namespace = metadata_namespace
|
|
|
|
self.metadata_namespace = metadata_namespace
|
|
|
|
self.pe_helper = pe_helper
|
|
|
|
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
|
|
|
|
@property
|
|
|
|
def metadata_namespace(self) -> Optional[str]:
|
|
|
|
def metadata_namespace(self) -> Optional[str]:
|
|
|
@ -44,36 +63,37 @@ class ZPool:
|
|
|
|
self._metadata_namespace = namespace
|
|
|
|
self._metadata_namespace = namespace
|
|
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
@property
|
|
|
|
def pe_helper(self) -> Optional[str]:
|
|
|
|
def pe_helper(self) -> Optional[PEHelperBase]:
|
|
|
|
'''
|
|
|
|
'''
|
|
|
|
Returns the pe_helper, which may be None if not set.
|
|
|
|
Returns the pe_helper, which may be None if not set.
|
|
|
|
'''
|
|
|
|
'''
|
|
|
|
return self._pe_helper
|
|
|
|
return self._pe_helper
|
|
|
|
|
|
|
|
|
|
|
|
@pe_helper.setter
|
|
|
|
@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,
|
|
|
|
Sets the privilege escalation (PE) helper. Supply ``None`` to unset it.
|
|
|
|
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:
|
|
|
|
if helper is None:
|
|
|
|
log.debug('PE helper is None')
|
|
|
|
log.debug('PE helper is None')
|
|
|
|
self._pe_helper = None
|
|
|
|
self._pe_helper = helper
|
|
|
|
else:
|
|
|
|
|
|
|
|
candidate = helper.strip()
|
|
|
|
@property
|
|
|
|
|
|
|
|
def pe_helper_mode(self) -> PEHelperMode:
|
|
|
|
mode = os.lstat(candidate).st_mode
|
|
|
|
'''
|
|
|
|
if not stat.S_ISREG(mode):
|
|
|
|
Returns whether the privilege escalation (PE) helper should be used and when. If the helper has not been set,
|
|
|
|
raise FileNotFoundError('PE helper must be a file')
|
|
|
|
this property evaluates to ``False``.
|
|
|
|
if not os.access(candidate, os.X_OK):
|
|
|
|
'''
|
|
|
|
raise FileNotFoundError('PE helper must be executable')
|
|
|
|
if self._pe_helper is None:
|
|
|
|
log.debug(f'Setting privilege escalation helper to "{candidate}"')
|
|
|
|
return PEHelperMode.DO_NOT_USE
|
|
|
|
self._pe_helper = candidate
|
|
|
|
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:
|
|
|
|
def get_zpool(api: str = 'cli', metadata_namespace: Optional[str] = None, **kwargs) -> ZPool:
|
|
|
|
'''
|
|
|
|
'''
|
|
|
|