Mini Shell
"""
Module to manage FreeBSD kernel modules
"""
import os
import re
import salt.utils.files
# Define the module's virtual name
__virtualname__ = "kmod"
_LOAD_MODULE = '{0}_load="YES"'
_LOADER_CONF = "/boot/loader.conf"
_MODULE_RE = '^{0}_load="YES"'
_MODULES_RE = r'^(\w+)_load="YES"'
def __virtual__():
"""
Only runs on FreeBSD systems
"""
if __grains__["kernel"] == "FreeBSD":
return __virtualname__
return (
False,
"The freebsdkmod execution module cannot be loaded: only available on FreeBSD"
" systems.",
)
def _new_mods(pre_mods, post_mods):
"""
Return a list of the new modules, pass an kldstat dict before running
modprobe and one after modprobe has run
"""
pre = set()
post = set()
for mod in pre_mods:
pre.add(mod["module"])
for mod in post_mods:
post.add(mod["module"])
return post - pre
def _rm_mods(pre_mods, post_mods):
"""
Return a list of the new modules, pass an kldstat dict before running
modprobe and one after modprobe has run
"""
pre = set()
post = set()
for mod in pre_mods:
pre.add(mod["module"])
for mod in post_mods:
post.add(mod["module"])
return pre - post
def _get_module_name(line):
match = re.search(_MODULES_RE, line)
if match:
return match.group(1)
return None
def _get_persistent_modules():
"""
Returns a list of modules in loader.conf that load on boot.
"""
mods = set()
with salt.utils.files.fopen(_LOADER_CONF, "r") as loader_conf:
for line in loader_conf:
line = salt.utils.stringutils.to_unicode(line)
line = line.strip()
mod_name = _get_module_name(line)
if mod_name:
mods.add(mod_name)
return mods
def _set_persistent_module(mod):
"""
Add a module to loader.conf to make it persistent.
"""
if not mod or mod in mod_list(True) or mod not in available():
return set()
__salt__["file.append"](_LOADER_CONF, _LOAD_MODULE.format(mod))
return {mod}
def _remove_persistent_module(mod, comment):
"""
Remove module from loader.conf. If comment is true only comment line where
module is.
"""
if not mod or mod not in mod_list(True):
return set()
if comment:
__salt__["file.comment"](_LOADER_CONF, _MODULE_RE.format(mod))
else:
__salt__["file.sed"](_LOADER_CONF, _MODULE_RE.format(mod), "")
return {mod}
def available():
"""
Return a list of all available kernel modules
CLI Example:
.. code-block:: bash
salt '*' kmod.available
"""
ret = []
for path in __salt__["file.find"]("/boot/kernel", name="*.ko$"):
bpath = os.path.basename(path)
comps = bpath.split(".")
if "ko" in comps:
# This is a kernel module, return it without the .ko extension
ret.append(".".join(comps[: comps.index("ko")]))
return ret
def check_available(mod):
"""
Check to see if the specified kernel module is available
CLI Example:
.. code-block:: bash
salt '*' kmod.check_available vmm
"""
return mod in available()
def lsmod():
"""
Return a dict containing information about currently loaded modules
CLI Example:
.. code-block:: bash
salt '*' kmod.lsmod
"""
ret = []
for line in __salt__["cmd.run"]("kldstat").splitlines():
comps = line.split()
if not len(comps) > 2:
continue
if comps[0] == "Id":
continue
if comps[4] == "kernel":
continue
ret.append({"module": comps[4][:-3], "size": comps[3], "depcount": comps[1]})
return ret
def mod_list(only_persist=False):
"""
Return a list of the loaded module names
CLI Example:
.. code-block:: bash
salt '*' kmod.mod_list
"""
mods = set()
if only_persist:
if not _get_persistent_modules():
return mods
for mod in _get_persistent_modules():
mods.add(mod)
else:
for mod in lsmod():
mods.add(mod["module"])
return sorted(list(mods))
def load(mod, persist=False):
"""
Load the specified kernel module
mod
Name of the module to add
persist
Write the module to sysrc kld_modules to make it load on system reboot
CLI Example:
.. code-block:: bash
salt '*' kmod.load bhyve
"""
pre_mods = lsmod()
response = __salt__["cmd.run_all"](f"kldload {mod}", python_shell=False)
if response["retcode"] == 0:
post_mods = lsmod()
mods = _new_mods(pre_mods, post_mods)
persist_mods = set()
if persist:
persist_mods = _set_persistent_module(mod)
return sorted(list(mods | persist_mods))
elif "module already loaded or in kernel" in response["stderr"]:
if persist and mod not in _get_persistent_modules():
persist_mods = _set_persistent_module(mod)
return sorted(list(persist_mods))
else:
# It's compiled into the kernel
return [None]
else:
return f"Module {mod} not found"
def is_loaded(mod):
"""
Check to see if the specified kernel module is loaded
CLI Example:
.. code-block:: bash
salt '*' kmod.is_loaded vmm
"""
return mod in mod_list()
def remove(mod, persist=False, comment=True):
"""
Remove the specified kernel module
mod
Name of module to remove
persist
Also remove module from /boot/loader.conf
comment
If persist is set don't remove line from /boot/loader.conf but only
comment it
CLI Example:
.. code-block:: bash
salt '*' kmod.remove vmm
"""
pre_mods = lsmod()
res = __salt__["cmd.run_all"](f"kldunload {mod}", python_shell=False)
if res["retcode"] == 0:
post_mods = lsmod()
mods = _rm_mods(pre_mods, post_mods)
persist_mods = set()
if persist:
persist_mods = _remove_persistent_module(mod, comment)
return sorted(list(mods | persist_mods))
else:
return "Error removing module {}: {}".format(mod, res["stderr"])
Zerion Mini Shell 1.0