Clean up specfile unit activation aspect.

Up until today, Qubes OS would insist on either masking or disabling
or activating units that should get their state properly changed
but only on first package install (when the template is built).

This commit adds the possibility of having two types of unit presets:

* Initial presets: these are only changed state during first package
  installs.
* Upgrade presets: these get their state changed during first
  package installs as well as during upgrades.

All the maintainer has to do is abide by the instructions in the
preset file.  Nothing else is necessary.

Namely, this allows users to enable SSHD on their templates or
standalone VMs and still keep it enabled even after the
qubes-core-vm-systemd package is upgraded.

Matt really wanted that, and so did I, so now we can do it!

:-)
This commit is contained in:
Manuel Amador (Rudd-O) 2016-10-28 05:47:59 +00:00
parent d15696ebef
commit 251ecbd529
2 changed files with 171 additions and 59 deletions

View File

@ -21,10 +21,88 @@
#
%define qubes_services qubes-core qubes-core-netvm qubes-core-early qubes-firewall qubes-netwatcher qubes-iptables qubes-updates-proxy qubes-qrexec-agent qubes-dvm
%define qubes_preset_file 75-qubes-vm.preset
%{!?version: %define version %(cat version)}
%{!?backend_vmm: %define backend_vmm %(echo $BACKEND_VMM)}
%define scriptletfuns is_static() { \
[ -f "%{_unitdir}/$1" ] && ! grep -q '^[[].nstall]' "%{_unitdir}/$1" \
} \
\
is_masked() { \
if [ ! -L %{_sysconfdir}/systemd/system/"$1" ] \
then \
return 1 \
fi \
target=`readlink %{_sysconfdir}/systemd/system/"$1" 2>/dev/null` || : \
if [ "$target" = "/dev/null" ] \
then \
return 0 \
fi \
return 1 \
} \
\
mask() { \
ln -sf /dev/null %{_sysconfdir}/systemd/system/"$1" \
} \
\
unmask() { \
if ! is_masked "$1" \
then \
return 0 \
fi \
rm -f %{_sysconfdir}/systemd/system/"$1" \
} \
\
preset_units() { \
local represet= \
cat "$1" | while read action unit_name \
do \
if [ "$action" = "#" -a "$unit_name" = "Units below this line will be re-preset on package upgrade" ] \
then \
represet=1 \
continue \
fi \
echo "$action $unit_name" | grep -q '^[[:space:]]*[^#;]' || continue \
[ -n "$action" -a -n "$unit_name" ] || continue \
if [ "$2" = "initial" -o "$represet" = "1" ] \
then \
if [ "$action" = "disable" ] && is_static "$unit_name" \
then \
if ! is_masked "$unit_name" \
then \
# We must effectively mask these units, even if they are static. \
mask "$unit_name" \
fi \
elif [ "$action" = "enable" ] && is_static "$unit_name" \
then \
if is_masked "$unit_name" \
then \
# We masked this static unit before, now we unmask it. \
unmask "$unit_name" \
fi \
systemctl --no-reload preset "$unit_name" >/dev/null 2>&1 || : \
else \
systemctl --no-reload preset "$unit_name" >/dev/null 2>&1 || : \
fi \
fi \
done \
} \
\
restore_units() { \
grep '^[[:space:]]*[^#;]' "$1" | while read action unit_name \
do \
if is_static "$unit_name" && is_masked "$unit_name" \
then \
# If the unit had been masked by us, we must unmask it here. \
# Otherwise systemctl preset will fail badly. \
unmask "$unit_name" \
fi \
systemctl --no-reload preset "$unit_name" >/dev/null 2>&1 || : \
done \
} \
Name: qubes-core-vm
Version: %{version}
Release: 1%{dist}
@ -554,7 +632,7 @@ The Qubes core startup configuration for SystemD init.
/lib/systemd/system/qubes-update-check.timer
/lib/systemd/system/qubes-updates-proxy.service
/lib/systemd/system/qubes-qrexec-agent.service
/lib/systemd/system-preset/75-qubes-vm.preset
/lib/systemd/system-preset/%qubes_preset_file
/lib/modules-load.d/qubes-core.conf
/lib/modules-load.d/qubes-misc.conf
/usr/lib/qubes/init/qubes-iptables
@ -582,68 +660,83 @@ The Qubes core startup configuration for SystemD init.
%post systemd
PRESET_FAILED=0
if [ $1 -eq 1 ]; then
/bin/systemctl --no-reload preset-all > /dev/null 2>&1 && PRESET_FAILED=0 || PRESET_FAILED=1
changed=
%scriptletfuns
if [ $1 -eq 1 ]
then
preset_units %{_presetdir}/%qubes_preset_file initial
changed=true
else
services="qubes-dvm qubes-misc-post qubes-firewall qubes-mount-dirs"
services="$services qubes-netwatcher qubes-network qubes-sysinit"
services="$services qubes-iptables qubes-updates-proxy qubes-qrexec-agent"
for srv in $services; do
/bin/systemctl --no-reload preset $srv.service
done
/bin/systemctl --no-reload preset qubes-update-check.timer
preset_units %{_presetdir}/%qubes_preset_file upgrade
changed=true
# Upgrade path - now qubes-iptables is used instead
if [ -f /lib/systemd/system/iptables.service ]; then
/bin/systemctl --no-reload preset iptables.service
fi
if [ -f /lib/systemd/system/ip6tables.service ]; then
/bin/systemctl --no-reload preset ip6tables.service
fi
for svc in iptables ip6tables
do
if [ -f "$svc".service ]
then
systemctl --no-reload preset "$svc".service
changed=true
fi
done
fi
# Set default "runlevel"
rm -f /etc/systemd/system/default.target
ln -s /lib/systemd/system/multi-user.target /etc/systemd/system/default.target
grep '^[[:space:]]*[^#;]' /lib/systemd/system-preset/75-qubes-vm.preset | while read action unit_name; do
case "$action" in
(disable)
if [ -f /lib/systemd/system/$unit_name ]; then
if ! fgrep -q '[Install]' /lib/systemd/system/$unit_name; then
# forcibly disable
ln -sf /dev/null /etc/systemd/system/$unit_name
fi
fi
;;
*)
# preset-all is not available in fc20; so preset each unit file listed in 75-qubes-vm.preset
if [ $1 -eq 1 -a "${PRESET_FAILED}" -eq 1 ]; then
systemctl --no-reload preset "${unit_name}" > /dev/null 2>&1 || true
fi
;;
esac
done
if [ $1 -eq 1 ]
then
# First install.
# Set default "runlevel".
# FIXME: this ought to be done via kernel command line.
# The fewer deviations of the template from the seed
# image, the better.
rm -f %{_sysconfdir}/systemd/system/default.target
ln -s %{_unitdir}/multi-user.target %{_sysconfdir}/systemd/system/default.target
changed=true
fi
# remove old symlinks
if [ -L /etc/systemd/system/sysinit.target.wants/qubes-random-seed.service ]; then
rm /etc/systemd/system/sysinit.target.wants/qubes-random-seed.service
if [ -L %{_sysconfdir}/systemd/system/sysinit.target.wants/qubes-random-seed.service ]
then
rm -f %{_sysconfdir}/systemd/system/sysinit.target.wants/qubes-random-seed.service
changed=true
fi
if [ -L /etc/systemd/system/multi-user.target.wants/qubes-mount-home.service ]; then
rm /etc/systemd/system/multi-user.target.wants/qubes-mount-home.service
if [ -L %{_sysconfdir}/systemd/system/multi-user.target.wants/qubes-mount-home.service ]
then
rm -f %{_sysconfdir}/systemd/system/multi-user.target.wants/qubes-mount-home.service
changed=true
fi
/bin/systemctl daemon-reload
if [ "x$changed" != "x" ]
then
systemctl daemon-reload
fi
exit 0
%preun systemd
if [ $1 -eq 0 ] ; then
# Run this only during uninstall.
# Save the preset file to later use it to re-preset services there
# once the Qubes OS preset file is removed.
mkdir -p %{_rundir}/qubes-uninstall
cp -f %{_presetdir}/%qubes_preset_file %{_rundir}/qubes-uninstall/
fi
%postun systemd
#Do not run this part on upgrades
if [ "$1" != 0 ] ; then
exit 0
changed=
%scriptletfuns
if [ -d %{_rundir}/qubes-uninstall ]
then
# We have a saved preset file (or more).
# Re-preset the units mentioned there.
restore_units %{_rundir}/qubes-uninstall/%qubes_preset_file
rm -rf %{_rundir}/qubes-uninstall
changed=true
fi
for srv in qubes-dvm qubes-sysinit qubes-misc-post qubes-mount-dirs qubes-netwatcher qubes-network qubes-qrexec-agent; do
/bin/systemctl disable $srv.service
do
if [ "x$changed" != "x" ]
then
systemctl daemon-reload
fi

View File

@ -14,13 +14,38 @@
# Qubes currently does not provide a way to permanently prevent such units from
# being masked.
#
# Maintainer information:
#
# * All units listed here are preset during first install of the *-systemd RPM.
# For those units which are disabled here, but don't have an install section
# (static units), we mask them during that install.
# * All units listed here that find themselves below the comment titled
# "# Units below this line will be re-preset on package upgrade"
# are preset both during install and during upgrade. This allows you to add
# new units here and have them become active when the user's machine upgrades
# their *-systemd RPM built by this project.
#
# Hi, Matt! I see you did great with this conversion to systemd presets!
# Thank you! Skyler sends you her regards from Europe!
# - Rudd-O
#
# https://groups.google.com/d/topic/qubes-users/dpM_GHfmEOk/discussion
disable alsa-store.service
disable alsa-restore.service
disable avahi.service
disable avahi-daemon.service
disable avahi-daemon.socket
# Fedora only services
disable rpcbind.service
disable sendmail.service
disable sm-client.service
disable sshd.service
disable backuppc.service
# Units below this line will be re-preset on package upgrade
disable alsa-store.service
disable alsa-restore.service
disable hwclock-save.service
disable mdmonitor.service
disable plymouth-start.service
@ -33,7 +58,6 @@ disable colord.service
disable systemd-timesyncd.service
# Fedora only services
disable backuppc.service
disable cpuspeed.service
disable dnf-makecache.timer
disable fedora-autorelabel.service
@ -50,10 +74,6 @@ disable mdmonitor-takeover.service
disable multipathd.service
disable openct.service
disable rngd.service
disable rpcbind.service
disable sendmail.service
disable sm-client.service
disable sshd.service
disable tcsd.service
enable qubes-sysinit.service
@ -61,7 +81,6 @@ enable qubes-early-vm-config.service
enable qubes-db.service
enable qubes-gui-agent.service
enable qubes-update-check.timer
enable qubes-update-check.timer
enable qubes-misc-post.service
enable qubes-updates-proxy.service
enable qubes-dvm.service