Mini Shell
"""
The service module for FreeBSD
.. important::
If you feel that Salt should be using this module to manage services on a
minion, and it is using a different module (or gives an error similar to
*'service.start' is not available*), see :ref:`here
<module-provider-override>`.
"""
import fnmatch
import logging
import os
import re
import salt.utils.decorators as decorators
import salt.utils.files
import salt.utils.path
from salt.exceptions import CommandNotFoundError
__func_alias__ = {"reload_": "reload"}
log = logging.getLogger(__name__)
# Define the module's virtual name
__virtualname__ = "service"
def __virtual__():
"""
Only work on FreeBSD
"""
# Disable on these platforms, specific service modules exist:
if __grains__["os"] == "FreeBSD":
return __virtualname__
return (
False,
"The freebsdservice execution module cannot be loaded: only available on"
" FreeBSD systems.",
)
@decorators.memoize
def _cmd(jail=None):
"""
Return full path to service command
.. versionchanged:: 2016.3.4
Support for jail (representing jid or jail name) keyword argument in kwargs
"""
service = salt.utils.path.which("service")
if not service:
raise CommandNotFoundError("'service' command not found")
if jail:
jexec = salt.utils.path.which("jexec")
if not jexec:
raise CommandNotFoundError("'jexec' command not found")
service = f"{jexec} {jail} {service}"
return service
def _get_jail_path(jail):
"""
.. versionadded:: 2016.3.4
Return the jail's root directory (path) as shown in jls
jail
The jid or jail name
"""
jls = salt.utils.path.which("jls")
if not jls:
raise CommandNotFoundError("'jls' command not found")
jails = __salt__["cmd.run_stdout"](f"{jls} -n jid name path")
for j in jails.splitlines():
jid, jname, path = (x.split("=")[1].strip() for x in j.split())
if jid == jail or jname == jail:
return path.rstrip("/")
# XΧΧ, TODO, not sure how to handle nonexistent jail
return ""
def _get_rcscript(name, jail=None):
"""
Return full path to service rc script
.. versionchanged:: 2016.3.4
Support for jail (representing jid or jail name) keyword argument in kwargs
"""
cmd = f"{_cmd(jail)} -r"
prf = _get_jail_path(jail) if jail else ""
for line in __salt__["cmd.run_stdout"](cmd, python_shell=False).splitlines():
if line.endswith(f"{os.path.sep}{name}"):
return os.path.join(prf, line.lstrip(os.path.sep))
return None
def _get_rcvar(name, jail=None):
"""
Return rcvar
.. versionchanged:: 2016.3.4
Support for jail (representing jid or jail name) keyword argument in kwargs
"""
if not available(name, jail):
log.error("Service %s not found", name)
return False
cmd = f"{_cmd(jail)} {name} rcvar"
for line in __salt__["cmd.run_stdout"](cmd, python_shell=False).splitlines():
if '_enable="' not in line:
continue
rcvar, _ = line.split("=", 1)
return rcvar
return None
def get_enabled(jail=None):
"""
Return what services are set to run on boot
.. versionchanged:: 2016.3.4
Support for jail (representing jid or jail name) keyword argument in kwargs
CLI Example:
.. code-block:: bash
salt '*' service.get_enabled
"""
ret = []
service = _cmd(jail)
prf = _get_jail_path(jail) if jail else ""
for svc in __salt__["cmd.run"](f"{service} -e").splitlines():
ret.append(os.path.basename(svc))
# This is workaround for bin/173454 bug
for svc in get_all(jail):
if svc in ret:
continue
if not os.path.exists(f"{prf}/etc/rc.conf.d/{svc}"):
continue
if enabled(svc, jail=jail):
ret.append(svc)
return sorted(ret)
def get_disabled(jail=None):
"""
Return what services are available but not enabled to start at boot
.. versionchanged:: 2016.3.4
Support for jail (representing jid or jail name) keyword argument in kwargs
CLI Example:
.. code-block:: bash
salt '*' service.get_disabled
"""
en_ = get_enabled(jail)
all_ = get_all(jail)
return sorted(set(all_) - set(en_))
def _switch(name, on, **kwargs): # pylint: disable=C0103 # pylint: disable=C0103
"""
Switch on/off service start at boot.
.. versionchanged:: 2016.3.4
Support for jail (representing jid or jail name) and chroot keyword argument
in kwargs. chroot should be used when jail's /etc is mounted read-only and
should point to a root directory where jail's /etc is mounted read-write.
"""
jail = kwargs.get("jail", "")
chroot = kwargs.get("chroot", "").rstrip("/")
if not available(name, jail):
return False
rcvar = _get_rcvar(name, jail)
if not rcvar:
log.error("rcvar for service %s not found", name)
return False
if jail and not chroot:
# prepend the jail's path in config paths when referring to a jail, when
# chroot is not provided. chroot should be provided when the jail's /etc
# is mounted read-only
chroot = _get_jail_path(jail)
config = kwargs.get(
"config",
__salt__["config.option"]("service.config", default=f"{chroot}/etc/rc.conf"),
)
if not config:
rcdir = f"{chroot}/etc/rc.conf.d"
if not os.path.exists(rcdir) or not os.path.isdir(rcdir):
log.error("%s not exists", rcdir)
return False
config = os.path.join(rcdir, rcvar.replace("_enable", ""))
nlines = []
edited = False
if on:
val = "YES"
else:
val = "NO"
if os.path.exists(config):
with salt.utils.files.fopen(config, "r") as ifile:
for line in ifile:
line = salt.utils.stringutils.to_unicode(line)
if not line.startswith(f"{rcvar}="):
nlines.append(line)
continue
rest = line[len(line.split()[0]) :] # keep comments etc
nlines.append(f'{rcvar}="{val}"{rest}')
edited = True
if not edited:
# Ensure that the file ends in a \n
if len(nlines) > 1 and nlines[-1][-1] != "\n":
nlines[-1] = f"{nlines[-1]}\n"
nlines.append(f'{rcvar}="{val}"\n')
with salt.utils.files.fopen(config, "w") as ofile:
nlines = [salt.utils.stringutils.to_str(_l) for _l in nlines]
ofile.writelines(nlines)
return True
def enable(name, **kwargs):
"""
Enable the named service to start at boot
name
service name
config : /etc/rc.conf
Config file for managing service. If config value is
empty string, then /etc/rc.conf.d/<service> used.
See man rc.conf(5) for details.
Also service.config variable can be used to change default.
.. versionchanged:: 2016.3.4
jail (optional keyword argument)
the jail's id or name
chroot (optional keyword argument)
the jail's chroot, if the jail's /etc is not mounted read-write
CLI Example:
.. code-block:: bash
salt '*' service.enable <service name>
"""
return _switch(name, True, **kwargs)
def disable(name, **kwargs):
"""
Disable the named service to start at boot
Arguments the same as for enable()
.. versionchanged:: 2016.3.4
jail (optional keyword argument)
the jail's id or name
chroot (optional keyword argument)
the jail's chroot, if the jail's /etc is not mounted read-write
CLI Example:
.. code-block:: bash
salt '*' service.disable <service name>
"""
return _switch(name, False, **kwargs)
def enabled(name, **kwargs):
"""
Return True if the named service is enabled, false otherwise
name
Service name
.. versionchanged:: 2016.3.4
Support for jail (representing jid or jail name) keyword argument in kwargs
CLI Example:
.. code-block:: bash
salt '*' service.enabled <service name>
"""
jail = kwargs.get("jail", "")
if not available(name, jail):
log.error("Service %s not found", name)
return False
cmd = f"{_cmd(jail)} {name} rcvar"
for line in __salt__["cmd.run_stdout"](cmd, python_shell=False).splitlines():
if '_enable="' not in line:
continue
_, state, _ = line.split('"', 2)
return state.lower() in ("yes", "true", "on", "1")
# probably will never reached
return False
def disabled(name, **kwargs):
"""
Return True if the named service is enabled, false otherwise
CLI Example:
.. code-block:: bash
salt '*' service.disabled <service name>
"""
return not enabled(name, **kwargs)
def available(name, jail=None):
"""
Check that the given service is available.
.. versionchanged:: 2016.3.4
jail: optional jid or jail name
CLI Example:
.. code-block:: bash
salt '*' service.available sshd
"""
return name in get_all(jail)
def missing(name, jail=None):
"""
The inverse of service.available.
Returns ``True`` if the specified service is not available, otherwise returns
``False``.
.. versionchanged:: 2016.3.4
jail: optional jid or jail name
CLI Example:
.. code-block:: bash
salt '*' service.missing sshd
"""
return name not in get_all(jail)
def get_all(jail=None):
"""
Return a list of all available services
.. versionchanged:: 2016.3.4
jail: optional jid or jail name
CLI Example:
.. code-block:: bash
salt '*' service.get_all
"""
ret = []
service = _cmd(jail)
for srv in __salt__["cmd.run"](f"{service} -l").splitlines():
if not srv.isupper():
ret.append(srv)
return sorted(ret)
def start(name, jail=None):
"""
Start the specified service
.. versionchanged:: 2016.3.4
jail: optional jid or jail name
CLI Example:
.. code-block:: bash
salt '*' service.start <service name>
"""
cmd = f"{_cmd(jail)} {name} onestart"
return not __salt__["cmd.retcode"](cmd, python_shell=False)
def stop(name, jail=None):
"""
Stop the specified service
.. versionchanged:: 2016.3.4
jail: optional jid or jail name
CLI Example:
.. code-block:: bash
salt '*' service.stop <service name>
"""
cmd = f"{_cmd(jail)} {name} onestop"
return not __salt__["cmd.retcode"](cmd, python_shell=False)
def restart(name, jail=None):
"""
Restart the named service
.. versionchanged:: 2016.3.4
jail: optional jid or jail name
CLI Example:
.. code-block:: bash
salt '*' service.restart <service name>
"""
cmd = f"{_cmd(jail)} {name} onerestart"
return not __salt__["cmd.retcode"](cmd, python_shell=False)
def reload_(name, jail=None):
"""
Restart the named service
.. versionchanged:: 2016.3.4
jail: optional jid or jail name
CLI Example:
.. code-block:: bash
salt '*' service.reload <service name>
"""
cmd = f"{_cmd(jail)} {name} onereload"
return not __salt__["cmd.retcode"](cmd, python_shell=False)
def status(name, sig=None, jail=None):
"""
Return the status for a service.
If the name contains globbing, a dict mapping service name to True/False
values is returned.
.. versionchanged:: 2016.3.4
.. versionchanged:: 2018.3.0
The service name can now be a glob (e.g. ``salt*``)
Args:
name (str): The name of the service to check
sig (str): Signature to use to find the service via ps
Returns:
bool: True if running, False otherwise
dict: Maps service name to True if running, False otherwise
CLI Example:
.. code-block:: bash
salt '*' service.status <service name> [service signature]
"""
if sig:
return bool(__salt__["status.pid"](sig))
contains_globbing = bool(re.search(r"\*|\?|\[.+\]", name))
if contains_globbing:
services = fnmatch.filter(get_all(), name)
else:
services = [name]
results = {}
for service in services:
cmd = f"{_cmd(jail)} {service} onestatus"
results[service] = not __salt__["cmd.retcode"](
cmd, python_shell=False, ignore_retcode=True
)
if contains_globbing:
return results
return results[name]
Zerion Mini Shell 1.0