[systemd-devel] Unwants

Dimitri John Ledkov dimitri.j.ledkov at intel.com
Fri Jan 23 05:11:47 PST 2015


On 22 January 2015 at 16:32, Andrei Borzenkov <arvidjaar at gmail.com> wrote:
> В Thu, 22 Jan 2015 15:46:26 +0100
> Michael Biebl <mbiebl at gmail.com> пишет:
>
>> 2015-01-22 15:08 GMT+01:00 Dimitri John Ledkov <dimitri.j.ledkov at intel.com>:
>> > At the moment, I'm looking at packaging symlinks in .wants directories
>> > under /usr and then allow to uninstall such a package as a means to
>> > override the default config. Since I would like to update how the
>> > default config is setup, without doing in /etc where I'd have to
>> > answer "is this my old config, or user modified it and I shouldn't
>> > touch it"
>>
>> That's indeed a tough problem. The upstream recommendation is, to run
>> "systemctl preset" during the initial installation.
>> If there are changes to the default in the unit files, those changes
>> are *not* applied on package upgrades.
>>
>> I don't think that's a particularly compelling solution.
>>
>> In Debian, we introduced a helper called i-s-h [1], which keeps some
>> additional state and tries to apply such changes on updates.
>
> There was long discussion on this just recently.
>
> http://lists.freedesktop.org/archives/systemd-devel/2014-November/025288.html
>

Thanks for this. The summary of that follows like so:

generic/typical systemd units ship, with a Install section WantedBy
multi-user.target an no other files.
It means it is inert / disabled by default.
Irrespective of the method (preset-all on empty/wiped /etc, preset at
first install only, enable (generated in packaging or run by an
admin),
the way to enable unit is by generating appropriate .wants/ symlinks in /etc.
It is viewed that distos should use presets whilst admins should use
enable, however the end result is the same on disk.
(E.g. distros can script things around enable/disable, and admins can
write /etc/systemd/system-preset and run preset from that file).
There are claims and assertions made as to what distro's should and
shouldn't do -> which are distro's decisions.
It is not possible to encode distro's choices with the suggested or
possible semantics, neither with presets nor shipping symlinks in
/usr.
Then end-result is that current semantics have a bias towards "disable
*" default policy.
(Unit by itself is not enabled, default policy not enable, if user or
preset enables, it is stored in "admin" dir /etc, rather than state
dirs under "/var")

The worst consequence of this, imho, is that .wants symlinks are
honoured from lower level directories even if the unit is out right
superseeded in a higher level directory.
E.g. cp /usr/lib/systemd/system/foo*.target /etc/systemd/system;
the /usr/lib/systemd/system/foo1.target.wants/foo2.target ->
../foo1.target is honoured.

Nor is there a way to "move" a wants to a later target in the boot process.
(e.g. most systemd intuitive way to add symlink to /dev/null & have
systectl commands that mirror add-wants/add-requires)

Furthermore, it appears that /etc is used as a snapshot of the preset
state as it was at the last time preset-all was run essentially. On my
books software state should live under /var rather under /etc. And in
the current generation philosophy this breaks the assumption that
"/etc" is user modified overrides only. But I think we can do better
than /var.

Do we really need symlinks on disk from presets?

Here is a proposal:

extend .wants/*; .requires/* semantics to allow removal:
e.g. "if the target of the symlink in .wants/ directory points at
/dev/null, instead of adding a dependency, such dependency is removed
if it no longer exists"
e.g. "Wants/Requires define dependencies to be added, or negating a
dependency if such already exists if prefixed with "!" "
e.g. add commands rm-wants / rm-requires -> which either create
symlink to /dev/null in /etc/***.wants/ for dependencies created in
lower-level configuration directories or removes existing symlink from
/etc/***.wants/

remove preset-* commands, or support mode of operation where preset
commands are no-op.
instead load and apply (on boot, daemon-reload, daemon-reexec) preset
directives in memory without storing a snapshot of "preset" results as
symlinks in /etc.
(this would make systemd stateless and be operational with less
symlinks on an even a read-only /etc without even a tmpfs rw mounted
/etc)

This makes the policies of "enable *" and "disable *" to be in full equilibrium:
- default policy applied from /usr
- user override is .wants/* symlinks based on Install section
-- to /dev/null to disable under enable * policy
-- to a valid unit to be enabled under disable * policy
-- no change in system under /usr (intentional or accidental) would
loose user choice

This would lead to one-time upgrade loss of state for "disable *"
distributions (i.e. the small number of distro enabled by default
units, which were disabled by the users, would get re-enabled. As a
one time upgrade, this can be detected and acted upon appropriately).
However this one time upgrade / miss-balance exaggerates the
complexity inflicted upon "enable *" distributions where this problem
is not for "small number of units" but for "the vast majority of
units". Given that there are roughly half and half market share of
"enable *" and "disable *" policy distributions - optimising for one
and stating that the other one is "don't do that" is not the best
choice. Also there are a lot of distributions that strike to make
upgrades be the same as fresh installs, in terms of defaults applied -
if defaults were not changed, new defaults should apply. Which, imho,
is also the notion why all configuration should be compiled in
constants or in /usr, with overrides in /run /etc and similar.

-- 
Regards,

Dimitri.
 -
Intel Corporation (UK) Ltd. - Co. Reg. #1134945 - Pipers Way, Swindon SN3 1RJ.


More information about the systemd-devel mailing list