diff --git a/changelog/67765.fixed.md b/changelog/67765.fixed.md new file mode 100644 index 000000000000..10e44c28bccf --- /dev/null +++ b/changelog/67765.fixed.md @@ -0,0 +1 @@ +Added back support for init.d service scripts diff --git a/pkg/debian/salt-api.init b/pkg/debian/salt-api.init new file mode 100644 index 000000000000..c9887f852a51 --- /dev/null +++ b/pkg/debian/salt-api.init @@ -0,0 +1,99 @@ +#!/bin/sh +### BEGIN INIT INFO +# Provides: salt-api +# Required-Start: $remote_fs $network +# Required-Stop: $remote_fs $network +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: REST API for Salt +# Description: salt-api provides a REST interface to the Salt master +### END INIT INFO + +# Author: Michael Prokop + +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="REST API for Salt" +NAME=salt-api +DAEMON=/usr/bin/salt-api +DAEMON_ARGS="-d" +PIDFILE=/var/run/$NAME.pid +SCRIPTNAME=/etc/init.d/$NAME + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Read configuration variable file if it is present +[ -r /etc/default/$NAME ] && . /etc/default/$NAME + +. /lib/init/vars.sh +. /lib/lsb/init-functions + +do_start() { + pid=$(pidofproc -p $PIDFILE $DAEMON) + if [ -n "$pid" ] ; then + log_begin_msg "$DESC already running." + log_end_msg 0 + exit 0 + fi + + log_daemon_msg "Starting salt-api daemon: " + start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- $DAEMON_ARGS + log_end_msg $? +} + +do_stop() { + log_begin_msg "Stopping $DESC ..." + start-stop-daemon --stop --retry TERM/5 --quiet --oknodo --pidfile $PIDFILE + RC=$? + [ $RC -eq 0 ] && rm -f $PIDFILE + log_end_msg $RC +} + +case "$1" in + start) + [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" + do_start + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + stop) + [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" + do_stop + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + status) + status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? + ;; + #reload) + # not implemented + #;; + restart|force-reload) + log_daemon_msg "Restarting $DESC" "$NAME" + do_stop + case "$?" in + 0|1) + do_start + case "$?" in + 0) log_end_msg 0 ;; + 1) log_end_msg 1 ;; # Old process is still running + *) log_end_msg 1 ;; # Failed to start + esac + ;; + *) + # Failed to stop + log_end_msg 1 + ;; + esac + ;; + *) + echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 + exit 3 + ;; +esac + +exit 0 diff --git a/pkg/debian/salt-master.init b/pkg/debian/salt-master.init new file mode 100644 index 000000000000..1edaa3e0e1ce --- /dev/null +++ b/pkg/debian/salt-master.init @@ -0,0 +1,112 @@ +#!/bin/sh +### BEGIN INIT INFO +# Provides: salt-master +# Required-Start: $remote_fs $network +# Required-Stop: $remote_fs $network +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: The Salt Master daemon +# Description: The Salt Master is the central server (management +# component) to which all Salt Minions connect +### END INIT INFO + +# Author: Michael Prokop + +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="The Salt Master daemon" +NAME=salt-master +DAEMON=/usr/bin/salt-master +DAEMON_ARGS="-d" +PIDFILE=/var/run/$NAME.pid +SCRIPTNAME=/etc/init.d/$NAME + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Read configuration variable file if it is present +[ -r /etc/default/$NAME ] && . /etc/default/$NAME + +. /lib/lsb/init-functions + +do_start() { + # Return + # 0 if daemon has been started + # 1 if daemon was already running + # 2 if daemon could not be started + pid=$(pidofproc -p $PIDFILE $DAEMON) + if [ -n "$pid" ] ; then + return 1 + fi + + start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \ + $DAEMON_ARGS \ + || return 2 +} + +do_stop() { + # Return + # 0 if daemon has been stopped + # 1 if daemon was already stopped + # 2 if daemon could not be stopped + # other if a failure occurred + pids=$(pidof -x $DAEMON) + if [ $? -eq 0 ] ; then + echo $pids | xargs kill 2&1> /dev/null + RETVAL=0 + else + RETVAL=1 + fi + + [ "$RETVAL" = 2 ] && return 2 + rm -f $PIDFILE + return "$RETVAL" +} + +case "$1" in + start) + [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" + do_start + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + stop) + [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" + do_stop + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + status) + status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? + ;; + #reload) + # not implemented + #;; + restart|force-reload) + log_daemon_msg "Restarting $DESC" "$NAME" + do_stop + case "$?" in + 0|1) + do_start + case "$?" in + 0) log_end_msg 0 ;; + 1) log_end_msg 1 ;; # Old process is still running + *) log_end_msg 1 ;; # Failed to start + esac + ;; + *) + # Failed to stop + log_end_msg 1 + ;; + esac + ;; + *) + echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 + exit 3 + ;; +esac + +exit 0 diff --git a/pkg/debian/salt-minion.init b/pkg/debian/salt-minion.init new file mode 100644 index 000000000000..e7eec559789a --- /dev/null +++ b/pkg/debian/salt-minion.init @@ -0,0 +1,107 @@ +#!/bin/sh +### BEGIN INIT INFO +# Provides: salt-minion +# Required-Start: $remote_fs $network +# Required-Stop: $remote_fs $network +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: The Salt Minion daemon +# Description: The Salt Minion is the agent component of Salt. It listens +# for instructions from the Master, runs jobs, and returns +# results back to the Salt Master +### END INIT INFO + +# Author: Michael Prokop + +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="The Salt Minion daemon" +NAME=salt-minion +DAEMON=/usr/bin/salt-minion +DAEMON_ARGS="-d" +PIDFILE=/var/run/$NAME.pid +SCRIPTNAME=/etc/init.d/$NAME + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Read configuration variable file if it is present +[ -r /etc/default/$NAME ] && . /etc/default/$NAME + +. /lib/lsb/init-functions + +do_start() { + # Return + # 0 if daemon has been started + # 1 if daemon was already running + # 2 if daemon could not be started + pid=$(pidofproc -p $PIDFILE $DAEMON) + if [ -n "$pid" ] ; then + return 1 + fi + + start-stop-daemon --start --quiet --background --pidfile $PIDFILE --exec $DAEMON -- \ + $DAEMON_ARGS \ + || return 2 +} + +do_stop() { + # Return + # 0 if daemon has been stopped + # 1 if daemon was already stopped + # 2 if daemon could not be stopped + # other if a failure occurred + start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME + RETVAL="$?" + [ "$RETVAL" = 2 ] && return 2 + rm -f $PIDFILE + return "$RETVAL" +} + +case "$1" in + start) + [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" + do_start + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + stop) + [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" + do_stop + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + status) + status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? + ;; + #reload) + # not implemented + #;; + restart|force-reload) + log_daemon_msg "Restarting $DESC" "$NAME" + do_stop + case "$?" in + 0|1) + do_start + case "$?" in + 0) log_end_msg 0 ;; + 1) log_end_msg 1 ;; # Old process is still running + *) log_end_msg 1 ;; # Failed to start + esac + ;; + *) + # Failed to stop + log_end_msg 1 + ;; + esac + ;; + *) + echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 + exit 3 + ;; +esac + +exit 0 diff --git a/pkg/debian/salt-syndic.init b/pkg/debian/salt-syndic.init new file mode 100644 index 000000000000..b3a8191947c4 --- /dev/null +++ b/pkg/debian/salt-syndic.init @@ -0,0 +1,107 @@ +#!/bin/sh +### BEGIN INIT INFO +# Provides: salt-syndic +# Required-Start: $remote_fs $network +# Required-Stop: $remote_fs $network +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: The Salt Syndic daemon +# Description: The Salt Syndic is a master daemon which can receive +# instructions from a higher-level Salt Master, allowing +# for tiered organization of your Salt infrastructure +### END INIT INFO + +# Author: Michael Prokop + +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="The Salt Syndic daemon" +NAME=salt-syndic +DAEMON=/usr/bin/salt-syndic +DAEMON_ARGS="-d" +PIDFILE=/var/run/$NAME.pid +SCRIPTNAME=/etc/init.d/$NAME + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Read configuration variable file if it is present +[ -r /etc/default/$NAME ] && . /etc/default/$NAME + +. /lib/lsb/init-functions + +do_start() { + # Return + # 0 if daemon has been started + # 1 if daemon was already running + # 2 if daemon could not be started + pid=$(pidofproc -p $PIDFILE $DAEMON) + if [ -n "$pid" ] ; then + return 1 + fi + + start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \ + $DAEMON_ARGS \ + || return 2 +} + +do_stop() { + # Return + # 0 if daemon has been stopped + # 1 if daemon was already stopped + # 2 if daemon could not be stopped + # other if a failure occurred + start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME + RETVAL="$?" + [ "$RETVAL" = 2 ] && return 2 + rm -f $PIDFILE + return "$RETVAL" +} + +case "$1" in + start) + [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" + do_start + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + stop) + [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" + do_stop + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + status) + status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? + ;; + #reload) + # not implemented + #;; + restart|force-reload) + log_daemon_msg "Restarting $DESC" "$NAME" + do_stop + case "$?" in + 0|1) + do_start + case "$?" in + 0) log_end_msg 0 ;; + 1) log_end_msg 1 ;; # Old process is still running + *) log_end_msg 1 ;; # Failed to start + esac + ;; + *) + # Failed to stop + log_end_msg 1 + ;; + esac + ;; + *) + echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 + exit 3 + ;; +esac + +exit 0 diff --git a/tests/pytests/pkg/upgrade/test_salt_upgrade.py b/tests/pytests/pkg/upgrade/test_salt_upgrade.py index 3fba8400ef61..05451490d96d 100644 --- a/tests/pytests/pkg/upgrade/test_salt_upgrade.py +++ b/tests/pytests/pkg/upgrade/test_salt_upgrade.py @@ -1,5 +1,7 @@ import logging +import os import pathlib +import subprocess import sys import time @@ -8,6 +10,7 @@ import pytest from pytestskipmarkers.utils import platform +import salt.utils.path from tests.support.pkg import pep440_public_equal log = logging.getLogger(__name__) @@ -184,7 +187,7 @@ def salt_test_upgrade( new_minion_pids = _get_running_named_salt_pid(process_minion_name) new_master_pids = _get_running_named_salt_pid(process_master_name) - if sys.platform == "linux" and install_salt.distro_id not in ("ubuntu", "debian"): + if sys.platform == "linux": assert new_minion_pids assert new_master_pids if start_version < packaging.version.parse(install_salt.artifact_version): @@ -254,6 +257,50 @@ def _get_installed_salt_packages(): return packages +def test_salt_sysv_service_files(install_salt): + """ + Test that init.d service scripts are present in Debian packages. + + RPM packages ship systemd units only; init.d scripts are not part of the + RPM payload, so this check only applies to .deb packages. + """ + if not install_salt.upgrade: + pytest.skip("Not testing an upgrade, do not run") + + if sys.platform != "linux": + pytest.skip("Not testing on a Linux platform, do not run") + + if not salt.utils.path.which("dpkg"): + pytest.skip("Not testing on a Debian family platform, do not run") + + test_pkgs = install_salt.pkgs + for test_pkg_name in test_pkgs: + test_pkg_basename = os.path.basename(test_pkg_name) + # Debian/Ubuntu name typically salt-minion_300xxxxxx + test_pkg_basename_dash_underscore = test_pkg_basename.split("300")[0] + test_pkg_basename_adj = test_pkg_basename_dash_underscore[:-1] + if test_pkg_basename_adj in ( + "salt-minion", + "salt-master", + "salt-syndic", + "salt-api", + ): + test_initd_name = f"/etc/init.d/{test_pkg_basename_adj}" + proc = subprocess.run( + ["dpkg", "-c", f"{test_pkg_name}"], + capture_output=True, + check=True, + ) + found_line = False + for line in proc.stdout.decode().splitlines(): + # If test_initd_name not present we should fail. + if test_initd_name in line: + found_line = True + break + + assert found_line, f"{test_initd_name} not found in {test_pkg_basename}" + + def test_salt_upgrade( salt_call_cli, install_salt, debian_disable_policy_rcd, salt_master, salt_minion ):