salt/tests/support/zfs.py
2024-02-29 12:30:49 +00:00

754 lines
30 KiB
Python

"""
tests.support.zfs
~~~~~~~~~~~~~~~~~
ZFS related unit test data structures
"""
import salt.utils.zfs
from tests.support.mock import MagicMock, patch
class ZFSMockData:
def __init__(self):
# property_map mocks
self.pmap_exec_zpool = {
"retcode": 2,
"stdout": "",
"stderr": "\n".join(
[
"missing property argument",
"usage:",
' get [-Hp] [-o "all" | field[,...]] <"all" |'
" property[,...]> <pool> ...",
"",
"the following properties are supported:",
"",
" PROPERTY EDIT VALUES",
"",
" allocated NO <size>",
" capacity NO <size>",
" dedupratio NO <1.00x or higher if deduped>",
" expandsize NO <size>",
" fragmentation NO <percent>",
" free NO <size>",
" freeing NO <size>",
" guid NO <guid>",
" health NO <state>",
" leaked NO <size>",
" size NO <size>",
" altroot YES <path>",
" autoexpand YES on | off",
" autoreplace YES on | off",
" bootfs YES <filesystem>",
" bootsize YES <size>",
" cachefile YES <file> | none",
" comment YES <comment-string>",
" dedupditto YES <threshold (min 100)>",
" delegation YES on | off",
" failmode YES wait | continue | panic",
" listsnapshots YES on | off",
" readonly YES on | off",
" version YES <version>",
" feature@... YES disabled | enabled | active",
"",
"The feature@ properties must be appended with a feature name.",
"See zpool-features(5). ",
]
),
}
self.pmap_zpool = {
"comment": {"edit": True, "type": "str", "values": "<comment-string>"},
"freeing": {"edit": False, "type": "size", "values": "<size>"},
"listsnapshots": {"edit": True, "type": "bool", "values": "on | off"},
"leaked": {"edit": False, "type": "size", "values": "<size>"},
"version": {"edit": True, "type": "numeric", "values": "<version>"},
"write": {"edit": False, "type": "size", "values": "<size>"},
"replace": {"edit": True, "type": "bool", "values": "on | off"},
"delegation": {"edit": True, "type": "bool", "values": "on | off"},
"dedupditto": {
"edit": True,
"type": "str",
"values": "<threshold (min 100)>",
},
"autoexpand": {"edit": True, "type": "bool", "values": "on | off"},
"alloc": {"edit": False, "type": "size", "values": "<size>"},
"allocated": {"edit": False, "type": "size", "values": "<size>"},
"guid": {"edit": False, "type": "numeric", "values": "<guid>"},
"size": {"edit": False, "type": "size", "values": "<size>"},
"cap": {"edit": False, "type": "numeric", "values": "<count>"},
"capacity": {"edit": False, "type": "size", "values": "<size>"},
"capacity-alloc": {"edit": False, "type": "size", "values": "<size>"},
"capacity-free": {"edit": False, "type": "size", "values": "<size>"},
"cachefile": {"edit": True, "type": "str", "values": "<file> | none"},
"cksum": {"edit": False, "type": "numeric", "values": "<count>"},
"bootfs": {"edit": True, "type": "str", "values": "<filesystem>"},
"autoreplace": {"edit": True, "type": "bool", "values": "on | off"},
"bandwidth-read": {"edit": False, "type": "size", "values": "<size>"},
"bandwidth-write": {"edit": False, "type": "size", "values": "<size>"},
"operations-read": {"edit": False, "type": "size", "values": "<size>"},
"operations-write": {"edit": False, "type": "size", "values": "<size>"},
"read": {"edit": False, "type": "size", "values": "<size>"},
"readonly": {"edit": True, "type": "bool", "values": "on | off"},
"dedupratio": {
"edit": False,
"type": "str",
"values": "<1.00x or higher if deduped>",
},
"health": {"edit": False, "type": "str", "values": "<state>"},
"feature@": {
"edit": True,
"type": "str",
"values": "disabled | enabled | active",
},
"expandsize": {"edit": False, "type": "size", "values": "<size>"},
"listsnaps": {"edit": True, "type": "bool", "values": "on | off"},
"bootsize": {"edit": True, "type": "size", "values": "<size>"},
"free": {"edit": False, "type": "size", "values": "<size>"},
"failmode": {
"edit": True,
"type": "str",
"values": "wait | continue | panic",
},
"altroot": {"edit": True, "type": "str", "values": "<path>"},
"expand": {"edit": True, "type": "bool", "values": "on | off"},
"frag": {"edit": False, "type": "str", "values": "<percent>"},
"fragmentation": {"edit": False, "type": "str", "values": "<percent>"},
}
# fmt: off
self.pmap_exec_zfs = {
"retcode": 2,
"stdout": "",
"stderr": "\n".join(
[
"missing property argument",
"usage:",
' get [-crHp] [-d max] [-o "all" | field[,...]]',
" [-t type[,...]] [-s source[,...]]",
' <"all" | property[,...]>'
" [filesystem|volume|snapshot|bookmark] ...",
"",
"The following properties are supported:",
"",
" PROPERTY EDIT INHERIT VALUES",
"",
" available NO NO <size>",
" clones NO NO <dataset>[,...]",
" compressratio NO NO <1.00x or higher if compressed>",
" creation NO NO <date>",
" defer_destroy NO NO yes | no",
" filesystem_count NO NO <count>",
" logicalreferenced NO NO <size>",
" logicalused NO NO <size>",
" mounted NO NO yes | no",
" origin NO NO <snapshot>",
" receive_resume_token NO NO <string token>",
" refcompressratio NO NO <1.00x or higher if compressed>",
" referenced NO NO <size>",
" snapshot_count NO NO <count>",
" type NO NO filesystem | volume | snapshot | bookmark",
" used NO NO <size>",
" usedbychildren NO NO <size>",
" usedbydataset NO NO <size>",
" usedbyrefreservation NO NO <size>",
" usedbysnapshots NO NO <size>",
" userrefs NO NO <count>",
" written NO NO <size>",
" aclinherit YES YES discard | noallow | restricted | passthrough | passthrough-x",
" aclmode YES YES discard | groupmask | passthrough | restricted",
" atime YES YES on | off",
" canmount YES NO on | off | noauto",
" casesensitivity NO YES sensitive | insensitive | mixed",
" checksum YES YES on | off | fletcher2 | fletcher4 | sha256 | sha512 | skein | edonr",
" compression YES YES on | off | lzjb | gzip | gzip-[1-9] | zle | lz4",
" copies YES YES 1 | 2 | 3",
" dedup YES YES on | off | verify | sha256[,verify], sha512[,verify], skein[,verify], edonr,verify",
" devices YES YES on | off",
" exec YES YES on | off",
" filesystem_limit YES NO <count> | none",
" logbias YES YES latency | throughput",
" mlslabel YES YES <sensitivity label>",
" mountpoint YES YES <path> | legacy | none",
" nbmand YES YES on | off",
" normalization NO YES none | formC | formD | formKC | formKD",
" primarycache YES YES all | none | metadata",
" quota YES NO <size> | none",
" readonly YES YES on | off",
" recordsize YES YES 512 to 1M, power of 2",
" redundant_metadata YES YES all | most",
" refquota YES NO <size> | none",
" refreservation YES NO <size> | none",
" reservation YES NO <size> | none",
" secondarycache YES YES all | none | metadata",
" setuid YES YES on | off",
" sharenfs YES YES on | off | share(1M) options",
" sharesmb YES YES on | off | sharemgr(1M) options",
" snapdir YES YES hidden | visible",
" snapshot_limit YES NO <count> | none",
" sync YES YES standard | always | disabled",
" utf8only NO YES on | off",
" version YES NO 1 | 2 | 3 | 4 | 5 | current",
" volblocksize NO YES 512 to 128k, power of 2",
" volsize YES NO <size>",
" vscan YES YES on | off",
" xattr YES YES on | off",
" zoned YES YES on | off",
" userused@... NO NO <size>",
" groupused@... NO NO <size>",
" userquota@... YES NO <size> | none",
" groupquota@... YES NO <size> | none",
" written@<snap> NO NO <size>",
"",
"Sizes are specified in bytes with standard units such as K, M, G, etc.",
"",
"User-defined properties can be specified by using a name containing a colon (:).",
"",
"The {user|group}{used|quota}@ properties must be appended with",
"a user or group specifier of one of these forms:",
' POSIX name (eg: "matt")',
' POSIX id (eg: "126829")',
' SMB name@domain (eg: "matt@sun")',
' SMB SID (eg: "S-1-234-567-89")',
]
),
}
# fmt: on
self.pmap_zfs = {
"origin": {
"edit": False,
"inherit": False,
"values": "<snapshot>",
"type": "str",
},
"setuid": {
"edit": True,
"inherit": True,
"values": "on | off",
"type": "bool",
},
"referenced": {
"edit": False,
"inherit": False,
"values": "<size>",
"type": "size",
},
"vscan": {
"edit": True,
"inherit": True,
"values": "on | off",
"type": "bool",
},
"logicalused": {
"edit": False,
"inherit": False,
"values": "<size>",
"type": "size",
},
"userrefs": {
"edit": False,
"inherit": False,
"values": "<count>",
"type": "numeric",
},
"primarycache": {
"edit": True,
"inherit": True,
"values": "all | none | metadata",
"type": "str",
},
"logbias": {
"edit": True,
"inherit": True,
"values": "latency | throughput",
"type": "str",
},
"creation": {
"edit": False,
"inherit": False,
"values": "<date>",
"type": "str",
},
"sync": {
"edit": True,
"inherit": True,
"values": "standard | always | disabled",
"type": "str",
},
"dedup": {
"edit": True,
"inherit": True,
"values": (
"on | off | verify | sha256[,verify], sha512[,verify],"
" skein[,verify], edonr,verify"
),
"type": "bool",
},
"sharenfs": {
"edit": True,
"inherit": True,
"values": "on | off | share(1m) options",
"type": "bool",
},
"receive_resume_token": {
"edit": False,
"inherit": False,
"values": "<string token>",
"type": "str",
},
"usedbyrefreservation": {
"edit": False,
"inherit": False,
"values": "<size>",
"type": "size",
},
"sharesmb": {
"edit": True,
"inherit": True,
"values": "on | off | sharemgr(1m) options",
"type": "bool",
},
"rdonly": {
"edit": True,
"inherit": True,
"values": "on | off",
"type": "bool",
},
"reservation": {
"edit": True,
"inherit": False,
"values": "<size> | none",
"type": "size",
},
"reserv": {
"edit": True,
"inherit": False,
"values": "<size> | none",
"type": "size",
},
"mountpoint": {
"edit": True,
"inherit": True,
"values": "<path> | legacy | none",
"type": "str",
},
"casesensitivity": {
"edit": False,
"inherit": True,
"values": "sensitive | insensitive | mixed",
"type": "str",
},
"utf8only": {
"edit": False,
"inherit": True,
"values": "on | off",
"type": "bool",
},
"usedbysnapshots": {
"edit": False,
"inherit": False,
"values": "<size>",
"type": "size",
},
"readonly": {
"edit": True,
"inherit": True,
"values": "on | off",
"type": "bool",
},
"written@": {
"edit": False,
"inherit": False,
"values": "<size>",
"type": "size",
},
"avail": {
"edit": False,
"inherit": False,
"values": "<size>",
"type": "size",
},
"recsize": {
"edit": True,
"inherit": True,
"values": "512 to 1m, power of 2",
"type": "str",
},
"atime": {
"edit": True,
"inherit": True,
"values": "on | off",
"type": "bool",
},
"compression": {
"edit": True,
"inherit": True,
"values": "on | off | lzjb | gzip | gzip-[1-9] | zle | lz4",
"type": "bool",
},
"snapdir": {
"edit": True,
"inherit": True,
"values": "hidden | visible",
"type": "str",
},
"aclmode": {
"edit": True,
"inherit": True,
"values": "discard | groupmask | passthrough | restricted",
"type": "str",
},
"zoned": {
"edit": True,
"inherit": True,
"values": "on | off",
"type": "bool",
},
"copies": {
"edit": True,
"inherit": True,
"values": "1 | 2 | 3",
"type": "numeric",
},
"snapshot_limit": {
"edit": True,
"inherit": False,
"values": "<count> | none",
"type": "numeric",
},
"aclinherit": {
"edit": True,
"inherit": True,
"values": (
"discard | noallow | restricted | passthrough | passthrough-x"
),
"type": "str",
},
"compressratio": {
"edit": False,
"inherit": False,
"values": "<1.00x or higher if compressed>",
"type": "str",
},
"xattr": {
"edit": True,
"inherit": True,
"values": "on | off",
"type": "bool",
},
"written": {
"edit": False,
"inherit": False,
"values": "<size>",
"type": "size",
},
"version": {
"edit": True,
"inherit": False,
"values": "1 | 2 | 3 | 4 | 5 | current",
"type": "numeric",
},
"recordsize": {
"edit": True,
"inherit": True,
"values": "512 to 1m, power of 2",
"type": "str",
},
"refquota": {
"edit": True,
"inherit": False,
"values": "<size> | none",
"type": "size",
},
"filesystem_limit": {
"edit": True,
"inherit": False,
"values": "<count> | none",
"type": "numeric",
},
"lrefer.": {
"edit": False,
"inherit": False,
"values": "<size>",
"type": "size",
},
"type": {
"edit": False,
"inherit": False,
"values": "filesystem | volume | snapshot | bookmark",
"type": "str",
},
"secondarycache": {
"edit": True,
"inherit": True,
"values": "all | none | metadata",
"type": "str",
},
"refer": {
"edit": False,
"inherit": False,
"values": "<size>",
"type": "size",
},
"available": {
"edit": False,
"inherit": False,
"values": "<size>",
"type": "size",
},
"used": {
"edit": False,
"inherit": False,
"values": "<size>",
"type": "size",
},
"exec": {
"edit": True,
"inherit": True,
"values": "on | off",
"type": "bool",
},
"compress": {
"edit": True,
"inherit": True,
"values": "on | off | lzjb | gzip | gzip-[1-9] | zle | lz4",
"type": "bool",
},
"volblock": {
"edit": False,
"inherit": True,
"values": "512 to 128k, power of 2",
"type": "str",
},
"refcompressratio": {
"edit": False,
"inherit": False,
"values": "<1.00x or higher if compressed>",
"type": "str",
},
"quota": {
"edit": True,
"inherit": False,
"values": "<size> | none",
"type": "size",
},
"groupquota@": {
"edit": True,
"inherit": False,
"values": "<size> | none",
"type": "size",
},
"userquota@": {
"edit": True,
"inherit": False,
"values": "<size> | none",
"type": "size",
},
"snapshot_count": {
"edit": False,
"inherit": False,
"values": "<count>",
"type": "numeric",
},
"volsize": {
"edit": True,
"inherit": False,
"values": "<size>",
"type": "size",
},
"clones": {
"edit": False,
"inherit": False,
"values": "<dataset>[,...]",
"type": "str",
},
"canmount": {
"edit": True,
"inherit": False,
"values": "on | off | noauto",
"type": "bool",
},
"mounted": {
"edit": False,
"inherit": False,
"values": "yes | no",
"type": "bool_alt",
},
"groupused@": {
"edit": False,
"inherit": False,
"values": "<size>",
"type": "size",
},
"normalization": {
"edit": False,
"inherit": True,
"values": "none | formc | formd | formkc | formkd",
"type": "str",
},
"usedbychildren": {
"edit": False,
"inherit": False,
"values": "<size>",
"type": "size",
},
"usedbydataset": {
"edit": False,
"inherit": False,
"values": "<size>",
"type": "size",
},
"mlslabel": {
"edit": True,
"inherit": True,
"values": "<sensitivity label>",
"type": "str",
},
"refreserv": {
"edit": True,
"inherit": False,
"values": "<size> | none",
"type": "size",
},
"defer_destroy": {
"edit": False,
"inherit": False,
"values": "yes | no",
"type": "bool_alt",
},
"volblocksize": {
"edit": False,
"inherit": True,
"values": "512 to 128k, power of 2",
"type": "str",
},
"lused.": {
"edit": False,
"inherit": False,
"values": "<size>",
"type": "size",
},
"redundant_metadata": {
"edit": True,
"inherit": True,
"values": "all | most",
"type": "str",
},
"filesystem_count": {
"edit": False,
"inherit": False,
"values": "<count>",
"type": "numeric",
},
"devices": {
"edit": True,
"inherit": True,
"values": "on | off",
"type": "bool",
},
"refreservation": {
"edit": True,
"inherit": False,
"values": "<size> | none",
"type": "size",
},
"userused@": {
"edit": False,
"inherit": False,
"values": "<size>",
"type": "size",
},
"logicalreferenced": {
"edit": False,
"inherit": False,
"values": "<size>",
"type": "size",
},
"checksum": {
"edit": True,
"inherit": True,
"values": (
"on | off | fletcher2 | fletcher4 | sha256 | sha512 | skein | edonr"
),
"type": "bool",
},
"nbmand": {
"edit": True,
"inherit": True,
"values": "on | off",
"type": "bool",
},
}
def _from_auto(self, name, value, source="auto"):
"""
some more complex patching for zfs.from_auto
"""
with patch.object(
salt.utils.zfs,
"property_data_zpool",
MagicMock(return_value=self.pmap_zpool),
), patch.object(
salt.utils.zfs, "property_data_zfs", MagicMock(return_value=self.pmap_zfs)
):
return salt.utils.zfs.from_auto(name, value, source)
def _from_auto_dict(self, values, source="auto"):
"""
some more complex patching for zfs.from_auto_dict
"""
with patch.object(
salt.utils.zfs,
"property_data_zpool",
MagicMock(return_value=self.pmap_zpool),
), patch.object(
salt.utils.zfs, "property_data_zfs", MagicMock(return_value=self.pmap_zfs)
):
return salt.utils.zfs.from_auto_dict(values, source)
def _to_auto(self, name, value, source="auto", convert_to_human=True):
"""
some more complex patching for zfs.to_auto
"""
with patch.object(
salt.utils.zfs,
"property_data_zpool",
MagicMock(return_value=self.pmap_zpool),
), patch.object(
salt.utils.zfs, "property_data_zfs", MagicMock(return_value=self.pmap_zfs)
):
return salt.utils.zfs.to_auto(name, value, source, convert_to_human)
def _to_auto_dict(self, values, source="auto", convert_to_human=True):
"""
some more complex patching for zfs.to_auto_dict
"""
with patch.object(
salt.utils.zfs,
"property_data_zpool",
MagicMock(return_value=self.pmap_zpool),
), patch.object(
salt.utils.zfs, "property_data_zfs", MagicMock(return_value=self.pmap_zfs)
):
return salt.utils.zfs.to_auto_dict(values, source, convert_to_human)
def get_patched_utils(self):
return {
"zfs.is_supported": MagicMock(return_value=True),
"zfs.has_feature_flags": MagicMock(return_value=True),
"zfs.property_data_zpool": MagicMock(return_value=self.pmap_zpool),
"zfs.property_data_zfs": MagicMock(return_value=self.pmap_zfs),
# NOTE: we make zpool_command and zfs_command a NOOP
# these are extensively tested in tests.unit.utils.test_zfs
"zfs.zpool_command": MagicMock(return_value="/bin/false"),
"zfs.zfs_command": MagicMock(return_value="/bin/false"),
# NOTE: from_auto_dict is a special snowflake
# internally it calls multiple calls from
# salt.utils.zfs but we cannot patch those using
# the common methode, __utils__ is not available
# so they are direct calls, we do some voodoo here.
"zfs.from_auto_dict": self._from_auto_dict,
"zfs.from_auto": self._from_auto,
"zfs.to_auto_dict": self._to_auto_dict,
"zfs.to_auto": self._to_auto,
}