mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-09-23 16:24:04 +00:00
fix(packaging): preserve xcatd init state on Debian (#7615)
* refactor(packaging): share precise systemd state detection * test(packaging): cover precise systemd state detection * test(packaging): allow explicit Debian init mode * fix(packaging): honor explicit Debian init targets * test(packaging): cover Debian init target detection * fix(packaging): add Debian xcatd init state helper * test(packaging): cover Debian xcatd init state helper * test(packaging): allow delegated SysV registration * fix(packaging): preserve Debian xcatd conffile lifecycle * test(packaging): mirror explicit Debian init mode * test(packaging): cover Debian xcatd conffile lifecycle * fix(packaging): contain init state file umask * test(packaging): cover init state permissions * fix(packaging): contain preinstall context umask * test(packaging): cover preinstall umask containment * fix(packaging): detect all systemd enablement links * test(packaging): cover all systemd enablement links * test(packaging): allow shared purge state path * refactor(packaging): reuse Debian init state path * fix(packaging): detect runtime systemd masks * test(packaging): cover runtime systemd masks * test(packaging): model Debian SysV registration * refactor(packaging): reuse shared init state detection * test(packaging): enforce shared Debian state probes * test(packaging): allow explicit unregistered masks * fix(packaging): preserve Debian SysV registration state * test(packaging): cover Debian SysV registration states * fix(packaging): clean failed Debian state writes * test(packaging): cover failed Debian state writes * fix(packaging): retain unregistered systemd provenance * test(packaging): cover unregistered systemd upgrades * fix(packaging): fail closed on shared state errors * test(packaging): cover shared state detector failures * test(packaging): mirror native xcatd runlevels * fix(packaging): recover rejected SysV layouts * test(packaging): cover rejected SysV layouts * test(packaging): cover SysV rebuild retries * refactor(packaging): reuse systemctl readiness guard * test(packaging): enforce shared systemctl guard
This commit is contained in:
@@ -8,7 +8,7 @@ Homepage: https://xcat.org/
|
||||
|
||||
Package: xcat-server
|
||||
Architecture: all
|
||||
Depends: ${perl:Depends}, grub2-xcat (>= 2.02-0.76.el7.1.snap201905160255), perl-xcat (>= 2.13-snap000000000000), xcat-client (>= 2.13-snap000000000000), libsys-syslog-perl, libio-socket-ssl-perl, libxml-simple-perl, make, libdbd-sqlite3-perl, libexpect-perl, libnet-dns-perl, libsoap-lite-perl, libxml-libxml-perl, libsnmp-perl, debootstrap, libdigest-sha-perl,libcrypt-rijndael-perl,libcrypt-cbc-perl,libjson-perl, libnet-https-nb-perl, libhttp-async-perl
|
||||
Depends: ${perl:Depends}, grub2-xcat (>= 2.02-0.76.el7.1.snap201905160255), perl-xcat (>= 2.13-snap000000000000), xcat-client (>= 2.13-snap000000000000), libsys-syslog-perl, libio-socket-ssl-perl, libxml-simple-perl, make, ucf, libdbd-sqlite3-perl, libexpect-perl, libnet-dns-perl, libsoap-lite-perl, libxml-libxml-perl, libsnmp-perl, debootstrap, libdigest-sha-perl,libcrypt-rijndael-perl,libcrypt-cbc-perl,libjson-perl, libnet-https-nb-perl, libhttp-async-perl
|
||||
Description: Server and configuration utilities of xCAT
|
||||
xCAT-server provides the core server and configuration management components
|
||||
of xCAT.
|
||||
|
||||
@@ -29,6 +29,8 @@ lib/xcat/Confluent/* opt/xcat/lib/perl/Confluent/
|
||||
|
||||
lib/xcat/shfunctions opt/xcat/lib
|
||||
etc/init.d/xcatd opt/xcat/share/xcat/scripts
|
||||
debian/xcatd.md5sum opt/xcat/share/xcat/scripts
|
||||
debian/xcatd-init-state opt/xcat/share/xcat/scripts
|
||||
etc/init.d/xcatd.service lib/systemd/system/
|
||||
xCAT-wsapi/* opt/xcat/ws/
|
||||
|
||||
|
||||
+64
-37
@@ -5,17 +5,48 @@
|
||||
|
||||
set -e
|
||||
|
||||
xcat_can_use_systemctl()
|
||||
{
|
||||
[ -d /run/systemd/system ] && command -v systemctl >/dev/null 2>&1
|
||||
}
|
||||
|
||||
xcatd_init_compat=/opt/xcat/share/xcat/scripts/xcatd-init-compat
|
||||
xcatd_init_state=/opt/xcat/share/xcat/scripts/xcatd-init-state
|
||||
xcatd_state_dir=/var/lib/xcat/xcatd-init-state
|
||||
xcatd_context_file=$xcatd_state_dir/context
|
||||
|
||||
if "$xcatd_init_compat" uses-systemd && \
|
||||
command -v dpkg-maintscript-helper >/dev/null 2>&1 && \
|
||||
dpkg-maintscript-helper supports rm_conffile; then
|
||||
dpkg-maintscript-helper rm_conffile /etc/init.d/xcatd -- "$@"
|
||||
if [ -L "$xcatd_state_dir" ] || \
|
||||
{ [ -e "$xcatd_state_dir" ] && [ ! -d "$xcatd_state_dir" ]; }; then
|
||||
echo "Invalid xcatd init state directory: $xcatd_state_dir" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if "$xcatd_init_compat" uses-systemd --explicit-target; then
|
||||
xcatd_uses_systemd=yes
|
||||
else
|
||||
xcatd_uses_systemd=no
|
||||
fi
|
||||
|
||||
if [ -r "$xcatd_context_file" ]; then
|
||||
xcatd_transition_context=$(cat "$xcatd_context_file")
|
||||
case "$xcatd_transition_context" in
|
||||
fresh|upgrade) ;;
|
||||
*)
|
||||
echo "Invalid xcatd package transition context: $xcatd_transition_context" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
elif [ "$1" = configure ] && [ -n "${2:-}" ]; then
|
||||
# Preserve state when invoked for an already configured package even if a
|
||||
# prior packaging tool did not provide the explicit preinst context.
|
||||
xcatd_transition_context=upgrade
|
||||
else
|
||||
xcatd_transition_context=fresh
|
||||
fi
|
||||
|
||||
if [ "$xcatd_uses_systemd" = yes ]; then
|
||||
if [ "$1" = configure ]; then
|
||||
"$xcatd_init_state" prepare-systemd "$xcatd_transition_context"
|
||||
fi
|
||||
if command -v dpkg-maintscript-helper >/dev/null 2>&1 && \
|
||||
dpkg-maintscript-helper supports rm_conffile; then
|
||||
dpkg-maintscript-helper rm_conffile /etc/init.d/xcatd -- "$@"
|
||||
fi
|
||||
fi
|
||||
|
||||
# summary of how this script can be called:
|
||||
@@ -34,47 +65,37 @@ fi
|
||||
case "$1" in
|
||||
configure)
|
||||
. /etc/profile.d/xcat.sh
|
||||
xcat_server_upgrade=0
|
||||
if [ -f /tmp/xCAT-server_upgrade.tmp ]; then
|
||||
xcat_server_upgrade=1
|
||||
fi
|
||||
|
||||
if "$xcatd_init_compat" uses-systemd; then
|
||||
legacy_xcatd_enabled=0
|
||||
if ls /etc/rc?.d/S??xcatd >/dev/null 2>&1; then
|
||||
legacy_xcatd_enabled=1
|
||||
fi
|
||||
if [ "$xcat_server_upgrade" = "1" ] && command -v update-rc.d >/dev/null 2>&1; then
|
||||
if [ "$xcatd_uses_systemd" = yes ]; then
|
||||
if command -v update-rc.d >/dev/null 2>&1; then
|
||||
update-rc.d -f xcatd remove
|
||||
fi
|
||||
|
||||
"$xcatd_init_compat" configure
|
||||
if xcat_can_use_systemctl; then
|
||||
"$xcatd_init_compat" configure --explicit-target
|
||||
if "$xcatd_init_compat" can-use-systemctl; then
|
||||
systemctl daemon-reload
|
||||
fi
|
||||
if command -v systemctl >/dev/null 2>&1 && \
|
||||
{ [ "$xcat_server_upgrade" = "0" ] || [ "$legacy_xcatd_enabled" = "1" ]; }; then
|
||||
# Fresh installs are enabled by default. Upgrades preserve the
|
||||
# legacy enabled state so HA nodes remain disabled.
|
||||
systemctl enable xcatd.service
|
||||
desired_enabled=$("$xcatd_init_state" get enabled)
|
||||
transition_origin=$("$xcatd_init_state" get origin)
|
||||
if command -v systemctl >/dev/null 2>&1; then
|
||||
case "$transition_origin:$desired_enabled" in
|
||||
fresh:yes|legacy:yes) systemctl enable xcatd.service ;;
|
||||
legacy:no|legacy:unregistered) systemctl disable xcatd.service ;;
|
||||
esac
|
||||
fi
|
||||
"$xcatd_init_state" commit-systemd
|
||||
else
|
||||
"$xcatd_init_compat" configure
|
||||
if [ "$xcat_server_upgrade" = "0" ] && \
|
||||
[ -x /etc/init.d/xcatd ] && \
|
||||
command -v update-rc.d >/dev/null 2>&1; then
|
||||
update-rc.d xcatd defaults
|
||||
fi
|
||||
"$xcatd_init_state" configure-legacy "$xcatd_transition_context"
|
||||
fi
|
||||
|
||||
if [ "$xcat_server_upgrade" = "1" ]; then
|
||||
# No need to reload xcatd here as it will be covered by xCAT/xCATsn now.
|
||||
rm -f /tmp/xCAT-server_upgrade.tmp
|
||||
fi
|
||||
ln -sf /opt/xcat/sbin/xcatd /usr/sbin/xcatd
|
||||
;;
|
||||
|
||||
abort-upgrade|abort-remove|abort-deconfigure)
|
||||
abort-upgrade)
|
||||
rm -f "$xcatd_context_file" "$xcatd_context_file.tmp."*
|
||||
;;
|
||||
|
||||
abort-remove|abort-deconfigure)
|
||||
;;
|
||||
|
||||
*)
|
||||
@@ -88,4 +109,10 @@ esac
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
if [ "$1" = configure ]; then
|
||||
# Keep explicit context across every fallible postinst step. A retry after
|
||||
# this point is a completed configuration and may safely drop it.
|
||||
rm -f "$xcatd_context_file" "$xcatd_context_file.tmp."*
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
||||
+114
-30
@@ -5,13 +5,76 @@
|
||||
|
||||
set -e
|
||||
|
||||
xcat_target_uses_systemd()
|
||||
xcatd_state_dir=/var/lib/xcat/xcatd-init-state
|
||||
xcatd_context_file=$xcatd_state_dir/context
|
||||
|
||||
clear_xcatd_pending_state()
|
||||
{
|
||||
if [ -d /run/systemd/system ]; then
|
||||
rm -f "$xcatd_state_dir/pending-xcatd" \
|
||||
"$xcatd_state_dir/pending-deleted" \
|
||||
"$xcatd_state_dir/pending-enabled" \
|
||||
"$xcatd_state_dir/pending-xcatd.tmp."*
|
||||
}
|
||||
|
||||
if [ -L "$xcatd_state_dir" ] || \
|
||||
{ [ -e "$xcatd_state_dir" ] && [ ! -d "$xcatd_state_dir" ]; }; then
|
||||
echo "Invalid xcatd init state directory: $xcatd_state_dir" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
xcat_systemd_os_release_status()
|
||||
{
|
||||
[ -r /etc/os-release ] || return 2
|
||||
|
||||
os_id=
|
||||
os_version=
|
||||
while IFS='=' read -r key value; do
|
||||
value=${value#\"}
|
||||
value=${value%\"}
|
||||
value=${value#\'}
|
||||
value=${value%\'}
|
||||
case "$key" in
|
||||
ID) os_id=$value ;;
|
||||
VERSION_ID) os_version=$value ;;
|
||||
esac
|
||||
done < /etc/os-release
|
||||
|
||||
if [ "$os_id" = "debian" ] && [ -z "$os_version" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ -x /usr/lib/systemd/systemd ] || [ -x /lib/systemd/systemd ]; then
|
||||
os_major=${os_version%%.*}
|
||||
case "$os_major" in
|
||||
''|*[!0-9]*) return 2 ;;
|
||||
esac
|
||||
|
||||
case "$os_id" in
|
||||
rhel|centos|rocky|almalinux|ol|scientific)
|
||||
[ "$os_major" -ge 7 ] && return 0
|
||||
return 1
|
||||
;;
|
||||
fedora|ubuntu)
|
||||
[ "$os_major" -ge 15 ] && return 0
|
||||
return 1
|
||||
;;
|
||||
debian)
|
||||
[ "$os_major" -ge 8 ] && return 0
|
||||
return 1
|
||||
;;
|
||||
sles|sled|opensuse|opensuse-leap|opensuse-tumbleweed)
|
||||
[ "$os_major" -ge 12 ] && return 0
|
||||
return 1
|
||||
;;
|
||||
*)
|
||||
return 2
|
||||
;;
|
||||
esac
|
||||
|
||||
}
|
||||
|
||||
xcat_target_uses_systemd()
|
||||
{
|
||||
if [ -d /run/systemd/system ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
@@ -19,35 +82,25 @@ xcat_target_uses_systemd()
|
||||
init_target=$(readlink /sbin/init 2>/dev/null || true)
|
||||
case "$init_target" in
|
||||
*systemd*) return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if [ -r /etc/os-release ]; then
|
||||
os_id=
|
||||
os_version=
|
||||
while IFS='=' read -r key value; do
|
||||
value=${value#\"}
|
||||
value=${value%\"}
|
||||
value=${value#\'}
|
||||
value=${value%\'}
|
||||
case "$key" in
|
||||
ID) os_id=$value ;;
|
||||
VERSION_ID) os_version=$value ;;
|
||||
esac
|
||||
done < /etc/os-release
|
||||
if [ -e /sbin/init ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$os_id" = "debian" ] && [ -z "$os_version" ]; then
|
||||
return 0
|
||||
if xcat_systemd_os_release_status; then
|
||||
return 0
|
||||
else
|
||||
os_release_status=$?
|
||||
if [ "$os_release_status" -eq 1 ]; then
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
os_major=${os_version%%.*}
|
||||
case "$os_major" in
|
||||
''|*[!0-9]*) return 1 ;;
|
||||
esac
|
||||
case "$os_id" in
|
||||
ubuntu) [ "$os_major" -ge 15 ] && return 0 ;;
|
||||
debian) [ "$os_major" -ge 8 ] && return 0 ;;
|
||||
esac
|
||||
if [ -x /usr/lib/systemd/systemd ] || [ -x /lib/systemd/systemd ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
@@ -75,16 +128,47 @@ fi
|
||||
|
||||
case "$1" in
|
||||
purge)
|
||||
rm -f /etc/init.d/xcatd
|
||||
rm -f /etc/init.d/xcatd \
|
||||
/etc/init.d/xcatd.ucf-old \
|
||||
/etc/init.d/xcatd.ucf-new \
|
||||
/etc/init.d/xcatd.ucf-dist \
|
||||
/etc/init.d/xcatd.dpkg-bak \
|
||||
/etc/init.d/xcatd.dpkg-backup \
|
||||
/etc/init.d/xcatd.dpkg-remove \
|
||||
/var/lib/xcat/xcatd-systemd-mode
|
||||
rm -f "$xcatd_state_dir/state" \
|
||||
"$xcatd_state_dir/xcatd" \
|
||||
"$xcatd_state_dir/state.tmp."* \
|
||||
"$xcatd_state_dir/xcatd.tmp."*
|
||||
clear_xcatd_pending_state
|
||||
rm -f "$xcatd_context_file" "$xcatd_context_file.tmp."*
|
||||
rmdir "$xcatd_state_dir" 2>/dev/null || true
|
||||
if command -v ucf >/dev/null 2>&1; then
|
||||
ucf --purge /etc/init.d/xcatd
|
||||
fi
|
||||
if command -v ucfr >/dev/null 2>&1; then
|
||||
ucfr --purge xcat-server /etc/init.d/xcatd
|
||||
fi
|
||||
;;
|
||||
|
||||
upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
|
||||
abort-install)
|
||||
clear_xcatd_pending_state
|
||||
rm -f "$xcatd_context_file" "$xcatd_context_file.tmp."*
|
||||
rmdir "$xcatd_state_dir" 2>/dev/null || true
|
||||
;;
|
||||
|
||||
abort-upgrade|disappear)
|
||||
rm -f "$xcatd_context_file" "$xcatd_context_file.tmp."*
|
||||
;;
|
||||
|
||||
upgrade|failed-upgrade)
|
||||
;;
|
||||
|
||||
remove)
|
||||
rm -f /usr/sbin/xcatd #remove the symbolic
|
||||
rm -f "$xcatd_context_file" "$xcatd_context_file.tmp."*
|
||||
rm -f /usr/sbin/xcatd #remove the symbolic
|
||||
|
||||
rm -f /etc/apache2/conf-enabled/xcat-ws.conf
|
||||
rm -f /etc/apache2/conf-enabled/xcat-ws.conf
|
||||
;;
|
||||
|
||||
*)
|
||||
|
||||
+228
-28
@@ -5,13 +5,59 @@
|
||||
|
||||
set -e
|
||||
|
||||
xcat_target_uses_systemd()
|
||||
xcat_systemd_os_release_status()
|
||||
{
|
||||
if [ -d /run/systemd/system ]; then
|
||||
[ -r /etc/os-release ] || return 2
|
||||
|
||||
os_id=
|
||||
os_version=
|
||||
while IFS='=' read -r key value; do
|
||||
value=${value#\"}
|
||||
value=${value%\"}
|
||||
value=${value#\'}
|
||||
value=${value%\'}
|
||||
case "$key" in
|
||||
ID) os_id=$value ;;
|
||||
VERSION_ID) os_version=$value ;;
|
||||
esac
|
||||
done < /etc/os-release
|
||||
|
||||
if [ "$os_id" = "debian" ] && [ -z "$os_version" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ -x /usr/lib/systemd/systemd ] || [ -x /lib/systemd/systemd ]; then
|
||||
os_major=${os_version%%.*}
|
||||
case "$os_major" in
|
||||
''|*[!0-9]*) return 2 ;;
|
||||
esac
|
||||
|
||||
case "$os_id" in
|
||||
rhel|centos|rocky|almalinux|ol|scientific)
|
||||
[ "$os_major" -ge 7 ] && return 0
|
||||
return 1
|
||||
;;
|
||||
fedora|ubuntu)
|
||||
[ "$os_major" -ge 15 ] && return 0
|
||||
return 1
|
||||
;;
|
||||
debian)
|
||||
[ "$os_major" -ge 8 ] && return 0
|
||||
return 1
|
||||
;;
|
||||
sles|sled|opensuse|opensuse-leap|opensuse-tumbleweed)
|
||||
[ "$os_major" -ge 12 ] && return 0
|
||||
return 1
|
||||
;;
|
||||
*)
|
||||
return 2
|
||||
;;
|
||||
esac
|
||||
|
||||
}
|
||||
|
||||
xcat_target_uses_systemd()
|
||||
{
|
||||
if [ -d /run/systemd/system ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
@@ -19,41 +65,193 @@ xcat_target_uses_systemd()
|
||||
init_target=$(readlink /sbin/init 2>/dev/null || true)
|
||||
case "$init_target" in
|
||||
*systemd*) return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if [ -r /etc/os-release ]; then
|
||||
os_id=
|
||||
os_version=
|
||||
while IFS='=' read -r key value; do
|
||||
value=${value#\"}
|
||||
value=${value%\"}
|
||||
value=${value#\'}
|
||||
value=${value%\'}
|
||||
case "$key" in
|
||||
ID) os_id=$value ;;
|
||||
VERSION_ID) os_version=$value ;;
|
||||
esac
|
||||
done < /etc/os-release
|
||||
if [ -e /sbin/init ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$os_id" = "debian" ] && [ -z "$os_version" ]; then
|
||||
return 0
|
||||
if xcat_systemd_os_release_status; then
|
||||
return 0
|
||||
else
|
||||
os_release_status=$?
|
||||
if [ "$os_release_status" -eq 1 ]; then
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
os_major=${os_version%%.*}
|
||||
case "$os_major" in
|
||||
''|*[!0-9]*) return 1 ;;
|
||||
esac
|
||||
case "$os_id" in
|
||||
ubuntu) [ "$os_major" -ge 15 ] && return 0 ;;
|
||||
debian) [ "$os_major" -ge 8 ] && return 0 ;;
|
||||
esac
|
||||
if [ -x /usr/lib/systemd/systemd ] || [ -x /lib/systemd/systemd ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
if xcat_target_uses_systemd && \
|
||||
xcatd_init_state=/opt/xcat/share/xcat/scripts/xcatd-init-state
|
||||
xcatd_init_compat=/opt/xcat/share/xcat/scripts/xcatd-init-compat
|
||||
xcatd_legacy_init=/etc/init.d/xcatd
|
||||
xcatd_state_dir=/var/lib/xcat/xcatd-init-state
|
||||
xcatd_old_systemd_marker=/var/lib/xcat/xcatd-systemd-mode
|
||||
xcatd_context_file=$xcatd_state_dir/context
|
||||
|
||||
write_xcatd_context()
|
||||
(
|
||||
context_value=$1
|
||||
context_tmp="$xcatd_context_file.tmp.$$"
|
||||
umask 077
|
||||
if ! printf '%s\n' "$context_value" > "$context_tmp" ||
|
||||
! mv -f "$context_tmp" "$xcatd_context_file"; then
|
||||
rm -f "$context_tmp"
|
||||
return 1
|
||||
fi
|
||||
)
|
||||
|
||||
clear_xcatd_pending_state()
|
||||
{
|
||||
rm -f "$xcatd_state_dir/pending-xcatd" \
|
||||
"$xcatd_state_dir/pending-deleted" \
|
||||
"$xcatd_state_dir/pending-enabled" \
|
||||
"$xcatd_state_dir/pending-xcatd.tmp."*
|
||||
}
|
||||
|
||||
xcatd_legacy_enable_state()
|
||||
{
|
||||
if [ -x "$xcatd_init_compat" ]; then
|
||||
if detected_legacy_state=$(
|
||||
"$xcatd_init_compat" debian-legacy-state 2>/dev/null
|
||||
); then
|
||||
case "$detected_legacy_state" in
|
||||
enabled) printf '%s\n' yes ;;
|
||||
disabled) printf '%s\n' no ;;
|
||||
unregistered) printf '%s\n' unregistered ;;
|
||||
*)
|
||||
echo "Invalid xcatd legacy state: $detected_legacy_state" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
return
|
||||
else
|
||||
detector_status=$?
|
||||
if [ "$detector_status" -ne 2 ]; then
|
||||
echo "Unable to query xcatd Debian legacy state with $xcatd_init_compat" >&2
|
||||
return "$detector_status"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Direct upgrades from a package without the Debian-specific command
|
||||
# still need to capture registration before dpkg removes the conffile.
|
||||
for rc_link in /etc/rc?.d/S??xcatd; do
|
||||
if [ -e "$rc_link" ] || [ -L "$rc_link" ]; then
|
||||
printf '%s\n' yes
|
||||
return
|
||||
fi
|
||||
done
|
||||
for rc_link in /etc/rc?.d/K??xcatd; do
|
||||
if [ -e "$rc_link" ] || [ -L "$rc_link" ]; then
|
||||
printf '%s\n' no
|
||||
return
|
||||
fi
|
||||
done
|
||||
printf '%s\n' unregistered
|
||||
}
|
||||
|
||||
if xcat_target_uses_systemd; then
|
||||
xcatd_uses_systemd=yes
|
||||
else
|
||||
xcatd_uses_systemd=no
|
||||
fi
|
||||
|
||||
xcatd_transition_context=
|
||||
case "$1" in
|
||||
upgrade) xcatd_transition_context=upgrade ;;
|
||||
install) xcatd_transition_context=fresh ;;
|
||||
esac
|
||||
|
||||
if [ -n "$xcatd_transition_context" ] || [ "$1" = abort-upgrade ]; then
|
||||
if [ -L "$xcatd_state_dir" ] || \
|
||||
{ [ -e "$xcatd_state_dir" ] && [ ! -d "$xcatd_state_dir" ]; }; then
|
||||
echo "Invalid xcatd init state directory: $xcatd_state_dir" >&2
|
||||
exit 1
|
||||
fi
|
||||
mkdir -p "$xcatd_state_dir"
|
||||
chmod 700 "$xcatd_state_dir"
|
||||
fi
|
||||
|
||||
if [ -n "$xcatd_transition_context" ] && \
|
||||
[ "$xcatd_uses_systemd" = yes ] && [ -x "$xcatd_init_state" ]; then
|
||||
"$xcatd_init_state" prepare-systemd "$xcatd_transition_context"
|
||||
elif [ -n "$xcatd_transition_context" ] && [ ! -x "$xcatd_init_state" ]; then
|
||||
# Before the first package carrying the state helper is unpacked, save
|
||||
# only the evidence that dpkg-maintscript-helper could remove.
|
||||
recovery_candidate=
|
||||
for candidate in \
|
||||
"$xcatd_legacy_init" \
|
||||
"$xcatd_legacy_init.dpkg-bak" \
|
||||
"$xcatd_legacy_init.dpkg-backup" \
|
||||
"$xcatd_legacy_init.dpkg-remove"; do
|
||||
if [ -e "$candidate" ] || [ -L "$candidate" ]; then
|
||||
recovery_candidate=$candidate
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
known_legacy=no
|
||||
if [ -e "$xcatd_state_dir/state" ] || \
|
||||
[ -L "$xcatd_state_dir/state" ]; then
|
||||
# Durable state from an earlier package is stronger than the
|
||||
# legacy dpkg metadata left behind after removal.
|
||||
clear_xcatd_pending_state
|
||||
elif [ -n "$recovery_candidate" ]; then
|
||||
clear_xcatd_pending_state
|
||||
pending_tmp="$xcatd_state_dir/pending-xcatd.tmp.$$"
|
||||
if ! cp -a "$recovery_candidate" "$pending_tmp" ||
|
||||
! mv -f "$pending_tmp" "$xcatd_state_dir/pending-xcatd"; then
|
||||
rm -f "$pending_tmp"
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$xcatd_old_systemd_marker"
|
||||
known_legacy=yes
|
||||
else
|
||||
conffile_record=
|
||||
if command -v dpkg-query >/dev/null 2>&1; then
|
||||
conffile_record=$(
|
||||
dpkg-query -W -f='${Conffiles}\n' xcat-server 2>/dev/null |
|
||||
sed -n '\|^ /etc/init.d/xcatd |p'
|
||||
)
|
||||
fi
|
||||
if [ -n "$conffile_record" ]; then
|
||||
case "$conffile_record" in
|
||||
*" obsolete"*)
|
||||
# The installed package already removed the conffile.
|
||||
# Record package omission rather than an admin deletion.
|
||||
clear_xcatd_pending_state
|
||||
touch "$xcatd_old_systemd_marker"
|
||||
;;
|
||||
*)
|
||||
# A still-owned conffile that is absent was deleted by
|
||||
# the administrator and must stay absent.
|
||||
clear_xcatd_pending_state
|
||||
rm -f "$xcatd_old_systemd_marker"
|
||||
touch "$xcatd_state_dir/pending-deleted"
|
||||
known_legacy=yes
|
||||
;;
|
||||
esac
|
||||
else
|
||||
# A retry without an installed conffile record must not reuse
|
||||
# evidence captured by an earlier, interrupted installation.
|
||||
clear_xcatd_pending_state
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$known_legacy" = yes ]; then
|
||||
xcatd_legacy_enable_state > "$xcatd_state_dir/pending-enabled"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$xcatd_uses_systemd" = yes ] && \
|
||||
command -v dpkg-maintscript-helper >/dev/null 2>&1 && \
|
||||
dpkg-maintscript-helper supports rm_conffile; then
|
||||
dpkg-maintscript-helper rm_conffile /etc/init.d/xcatd -- "$@"
|
||||
@@ -70,12 +268,14 @@ fi
|
||||
|
||||
case "$1" in
|
||||
upgrade)
|
||||
touch /tmp/xCAT-server_upgrade.tmp
|
||||
write_xcatd_context upgrade
|
||||
;;
|
||||
install)
|
||||
write_xcatd_context fresh
|
||||
;;
|
||||
|
||||
abort-upgrade)
|
||||
rm -f "$xcatd_context_file" "$xcatd_context_file.tmp."*
|
||||
;;
|
||||
|
||||
*)
|
||||
|
||||
@@ -5,11 +5,6 @@
|
||||
|
||||
set -e
|
||||
|
||||
xcat_can_use_systemctl()
|
||||
{
|
||||
[ -d /run/systemd/system ] && command -v systemctl >/dev/null 2>&1
|
||||
}
|
||||
|
||||
xcatd_init_compat=/opt/xcat/share/xcat/scripts/xcatd-init-compat
|
||||
|
||||
# summary of how this script can be called:
|
||||
@@ -27,13 +22,13 @@ xcatd_init_compat=/opt/xcat/share/xcat/scripts/xcatd-init-compat
|
||||
case "$1" in
|
||||
remove)
|
||||
if [ -f "/proc/cmdline" ]; then # prevent running it during install into chroot image
|
||||
if xcat_can_use_systemctl; then
|
||||
if "$xcatd_init_compat" can-use-systemctl; then
|
||||
systemctl stop xcatd.service
|
||||
elif ! "$xcatd_init_compat" uses-systemd && [ -x /etc/init.d/xcatd ]; then
|
||||
elif ! "$xcatd_init_compat" uses-systemd --explicit-target && [ -x /etc/init.d/xcatd ]; then
|
||||
/etc/init.d/xcatd stop
|
||||
fi
|
||||
fi
|
||||
if "$xcatd_init_compat" uses-systemd; then
|
||||
if "$xcatd_init_compat" uses-systemd --explicit-target; then
|
||||
if command -v systemctl >/dev/null 2>&1; then
|
||||
systemctl disable xcatd.service
|
||||
fi
|
||||
|
||||
Executable
+701
@@ -0,0 +1,701 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Preserve the Debian xcatd SysV configuration while the target uses systemd.
|
||||
# The state file is parsed as data; it is never sourced.
|
||||
|
||||
set -e
|
||||
|
||||
compat_root=${XCAT_COMPAT_ROOT:-}
|
||||
compat_root=${compat_root%/}
|
||||
xcat_root=${XCATROOT:-/opt/xcat}
|
||||
|
||||
case "$xcat_root" in
|
||||
/*) ;;
|
||||
*)
|
||||
echo "XCATROOT must be an absolute path" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
|
||||
legacy_init="$compat_root/etc/init.d/xcatd"
|
||||
legacy_template="$compat_root$xcat_root/share/xcat/scripts/xcatd"
|
||||
init_compat="$compat_root$xcat_root/share/xcat/scripts/xcatd-init-compat"
|
||||
state_dir="$compat_root/var/lib/xcat/xcatd-init-state"
|
||||
state_file="$state_dir/state"
|
||||
state_stash="$state_dir/xcatd"
|
||||
pending_stash="$state_dir/pending-xcatd"
|
||||
pending_deleted="$state_dir/pending-deleted"
|
||||
pending_enabled="$state_dir/pending-enabled"
|
||||
old_systemd_marker="$compat_root/var/lib/xcat/xcatd-systemd-mode"
|
||||
|
||||
state_mode=unknown
|
||||
state_content=unknown
|
||||
state_enabled=unknown
|
||||
state_origin=unknown
|
||||
state_format=
|
||||
|
||||
read_state()
|
||||
{
|
||||
[ -r "$state_file" ] || return 1
|
||||
|
||||
state_mode=unknown
|
||||
state_content=unknown
|
||||
state_enabled=unknown
|
||||
state_origin=unknown
|
||||
state_format=
|
||||
seen_format=0
|
||||
seen_mode=0
|
||||
seen_content=0
|
||||
seen_enabled=0
|
||||
seen_origin=0
|
||||
while IFS='=' read -r state_key state_value; do
|
||||
case "$state_key" in
|
||||
format)
|
||||
[ "$seen_format" -eq 0 ] || return 1
|
||||
state_format=$state_value
|
||||
seen_format=1
|
||||
;;
|
||||
mode)
|
||||
[ "$seen_mode" -eq 0 ] || return 1
|
||||
state_mode=$state_value
|
||||
seen_mode=1
|
||||
;;
|
||||
content)
|
||||
[ "$seen_content" -eq 0 ] || return 1
|
||||
state_content=$state_value
|
||||
seen_content=1
|
||||
;;
|
||||
enabled)
|
||||
[ "$seen_enabled" -eq 0 ] || return 1
|
||||
state_enabled=$state_value
|
||||
seen_enabled=1
|
||||
;;
|
||||
origin)
|
||||
[ "$seen_origin" -eq 0 ] || return 1
|
||||
state_origin=$state_value
|
||||
seen_origin=1
|
||||
;;
|
||||
'') ;;
|
||||
*)
|
||||
echo "Invalid xcatd init state key: $state_key" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
done < "$state_file"
|
||||
|
||||
if [ "$seen_format" -ne 1 ] || [ "$seen_mode" -ne 1 ] ||
|
||||
[ "$seen_content" -ne 1 ] || [ "$seen_enabled" -ne 1 ] ||
|
||||
[ "$seen_origin" -ne 1 ]; then
|
||||
echo "Invalid xcatd init state format: ${state_format:-missing}" >&2
|
||||
return 1
|
||||
fi
|
||||
case "$state_format" in
|
||||
1|2) ;;
|
||||
*)
|
||||
echo "Invalid xcatd init state format: ${state_format:-missing}" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
case "$state_mode" in
|
||||
legacy|systemd|transition-systemd|transition-legacy|unknown) ;;
|
||||
*)
|
||||
echo "Invalid xcatd init mode state: $state_mode" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
case "$state_content" in
|
||||
active|stashed|deleted|package-default|unknown) ;;
|
||||
*)
|
||||
echo "Invalid xcatd init content state: $state_content" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
case "$state_enabled" in
|
||||
yes|no|unknown) ;;
|
||||
unregistered)
|
||||
if [ "$state_format" = 2 ]; then
|
||||
:
|
||||
else
|
||||
echo "Invalid xcatd init enablement state: $state_enabled" >&2
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Invalid xcatd init enablement state: $state_enabled" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
case "$state_origin" in
|
||||
fresh|legacy|systemd|unknown) ;;
|
||||
*)
|
||||
echo "Invalid xcatd init transition origin: $state_origin" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Format 1 collapsed registered-disabled and unregistered into "no",
|
||||
# then restored that value by removing every SysV link. Preserve that
|
||||
# behavior when recovering an interrupted pre-format-2 transaction.
|
||||
if [ "$state_format" = 1 ] && [ "$state_enabled" = no ]; then
|
||||
state_enabled=unregistered
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_state_dir()
|
||||
{
|
||||
if [ -L "$state_dir" ] || { [ -e "$state_dir" ] && [ ! -d "$state_dir" ]; }; then
|
||||
echo "Invalid xcatd init state directory: $state_dir" >&2
|
||||
exit 1
|
||||
fi
|
||||
mkdir -p "$state_dir"
|
||||
chmod 700 "$state_dir"
|
||||
}
|
||||
|
||||
write_state()
|
||||
{
|
||||
new_mode=$1
|
||||
new_content=$2
|
||||
new_enabled=$3
|
||||
new_origin=$4
|
||||
|
||||
ensure_state_dir
|
||||
state_tmp="$state_file.tmp.$$"
|
||||
if ! (
|
||||
umask 077
|
||||
printf 'format=2\nmode=%s\ncontent=%s\nenabled=%s\norigin=%s\n' \
|
||||
"$new_mode" "$new_content" "$new_enabled" "$new_origin" > "$state_tmp" &&
|
||||
mv -f "$state_tmp" "$state_file"
|
||||
); then
|
||||
rm -f "$state_tmp"
|
||||
return 1
|
||||
fi
|
||||
state_mode=$new_mode
|
||||
state_content=$new_content
|
||||
state_enabled=$new_enabled
|
||||
state_origin=$new_origin
|
||||
}
|
||||
|
||||
legacy_init_exists()
|
||||
{
|
||||
[ -e "$legacy_init" ] || [ -L "$legacy_init" ]
|
||||
}
|
||||
|
||||
find_recovery_candidate()
|
||||
{
|
||||
recovery_candidate=
|
||||
for candidate in \
|
||||
"$legacy_init" \
|
||||
"$legacy_init.dpkg-bak" \
|
||||
"$legacy_init.dpkg-backup" \
|
||||
"$legacy_init.dpkg-remove"; do
|
||||
if [ -e "$candidate" ] || [ -L "$candidate" ]; then
|
||||
recovery_candidate=$candidate
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
stash_candidate()
|
||||
{
|
||||
stash_source=$1
|
||||
ensure_state_dir
|
||||
stash_tmp="$state_stash.tmp.$$"
|
||||
rm -f "$stash_tmp"
|
||||
if ! cp -a "$stash_source" "$stash_tmp" ||
|
||||
! mv -f "$stash_tmp" "$state_stash"; then
|
||||
rm -f "$stash_tmp"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
shared_init_state()
|
||||
{
|
||||
if [ ! -x "$init_compat" ]; then
|
||||
echo "Missing xcatd init compatibility helper: $init_compat" >&2
|
||||
return 1
|
||||
fi
|
||||
"$init_compat" "$@"
|
||||
}
|
||||
|
||||
legacy_enable_state()
|
||||
{
|
||||
if ! detected_legacy_state=$(shared_init_state debian-legacy-state); then
|
||||
return 1
|
||||
fi
|
||||
case "$detected_legacy_state" in
|
||||
enabled) printf '%s\n' yes ;;
|
||||
disabled) printf '%s\n' no ;;
|
||||
unregistered) printf '%s\n' unregistered ;;
|
||||
*)
|
||||
echo "Invalid legacy state from $init_compat: $detected_legacy_state" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
systemd_enable_state()
|
||||
{
|
||||
if ! detected_systemd_state=$(shared_init_state systemd-state --allow-unknown); then
|
||||
return 1
|
||||
fi
|
||||
case "$detected_systemd_state" in
|
||||
enabled) printf '%s\n' yes ;;
|
||||
disabled) printf '%s\n' no ;;
|
||||
masked) printf '%s\n' unregistered ;;
|
||||
unknown) printf '%s\n' unknown ;;
|
||||
*)
|
||||
echo "Invalid systemd state from $init_compat: $detected_systemd_state" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
validate_context()
|
||||
{
|
||||
case "$1" in
|
||||
fresh|upgrade) ;;
|
||||
*)
|
||||
echo "Invalid xcatd init transition context: $1" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
prepare_systemd()
|
||||
{
|
||||
transition_context=$1
|
||||
validate_context "$transition_context"
|
||||
|
||||
if [ -e "$state_file" ]; then
|
||||
read_state
|
||||
had_state=yes
|
||||
else
|
||||
had_state=no
|
||||
state_mode=unknown
|
||||
state_content=unknown
|
||||
state_enabled=unknown
|
||||
state_origin=unknown
|
||||
if [ -f "$old_systemd_marker" ]; then
|
||||
state_mode=systemd
|
||||
state_content=package-default
|
||||
fi
|
||||
fi
|
||||
|
||||
previous_mode=$state_mode
|
||||
previous_origin=$state_origin
|
||||
known_legacy=no
|
||||
case "$previous_mode" in
|
||||
systemd|transition-systemd|transition-legacy) from_systemd=yes ;;
|
||||
*) from_systemd=no ;;
|
||||
esac
|
||||
case "$previous_mode" in
|
||||
transition-systemd|transition-legacy) transition_origin=$previous_origin ;;
|
||||
systemd) transition_origin=systemd ;;
|
||||
legacy) transition_origin=legacy ;;
|
||||
*)
|
||||
if [ "$transition_context" = fresh ]; then
|
||||
transition_origin=fresh
|
||||
else
|
||||
transition_origin=systemd
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
detected_systemd_enabled=$(systemd_enable_state)
|
||||
|
||||
if [ "$had_state" = no ] && \
|
||||
{ [ -e "$pending_stash" ] || [ -L "$pending_stash" ]; }; then
|
||||
stash_candidate "$pending_stash"
|
||||
state_content=stashed
|
||||
known_legacy=yes
|
||||
transition_origin=legacy
|
||||
elif [ "$had_state" = no ] && [ -f "$pending_deleted" ]; then
|
||||
rm -f "$state_stash"
|
||||
state_content=deleted
|
||||
known_legacy=yes
|
||||
transition_origin=legacy
|
||||
elif [ "$previous_mode" = transition-legacy ]; then
|
||||
case "$state_content" in
|
||||
stashed)
|
||||
if [ ! -e "$state_stash" ] && [ ! -L "$state_stash" ]; then
|
||||
echo "Stashed xcatd init script is missing: $state_stash" >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
active)
|
||||
if legacy_init_exists; then
|
||||
stash_candidate "$legacy_init"
|
||||
state_content=stashed
|
||||
else
|
||||
echo "Active xcatd init transition has no recoverable script" >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
elif legacy_init_exists; then
|
||||
stash_candidate "$legacy_init"
|
||||
state_content=stashed
|
||||
if [ "$from_systemd" = no ]; then
|
||||
known_legacy=yes
|
||||
transition_origin=legacy
|
||||
fi
|
||||
elif [ "$from_systemd" = no ] && find_recovery_candidate; then
|
||||
stash_candidate "$recovery_candidate"
|
||||
state_content=stashed
|
||||
known_legacy=yes
|
||||
transition_origin=legacy
|
||||
elif [ "$previous_mode" = legacy ]; then
|
||||
rm -f "$state_stash"
|
||||
state_content=deleted
|
||||
known_legacy=yes
|
||||
transition_origin=legacy
|
||||
elif [ "$from_systemd" = no ] && [ "$transition_context" = fresh ]; then
|
||||
rm -f "$state_stash"
|
||||
state_content=package-default
|
||||
transition_origin=fresh
|
||||
elif [ "$from_systemd" = no ]; then
|
||||
rm -f "$state_stash"
|
||||
if [ "$detected_systemd_enabled" = yes ]; then
|
||||
state_content=package-default
|
||||
else
|
||||
state_content=unknown
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$detected_systemd_enabled" = unregistered ]; then
|
||||
state_enabled=unregistered
|
||||
transition_origin=systemd
|
||||
elif [ "$transition_context" = fresh ]; then
|
||||
state_enabled=yes
|
||||
transition_origin=fresh
|
||||
elif [ "$known_legacy" = yes ]; then
|
||||
if [ -r "$pending_enabled" ]; then
|
||||
pending_enabled_value=$(sed -n '1p' "$pending_enabled")
|
||||
else
|
||||
pending_enabled_value=unknown
|
||||
fi
|
||||
case "$pending_enabled_value" in
|
||||
yes|no|unregistered) legacy_enabled=$pending_enabled_value ;;
|
||||
*) legacy_enabled=$(legacy_enable_state) ;;
|
||||
esac
|
||||
|
||||
if [ "$legacy_enabled" = yes ]; then
|
||||
state_enabled=yes
|
||||
elif [ "$had_state" = no ]; then
|
||||
if [ "$detected_systemd_enabled" = yes ]; then
|
||||
state_enabled=yes
|
||||
else
|
||||
state_enabled=$legacy_enabled
|
||||
fi
|
||||
else
|
||||
state_enabled=$legacy_enabled
|
||||
fi
|
||||
elif { [ "$previous_mode" = transition-systemd ] ||
|
||||
[ "$previous_mode" = transition-legacy ]; } && \
|
||||
[ "$state_enabled" != unknown ]; then
|
||||
:
|
||||
else
|
||||
case "$detected_systemd_enabled" in
|
||||
yes) state_enabled=yes ;;
|
||||
no)
|
||||
if [ "$state_enabled" != unregistered ]; then
|
||||
state_enabled=no
|
||||
fi
|
||||
;;
|
||||
unregistered) state_enabled=unregistered ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
write_state transition-systemd "$state_content" "$state_enabled" "$transition_origin"
|
||||
rm -f "$pending_stash" "$pending_deleted" "$pending_enabled"
|
||||
}
|
||||
|
||||
commit_systemd()
|
||||
{
|
||||
read_state
|
||||
write_state systemd "$state_content" "$state_enabled" unknown
|
||||
rm -f "$old_systemd_marker"
|
||||
}
|
||||
|
||||
apply_legacy_registration()
|
||||
{
|
||||
command -v update-rc.d >/dev/null 2>&1 || return 0
|
||||
|
||||
case "$state_content" in
|
||||
deleted|unknown)
|
||||
update-rc.d -f xcatd remove
|
||||
return
|
||||
;;
|
||||
esac
|
||||
if [ -x "$legacy_init" ]; then
|
||||
case "$state_enabled" in
|
||||
yes)
|
||||
update-rc.d xcatd defaults
|
||||
;;
|
||||
no)
|
||||
update-rc.d xcatd defaults
|
||||
if ! update-rc.d xcatd disable; then
|
||||
# defaults preserves any existing registration, including
|
||||
# links outside xcatd's declared start runlevels that the
|
||||
# native disable operation cannot toggle. Canonicalize
|
||||
# only after that unusable layout is rejected.
|
||||
update-rc.d -f xcatd remove
|
||||
update-rc.d xcatd defaults
|
||||
update-rc.d xcatd disable
|
||||
fi
|
||||
;;
|
||||
unregistered|unknown)
|
||||
update-rc.d -f xcatd remove
|
||||
;;
|
||||
esac
|
||||
else
|
||||
update-rc.d -f xcatd remove
|
||||
fi
|
||||
}
|
||||
|
||||
configure_legacy()
|
||||
{
|
||||
transition_context=$1
|
||||
validate_context "$transition_context"
|
||||
|
||||
returning_from_systemd=no
|
||||
refresh_systemd_enabled=no
|
||||
resuming_legacy_transition=no
|
||||
resuming_stashed_transition=no
|
||||
stable_legacy_upgrade=no
|
||||
detected_systemd_enabled=unknown
|
||||
transition_origin=legacy
|
||||
if [ -e "$state_file" ]; then
|
||||
read_state
|
||||
had_state=yes
|
||||
if [ "$state_mode" = legacy ] && \
|
||||
[ "$transition_context" = upgrade ]; then
|
||||
stable_legacy_upgrade=yes
|
||||
else
|
||||
detected_systemd_enabled=$(systemd_enable_state)
|
||||
fi
|
||||
if [ "$state_mode" = transition-legacy ]; then
|
||||
resuming_legacy_transition=yes
|
||||
if [ "$state_content" = stashed ] &&
|
||||
{ [ -e "$state_stash" ] || [ -L "$state_stash" ]; }; then
|
||||
resuming_stashed_transition=yes
|
||||
fi
|
||||
fi
|
||||
case "$state_mode" in
|
||||
systemd)
|
||||
returning_from_systemd=yes
|
||||
refresh_systemd_enabled=yes
|
||||
transition_origin=systemd
|
||||
;;
|
||||
transition-systemd)
|
||||
returning_from_systemd=yes
|
||||
transition_origin=$state_origin
|
||||
;;
|
||||
transition-legacy)
|
||||
transition_origin=$state_origin
|
||||
returning_from_systemd=yes
|
||||
;;
|
||||
legacy)
|
||||
transition_origin=legacy
|
||||
if legacy_init_exists; then
|
||||
state_content=active
|
||||
else
|
||||
state_content=deleted
|
||||
fi
|
||||
if [ "$transition_context" = upgrade ]; then
|
||||
state_enabled=$(legacy_enable_state)
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
else
|
||||
had_state=no
|
||||
detected_systemd_enabled=$(systemd_enable_state)
|
||||
state_mode=unknown
|
||||
state_content=unknown
|
||||
state_enabled=unknown
|
||||
state_origin=unknown
|
||||
if [ -e "$pending_stash" ] || [ -L "$pending_stash" ]; then
|
||||
stash_candidate "$pending_stash"
|
||||
state_content=stashed
|
||||
transition_origin=legacy
|
||||
elif [ -f "$pending_deleted" ]; then
|
||||
rm -f "$state_stash"
|
||||
state_content=deleted
|
||||
transition_origin=legacy
|
||||
elif [ -f "$old_systemd_marker" ]; then
|
||||
returning_from_systemd=yes
|
||||
refresh_systemd_enabled=yes
|
||||
transition_origin=systemd
|
||||
state_content=package-default
|
||||
elif find_recovery_candidate; then
|
||||
if [ "$recovery_candidate" = "$legacy_init" ]; then
|
||||
state_content=active
|
||||
transition_origin=legacy
|
||||
else
|
||||
stash_candidate "$recovery_candidate"
|
||||
state_content=stashed
|
||||
returning_from_systemd=yes
|
||||
refresh_systemd_enabled=yes
|
||||
transition_origin=systemd
|
||||
fi
|
||||
elif [ "$transition_context" = fresh ]; then
|
||||
state_content=package-default
|
||||
state_enabled=yes
|
||||
transition_origin=fresh
|
||||
else
|
||||
returning_from_systemd=yes
|
||||
refresh_systemd_enabled=yes
|
||||
transition_origin=systemd
|
||||
state_enabled=$detected_systemd_enabled
|
||||
if [ "$detected_systemd_enabled" = yes ]; then
|
||||
state_content=package-default
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if legacy_init_exists && [ "$resuming_legacy_transition" = no ]; then
|
||||
case "$returning_from_systemd:$state_content" in
|
||||
yes:*|*:active)
|
||||
stash_candidate "$legacy_init"
|
||||
state_content=stashed
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if [ "$stable_legacy_upgrade" = yes ]; then
|
||||
:
|
||||
elif [ "$detected_systemd_enabled" = unregistered ]; then
|
||||
state_enabled=unregistered
|
||||
transition_origin=systemd
|
||||
elif [ "$transition_context" = fresh ]; then
|
||||
state_enabled=yes
|
||||
transition_origin=fresh
|
||||
elif [ "$had_state" = no ]; then
|
||||
if [ -r "$pending_enabled" ]; then
|
||||
pending_enabled_value=$(sed -n '1p' "$pending_enabled")
|
||||
else
|
||||
pending_enabled_value=unknown
|
||||
fi
|
||||
case "$pending_enabled_value" in
|
||||
yes|no|unregistered) legacy_enabled=$pending_enabled_value ;;
|
||||
*) legacy_enabled=$(legacy_enable_state) ;;
|
||||
esac
|
||||
if [ "$legacy_enabled" = yes ] || \
|
||||
[ "$detected_systemd_enabled" = yes ]; then
|
||||
state_enabled=yes
|
||||
elif [ "$transition_origin" = legacy ] && \
|
||||
{ [ "$legacy_enabled" = no ] || \
|
||||
[ "$legacy_enabled" = unregistered ]; }; then
|
||||
state_enabled=$legacy_enabled
|
||||
elif [ "$detected_systemd_enabled" = no ]; then
|
||||
state_enabled=no
|
||||
elif [ "$detected_systemd_enabled" = unregistered ]; then
|
||||
state_enabled=unregistered
|
||||
else
|
||||
state_enabled=$legacy_enabled
|
||||
fi
|
||||
elif [ "$refresh_systemd_enabled" = yes ]; then
|
||||
case "$detected_systemd_enabled" in
|
||||
yes) state_enabled=yes ;;
|
||||
no)
|
||||
if [ "$state_enabled" != unregistered ]; then
|
||||
state_enabled=no
|
||||
fi
|
||||
;;
|
||||
unregistered) state_enabled=unregistered ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
write_state transition-legacy "$state_content" "$state_enabled" "$transition_origin"
|
||||
|
||||
case "$state_content" in
|
||||
stashed)
|
||||
if [ ! -e "$state_stash" ] && [ ! -L "$state_stash" ]; then
|
||||
echo "Stashed xcatd init script is missing: $state_stash" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ "$resuming_stashed_transition" = yes ]; then
|
||||
rm -f "$legacy_init"
|
||||
mkdir -p "$compat_root/etc/init.d"
|
||||
cp -a "$state_stash" "$legacy_init"
|
||||
elif ! legacy_init_exists; then
|
||||
mkdir -p "$compat_root/etc/init.d"
|
||||
cp -a "$state_stash" "$legacy_init"
|
||||
fi
|
||||
ucf "$legacy_template" "$legacy_init"
|
||||
;;
|
||||
active)
|
||||
if legacy_init_exists; then
|
||||
ucf "$legacy_template" "$legacy_init"
|
||||
fi
|
||||
;;
|
||||
package-default)
|
||||
mkdir -p "$compat_root/etc/init.d"
|
||||
if [ "$resuming_legacy_transition" = yes ]; then
|
||||
rm -f "$legacy_init"
|
||||
fi
|
||||
UCF_FORCE_CONFFMISS=1 ucf "$legacy_template" "$legacy_init"
|
||||
;;
|
||||
deleted)
|
||||
rm -f "$legacy_init"
|
||||
;;
|
||||
unknown)
|
||||
echo "xcat-server: prior xcatd init state is ambiguous; preserving its absence" >&2
|
||||
;;
|
||||
esac
|
||||
|
||||
ucfr xcat-server "$legacy_init"
|
||||
|
||||
if [ "$transition_context" = fresh ] || \
|
||||
[ "$returning_from_systemd" = yes ] || [ "$had_state" = no ]; then
|
||||
apply_legacy_registration
|
||||
fi
|
||||
|
||||
if legacy_init_exists; then
|
||||
final_content=active
|
||||
else
|
||||
final_content=deleted
|
||||
fi
|
||||
final_enabled=$(legacy_enable_state)
|
||||
write_state legacy "$final_content" "$final_enabled" unknown
|
||||
rm -f "$state_stash" "$old_systemd_marker" \
|
||||
"$pending_stash" "$pending_deleted" "$pending_enabled" \
|
||||
"$legacy_init.dpkg-bak" "$legacy_init.dpkg-backup" \
|
||||
"$legacy_init.dpkg-remove"
|
||||
}
|
||||
|
||||
get_state()
|
||||
{
|
||||
requested_field=$1
|
||||
read_state
|
||||
case "$requested_field" in
|
||||
mode) printf '%s\n' "$state_mode" ;;
|
||||
content) printf '%s\n' "$state_content" ;;
|
||||
enabled) printf '%s\n' "$state_enabled" ;;
|
||||
origin) printf '%s\n' "$state_origin" ;;
|
||||
*)
|
||||
echo "Usage: $0 get {mode|content|enabled|origin}" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
case "${1:-}" in
|
||||
prepare-systemd)
|
||||
prepare_systemd "${2:-}"
|
||||
;;
|
||||
commit-systemd)
|
||||
[ "$#" -eq 1 ] || exit 2
|
||||
commit_systemd
|
||||
;;
|
||||
configure-legacy)
|
||||
configure_legacy "${2:-}"
|
||||
;;
|
||||
get)
|
||||
get_state "${2:-}"
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {prepare-systemd {fresh|upgrade}|commit-systemd|configure-legacy {fresh|upgrade}|get {mode|content|enabled|origin}}" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,9 @@
|
||||
be74fa94c7cae192b0522b094ab13f88 2.7.8
|
||||
106298b7314976e37b61359ac0639f47 2.8.3
|
||||
22b3d638134b58d249337c7193466f91 2.8.4
|
||||
ec7700a6317954bd773bb07bc3d352f4 2.9.2_release
|
||||
7f7b7bf464770c6ed6c6433c340de757 2.12
|
||||
78730e365b6861c45fedb51f8359bb37 2.12.1
|
||||
d0f83472c8ad6d9a5aa9a64e50bb5dc5 2.12.2
|
||||
0b1eea60994ff79faa9a8d0bcd53c558 2.17.0
|
||||
8797eef6731719e0eacff59612b3e916 2.18.0
|
||||
@@ -130,22 +130,32 @@ can_use_systemctl()
|
||||
|
||||
legacy_state()
|
||||
{
|
||||
for legacy_link in \
|
||||
"$compat_root"/etc/rc.d/rc?.d/S??xcatd \
|
||||
"$compat_root"/etc/rc?.d/S??xcatd \
|
||||
"$compat_root"/etc/init.d/rc?.d/S??xcatd
|
||||
do
|
||||
detection_mode=${1:-compat}
|
||||
|
||||
if [ "$detection_mode" = debian-layout ]; then
|
||||
set -- "$compat_root"/etc/rc?.d/S??xcatd
|
||||
else
|
||||
set -- \
|
||||
"$compat_root"/etc/rc.d/rc?.d/S??xcatd \
|
||||
"$compat_root"/etc/rc?.d/S??xcatd \
|
||||
"$compat_root"/etc/init.d/rc?.d/S??xcatd
|
||||
fi
|
||||
for legacy_link in "$@"; do
|
||||
if [ -e "$legacy_link" ] || [ -L "$legacy_link" ]; then
|
||||
echo enabled
|
||||
return
|
||||
fi
|
||||
done
|
||||
|
||||
for legacy_link in \
|
||||
"$compat_root"/etc/rc.d/rc?.d/K??xcatd \
|
||||
"$compat_root"/etc/rc?.d/K??xcatd \
|
||||
"$compat_root"/etc/init.d/rc?.d/K??xcatd
|
||||
do
|
||||
if [ "$detection_mode" = debian-layout ]; then
|
||||
set -- "$compat_root"/etc/rc?.d/K??xcatd
|
||||
else
|
||||
set -- \
|
||||
"$compat_root"/etc/rc.d/rc?.d/K??xcatd \
|
||||
"$compat_root"/etc/rc?.d/K??xcatd \
|
||||
"$compat_root"/etc/init.d/rc?.d/K??xcatd
|
||||
fi
|
||||
for legacy_link in "$@"; do
|
||||
if [ -e "$legacy_link" ] || [ -L "$legacy_link" ]; then
|
||||
echo disabled
|
||||
return
|
||||
@@ -184,7 +194,7 @@ legacy_transition_state()
|
||||
esac
|
||||
}
|
||||
|
||||
systemd_state()
|
||||
systemd_is_masked()
|
||||
{
|
||||
for systemd_mask in \
|
||||
"$compat_root/etc/systemd/system/xcatd.service" \
|
||||
@@ -194,27 +204,17 @@ systemd_state()
|
||||
systemd_mask_target=$(readlink "$systemd_mask" 2>/dev/null || true)
|
||||
case "$systemd_mask_target" in
|
||||
/dev/null|*/dev/null)
|
||||
echo masked
|
||||
return
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -z "$compat_root" ] && command -v systemctl >/dev/null 2>&1; then
|
||||
detected_systemd_state=$(systemctl is-enabled xcatd.service 2>/dev/null || true)
|
||||
case "$detected_systemd_state" in
|
||||
enabled*)
|
||||
echo enabled
|
||||
return
|
||||
;;
|
||||
masked*)
|
||||
echo masked
|
||||
return
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
systemd_links_enabled()
|
||||
{
|
||||
for systemd_link in \
|
||||
"$compat_root"/etc/systemd/system/*.wants/xcatd.service \
|
||||
"$compat_root"/etc/systemd/system/*.requires/xcatd.service \
|
||||
@@ -222,11 +222,90 @@ systemd_state()
|
||||
"$compat_root"/run/systemd/system/*.requires/xcatd.service
|
||||
do
|
||||
if [ -e "$systemd_link" ] || [ -L "$systemd_link" ]; then
|
||||
echo enabled
|
||||
return
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
systemctl_enable_state()
|
||||
{
|
||||
detection_mode=${1:-compat}
|
||||
|
||||
command -v systemctl >/dev/null 2>&1 || return 1
|
||||
|
||||
if [ -n "$compat_root" ]; then
|
||||
detected_systemd_state=$(systemctl --root="$compat_root" is-enabled xcatd.service 2>/dev/null || true)
|
||||
else
|
||||
detected_systemd_state=$(systemctl is-enabled xcatd.service 2>/dev/null || true)
|
||||
fi
|
||||
if [ "$detection_mode" = precise ]; then
|
||||
case "$detected_systemd_state" in
|
||||
enabled|enabled-runtime) echo enabled ;;
|
||||
masked|masked-runtime) echo masked ;;
|
||||
disabled|linked|linked-runtime|alias|static|indirect|generated|transient)
|
||||
echo disabled
|
||||
;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
else
|
||||
case "$detected_systemd_state" in
|
||||
enabled*) echo enabled ;;
|
||||
masked*) echo masked ;;
|
||||
disabled|linked|linked-runtime|alias|static|indirect|generated|transient)
|
||||
echo disabled
|
||||
;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
|
||||
systemd_state()
|
||||
{
|
||||
detection_mode=${1:-compat}
|
||||
detected_systemd_state=
|
||||
|
||||
if systemd_is_masked; then
|
||||
echo masked
|
||||
return
|
||||
fi
|
||||
|
||||
if [ "$detection_mode" = allow-unknown ]; then
|
||||
detected_systemd_state=$(systemctl_enable_state precise || true)
|
||||
if [ "$detected_systemd_state" = masked ]; then
|
||||
echo masked
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
# Preserve the historical host-first order for existing callers.
|
||||
if [ "$detection_mode" = compat ] && [ -z "$compat_root" ]; then
|
||||
detected_systemd_state=$(systemctl_enable_state || true)
|
||||
case "$detected_systemd_state" in
|
||||
enabled|masked)
|
||||
echo "$detected_systemd_state"
|
||||
return
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if systemd_links_enabled; then
|
||||
echo enabled
|
||||
return
|
||||
fi
|
||||
|
||||
if [ "$detection_mode" = allow-unknown ]; then
|
||||
case "$detected_systemd_state" in
|
||||
enabled|disabled)
|
||||
echo "$detected_systemd_state"
|
||||
return
|
||||
;;
|
||||
esac
|
||||
echo unknown
|
||||
return
|
||||
fi
|
||||
|
||||
echo disabled
|
||||
}
|
||||
|
||||
@@ -412,11 +491,22 @@ case "${1:-}" in
|
||||
legacy-state)
|
||||
legacy_state
|
||||
;;
|
||||
debian-legacy-state)
|
||||
if [ "$#" -ne 1 ]; then
|
||||
echo "Usage: $0 debian-legacy-state" >&2
|
||||
exit 2
|
||||
fi
|
||||
legacy_state debian-layout
|
||||
;;
|
||||
legacy-transition-state)
|
||||
legacy_transition_state
|
||||
;;
|
||||
systemd-state)
|
||||
systemd_state
|
||||
if [ "$#" -eq 2 ] && [ "${2:-}" = --allow-unknown ]; then
|
||||
systemd_state allow-unknown
|
||||
else
|
||||
systemd_state
|
||||
fi
|
||||
;;
|
||||
register-legacy)
|
||||
case "${2:-}" in
|
||||
@@ -455,7 +545,7 @@ case "${1:-}" in
|
||||
remove_managed_legacy_init
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {uses-systemd [--explicit-target]|can-use-systemctl|legacy-state|legacy-transition-state|systemd-state|register-legacy {default|enabled|disabled}|unregister-legacy|disable-systemd [--links-only]|unregister-all|configure [--replace] [--explicit-target] [--track-managed]|remove|remove-managed}" >&2
|
||||
echo "Usage: $0 {uses-systemd [--explicit-target]|can-use-systemctl|legacy-state|debian-legacy-state|legacy-transition-state|systemd-state [--allow-unknown]|register-legacy {default|enabled|disabled}|unregister-legacy|disable-systemd [--links-only]|unregister-all|configure [--replace] [--explicit-target] [--track-managed]|remove|remove-managed}" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env perl
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Digest::MD5 qw(md5_hex);
|
||||
use File::Spec;
|
||||
use FindBin;
|
||||
use Test::More;
|
||||
|
||||
my $repo_root = File::Spec->catdir( $FindBin::Bin, '..', '..' );
|
||||
|
||||
sub read_file {
|
||||
my ($path) = @_;
|
||||
open( my $fh, '<', $path ) or die "Unable to read $path: $!";
|
||||
binmode($fh);
|
||||
my $contents = do { local $/; <$fh> };
|
||||
close($fh);
|
||||
return $contents;
|
||||
}
|
||||
|
||||
my $deb_install = read_file(
|
||||
File::Spec->catfile( $repo_root, 'xCAT-server', 'debian', 'install' )
|
||||
);
|
||||
my $dpkg_managed =
|
||||
$deb_install =~ qr{^etc/init\.d/xcatd etc/init\.d$}m;
|
||||
my $ucf_managed =
|
||||
$deb_install =~ qr{^etc/init\.d/xcatd opt/xcat/share/xcat/scripts$}m;
|
||||
|
||||
ok( $dpkg_managed || $ucf_managed,
|
||||
'Debian selects a configuration-aware legacy init backend' );
|
||||
|
||||
if ($dpkg_managed) {
|
||||
pass('dpkg owns the directly packaged legacy init conffile');
|
||||
done_testing();
|
||||
exit;
|
||||
}
|
||||
|
||||
my $deb_control = read_file(
|
||||
File::Spec->catfile( $repo_root, 'xCAT-server', 'debian', 'control' )
|
||||
);
|
||||
like( $deb_control, qr{^Depends:.*(?:,\s+|^)ucf(?:,|$)}m,
|
||||
'the generated-conffile backend depends on ucf' );
|
||||
like( $deb_install,
|
||||
qr{^debian/xcatd\.md5sum opt/xcat/share/xcat/scripts$}m,
|
||||
'historical template checksums are installed beside the template' );
|
||||
|
||||
my $sum_path = File::Spec->catfile(
|
||||
$repo_root, 'xCAT-server', 'debian', 'xcatd.md5sum'
|
||||
);
|
||||
ok( -f $sum_path, 'the Debian package carries historical template checksums' );
|
||||
my $sums = -f $sum_path ? read_file($sum_path) : '';
|
||||
like( $sums, qr{^0b1eea60994ff79faa9a8d0bcd53c558\s+2\.17\.0$}m,
|
||||
'the last pre-transition release is recognized as unmodified' );
|
||||
|
||||
my $template = read_file(
|
||||
File::Spec->catfile(
|
||||
$repo_root, 'xCAT-server', 'etc', 'init.d', 'xcatd'
|
||||
)
|
||||
);
|
||||
like( $sums, qr{^\Q@{[ md5_hex($template) ]}\E\s+2\.18\.0$}m,
|
||||
'the current released template is recognized as unmodified' );
|
||||
|
||||
my $postinst = read_file(
|
||||
File::Spec->catfile( $repo_root, 'xCAT-server', 'debian', 'postinst' )
|
||||
);
|
||||
like( $postinst,
|
||||
qr{"\$xcatd_init_state" configure-legacy "\$xcatd_transition_context"},
|
||||
'postinst delegates legacy conffile transitions to the state helper' );
|
||||
|
||||
my $state_helper = read_file(
|
||||
File::Spec->catfile( $repo_root, 'xCAT-server', 'debian', 'xcatd-init-state' )
|
||||
);
|
||||
like( $state_helper, qr{ucf "\$legacy_template" "\$legacy_init"},
|
||||
'legacy configuration delegates updates to ucf' );
|
||||
like( $state_helper, qr{ucfr xcat-server "\$legacy_init"},
|
||||
'legacy configuration registers ucf ownership' );
|
||||
like( $state_helper, qr{state_content=stashed.*?stash_candidate}s,
|
||||
'a present legacy script is represented by an exact stash' );
|
||||
like( $state_helper, qr{state_content=deleted},
|
||||
'administrator deletion has a distinct persistent state' );
|
||||
like( $state_helper,
|
||||
qr{package-default\).*?UCF_FORCE_CONFFMISS=1 ucf}s,
|
||||
'only known package omission forces recreation of a missing script' );
|
||||
like( $state_helper,
|
||||
qr{state_content=unknown.*?preserving its absence}s,
|
||||
'ambiguous markerless upgrades preserve absence instead of guessing' );
|
||||
|
||||
my $postrm = read_file(
|
||||
File::Spec->catfile( $repo_root, 'xCAT-server', 'debian', 'postrm' )
|
||||
);
|
||||
like( $postrm,
|
||||
qr{xcatd\.ucf-old.*?xcatd\.ucf-new.*?xcatd\.ucf-dist}s,
|
||||
'purge removes ucf backup artifacts' );
|
||||
like( $postrm, qr{ucf --purge /etc/init\.d/xcatd},
|
||||
'purge removes ucf checksum state' );
|
||||
like( $postrm, qr{ucfr --purge xcat-server /etc/init\.d/xcatd},
|
||||
'purge removes the ucf ownership registration' );
|
||||
like( $postrm,
|
||||
qr{xcatd_state_dir=/var/lib/xcat/xcatd-init-state.*?(?:/var/lib/xcat/xcatd-init-state/state|"\$xcatd_state_dir/state")}s,
|
||||
'purge removes the persistent init transition state' );
|
||||
|
||||
done_testing();
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,9 @@
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use File::Path qw(make_path);
|
||||
use File::Spec;
|
||||
use File::Temp qw(tempdir);
|
||||
use FindBin;
|
||||
use Test::More;
|
||||
|
||||
@@ -16,6 +18,69 @@ sub read_file {
|
||||
return $contents;
|
||||
}
|
||||
|
||||
sub init_classifier_block {
|
||||
my ($script) = @_;
|
||||
return $1
|
||||
if $script =~
|
||||
/(xcat_systemd_os_release_status\(\).*?\n}\n\nxcat_target_uses_systemd\(\).*?\n})\n\n/s;
|
||||
return '';
|
||||
}
|
||||
|
||||
sub pending_cleanup_block {
|
||||
my ($script) = @_;
|
||||
return $1
|
||||
if $script =~ /(clear_xcatd_pending_state\(\)\n\{.*?\n\})\n/s;
|
||||
return '';
|
||||
}
|
||||
|
||||
sub legacy_state_block {
|
||||
my ($script) = @_;
|
||||
return $1
|
||||
if $script =~
|
||||
/(xcatd_legacy_enable_state\(\)\n\{.*?\n\})\n\nif xcat_target_uses_systemd/s;
|
||||
return '';
|
||||
}
|
||||
|
||||
sub run_legacy_state_block {
|
||||
my ( $block, $helper_source ) = @_;
|
||||
my $root = tempdir( CLEANUP => 1 );
|
||||
my $helper = File::Spec->catfile( $root, 'xcatd-init-compat' );
|
||||
open( my $helper_fh, '>', $helper )
|
||||
or die "Unable to stage compatibility helper: $!";
|
||||
print {$helper_fh} $helper_source;
|
||||
close($helper_fh);
|
||||
chmod 0755, $helper;
|
||||
|
||||
my $rpm_runlevel =
|
||||
File::Spec->catdir( $root, 'etc', 'rc.d', 'rc3.d' );
|
||||
make_path($rpm_runlevel);
|
||||
symlink( '/etc/init.d/xcatd',
|
||||
File::Spec->catfile( $rpm_runlevel, 'S85xcatd' ) )
|
||||
or die "Unable to stage RPM-only runlevel link: $!";
|
||||
|
||||
my $isolated_block = $block;
|
||||
$isolated_block =~ s{/etc/rc}{\$fixture_root/etc/rc}g;
|
||||
my $runner = File::Spec->catfile( $root, 'run-detector' );
|
||||
open( my $runner_fh, '>', $runner )
|
||||
or die "Unable to stage detector runner: $!";
|
||||
print {$runner_fh} "#!/bin/sh\nset -e\n";
|
||||
print {$runner_fh} "fixture_root=\${XCAT_TEST_ROOT:?}\n";
|
||||
print {$runner_fh} "xcatd_init_compat=\${XCAT_TEST_HELPER:?}\n";
|
||||
print {$runner_fh} "$isolated_block\n\nxcatd_legacy_enable_state\n";
|
||||
close($runner_fh);
|
||||
chmod 0755, $runner;
|
||||
|
||||
local $ENV{XCAT_TEST_ROOT} = $root;
|
||||
local $ENV{XCAT_TEST_HELPER} = $helper;
|
||||
open( my $pipe, '-|', '/bin/sh', $runner )
|
||||
or die "Unable to run preinst detector: $!";
|
||||
my $output = do { local $/; <$pipe> };
|
||||
close($pipe);
|
||||
my $status = $? >> 8;
|
||||
$output =~ s/\s+\z//;
|
||||
return ( $status, $output );
|
||||
}
|
||||
|
||||
my $deb_install = read_file(
|
||||
File::Spec->catfile( $repo_root, 'xCAT-server', 'debian', 'install' )
|
||||
);
|
||||
@@ -45,31 +110,230 @@ my $deb_postinst = read_file(
|
||||
File::Spec->catfile( $repo_root, 'xCAT-server', 'debian', 'postinst' )
|
||||
);
|
||||
like( $deb_postinst,
|
||||
qr{if "\$xcatd_init_compat" uses-systemd; then},
|
||||
qr{if "\$xcatd_init_compat" uses-systemd --explicit-target; then},
|
||||
'Debian postinst delegates target init detection to the packaged helper' );
|
||||
unlike( $deb_postinst,
|
||||
qr{"\$xcatd_init_compat" (?:uses-systemd|configure)(?! --explicit-target)},
|
||||
'every Debian postinst helper call uses explicit target detection' );
|
||||
unlike( $deb_postinst, qr{sub xcat_target_uses_systemd|xcat_target_uses_systemd\(\)},
|
||||
'Debian postinst does not carry weaker duplicate init detection' );
|
||||
my $deb_init_state = read_file(
|
||||
File::Spec->catfile(
|
||||
$repo_root, 'xCAT-server', 'debian', 'xcatd-init-state'
|
||||
)
|
||||
);
|
||||
like( $deb_init_state,
|
||||
qr{\[ -x "\$legacy_init" \].*?update-rc\.d xcatd defaults}s,
|
||||
'Debian registers SysV only after materializing an executable script' );
|
||||
like( $deb_init_state,
|
||||
qr{apply_legacy_registration\(\).*?no\).*?update-rc\.d xcatd defaults.*?update-rc\.d xcatd disable.*?unregistered\|unknown\).*?update-rc\.d -f xcatd remove}s,
|
||||
'Debian distinguishes registered-disabled from unregistered SysV state' );
|
||||
like( $deb_init_state,
|
||||
qr{stash_candidate\(\).*?if ! cp -a.*?\|\|\s*! mv -f.*?rm -f "\$stash_tmp".*?return 1}s,
|
||||
'Debian removes a failed atomic stash temporary' );
|
||||
like( $deb_init_state, qr{printf 'format=2},
|
||||
'Debian writes registration-aware state format 2' );
|
||||
like( $deb_init_state,
|
||||
qr{state_format" = 1.*?state_enabled" = no.*?state_enabled=unregistered}s,
|
||||
'Debian preserves format-1 remove-all-links behavior' );
|
||||
my @unregistered_refresh_guards =
|
||||
$deb_init_state =~ /state_enabled" != unregistered/g;
|
||||
is( scalar @unregistered_refresh_guards, 2,
|
||||
'both systemd refresh paths retain unregistered provenance' );
|
||||
like( $deb_init_state,
|
||||
qr{init_compat=.*?xcatd-init-compat.*?shared_init_state\(\).*?"\$init_compat" "\$\@".*?debian-legacy-state.*?systemd-state --allow-unknown}s,
|
||||
'Debian delegates legacy and precise systemd state detection to the shared helper' );
|
||||
like( $deb_init_state,
|
||||
qr{if ! detected_legacy_state=.*?return 1.*?if ! detected_systemd_state=.*?return 1}s,
|
||||
'Debian propagates failures from both shared state probes' );
|
||||
unlike( $deb_init_state,
|
||||
qr{systemctl (?:--root=.*? )?is-enabled|systemd/system/\*\.(?:wants|requires)/xcatd\.service|rc\?\.d/S\?\?xcatd},
|
||||
'Debian init state does not duplicate shared service-state probes' );
|
||||
unlike( $deb_init_state, qr{systemd_is_masked},
|
||||
'Debian does not hide detector failures in a boolean mask probe' );
|
||||
like( $deb_postinst,
|
||||
qr{\[ -x /etc/init\.d/xcatd \].*?update-rc\.d xcatd defaults}s,
|
||||
'Debian postinst registers SysV only after materializing an executable script' );
|
||||
qr{transition_origin=.*?get origin.*?fresh:yes\|legacy:yes.*?systemctl enable}s,
|
||||
'Debian changes systemd enablement only for fresh installs and init transitions' );
|
||||
like( $deb_postinst,
|
||||
qr{legacy:no\|legacy:unregistered\) systemctl disable xcatd\.service},
|
||||
'Debian maps both disabled SysV registration states to systemd disablement' );
|
||||
unlike( $deb_postinst, qr{systemd:yes.*?systemctl enable}s,
|
||||
'Debian same-systemd upgrades do not normalize existing enablement' );
|
||||
|
||||
my %classifier_blocks;
|
||||
foreach my $fallback_script (qw(preinst postrm)) {
|
||||
my $script = read_file(
|
||||
File::Spec->catfile( $repo_root, 'xCAT-server', 'debian', $fallback_script )
|
||||
);
|
||||
$classifier_blocks{$fallback_script} = init_classifier_block($script);
|
||||
ok( $classifier_blocks{$fallback_script} ne '',
|
||||
"Debian $fallback_script classifier can be extracted" );
|
||||
like( $script, qr{VERSION_ID.*?ubuntu.*?-ge 15.*?debian.*?-ge 8}s,
|
||||
"Debian $fallback_script recognizes stripped modern targets" );
|
||||
like( $script, qr{\[ "\$os_id" = "debian" \].*?\[ -z "\$os_version" \]}s,
|
||||
"Debian $fallback_script recognizes testing and sid without VERSION_ID" );
|
||||
like( $script, qr{value=\$\{value#\\'\}\s+value=\$\{value%\\'\}}s,
|
||||
"Debian $fallback_script strips single-quoted os-release values" );
|
||||
like( $script,
|
||||
qr{xcat_target_uses_systemd\(\).*?\[ -d /run/systemd/system \].*?\[ -L /sbin/init \].*?\*\) return 1 ;;.*?\[ -e /sbin/init \].*?return 1.*?if xcat_systemd_os_release_status; then.*?\[ -x /usr/lib/systemd/systemd \]}s,
|
||||
"Debian $fallback_script prefers active and explicit target evidence" );
|
||||
like( $script,
|
||||
qr{xcat_systemd_os_release_status\(\).*?return 2.*?return 1.*?return 2}s,
|
||||
"Debian $fallback_script distinguishes legacy from unknown releases" );
|
||||
}
|
||||
my $deb_preinst = read_file(
|
||||
File::Spec->catfile( $repo_root, 'xCAT-server', 'debian', 'preinst' )
|
||||
);
|
||||
my $preinst_legacy_state_block = legacy_state_block($deb_preinst);
|
||||
ok( $preinst_legacy_state_block ne '',
|
||||
'preinst legacy registration detector can be extracted' );
|
||||
is_deeply(
|
||||
[ run_legacy_state_block( $preinst_legacy_state_block, <<'SH' ) ],
|
||||
#!/bin/sh
|
||||
root=${XCAT_TEST_ROOT:?}
|
||||
case "${1:-}" in
|
||||
legacy-state)
|
||||
for link in "$root"/etc/rc.d/rc?.d/S??xcatd; do
|
||||
if [ -e "$link" ] || [ -L "$link" ]; then
|
||||
printf '%s\n' enabled
|
||||
exit 0
|
||||
fi
|
||||
done
|
||||
printf '%s\n' unregistered
|
||||
;;
|
||||
*) exit 2 ;;
|
||||
esac
|
||||
SH
|
||||
[ 0, 'unregistered' ],
|
||||
'preinst falls back to Debian links when the installed helper lacks the command'
|
||||
);
|
||||
is_deeply(
|
||||
[ run_legacy_state_block( $preinst_legacy_state_block, <<'SH' ) ],
|
||||
#!/bin/sh
|
||||
root=${XCAT_TEST_ROOT:?}
|
||||
case "${1:-}:$#" in
|
||||
debian-legacy-state:1)
|
||||
for link in "$root"/etc/rc?.d/S??xcatd; do
|
||||
if [ -e "$link" ] || [ -L "$link" ]; then
|
||||
printf '%s\n' enabled
|
||||
exit 0
|
||||
fi
|
||||
done
|
||||
printf '%s\n' unregistered
|
||||
;;
|
||||
*) exit 2 ;;
|
||||
esac
|
||||
SH
|
||||
[ 0, 'unregistered' ],
|
||||
'preinst uses Debian-only state from a command-aware installed helper'
|
||||
);
|
||||
my ( $malformed_helper_status, $malformed_helper_output ) =
|
||||
run_legacy_state_block( $preinst_legacy_state_block, <<'SH' );
|
||||
#!/bin/sh
|
||||
[ "${1:-}" = debian-legacy-state ] || exit 2
|
||||
printf '%s\n' malformed
|
||||
SH
|
||||
is( $malformed_helper_status, 1,
|
||||
'preinst rejects malformed successful helper output' );
|
||||
is( $malformed_helper_output, '',
|
||||
'preinst does not promote malformed helper output' );
|
||||
my ( $failed_helper_status, $failed_helper_output ) =
|
||||
run_legacy_state_block( $preinst_legacy_state_block, <<'SH' );
|
||||
#!/bin/sh
|
||||
exit 7
|
||||
SH
|
||||
is( $failed_helper_status, 7,
|
||||
'preinst fails closed on non-capability helper errors' );
|
||||
is( $failed_helper_output, '',
|
||||
'preinst does not fall back after a real helper failure' );
|
||||
like( $deb_preinst,
|
||||
qr{write_xcatd_context\(\)\s*\(.*?umask 077.*?\n\)}s,
|
||||
'preinst confines the context-file umask to a subshell' );
|
||||
like( $deb_preinst,
|
||||
qr{context_tmp=.*?if ! printf.*?\|\|\s*! mv -f.*?rm -f "\$context_tmp".*?return 1}s,
|
||||
'preinst removes a failed context-file temporary' );
|
||||
my $preinst_pending_cleanup = pending_cleanup_block($deb_preinst);
|
||||
like( $preinst_pending_cleanup,
|
||||
qr{pending-xcatd.*?pending-deleted.*?pending-enabled.*?pending-xcatd\.tmp\.}s,
|
||||
'preinst clears every transaction-local pending state artifact' );
|
||||
like( $deb_preinst,
|
||||
qr{conffile_record=.*?dpkg-query.*?case "\$conffile_record" in.*?obsolete.*?touch "\$xcatd_old_systemd_marker".*?\*\).*?touch "\$xcatd_state_dir/pending-deleted"}s,
|
||||
'preinst distinguishes package-obsolete conffiles from administrator deletion' );
|
||||
like( $deb_preinst,
|
||||
qr{xcatd_transition_context=\s*case "\$1" in\s*upgrade\) xcatd_transition_context=upgrade ;;\s*install\) xcatd_transition_context=fresh ;;\s*esac\s*if \[ -n "\$xcatd_transition_context" \]}s,
|
||||
'preinst prepares transition state only for install and upgrade calls' );
|
||||
like( $deb_preinst,
|
||||
qr{\$xcatd_legacy_init\.dpkg-bak.*?\$xcatd_legacy_init\.dpkg-backup.*?\$xcatd_legacy_init\.dpkg-remove}s,
|
||||
'preinst recovers every conffile backup name used during interrupted removal' );
|
||||
like( $deb_preinst,
|
||||
qr{pending_tmp=.*?if ! cp -a.*?\|\|\s*! mv -f.*?rm -f "\$pending_tmp".*?exit 1}s,
|
||||
'preinst removes a failed pending-stash temporary' );
|
||||
like( $deb_preinst,
|
||||
qr{if \[ -n "\$conffile_record" \]; then.*?case "\$conffile_record" in.*?esac\s*else\s*# A retry without an installed conffile record.*?clear_xcatd_pending_state\s*fi}s,
|
||||
'preinst discards stale pending evidence when dpkg has no conffile record' );
|
||||
like( $deb_preinst,
|
||||
qr{xcatd_legacy_enable_state\(\).*?"\$xcatd_init_compat" debian-legacy-state 2>/dev/null.*?detector_status=\$\?.*?"\$detector_status" -ne 2.*?/etc/rc\?\.d/S\?\?xcatd.*?/etc/rc\?\.d/K\?\?xcatd.*?unregistered}s,
|
||||
'preinst reuses shared registration detection with a pre-unpack S/K fallback' );
|
||||
like( $deb_preinst,
|
||||
qr{upgrade\)\s*write_xcatd_context upgrade.*?install\)\s*write_xcatd_context fresh.*?abort-upgrade\)\s*rm -f "\$xcatd_context_file"}s,
|
||||
'preinst records explicit durable package transition context' );
|
||||
like( $deb_postinst,
|
||||
qr{ln -sf /opt/xcat/sbin/xcatd /usr/sbin/xcatd.*?#DEBHELPER#.*?rm -f "\$xcatd_context_file"}s,
|
||||
'postinst retains upgrade context until every fallible installation step succeeds' );
|
||||
like( $deb_postinst,
|
||||
qr{if \[ -r "\$xcatd_context_file" \].*?fresh\|upgrade.*?elif \[ "\$1" = configure \] && \[ -n "\$\{2:-\}" \].*?xcatd_transition_context=upgrade}s,
|
||||
'postinst validates explicit context and preserves state on configured-package fallback' );
|
||||
unlike( "$deb_preinst\n$deb_postinst", qr{/tmp/xCAT-server_upgrade\.tmp},
|
||||
'maintainer scripts keep transaction state out of shared temporary storage' );
|
||||
is( $classifier_blocks{preinst}, $classifier_blocks{postrm},
|
||||
'Debian preinst and postrm carry the same lifecycle-safe classifier' );
|
||||
|
||||
my $deb_postrm = read_file(
|
||||
File::Spec->catfile( $repo_root, 'xCAT-server', 'debian', 'postrm' )
|
||||
);
|
||||
my $postrm_pending_cleanup = pending_cleanup_block($deb_postrm);
|
||||
is( $postrm_pending_cleanup, $preinst_pending_cleanup,
|
||||
'preinst and postrm share the same pending-state cleanup contract' );
|
||||
unlike( $deb_postrm, qr{/tmp/xCAT-server_upgrade\.tmp},
|
||||
'postrm keeps transaction state out of shared temporary storage' );
|
||||
my ($abort_install) = $deb_postrm =~ /\n\s*abort-install\)\n(.*?)\n\s*;;/s;
|
||||
my ($abort_upgrade) =
|
||||
$deb_postrm =~ /\n\s*abort-upgrade\|disappear\)\n(.*?)\n\s*;;/s;
|
||||
ok( defined($abort_install) && defined($abort_upgrade),
|
||||
'postrm abort recovery arms can be inspected independently' );
|
||||
like( $abort_install,
|
||||
qr{clear_xcatd_pending_state.*?rm -f "\$xcatd_context_file".*?rmdir "\$xcatd_state_dir"}s,
|
||||
'abort-install clears pending context and removes only an empty state directory' );
|
||||
unlike( $abort_install,
|
||||
qr{\$xcatd_state_dir/(?:state|xcatd)|xcatd_old_systemd_marker},
|
||||
'abort-install preserves durable init state and compatibility evidence' );
|
||||
like( $abort_upgrade, qr{rm -f "\$xcatd_context_file"},
|
||||
'abort-upgrade clears only the completed-attempt context' );
|
||||
unlike( $abort_upgrade,
|
||||
qr{clear_xcatd_pending_state|pending-(?:xcatd|deleted|enabled)},
|
||||
'abort-upgrade preserves pending recovery evidence for retry' );
|
||||
like( $deb_postrm,
|
||||
qr{purge\).*?rm -f "\$xcatd_context_file".*?upgrade\|failed-upgrade\)\s*;;.*?remove\).*?rm -f "\$xcatd_context_file"}s,
|
||||
'postrm clears upgrade context only when installation cannot continue' );
|
||||
|
||||
my $deb_prerm = read_file(
|
||||
File::Spec->catfile( $repo_root, 'xCAT-server', 'debian', 'prerm' )
|
||||
);
|
||||
like( $deb_prerm,
|
||||
qr{if "\$xcatd_init_compat" uses-systemd; then.*?update-rc\.d -f xcatd remove}s,
|
||||
qr{if "\$xcatd_init_compat" uses-systemd --explicit-target; then.*?update-rc\.d -f xcatd remove}s,
|
||||
'Debian prerm removes registration through the detected init implementation' );
|
||||
unlike( $deb_prerm,
|
||||
qr{"\$xcatd_init_compat" uses-systemd(?! --explicit-target)},
|
||||
'every Debian prerm helper call uses explicit target detection' );
|
||||
unlike( $deb_postinst, qr{xcat_can_use_systemctl},
|
||||
'Debian postinst does not duplicate the shared systemctl readiness guard' );
|
||||
like( $deb_postinst,
|
||||
qr{if "\$xcatd_init_compat" can-use-systemctl; then\s+systemctl daemon-reload}s,
|
||||
'Debian postinst delegates its active-systemd guard to the shared helper' );
|
||||
unlike( $deb_prerm, qr{xcat_can_use_systemctl},
|
||||
'Debian prerm does not duplicate the shared systemctl readiness guard' );
|
||||
like( $deb_prerm,
|
||||
qr{if "\$xcatd_init_compat" can-use-systemctl; then\s+systemctl stop xcatd\.service}s,
|
||||
'Debian prerm delegates its active-systemd guard to the shared helper' );
|
||||
|
||||
done_testing();
|
||||
|
||||
@@ -30,9 +30,29 @@ sub stage_root {
|
||||
my $scripts = File::Spec->catdir(
|
||||
$root, 'opt', 'xcat', 'share', 'xcat', 'scripts'
|
||||
);
|
||||
make_path($scripts);
|
||||
my $fake_bin = File::Spec->catdir( $root, 'test-bin' );
|
||||
make_path( $scripts, $fake_bin );
|
||||
copy( $template, File::Spec->catfile( $scripts, 'xcatd' ) )
|
||||
or die "Unable to stage legacy init template: $!";
|
||||
my $systemctl = File::Spec->catfile( $fake_bin, 'systemctl' );
|
||||
open( my $systemctl_fh, '>', $systemctl )
|
||||
or die "Unable to stage fake systemctl: $!";
|
||||
print {$systemctl_fh} <<'SH';
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
root=${XCAT_COMPAT_ROOT:?}
|
||||
case "${1:-}" in
|
||||
--root=*) shift ;;
|
||||
esac
|
||||
[ "${1:-}" = is-enabled ] || exit 1
|
||||
if [ -r "$root/systemctl-state" ]; then
|
||||
sed -n '1p' "$root/systemctl-state"
|
||||
else
|
||||
echo unknown
|
||||
fi
|
||||
SH
|
||||
close($systemctl_fh);
|
||||
chmod 0755, $systemctl;
|
||||
return $root;
|
||||
}
|
||||
|
||||
@@ -49,10 +69,20 @@ sub stage_systemd_binary {
|
||||
return $binary;
|
||||
}
|
||||
|
||||
sub set_systemd_state {
|
||||
my ( $root, $state ) = @_;
|
||||
my $path = File::Spec->catfile( $root, 'systemctl-state' );
|
||||
open( my $fh, '>', $path )
|
||||
or die "Unable to stage systemd state: $!";
|
||||
print {$fh} "$state\n";
|
||||
close($fh);
|
||||
}
|
||||
|
||||
sub run_helper {
|
||||
my ( $root, @arguments ) = @_;
|
||||
local $ENV{XCAT_COMPAT_ROOT} = $root;
|
||||
local $ENV{XCATROOT} = '/opt/xcat';
|
||||
local $ENV{PATH} = File::Spec->catdir( $root, 'test-bin' ) . ':/usr/bin:/bin';
|
||||
system( '/bin/sh', $helper, @arguments );
|
||||
return $? >> 8;
|
||||
}
|
||||
@@ -61,6 +91,7 @@ sub helper_output {
|
||||
my ( $root, @arguments ) = @_;
|
||||
local $ENV{XCAT_COMPAT_ROOT} = $root;
|
||||
local $ENV{XCATROOT} = '/opt/xcat';
|
||||
local $ENV{PATH} = File::Spec->catdir( $root, 'test-bin' ) . ':/usr/bin:/bin';
|
||||
open( my $pipe, '-|', '/bin/sh', $helper, @arguments )
|
||||
or die "Unable to run compatibility helper: $!";
|
||||
my $output = do { local $/; <$pipe> };
|
||||
@@ -255,6 +286,34 @@ is( helper_output( $legacy_state_root, 'legacy-state' ), 'enabled',
|
||||
is( helper_output( $legacy_state_root, 'legacy-transition-state' ), 'enabled',
|
||||
'enabled SysV state takes precedence during a legacy transition' );
|
||||
|
||||
my $rpm_layout_root = stage_root();
|
||||
stage_symlink(
|
||||
$rpm_layout_root, '/etc/init.d/xcatd',
|
||||
qw(etc rc.d rc3.d S85xcatd)
|
||||
);
|
||||
is( helper_output( $rpm_layout_root, 'legacy-state' ), 'enabled',
|
||||
'default legacy state continues to recognize RPM runlevel layouts' );
|
||||
is( helper_output( $rpm_layout_root, 'debian-legacy-state' ),
|
||||
'unregistered', 'Debian legacy state ignores RPM-only runlevel links' );
|
||||
is( helper_output( $rpm_layout_root, 'legacy-state', '--debian-layout' ),
|
||||
'enabled', 'legacy state preserves ignored historical extra arguments' );
|
||||
is( run_helper( $rpm_layout_root, 'debian-legacy-state', 'extra' ), 2,
|
||||
'Debian legacy state rejects extra arguments' );
|
||||
|
||||
my $debian_layout_root = stage_root();
|
||||
stage_symlink(
|
||||
$debian_layout_root, '/etc/init.d/xcatd',
|
||||
qw(etc rc3.d K60xcatd)
|
||||
);
|
||||
is( helper_output( $debian_layout_root, 'debian-legacy-state' ),
|
||||
'disabled', 'Debian legacy state recognizes native kill links' );
|
||||
stage_symlink(
|
||||
$debian_layout_root, '/etc/init.d/xcatd',
|
||||
qw(etc rc3.d S85xcatd)
|
||||
);
|
||||
is( helper_output( $debian_layout_root, 'debian-legacy-state' ),
|
||||
'enabled', 'Debian legacy state gives native start links precedence' );
|
||||
|
||||
my $unregistered_legacy_root = stage_root();
|
||||
make_path( File::Spec->catdir( $unregistered_legacy_root, 'etc', 'init.d' ) );
|
||||
copy( $template, legacy_init($unregistered_legacy_root) )
|
||||
@@ -275,6 +334,11 @@ is( helper_output( $deleted_managed_root, 'legacy-transition-state' ),
|
||||
my $systemd_state_root = stage_root();
|
||||
is( helper_output( $systemd_state_root, 'systemd-state' ), 'disabled',
|
||||
'systemd state reports disabled when enablement links are absent' );
|
||||
is( helper_output( $systemd_state_root, 'systemd-state', '--allow-unknown' ),
|
||||
'unknown', 'precise systemd state preserves indeterminate evidence' );
|
||||
set_systemd_state( $systemd_state_root, 'disabled' );
|
||||
is( helper_output( $systemd_state_root, 'systemd-state', '--allow-unknown' ),
|
||||
'disabled', 'precise systemd state recognizes an explicit disablement' );
|
||||
stage_symlink(
|
||||
$systemd_state_root, '/usr/lib/systemd/system/xcatd.service',
|
||||
qw(etc systemd system multi-user.target.wants xcatd.service)
|
||||
@@ -283,6 +347,63 @@ is( helper_output( $systemd_state_root, 'systemd-state' ), 'enabled',
|
||||
'systemd state recognizes persistent wants links' );
|
||||
is( helper_output( $systemd_state_root, 'legacy-transition-state' ), 'enabled',
|
||||
'enabled systemd state transfers to an enabled SysV service' );
|
||||
is( helper_output( $systemd_state_root, 'systemd-state', '--allow-unknown' ),
|
||||
'enabled', 'enablement links override stale disabled manager output' );
|
||||
|
||||
my $manager_masked_link_root = stage_root();
|
||||
set_systemd_state( $manager_masked_link_root, 'masked' );
|
||||
stage_symlink(
|
||||
$manager_masked_link_root, '/usr/lib/systemd/system/xcatd.service',
|
||||
qw(etc systemd system multi-user.target.wants xcatd.service)
|
||||
);
|
||||
is( helper_output( $manager_masked_link_root, 'systemd-state' ), 'enabled',
|
||||
'compatibility state keeps historical link precedence for target roots' );
|
||||
is( helper_output(
|
||||
$manager_masked_link_root, 'systemd-state', '--allow-unknown'
|
||||
),
|
||||
'masked', 'precise systemd state gives a manager mask precedence over links' );
|
||||
|
||||
for my $manager_state_case (
|
||||
[ 'enabled', 'enabled' ],
|
||||
[ 'enabled-runtime', 'enabled' ],
|
||||
[ 'masked', 'masked' ],
|
||||
[ 'masked-runtime', 'masked' ],
|
||||
[ 'disabled', 'disabled' ],
|
||||
[ 'linked', 'disabled' ],
|
||||
[ 'linked-runtime', 'disabled' ],
|
||||
[ 'alias', 'disabled' ],
|
||||
[ 'static', 'disabled' ],
|
||||
[ 'indirect', 'disabled' ],
|
||||
[ 'generated', 'disabled' ],
|
||||
[ 'transient', 'disabled' ],
|
||||
[ 'enabled-garbage', 'unknown' ],
|
||||
[ 'masked-garbage', 'unknown' ],
|
||||
) {
|
||||
my ( $manager_state, $expected_state ) = @{$manager_state_case};
|
||||
my $manager_state_root = stage_root();
|
||||
set_systemd_state( $manager_state_root, $manager_state );
|
||||
is( helper_output(
|
||||
$manager_state_root, 'systemd-state', '--allow-unknown'
|
||||
),
|
||||
$expected_state, "precise systemd state parses $manager_state exactly" );
|
||||
}
|
||||
|
||||
for my $precise_link_case (
|
||||
[ qw(etc wants) ],
|
||||
[ qw(etc requires) ],
|
||||
[ qw(run wants) ],
|
||||
[ qw(run requires) ],
|
||||
) {
|
||||
my ( $scope, $relation ) = @{$precise_link_case};
|
||||
my $precise_link_root = stage_root();
|
||||
stage_symlink(
|
||||
$precise_link_root, '/usr/lib/systemd/system/xcatd.service',
|
||||
$scope, 'systemd', 'system', "multi-user.target.$relation",
|
||||
'xcatd.service'
|
||||
);
|
||||
is( helper_output( $precise_link_root, 'systemd-state', '--allow-unknown' ),
|
||||
'enabled', "precise systemd state recognizes $scope $relation links" );
|
||||
}
|
||||
|
||||
my $systemd_requires_root = stage_root();
|
||||
stage_symlink(
|
||||
@@ -311,6 +432,24 @@ is( helper_output( $systemd_masked_root, 'systemd-state' ), 'masked',
|
||||
'systemd state preserves an administrator mask' );
|
||||
is( helper_output( $systemd_masked_root, 'legacy-transition-state' ), 'masked',
|
||||
'a systemd mask prevents SysV registration during a legacy transition' );
|
||||
is( helper_output( $systemd_masked_root, 'systemd-state', '--allow-unknown' ),
|
||||
'masked', 'precise systemd state recognizes persistent masks' );
|
||||
|
||||
my $systemd_runtime_masked_root = stage_root();
|
||||
stage_symlink(
|
||||
$systemd_runtime_masked_root, '/dev/null',
|
||||
qw(run systemd system xcatd.service)
|
||||
);
|
||||
is( helper_output( $systemd_runtime_masked_root,
|
||||
'systemd-state', '--allow-unknown' ),
|
||||
'masked', 'precise systemd state recognizes runtime masks' );
|
||||
my $systemd_argv_root = stage_root();
|
||||
is( helper_output( $systemd_argv_root, 'systemd-state', '--invalid' ),
|
||||
'disabled', 'systemd state preserves ignored historical extra arguments' );
|
||||
is( helper_output(
|
||||
$systemd_argv_root, 'systemd-state', '--allow-unknown', 'extra'
|
||||
),
|
||||
'disabled', 'only the exact precision option activates precise state' );
|
||||
|
||||
my $cleanup_root = stage_root();
|
||||
my @cleanup_links = (
|
||||
|
||||
Reference in New Issue
Block a user