[systemd-devel] /usr vs /etc for default distro units enablement

Didier Roche didrocks at ubuntu.com
Fri Dec 5 02:06:05 PST 2014

Le 05/12/2014 02:13, Lennart Poettering a écrit :
> On Tue, 02.12.14 12:50, Didier Roche (didrocks at ubuntu.com) wrote:
>> Just to sum up other branches of this thread: we are trying to avoid having
>> systemctl calls in debian/ubuntu postinst (or duplicated manual symlinks
>> logic as we currently have).
>> systemctl preset seems the cleanest path, but we want to ensure corner cases
>> can be handled.
>> d/u policy is to enable newly installed package by default (difference from
>> other distributions)
>> Le 02/12/2014 01:59, Lennart Poettering a écrit :
>>>> I don't think we should have systemctl preset <new_service> running under
>>>> any condition as a wipe of /etc and then "systemctl preset-all" would give a
>>>> potential different result (I'm not even sure how this will work with those
>>>> alias, the first matching the alias wins and get the symlinks?)
>>> Dont follow? "wipe"?
>> I meant deleting the entire "/etc" content (or I guess as you told using
>> systemctl preset-all to reset to default):
>> 1. lightdm and gdm were installed on my system.
>> 2. gdm was enabled as the default display-manager.
>> 3. I then use "systemctl preset-all"
>> -> how the behavior of selecting the display-manager will be determined? See
>> below implementing this with presets where enabling all services is the
>> default.
> Hmm, this is actually undefined currently. THe code for preset-all
> iterates through the unit paths and processes the files in the order
> they are read by readdir(), which is pretty much undefined. We really
> should investigate what to do about that. Probably just order things
> lexicographically. I added this to the TODO list for now.

See my suggestion below.

>> So we need for any services shipping Aliases to have a preset list per
>> flavor (if their behaviors differs) with:
>> 99-ubuntu-desktop.preset:
>> enable lightdm.service
>> disable kdm.service
>> disable gdm.service
>> disable nodm.service
>> (and whatnot… dm files in distro)
> Hmm, indeed I guess...
>> Then, we would have 01-ubuntu-gnome.preset:
>> enable gdm.service
>> disable lightdm.service
>> disable kdm.service
>> It seems maintaining this list in sync for all flavors would be a growing
>> pain (this is a positive effect of the disable by default: you don't have to
>> maintain such a list), or do you think we can come with something
>> better?
> Hmm, yuck. No good suggestion. I figure this problem doesn't exist
> with the fedora default of everything is disabled by default...
> All open to ideas...

Can we maybe extend the preset dictionary by having an alias (or 
alias-default) keyword taking a pair of arguments, like:
alias display-manager.service lightdm.service

Then, the preset command, for each alias, will stop at the first one it 
encounters. If the service doesn't exist, it's a noop, if it's there, it 
enables (--force in case something else was enabled for that Alias?) 
lightdm.service. It means of course that lightdm.service should contain:

or preset would then generates a warning.

>> Finally, on the "know what the administrator did on this machine", here are
>> two cases that we can identify:
>> I. if the administrator removes the service package, we usually keep current
>> service state (enabled/disabled) on reinstall.
>> So:
>> <foo.service> enabled by default
>> 1. systemctl disable foo.service
>> 2. apt-get remove foo
>> 3. apt-get install foo
>> -> foo should still be disabled. However, that won't be the case as on
>> reinstall, systemctl preset will re-enable the service as of the preset
>> policy.
>> Indeed, we don't have any record that the admin disabled it compared default
>> distro policy as there is no difference between: "no previous installation
>> state" and "service being disabled state" (no symlink).
> Yeah, not sure how you can provide that with the scheme we devised
> there in systemd. Sorry!
> All ears for ideas...
>> So, I think we should really be able to fix case I.
> I mean, you can fix case I, by explicitly storing the state away
> before you remove a package.

Or storing only the previous *default* state?
Then, we can have a trigger updating that previous distro state 
(combining services installed and default preset) everytime we 
install/update a package containing a preset file or a an unit file?

> How does this all precisely work on  on ?

Most of them shipped a conffile like /etc/default/<service_name> file 
with an ENABLED=true/false keyword. This doesn't really map in the 
systemd world (repetition of enablement/disablement states)
* "apt-get remove" keeps conffiles
* "apt-get remove --purge" deletes them.
* When an upgrade occurs:
   - if the package conffile didn't change -> kept with the 
modifications if any
   - if the package conffile did change -> infamous debconf prompt about 
"a maintainer configuration file changes, do you want to apply 
maintainer changes/keep as it is/see the diff…"

That's how all those use cases are handled on sysvinit.
Of course, we could introduce that back with ExecStartPre=`grep …` but 
well, 2 places (systemd symlinks + a /etc/default/ file) to decide one 
thing isn't really appealing nor wanted :)

>> Also, we would have to condition the systemctl preset call (we have
>> idempotent postinst script, and need to track new installs from
>> upgrade, as we run those during postinst configure). We proposed the
>> separate /usr vs /etc as this would have been a simple way to know
>> what the admins changed compared to the default. Any idea on how we
>> can solve that with the existing concepts?
> Hmm, not following? .deb packages scriptlets can determine if they are
> running on first install or on upgrade, right? So you can invoke
> "systemctl preset" in the first case only, right?

Only preinst can (getting the "install" or "upgrade" argument), not 
postinst (getting "configure" in both case). And we need to run the 
preset/enable in postinst (meaning: after unpacking).

I'm happy to prototype any idea that can come along or if there is a 
start of agreement on.
We can either discuss that on pre-FOSDEM hackfest as it may be easier to 
have that discussion live, but I can work on something a little bit 
earlier if there is a clear direction on how to handle this as close as 
upstream (I would prefer to have those facilities in systemd code 
itself, even if it's a separate binary that we trigger than a distro-patch).

For now, it seems that storing the previous (I guess default) state 
would be the best option, get the new files (with eventually new 
defaults) installed, and compute what was the difference between old 
state <-> admin choice difference to know which units we shouldn't rerun 
preset on.
If a package is purged, we remove that unit old default state from this 

Does it makes sense? I'm starting to draft all use cases in a 
(hopefully) clear small document. I'm opened to any suggestions (and 
once again, happy to push that case/work on that case forward) ;)

More information about the systemd-devel mailing list