From 1c35fc6cef323c439ce83ca19e19ce41315586c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Ferr=C3=A3o?= <2031761+viniciusferrao@users.noreply.github.com> Date: Thu, 16 Jul 2026 01:43:16 -0300 Subject: [PATCH] fix(packaging): avoid SysV init paths in modern DEBs (cherry picked from commit 6a3f71bf68c91dbe8ca88dd3d86ce4ba41cd51bd) --- xCAT-server/debian/dirs | 1 - xCAT-server/debian/install | 2 +- xCAT-server/debian/postinst | 58 +++++++++----- xCAT-server/debian/postrm | 60 ++++++++++++++- xCAT-server/debian/preinst | 54 +++++++++++++ xCAT-server/debian/prerm | 16 ++-- .../unit/xcatd_debian_service_packaging.t | 75 +++++++++++++++++++ 7 files changed, 240 insertions(+), 26 deletions(-) create mode 100644 xCAT-test/unit/xcatd_debian_service_packaging.t diff --git a/xCAT-server/debian/dirs b/xCAT-server/debian/dirs index 2171d2d80..2bb20f45b 100644 --- a/xCAT-server/debian/dirs +++ b/xCAT-server/debian/dirs @@ -34,7 +34,6 @@ opt/xcat/lib/perl/xCAT_monitoring/pcp opt/xcat/xdsh opt/xcat/xdsh/Context opt/xcat/ws -etc/init.d lib/systemd/system etc/xcat etc/apache2/conf-enabled diff --git a/xCAT-server/debian/install b/xCAT-server/debian/install index 320403a55..6858f3764 100644 --- a/xCAT-server/debian/install +++ b/xCAT-server/debian/install @@ -28,7 +28,7 @@ lib/xcat/dsh/Context/* opt/xcat/xdsh/Context lib/xcat/Confluent/* opt/xcat/lib/perl/Confluent/ lib/xcat/shfunctions opt/xcat/lib -etc/init.d/xcatd etc/init.d +etc/init.d/xcatd opt/xcat/share/xcat/scripts etc/init.d/xcatd.service lib/systemd/system/ xCAT-wsapi/* opt/xcat/ws/ diff --git a/xCAT-server/debian/postinst b/xCAT-server/debian/postinst index 9adc9ce84..f303134c8 100644 --- a/xCAT-server/debian/postinst +++ b/xCAT-server/debian/postinst @@ -10,6 +10,14 @@ 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 + +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 -- "$@" +fi + # summary of how this script can be called: # * `configure' # * `abort-upgrade' @@ -26,28 +34,42 @@ xcat_can_use_systemctl() case "$1" in configure) . /etc/profile.d/xcat.sh + xcat_server_upgrade=0 if [ -f /tmp/xCAT-server_upgrade.tmp ]; then - if xcat_can_use_systemctl; then - if [ -f /run/systemd/generator.late/xcatd.service ]; then - # To cover the case upgrade from no xcatd systemd unit file (cannot enable by default for HA case) - if ls /etc/rc?.d/S??xcatd >/dev/null 2>&1; then - [ -x /usr/sbin/update-rc.d ] && /usr/sbin/update-rc.d xcatd remove - systemctl daemon-reload - systemctl enable xcatd.service - fi - else + 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 + update-rc.d -f xcatd remove + fi + + "$xcatd_init_compat" configure + if xcat_can_use_systemctl; then systemctl daemon-reload fi - fi - # No need to reload xcatd here as it will be covered by xCAT/xCATsn now - rm /tmp/xCAT-server_upgrade.tmp + 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 + fi else - if xcat_can_use_systemctl; then - systemctl daemon-reload - systemctl enable xcatd.service - elif command -v update-rc.d >/dev/null 2>&1; then - update-rc.d xcatd defaults - fi + "$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 + 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 ;; diff --git a/xCAT-server/debian/postrm b/xCAT-server/debian/postrm index bdbefba81..955ded4d0 100644 --- a/xCAT-server/debian/postrm +++ b/xCAT-server/debian/postrm @@ -5,6 +5,60 @@ set -e +xcat_target_uses_systemd() +{ + if [ -d /run/systemd/system ]; then + return 0 + fi + + if [ -x /usr/lib/systemd/systemd ] || [ -x /lib/systemd/systemd ]; then + return 0 + fi + + if [ -L /sbin/init ]; then + init_target=$(readlink /sbin/init 2>/dev/null || true) + case "$init_target" in + *systemd*) return 0 ;; + 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 [ "$os_id" = "debian" ] && [ -z "$os_version" ]; then + return 0 + 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 + fi + + return 1 +} + +if xcat_target_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 -- "$@" +fi + # summary of how this script can be called: # * `remove' # * `purge' @@ -20,7 +74,11 @@ set -e case "$1" in - purge|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) + purge) + rm -f /etc/init.d/xcatd + ;; + + upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) ;; remove) diff --git a/xCAT-server/debian/preinst b/xCAT-server/debian/preinst index 139732e80..1aabad540 100644 --- a/xCAT-server/debian/preinst +++ b/xCAT-server/debian/preinst @@ -5,6 +5,60 @@ set -e +xcat_target_uses_systemd() +{ + if [ -d /run/systemd/system ]; then + return 0 + fi + + if [ -x /usr/lib/systemd/systemd ] || [ -x /lib/systemd/systemd ]; then + return 0 + fi + + if [ -L /sbin/init ]; then + init_target=$(readlink /sbin/init 2>/dev/null || true) + case "$init_target" in + *systemd*) return 0 ;; + 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 [ "$os_id" = "debian" ] && [ -z "$os_version" ]; then + return 0 + 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 + fi + + return 1 +} + +if xcat_target_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 -- "$@" +fi + # summary of how this script can be called: # * `install' # * `install' diff --git a/xCAT-server/debian/prerm b/xCAT-server/debian/prerm index 9a3c1d4dd..818be25a4 100644 --- a/xCAT-server/debian/prerm +++ b/xCAT-server/debian/prerm @@ -10,6 +10,8 @@ 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: # * `remove' # * `upgrade' @@ -27,14 +29,18 @@ case "$1" in if [ -f "/proc/cmdline" ]; then # prevent running it during install into chroot image if xcat_can_use_systemctl; then systemctl stop xcatd.service - elif [ -x /etc/init.d/xcatd ]; then + elif ! "$xcatd_init_compat" uses-systemd && [ -x /etc/init.d/xcatd ]; then /etc/init.d/xcatd stop fi fi - if xcat_can_use_systemctl; then - systemctl disable xcatd.service - elif command -v update-rc.d >/dev/null 2>&1; then - update-rc.d -f xcatd remove + if "$xcatd_init_compat" uses-systemd; then + if command -v systemctl >/dev/null 2>&1; then + systemctl disable xcatd.service + fi + else + if command -v update-rc.d >/dev/null 2>&1; then + update-rc.d -f xcatd remove + fi fi ;; upgrade|deconfigure) diff --git a/xCAT-test/unit/xcatd_debian_service_packaging.t b/xCAT-test/unit/xcatd_debian_service_packaging.t new file mode 100644 index 000000000..e2e209918 --- /dev/null +++ b/xCAT-test/unit/xcatd_debian_service_packaging.t @@ -0,0 +1,75 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +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: $!"; + my $contents = do { local $/; <$fh> }; + close($fh); + return $contents; +} + +my $deb_install = read_file( + File::Spec->catfile( $repo_root, 'xCAT-server', 'debian', 'install' ) +); +like( $deb_install, qr{^etc/init\.d/xcatd opt/xcat/share/xcat/scripts$}m, + 'Debian stages the legacy script as a compatibility template' ); +unlike( $deb_install, qr{^etc/init\.d/xcatd etc/init\.d$}m, + 'Debian does not install the legacy script directly' ); + +my $deb_dirs = read_file( + File::Spec->catfile( $repo_root, 'xCAT-server', 'debian', 'dirs' ) +); +unlike( $deb_dirs, qr{^etc/init\.d/?$}m, + 'Debian does not package an empty legacy init directory' ); + +foreach my $maintainer_script (qw(preinst postinst postrm)) { + my $script = read_file( + File::Spec->catfile( + $repo_root, 'xCAT-server', 'debian', $maintainer_script + ) + ); + like( $script, + qr{dpkg-maintscript-helper rm_conffile /etc/init\.d/xcatd -- "\$\@"}, + "Debian $maintainer_script participates in graceful conffile removal" ); +} + +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}, + 'Debian postinst delegates target init detection to the packaged helper' ); +unlike( $deb_postinst, qr{sub xcat_target_uses_systemd|xcat_target_uses_systemd\(\)}, + 'Debian postinst does not carry weaker duplicate init detection' ); +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' ); + +foreach my $fallback_script (qw(preinst postrm)) { + my $script = read_file( + File::Spec->catfile( $repo_root, 'xCAT-server', 'debian', $fallback_script ) + ); + 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" ); +} + +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, + 'Debian prerm removes registration through the detected init implementation' ); + +done_testing();