Discussion:
/usr vs /etc for default distro units enablement
(too old to reply)
Didier Roche
2014-11-18 11:11:33 UTC
Permalink
Fedora doesn't enable and start all units on package installation: there
are some preset files, based on flavors, which is basically the policy
stating which units to enable/disable by default. Some other units are
always enabled (unless masked), by using symlinks directly shipped with
the package like in /usr/lib/systemd/system/multi-users.target.wants/
for intance. Contrary to that, Debian/Ubuntu has the policy to
enable/start services and facilities on package installation during
postinst. This is done (indirectly) via "systemctl enable", which
creates symlinks in /etc/systemd/system/*.wants/.

This has 3 drawbacks:
- Duplicate symlinks for the same targets between /etc and units enabled
in /usr/lib for units which are already enabled via /usr/lib, if the
admin runs "enable"
- Wrt. the "golden image, /etc reset" approach of reducing base os
installation defaults in /etc, this is another instance of "always needs
to be there" clutter in /etc. If the package default is to start the
service, then it's better to just ship that wants.d/ symlink in the
package (and thus in /usr) instead of always having to create the
symlink in /etc at package install time or after a factory reset.
- We are mixing sys admin information and distro default choices in the
same directories, and can't tell apart what is what.

We were thus thinking about having all default distro choices shipping
target symlinks in /usr/lib, and having the administrator overrides this
in /etc via systemctl. This could look similar to masking a unit, i. e.
a symlink "/etc/.../wants.d/foo -> /dev/null" overrides
"/usr/lib/.../wants.d/foo -> ../foo.service", and would be an explicit
representation of "the admin does not want foo.service to autostart" in
/etc.


However, we did notice the following: taking an unit, with an [Install]
section and a symlink to enable in via that target in /usr/lib:
- systemctl status <unit> will report "disabled", where it's actually
enabled and starting for that unit. This is a bug which should be fixed
in any case, as "disabled" is outright wrong. On IRC it was suggested
that those are "static" units, but then it should say at least that.
- systemctl enable <unit> will duplicate the symlink in /etc
- If we ln -s /dev/null /etc/<
>/<
>.wants/<unit>, then systemctl status
<unit> will display the unit as being enabled, and it will activated
once the target is reached. This is also counterintuitive, as usually
this means to mask/completely disable the unit.

Part of the discussion on #systemd pointed out that the admin should
then use systemctl mask <unit>. However, that means:
- The admin can't retarget a default installed unit without recreating
another unit file
- There are 2 commands to "disable" an unit: mask for some, disable for
others, this can bring confusion and admins won't know the semantic
difference between the two (and indeed this is rather technical and
unintuitive)
- The status reported with systemctl is still disabled when it's not.

Tested with systemd 216 on fedora 21 and systemd 215 on ubuntu vivid.

It will be great if we can come to some common grounds on how we should
separate admin choices and default distro choices, while still working
on the "remove /etc default distro configuration" . I'm happy to give a
hand on the desired solutions there.

Cheers,
Didier
Colin Guthrie
2014-11-18 11:30:43 UTC
Permalink
Post by Didier Roche
Fedora doesn't enable and start all units on package installation: there
are some preset files, based on flavors, which is basically the policy
stating which units to enable/disable by default. Some other units are
always enabled (unless masked), by using symlinks directly shipped with
the package like in /usr/lib/systemd/system/multi-users.target.wants/
for intance. Contrary to that, Debian/Ubuntu has the policy to
enable/start services and facilities on package installation during
postinst. This is done (indirectly) via "systemctl enable", which
creates symlinks in /etc/systemd/system/*.wants/.
I believe that it is generally discouraged to use "systemctl enable"
indirectly or otherwise during postinst.

You should instead use systemctl preset which uses information in
various distro provided *.preset files that contain rules for which
units should be enabled or disabled.

This allows a "default" /etc tree of symlinks to be repopulated easily.
Post by Didier Roche
- Duplicate symlinks for the same targets between /etc and units enabled
in /usr/lib for units which are already enabled via /usr/lib, if the
admin runs "enable"
If a package ships a unit enabled via a symlink in /usr/lib, then that
same package should ensure the systemd unit does NOT have an [Install]
section.

Doing so is confusing to the user, so if the packager makes this
decision, he should follow it through properly.

If this is an upstream make-install rule, then it should be fixed
upstream to make it consistent - again the rules is "if you ship a
symlink in /usr/lib, you should not have an [Install] section" (I think
this is good advice but I'm sure someone will correct me if I'm wrong!).


I won't discuss the merits of shipping an enabling link in /usr/lib.
Post by Didier Roche
- Wrt. the "golden image, /etc reset" approach of reducing base os
installation defaults in /etc, this is another instance of "always needs
to be there" clutter in /etc. If the package default is to start the
service, then it's better to just ship that wants.d/ symlink in the
package (and thus in /usr) instead of always having to create the
symlink in /etc at package install time or after a factory reset.
Yes and no. Depending on your use case perhaps shipping it in /usr/lib
is OK (e.g. an embedded system that still wants to support factory
reset), but I'd say that generally speaking, this is what *.preset files
and systemctl preset is meant to achieve. They represent the distro
rules, but still give users full control after the default rules are
applied.
Post by Didier Roche
- We are mixing sys admin information and distro default choices in the
same directories, and can't tell apart what is what.
/etc is admin, and the distro *default* is applied there (via *.preset
files) but the admin still has full control.
Post by Didier Roche
We were thus thinking about having all default distro choices shipping
target symlinks in /usr/lib, and having the administrator overrides this
in /etc via systemctl. This could look similar to masking a unit, i. e.
a symlink "/etc/.../wants.d/foo -> /dev/null" overrides
"/usr/lib/.../wants.d/foo -> ../foo.service", and would be an explicit
representation of "the admin does not want foo.service to autostart" in
/etc.
I really don't think that's a good idea. Just use preset and setup /etc/
by default, but let the admin override it as needed.
Post by Didier Roche
However, we did notice the following: taking an unit, with an [Install]
- systemctl status <unit> will report "disabled", where it's actually
enabled and starting for that unit. This is a bug which should be fixed
in any case, as "disabled" is outright wrong.
This is why I stated above that if you ship an enabling symlink in
/usr/lib, you should also remove the [Install] section. I still think
this is the right solution here.
Post by Didier Roche
On IRC it was suggested
that those are "static" units, but then it should say at least that.
- systemctl enable <unit> will duplicate the symlink in /etc
- If we ln -s /dev/null /etc/<…>/<…>.wants/<unit>, then systemctl status
<unit> will display the unit as being enabled, and it will activated
once the target is reached. This is also counterintuitive, as usually
this means to mask/completely disable the unit.
I don't think this is a good idea. I really think you should just use
*.preset files properly and generally discourage the shipping of any
enabling symlinks in /usr/lib. And if you do have some special cases
where you want to do that, have a policy that bans an [Install] section
in such units.
Post by Didier Roche
It will be great if we can come to some common grounds on how we should
separate admin choices and default distro choices, while still working
on the "remove /etc default distro configuration" . I'm happy to give a
hand on the desired solutions there.
I think the following is best practice and solves the general issues here:

1. Discourage strongly the shipping of enabling symlinks in /usr/lib
(but aliases are probably OK).
2. If a special case arises where a an enabling /usr/lib symlink is
deemed the best option, the unit must not have an [Install] section.
3. Do not use "systemctl enable myunit.service" (directly or indirectly)
in packaging postinst, but rely on "systemctl preset myunit.service"
instead to capture the distribution (or spin) rules.

This deals means:

1. distro installs the default setup for users, but admins can override
later
2. factory reset works fine (assuming "systemctl preset-all
--preset-mode=enable" is run after reset)
3. systemctl status will work (because only units without [Install]
sections will have enabling links in /usr/lib)

Have I missed something or does this sound good to you too?

Col
--
Colin Guthrie
gmane(at)colin.guthr.ie
http://colin.guthr.ie/

Day Job:
Tribalogic Limited http://www.tribalogic.net/
Open Source:
Mageia Contributor http://www.mageia.org/
PulseAudio Hacker http://www.pulseaudio.org/
Trac Hacker http://trac.edgewall.org/
Martin Pitt
2014-11-18 12:01:51 UTC
Permalink
Hello Colin, all,
Post by Colin Guthrie
I believe that it is generally discouraged to use "systemctl enable"
indirectly or otherwise during postinst.
Right, I don't like this either, hence this discussion. :-) I don't
know whether Debian's current way of enabling units on package install
has ever been discussed here, but Didier and I would like to
understand the options and some recommendations, to consider whether
it makes sense to change this in D/U.
Post by Colin Guthrie
You should instead use systemctl preset which uses information in
various distro provided *.preset files that contain rules for which
units should be enabled or disabled.
This allows a "default" /etc tree of symlinks to be repopulated easily.
We can certainly ship a preset of "enable *" to reflect the policy
that in general services do get enabled by default. But this still
leaves some issues:

* I suppose even wich such a policy the post-installation script
still needs to call some systemd-update-policy-mumble-mumble magic
to actually apply the new policy?

* With that, how would a package then say that it does *not* want a
particular unit to get enabled?

* This doesn't solve the problem of having these rather uninteresting
and cluttering symlinks in /etc at all; the wants.d symlinks would
still be as they are now, just the place that decides when to
enable them changes.
Post by Colin Guthrie
If a package ships a unit enabled via a symlink in /usr/lib, then that
same package should ensure the systemd unit does NOT have an [Install]
section.
Doing so is confusing to the user, so if the packager makes this
decision, he should follow it through properly.
But then you would entirely lose the information into which target a
service belongs by default. In particular, an administrator couldn't
override the default it with "systemd disable" (I know that this
doesn't work right now, but it's part of the discussion).
Post by Colin Guthrie
If this is an upstream make-install rule, then it should be fixed
upstream to make it consistent - again the rules is "if you ship a
symlink in /usr/lib, you should not have an [Install] section" (I think
this is good advice but I'm sure someone will correct me if I'm wrong!).
I think there are some plymouth .service files with that problem, but
as far as I can see, most upstreams leave it to packagers to enable
their units.
Post by Colin Guthrie
Post by Didier Roche
- Wrt. the "golden image, /etc reset" approach of reducing base os
installation defaults in /etc, this is another instance of "always needs
to be there" clutter in /etc. If the package default is to start the
service, then it's better to just ship that wants.d/ symlink in the
package (and thus in /usr) instead of always having to create the
symlink in /etc at package install time or after a factory reset.
Yes and no. Depending on your use case perhaps shipping it in /usr/lib
is OK (e.g. an embedded system that still wants to support factory
reset), but I'd say that generally speaking, this is what *.preset files
and systemctl preset is meant to achieve. They represent the distro
rules, but still give users full control after the default rules are
applied.
I might misunderstand presets, but as I wrote above they don't address
this at all -- even with them you have preset-induced wants.d/
symlinks in /etc.

I. e. my question is not so much about being able to restore the
default wants.d symlinks in /etc after a factory reset -- there are
multiple ways how this can be done: with presets or iterating over the
installed packages and re-enabling them (Debian also does some
house-keeping which unit files got enabled by postinstall scripts,
which can simply be replayed).

I was rather wondering whether we couldn't make all that
post-processing much simpler by not requiring any /etc/**/wants.d/
links at all. And everything which *is* in /etc/**/wants.d/ would then
be explicit admin choices, with both enabling and disabling units.
Post by Colin Guthrie
Post by Didier Roche
- We are mixing sys admin information and distro default choices in the
same directories, and can't tell apart what is what.
/etc is admin, and the distro *default* is applied there (via *.preset
files) but the admin still has full control.
Sure she does, but this still makes it waaay harder to see on a system
how it deviates from the default install.
Post by Colin Guthrie
1. Discourage strongly the shipping of enabling symlinks in /usr/lib
(but aliases are probably OK).
I'm interested in the reason for that. This basically cements the
status quo that one *has* to have a gazillion links in /etc in order
for your system to work, even if they are not at all specific to the
particular system or represent a deviation from the default install.
Post by Colin Guthrie
2. If a special case arises where a an enabling /usr/lib symlink is
deemed the best option, the unit must not have an [Install] section.
I rather want to discuss this in the general case, to reduce the
clutter in /etc/. I don't think it's right to remove [Install] for
all units, see above.
Post by Colin Guthrie
3. Do not use "systemctl enable myunit.service" (directly or indirectly)
in packaging postinst, but rely on "systemctl preset myunit.service"
instead to capture the distribution (or spin) rules.
That part is fair enough, and we can see whether that should be done
in Debian, but in practice it will make absolutely no difference wrt.
file system layout, cleaning up /etc/, and making admin choices more
obvious.
Post by Colin Guthrie
1. distro installs the default setup for users, but admins can override
later
2. factory reset works fine (assuming "systemctl preset-all
--preset-mode=enable" is run after reset)
3. systemctl status will work (because only units without [Install]
sections will have enabling links in /usr/lib)
I fully agree on these properties; your recommendations from above
(which is essentially the status quo) certainly works for that, but I
really think we can do better here.

With our proposal these properties would also be satisfied, except
with no churn in package install (systemctl enable or preset),
initialization of a system with empty /etc/, and cleanliness of /etc.

Thanks,

Martin
--
Martin Pitt | http://www.piware.de
Ubuntu Developer (www.ubuntu.com) | Debian Developer (www.debian.org)
Colin Guthrie
2014-11-18 13:01:46 UTC
Permalink
Post by Martin Pitt
Hello Colin, all,
Post by Colin Guthrie
I believe that it is generally discouraged to use "systemctl enable"
indirectly or otherwise during postinst.
Right, I don't like this either, hence this discussion. :-) I don't
know whether Debian's current way of enabling units on package install
has ever been discussed here, but Didier and I would like to
understand the options and some recommendations, to consider whether
it makes sense to change this in D/U.
Post by Colin Guthrie
You should instead use systemctl preset which uses information in
various distro provided *.preset files that contain rules for which
units should be enabled or disabled.
This allows a "default" /etc tree of symlinks to be repopulated easily.
We can certainly ship a preset of "enable *" to reflect the policy
that in general services do get enabled by default. But this still
* I suppose even wich such a policy the post-installation script
still needs to call some systemd-update-policy-mumble-mumble magic
to actually apply the new policy?
Well, the *.policy files are simply read when calling "systemctl preset"

The idea is that there are very few policy files shipped in a distro and
on initial installation (and depending on how the installer wors), they
would be installed very early on such that any postinst script of
packages getting installed would adhere to that policy.

I would say it's generally discouraged to "reapply" a policy again at a
later date as this would override any admin decisions made in the meantime.

I'd say it's perfectly acceptable to call systemctl preset-all
--preset-mode=full at the end of an installation however.
Post by Martin Pitt
* With that, how would a package then say that it does *not* want a
particular unit to get enabled?
The idea is that you don't really decide that at a package level, but at
a distro level.

The distro (or spin) might make these default decisions and ship them in
the ubuntu.preset file accordingly.

So ultimately the *package* doesn't decided. The vendor decides that
"this is a package that should go against our normal policy" and embed
that information in their policy file.

It's not generally encouraged to ship *.preset files with packages
(nothing to stop you of course, but the idea is to keep these preset
files fairly manageable and thus allow easy respins of distros using the
same packages but perhaps taking on different policies).
Post by Martin Pitt
* This doesn't solve the problem of having these rather uninteresting
and cluttering symlinks in /etc at all; the wants.d symlinks would
still be as they are now, just the place that decides when to
enable them changes.
Indeed, but ultimately if you want to make something configurable in
some capacity, you have to put that configuration somewhere and /etc is
the defacto place to put it.

So I'd say that if these really are things you want admins to be able to
disable, then having them here is correct.
Post by Martin Pitt
Post by Colin Guthrie
If a package ships a unit enabled via a symlink in /usr/lib, then that
same package should ensure the systemd unit does NOT have an [Install]
section.
Doing so is confusing to the user, so if the packager makes this
decision, he should follow it through properly.
But then you would entirely lose the information into which target a
service belongs by default.
Only if you don't look at the shipped symlink - it would still be
embedded in that.
Post by Martin Pitt
In particular, an administrator couldn't
override the default it with "systemd disable" (I know that this
doesn't work right now, but it's part of the discussion).
Yes, it's true that an admin could not override the default target but
he could easily add the unit to *another* target via a wants symlink in
/etc/.

But I'd say that if you, as a vendor, are shipping an enabling symlink
in /usr/lib in the first place, you're making a concious decision that
this is something you don't generally want an admin to override easily.
The admin only really has the choice of masking it.

My general recommendation would be that if you want to let the admin
control things, then don't ship the enabling symlink in /usr/lib :)
Post by Martin Pitt
Post by Colin Guthrie
If this is an upstream make-install rule, then it should be fixed
upstream to make it consistent - again the rules is "if you ship a
symlink in /usr/lib, you should not have an [Install] section" (I think
this is good advice but I'm sure someone will correct me if I'm wrong!).
I think there are some plymouth .service files with that problem, but
as far as I can see, most upstreams leave it to packagers to enable
their units.
All of my plymouth units show as static here so I don't think any have
[Install] sections:


[***@jimmy log (master)]$ systemctl status plymouth-*
● plymouth-start.service - Show Plymouth Boot Screen
Loaded: loaded (/usr/lib/systemd/system/plymouth-start.service; static)
Active: inactive (dead) since Fri 2014-11-14 15:28:55 GMT; 3 days ago
Main PID: 150 (code=exited, status=0/SUCCESS)

● plymouth-read-write.service - Tell Plymouth To Write Out Runtime Data
Loaded: loaded (/usr/lib/systemd/system/plymouth-read-write.service;
static)
Active: inactive (dead) since Fri 2014-11-14 15:28:53 GMT; 3 days ago
Main PID: 279 (code=exited, status=0/SUCCESS)

● plymouth-quit.service - Terminate Plymouth Boot Screen
Loaded: loaded (/usr/lib/systemd/system/plymouth-quit.service; static)
Active: inactive (dead)

● plymouth-quit-wait.service - Wait for Plymouth Boot Screen to Quit
Loaded: loaded (/usr/lib/systemd/system/plymouth-quit-wait.service;
static)
Active: inactive (dead) since Fri 2014-11-14 15:28:55 GMT; 3 days ago
Main PID: 373 (code=exited, status=0/SUCCESS)


("grep Install /usr/lib/systemd/system/plymouth*.service" confirms no
matches and I don't see any downstream patches)


But indeed, most upstreams do (and indeed should) not ship an enabling
symlink. Most things are ultimately admin decisions so it's quite rare
that you'd want such symlinks. I'd say plymouth is a good example of
somewhere where it makes sense to enable them all the time as it has a
different enabling mechanism outside of systemd and thus shipping the
enabling symlinks kinda makes sense and avoids potential breakage if
admins interfere!
Post by Martin Pitt
Post by Colin Guthrie
Post by Didier Roche
- Wrt. the "golden image, /etc reset" approach of reducing base os
installation defaults in /etc, this is another instance of "always needs
to be there" clutter in /etc. If the package default is to start the
service, then it's better to just ship that wants.d/ symlink in the
package (and thus in /usr) instead of always having to create the
symlink in /etc at package install time or after a factory reset.
Yes and no. Depending on your use case perhaps shipping it in /usr/lib
is OK (e.g. an embedded system that still wants to support factory
reset), but I'd say that generally speaking, this is what *.preset files
and systemctl preset is meant to achieve. They represent the distro
rules, but still give users full control after the default rules are
applied.
I might misunderstand presets, but as I wrote above they don't address
this at all -- even with them you have preset-induced wants.d/
symlinks in /etc.
I. e. my question is not so much about being able to restore the
default wants.d symlinks in /etc after a factory reset -- there are
multiple ways how this can be done: with presets or iterating over the
installed packages and re-enabling them (Debian also does some
house-keeping which unit files got enabled by postinstall scripts,
which can simply be replayed).
I was rather wondering whether we couldn't make all that
post-processing much simpler by not requiring any /etc/**/wants.d/
links at all. And everything which *is* in /etc/**/wants.d/ would then
be explicit admin choices, with both enabling and disabling units.
OK, but I think this is the wrong approach personally.

I see the symlinks as desirable and necessary and they accurately
reflect the state of things as desired by the vendor and/or the admin,
whether this is immediately after a factory reset, after a puppet run or
after several years of admins randomly enabling and disabling things.


I think moving enabling symlinks into the packages (and thus /usr) has
several drawbacks:

1. It pushes decision making on such policy to be distributed through
thousands of packages rather than being centralised and thus makes it
very difficult to do respins and change such policy centrally.

2. It makes the packaging task more complex - these links have to be
created during packaging (although I'm sure this could be mostly automated).

3. I makes it much less clear to users if they see such links embedded
and shipped with packages (IMO) but can still disable them if they so wish.


So I guess my reply to this is, this is OK, and I think this goal is not
one to aim for. It's "state" information and it should be represented in
/etc and I don't think trying to reduce this is a good idea (personally!) :)
Post by Martin Pitt
Post by Colin Guthrie
Post by Didier Roche
- We are mixing sys admin information and distro default choices in the
same directories, and can't tell apart what is what.
/etc is admin, and the distro *default* is applied there (via *.preset
files) but the admin still has full control.
Sure she does, but this still makes it waaay harder to see on a system
how it deviates from the default install.
Perhaps teaching systemd-delta or systemctl status to show you the
preset state would solve this problem? e.g. if it showed something like:


[***@jimmy log (master)]$ systemctl status sshd.service
● sshd.service - OpenSSH server daemon
Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled
[preset: disabled])
Active: active (running) since Fri 2014-11-14 15:29:28 GMT; 3 days ago
Main PID: 18816 (sshd)
CGroup: /system.slice/sshd.service
└─18816 /usr/sbin/sshd -D


Perhaps that would help?

Perhaps we could even add two more (optional) columns to systemctl
list-units for "ENABLED" and "PRESET"?

This way it works just as well for ssh (which you maybe enable by
default on Ubuntu - I've not checked!) to properly reflect the preset
state when shipped with a "Secbuntu" respin which has more paranoid
service policy (because it ships different preset files) without needing
to actually ship a different sshd package.
Post by Martin Pitt
Post by Colin Guthrie
1. Discourage strongly the shipping of enabling symlinks in /usr/lib
(but aliases are probably OK).
I'm interested in the reason for that. This basically cements the
status quo that one *has* to have a gazillion links in /etc in order
for your system to work, even if they are not at all specific to the
particular system or represent a deviation from the default install.
Depends what you mean by "work" here tho'. I mean, the system should be
able to *boot* without lots of service enabled, but it's ultimately your
*choice* that you want to run sshd or faxd or postfix etc and I
personally don't see a problem with storing this configuration (aka a
gazillion links) in /etc.
Post by Martin Pitt
Post by Colin Guthrie
2. If a special case arises where a an enabling /usr/lib symlink is
deemed the best option, the unit must not have an [Install] section.
I rather want to discuss this in the general case, to reduce the
clutter in /etc/. I don't think it's right to remove [Install] for
all units, see above.
Fair enough, I won't beat the drum too much :) But I do think this
configuration is exactly that, configuration, and thus living in /etc/
is both expected and normal.
Post by Martin Pitt
Post by Colin Guthrie
3. Do not use "systemctl enable myunit.service" (directly or indirectly)
in packaging postinst, but rely on "systemctl preset myunit.service"
instead to capture the distribution (or spin) rules.
That part is fair enough, and we can see whether that should be done
in Debian, but in practice it will make absolutely no difference wrt.
file system layout, cleaning up /etc/, and making admin choices more
obvious.
I kinda disagree that it makes admin choices more obvious. I often list
files in a package to look at what it contains and if I see an enabling
symlink I might be fooled into thinking something should be enabled,
even if some other, non-packaged, config overrules it. This can happen
just now for masking but opening it up for regular disabling too would
seem like a bad idea with respect to clarity to me (again, just my
personal opinion).

But hopefully my systemctl status/list-units suggestions above might be
good solutions here anyway.
Post by Martin Pitt
Post by Colin Guthrie
1. distro installs the default setup for users, but admins can override
later
2. factory reset works fine (assuming "systemctl preset-all
--preset-mode=enable" is run after reset)
3. systemctl status will work (because only units without [Install]
sections will have enabling links in /usr/lib)
I fully agree on these properties; your recommendations from above
(which is essentially the status quo) certainly works for that, but I
really think we can do better here.
With our proposal these properties would also be satisfied, except
with no churn in package install (systemctl enable or preset),
initialization of a system with empty /etc/, and cleanliness of /etc.
Well, I really think that pushing policy down to the package level is a
real backward step. I mean, it's one of the main principles that the
systemctl preset feature was developed to *avoid* in the first place!
See the first paragraph under "The Logic" on the preset wiki page:

http://freedesktop.org/wiki/Software/systemd/Preset/


But anyway, I think I've made my opinion clear enough, so will let
others comment on your general suggestions.

All the best!

Col
--
Colin Guthrie
gmane(at)colin.guthr.ie
http://colin.guthr.ie/

Day Job:
Tribalogic Limited http://www.tribalogic.net/
Open Source:
Mageia Contributor http://www.mageia.org/
PulseAudio Hacker http://www.pulseaudio.org/
Trac Hacker http://trac.edgewall.org/
Martin Pitt
2014-11-18 13:52:04 UTC
Permalink
Hey Colin,

thanks for the discussion! Trimming heavily; as you said we should let
some other upstreams chime in too, I just have some followup
questions.
Post by Colin Guthrie
Post by Martin Pitt
* I suppose even wich such a policy the post-installation script
still needs to call some systemd-update-policy-mumble-mumble magic
to actually apply the new policy?
Well, the *.policy files are simply read when calling "systemctl preset"
Right. I meant, even with using presets, a newly installed package
still needs to call "systemd preset foo.service" for all the units
that it ships, so that the /etc symlinks are generated. I. e. we
merely replace "enable" (what the current Debian packages do) with
"preset" in the postinst.

We need to do that as systemd doesn't automagically spot newly
installed units (via inotify or what not) and enable them.

Or did I misunderstand this?
Post by Colin Guthrie
The idea is that there are very few policy files shipped in a distro
Indeed. A generic distro should have exactly one, with "disable *"
(Fedora policy) or "enable *" (Debian policy). Anything more special
would be customization for specialized images/spins/etc.
Post by Colin Guthrie
Post by Martin Pitt
* With that, how would a package then say that it does *not* want a
particular unit to get enabled?
The idea is that you don't really decide that at a package level, but at
a distro level.
We do (and that policy drives the auto-generated postinst), but there
are always special cases where a package might want to ship a unit
which doesn't get enabled by default. I was wondering how that could
be accomodated. So for that, the package itself could ship its own
preset file, containing a "disable myself.service"? That would make
sense (if I understood it right). Either way, this is certainly the
rare exception.
Post by Colin Guthrie
Post by Martin Pitt
* This doesn't solve the problem of having these rather uninteresting
and cluttering symlinks in /etc at all; the wants.d symlinks would
still be as they are now, just the place that decides when to
enable them changes.
Indeed, but ultimately if you want to make something configurable in
some capacity, you have to put that configuration somewhere and /etc is
the defacto place to put it.
Fully agreed. Any admin change should go into /etc. My point is,
distro/package defaults should *not*.
Post by Colin Guthrie
But I'd say that if you, as a vendor, are shipping an enabling symlink
in /usr/lib in the first place, you're making a concious decision that
this is something you don't generally want an admin to override easily.
The admin only really has the choice of masking it.
Yeah, that's not what I had in mind. I want to keep the interface and
notion of enable/disable for admins, just implement the
representation of these choices differently in /etc/ (i. e. just
represent the admin changes, not distro defaults plus admin changes).
Post by Colin Guthrie
I think moving enabling symlinks into the packages (and thus /usr) has
1. It pushes decision making on such policy to be distributed through
thousands of packages rather than being centralised and thus makes it
very difficult to do respins and change such policy centrally.
Right, this can't be done with Debian ATM as postinsts use systemctl
enable. Moving to preset would fix that part. So, thanks again for
pointing that out, this is something that we should do, independently
of the (totally orthogonal) discussion of how to treat wants symlinks
in /etc/ vs. /usr.
Post by Colin Guthrie
2. It makes the packaging task more complex - these links have to be
created during packaging (although I'm sure this could be mostly automated).
Yeah, it is.
Post by Colin Guthrie
So I guess my reply to this is, this is OK, and I think this goal is not
one to aim for. It's "state" information and it should be represented in
/etc and I don't think trying to reduce this is a good idea (personally!) :)
Okay. I was wondering if that was merely an oversight, or if there are
people who actually want it the way it is currently. Here is the answer :-)
Post by Colin Guthrie
Perhaps teaching systemd-delta or systemctl status to show you the
● sshd.service - OpenSSH server daemon
Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled
[preset: disabled])
Perhaps that would help?
That would certainly help already, as then admins would have *a* way
to check what was changed in the system.
Post by Colin Guthrie
Well, I really think that pushing policy down to the package level is a
real backward step. I mean, it's one of the main principles that the
systemctl preset feature was developed to *avoid* in the first place!
Indeed! I think the current packaging scripts in Debian still date
from the time when presets didn't exist, so systemctl enable is all we
had.

Thanks,

Martin
--
Martin Pitt | http://www.piware.de
Ubuntu Developer (www.ubuntu.com) | Debian Developer (www.debian.org)
Colin Guthrie
2014-11-18 14:40:14 UTC
Permalink
Post by Martin Pitt
Hey Colin,
thanks for the discussion! Trimming heavily; as you said we should let
some other upstreams chime in too, I just have some followup
questions.
Post by Colin Guthrie
Post by Martin Pitt
* I suppose even wich such a policy the post-installation script
still needs to call some systemd-update-policy-mumble-mumble magic
to actually apply the new policy?
Well, the *.policy files are simply read when calling "systemctl preset"
Right. I meant, even with using presets, a newly installed package
still needs to call "systemd preset foo.service" for all the units
that it ships, so that the /etc symlinks are generated. I. e. we
merely replace "enable" (what the current Debian packages do) with
"preset" in the postinst.
We need to do that as systemd doesn't automagically spot newly
installed units (via inotify or what not) and enable them.
Or did I misunderstand this?
Oh right I see what you mean.

Well the "upstream blessed" RPM way is to call "%systemd_post" macro in
your %post script, but (personally) I don't like this as it makes the
implementation very much embedded into the RPMs so changing the upstream
macro needs a full package rebuild.

In Mageia we do something similar but we shell out to a script instead.
This allows us to replace the implementation without rebuilding all
packages. This is a double edged sword however, as on distro upgrades
we've got to make sure the package we ship our scripts in is upgraded
before we actually do anything.

Longer term, I want to move this to filetriggers. We have been using
filetriggers for a while via an RPM patch and it looks like some kind of
similar functionality will be (at long last) making it to upstream RPM
in the nearish future. I believe .deb supports something like this?

If this is the case, I'd use a filetrigger to spot the
/usr/lib/systemd/system/*.{service,socket,...} units and then call
systemctl preset on them.

I've not yet switched over to this logic yet myself (mainly due to lack
of time to refactor stuff) so I can't really talk from practical
experience yet or highlight any "gotchas" (one thing I do know is that
any service start/reload/restart we may do in %post would have to be
delayed and left to a filetrigger too because we'd have to do this
*after* the call to preset. So I may have to make the current
%_post_service macro just write out some kind of state somewhere to say
"try to start/reload/restart this service" and then process that state
in another filetrigger with the same matching regexp but which runs
later in the %posttrans)

Sorry if that's a bit RPM specific, but I think the same concepts hold
true in .deb.
Post by Martin Pitt
Post by Colin Guthrie
Post by Martin Pitt
* With that, how would a package then say that it does *not* want a
particular unit to get enabled?
The idea is that you don't really decide that at a package level, but at
a distro level.
We do (and that policy drives the auto-generated postinst), but there
are always special cases where a package might want to ship a unit
which doesn't get enabled by default. I was wondering how that could
be accomodated. So for that, the package itself could ship its own
preset file, containing a "disable myself.service"? That would make
sense (if I understood it right). Either way, this is certainly the
rare exception.
Indeed there is nothing stopping that but it's also perfectly valid to
decide this centrally too, and just ship your default.preset file with:

disable myservice.service
enable *

(perhaps the other order is wrong tho' - I can't remember the semantics!)

As this is the rare exception there shouldn't be too much churn on this
and mentioning things in the default policy that are not installed is
perfectly OK (even if it might waste a few extra bits).

The ensures the policy (even with it's exceptions) is still managed
centrally and individual packagers are not encouraged to deviate from
this policy.

But ultimately this is just a "recommendation" and there is nothing
stopping you being a rebel :D
Post by Martin Pitt
snipped a bunch of stuff where I was harping on about how things
currently work, ignoring your ideas to change the status quo ;)
Post by Martin Pitt
Post by Colin Guthrie
1. It pushes decision making on such policy to be distributed through
thousands of packages rather than being centralised and thus makes it
very difficult to do respins and change such policy centrally.
Right, this can't be done with Debian ATM as postinsts use systemctl
enable. Moving to preset would fix that part. So, thanks again for
pointing that out, this is something that we should do, independently
of the (totally orthogonal) discussion of how to treat wants symlinks
in /etc/ vs. /usr.
Cool.
Post by Martin Pitt
Post by Colin Guthrie
So I guess my reply to this is, this is OK, and I think this goal is not
one to aim for. It's "state" information and it should be represented in
/etc and I don't think trying to reduce this is a good idea (personally!) :)
Okay. I was wondering if that was merely an oversight, or if there are
people who actually want it the way it is currently. Here is the answer :-)
It could be as the /etc/ enablement stuff pre-dates the more aggressive
push towards a nice, empty /etc. But that said, the preset stuff was
done pretty early and I do still think it's can achieve a nicely
structured outcome (albeit retaining the links in /etc) without adding
other complications with regards to more complex semantics (and possibly
changing semantics currently deployed) and without pushing more burden
onto packaging.
Post by Martin Pitt
Post by Colin Guthrie
Perhaps teaching systemd-delta or systemctl status to show you the
● sshd.service - OpenSSH server daemon
Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled
[preset: disabled])
Perhaps that would help?
That would certainly help already, as then admins would have *a* way
to check what was changed in the system.
Seems Tom made the same suggestion too! :)


Cheers

Col
--
Colin Guthrie
gmane(at)colin.guthr.ie
http://colin.guthr.ie/

Day Job:
Tribalogic Limited http://www.tribalogic.net/
Open Source:
Mageia Contributor http://www.mageia.org/
PulseAudio Hacker http://www.pulseaudio.org/
Trac Hacker http://trac.edgewall.org/
Martin Pitt
2014-11-18 14:49:30 UTC
Permalink
Hey Colin,
Post by Colin Guthrie
In Mageia we do something similar but we shell out to a script instead.
This allows us to replace the implementation without rebuilding all
packages.
Debian does the same, there's a "deb-systemd-helper" wrapper called in
the postinst scripts which then does that.
Post by Colin Guthrie
Longer term, I want to move this to filetriggers. We have been using
filetriggers for a while via an RPM patch and it looks like some kind of
similar functionality will be (at long last) making it to upstream RPM
in the nearish future. I believe .deb supports something like this?
Yes, it has for many years. We've used it for ldconfig, rebuilding the
initrd, updating gsettings schemas and the like, but not so far for
units (and not sure if we actually should, given that not all units
*should* be enabled by default -- hence we want to keep this knowledge
in the package only).
Post by Colin Guthrie
But ultimately this is just a "recommendation" and there is nothing
stopping you being a rebel :D
Heh; well, we deliberately wanted to start discussing it here first,
as none of this is really very distro specific. After all, one of
systemd's aims is to make all the various distros somewhat more alike.
I. e. if that "minimal /etc/" proposal is refused, we just go on and
live with the clutter.

Martin
--
Martin Pitt | http://www.piware.de
Ubuntu Developer (www.ubuntu.com) | Debian Developer (www.debian.org)
Michael Biebl
2014-11-18 15:15:38 UTC
Permalink
Post by Colin Guthrie
Longer term, I want to move this to filetriggers. We have been using
filetriggers for a while via an RPM patch and it looks like some kind of
similar functionality will be (at long last) making it to upstream RPM
in the nearish future. I believe .deb supports something like this?
If this is the case, I'd use a filetrigger to spot the
/usr/lib/systemd/system/*.{service,socket,...} units and then call
systemctl preset on them.
I've not yet switched over to this logic yet myself (mainly due to lack
of time to refactor stuff) so I can't really talk from practical
experience yet or highlight any "gotchas" (one thing I do know is that
any service start/reload/restart we may do in %post would have to be
delayed and left to a filetrigger too because we'd have to do this
*after* the call to preset. So I may have to make the current
%_post_service macro just write out some kind of state somewhere to say
"try to start/reload/restart this service" and then process that state
in another filetrigger with the same matching regexp but which runs
later in the %posttrans)
Sorry if that's a bit RPM specific, but I think the same concepts hold
true in .deb.
As a maybe interesting datapoint, we did use file-triggers in Debian
wheezy to enable unit files.

But this proved to be to inflexible, so we moved away from that model
and let this be done via maintainerscripts now, via dh-systemd helper
to autogenerate that code.

file triggers are great for simple cases, like rebuilding icon caches,
updating the initramfs etc, though.
Lennart Poettering
2014-12-02 00:25:09 UTC
Permalink
Post by Colin Guthrie
Well the "upstream blessed" RPM way is to call "%systemd_post" macro in
your %post script, but (personally) I don't like this as it makes the
implementation very much embedded into the RPMs so changing the upstream
macro needs a full package rebuild.
In Mageia we do something similar but we shell out to a script
instead.
The idea was to make "systemctl preset" generic enough so that it is
all we need to change should we want to change the effect of the RPM
macros one day, if you follow what I mean...

Lennart
--
Lennart Poettering, Red Hat
Colin Guthrie
2014-12-02 10:15:05 UTC
Permalink
Post by Lennart Poettering
Post by Colin Guthrie
Well the "upstream blessed" RPM way is to call "%systemd_post" macro in
your %post script, but (personally) I don't like this as it makes the
implementation very much embedded into the RPMs so changing the upstream
macro needs a full package rebuild.
In Mageia we do something similar but we shell out to a script instead.
The idea was to make "systemctl preset" generic enough so that it is
all we need to change should we want to change the effect of the RPM
macros one day, if you follow what I mean...
Yeah, I follow, and I generally agree with that reasoning for a fresh
install of a fully systemd distro.

In our case, we needed to handle things like transition from sysvinit
scripts to native units, tracking whether they were enabled as sysvinit
and ensuring that state information was mapped over to the native unit
state too (as this was an upgrade, the "systemctl preset" was never run
anyway).

But, yeah, longer term I agree with the rationale.

Col
--
Colin Guthrie
gmane(at)colin.guthr.ie
http://colin.guthr.ie/

Day Job:
Tribalogic Limited http://www.tribalogic.net/
Open Source:
Mageia Contributor http://www.mageia.org/
PulseAudio Hacker http://www.pulseaudio.org/
Trac Hacker http://trac.edgewall.org/
Michael Biebl
2014-11-18 16:11:21 UTC
Permalink
Post by Martin Pitt
Post by Colin Guthrie
Post by Martin Pitt
* I suppose even wich such a policy the post-installation script
still needs to call some systemd-update-policy-mumble-mumble magic
to actually apply the new policy?
Well, the *.policy files are simply read when calling "systemctl preset"
Right. I meant, even with using presets, a newly installed package
still needs to call "systemd preset foo.service" for all the units
that it ships, so that the /etc symlinks are generated. I. e. we
merely replace "enable" (what the current Debian packages do) with
"preset" in the postinst.
We need to do that as systemd doesn't automagically spot newly
installed units (via inotify or what not) and enable them.
Or did I misunderstand this?
Post by Colin Guthrie
The idea is that there are very few policy files shipped in a distro
Indeed. A generic distro should have exactly one, with "disable *"
(Fedora policy) or "enable *" (Debian policy). Anything more special
would be customization for specialized images/spins/etc.
Post by Colin Guthrie
Post by Martin Pitt
* With that, how would a package then say that it does *not* want a
particular unit to get enabled?
The idea is that you don't really decide that at a package level, but at
a distro level.
We do (and that policy drives the auto-generated postinst), but there
are always special cases where a package might want to ship a unit
which doesn't get enabled by default. I was wondering how that could
be accomodated. So for that, the package itself could ship its own
preset file, containing a "disable myself.service"? That would make
sense (if I understood it right). Either way, this is certainly the
rare exception.
I'm not sure if this preset feature with a single, centrally managed
and distro-provided file
is going to work with 1000+ packages shipping sysv init scripts (or in
the future, systemd .service files).

We really need the flexibility to decide that on a per package basis.
--
Why is it that all of the instruments seeking intelligent life in the
universe are pointed away from Earth?
Tom Gundersen
2014-11-18 16:19:39 UTC
Permalink
Post by Michael Biebl
Post by Martin Pitt
Post by Colin Guthrie
Post by Martin Pitt
* I suppose even wich such a policy the post-installation script
still needs to call some systemd-update-policy-mumble-mumble magic
to actually apply the new policy?
Well, the *.policy files are simply read when calling "systemctl preset"
Right. I meant, even with using presets, a newly installed package
still needs to call "systemd preset foo.service" for all the units
that it ships, so that the /etc symlinks are generated. I. e. we
merely replace "enable" (what the current Debian packages do) with
"preset" in the postinst.
We need to do that as systemd doesn't automagically spot newly
installed units (via inotify or what not) and enable them.
Or did I misunderstand this?
Post by Colin Guthrie
The idea is that there are very few policy files shipped in a distro
Indeed. A generic distro should have exactly one, with "disable *"
(Fedora policy) or "enable *" (Debian policy). Anything more special
would be customization for specialized images/spins/etc.
Post by Colin Guthrie
Post by Martin Pitt
* With that, how would a package then say that it does *not* want a
particular unit to get enabled?
The idea is that you don't really decide that at a package level, but at
a distro level.
We do (and that policy drives the auto-generated postinst), but there
are always special cases where a package might want to ship a unit
which doesn't get enabled by default. I was wondering how that could
be accomodated. So for that, the package itself could ship its own
preset file, containing a "disable myself.service"? That would make
sense (if I understood it right). Either way, this is certainly the
rare exception.
I'm not sure if this preset feature with a single, centrally managed
and distro-provided file
is going to work with 1000+ packages shipping sysv init scripts (or in
the future, systemd .service files).
We really need the flexibility to decide that on a per package basis.
You already have this flexibility right? You can drop in any number of
preset files (even one per package if that makes the most sense).

Cheers,

Tom
Lennart Poettering
2014-12-02 00:20:26 UTC
Permalink
Post by Martin Pitt
We can certainly ship a preset of "enable *" to reflect the policy
that in general services do get enabled by default. But this still
No need to ship "enable *", btw. It's the implied default if no preset
file is found or no matching line is found in them. Or in other words:
the fedora default of "disable *" needs an explicit preset file, but
the Debian default of "enable *" is actually the upstream default
without preset file, too.
Post by Martin Pitt
* This doesn't solve the problem of having these rather uninteresting
and cluttering symlinks in /etc at all; the wants.d symlinks would
still be as they are now, just the place that decides when to
enable them changes.
If they are so uninteresting that there's no real benefit in allowing
them to be modified, then I'd really recommend to simply ship the
symlinks in /usr/lib, and not include an [Install] section. A lot of
systemd's own units are like that. For example, since disabling udev
or journald will only have the effect of making your system unbootable
we don't ship [Install] sections for them, and instead hook them in
statically.
Post by Martin Pitt
I. e. my question is not so much about being able to restore the
default wants.d symlinks in /etc after a factory reset -- there are
multiple ways how this can be done: with presets or iterating over the
installed packages and re-enabling them (Debian also does some
house-keeping which unit files got enabled by postinstall scripts,
which can simply be replayed).
Note that "systemctl preset-all" erally just iterates throught unit
files that are installed and individually does the equivalent of
"systemctl preset". There's little magic in there...
Post by Martin Pitt
I'm interested in the reason for that. This basically cements the
status quo that one *has* to have a gazillion links in /etc in order
for your system to work, even if they are not at all specific to the
particular system or represent a deviation from the default install.
It's not a gazillion really. It's 15 or so on my laptop here...

Lennart
--
Lennart Poettering, Red Hat
Tom Gundersen
2014-11-18 13:10:49 UTC
Permalink
Hi Didier,
- Duplicate symlinks for the same targets between /etc and units enabled in
/usr/lib for units which are already enabled via /usr/lib, if the admin runs
"enable"
This I think should be considered a bug in the unit file. If a unit
has a /usr/lib symlink, then it is statically enabled (i.e.,
'enable'/'disable' has no effect), so it should not install symlinks
in /etc, and hence not have an [Install] section. At least with the
current semantics.
- Wrt. the "golden image, /etc reset" approach of reducing base os
installation defaults in /etc, this is another instance of "always needs to
be there" clutter in /etc. If the package default is to start the service,
then it's better to just ship that wants.d/ symlink in the package (and thus
in /usr) instead of always having to create the symlink in /etc at package
install time or after a factory reset.
I get where you are coming from, but presets will give you the same result, no?
- We are mixing sys admin information and distro default choices in the same
directories, and can't tell apart what is what.
That is true. Could we perhaps improve on systemctl by printing
"enabled (preset)"/"disable (preset)" for units that are in the
default state? I know this does not change the fact that you have
distro-default (via presets) links in /etc, but it should give the
end-user a nicer experienc I guess?
We were thus thinking about having all default distro choices shipping
target symlinks in /usr/lib, and having the administrator overrides this in
/etc via systemctl. This could look similar to masking a unit, i. e. a
symlink "/etc/.../wants.d/foo -> /dev/null" overrides
"/usr/lib/.../wants.d/foo -> ../foo.service", and would be an explicit
representation of "the admin does not want foo.service to autostart" in
/etc.
So you are essentially proposing to replace the preset concept?

We now have:

enabeld - [Install] section and symlink in /etc/**/*.wants.d/
disabled - [Install] section and no symlink in /etc/**/*.wants.d/
static - no [Install] section and symlink in /usr/lib/**/*.wants.d/
masked - symlink from the unit file-name to /dev/null in /etc

you want in addition:

preset (or something like that) - [Install] section and symlink in
/usr/lib/**/*.wants.d/
unpreset (or something like that) - [Install] section and symlink in
/usr/lib/**/*.wants.d/ and an overriding symlink in /etc pointing at
/dev/null

Doing 'enable' on a preset unit will then just delete the symlink to
/dev/null from /etc (if it exists) and doing 'disable' will add it.
This would also entail changing the current logic to check the target
of /**/*.wants.d/ symlinks to see if they point to /dev/null, in which
case they should be ignored.

Did I understand that correctly?
However, we did notice the following: taking an unit, with an [Install]
Yeah, I would not expect this to work with the current semantics, as
it appears to be a contradiction. We can probably improve on the
status-quo even if your proposal is not implemented.
- systemctl status <unit> will report "disabled", where it's actually
enabled and starting for that unit. This is a bug which should be fixed in
any case, as "disabled" is outright wrong. On IRC it was suggested that
those are "static" units, but then it should say at least that.
I agree, this should be fixed to report them as 'static' (as any state
in /etc apart from masking is irrelevant).
- systemctl enable <unit> will duplicate the symlink in /etc
I guess this should also be dropped (though the situation here is
weird as it anyway is a noop). Maybe a warning should be printed.
- If we ln -s /dev/null /etc/<…>/<…>.wants/<unit>, then systemctl status
<unit> will display the unit as being enabled, and it will activated once
the target is reached. This is also counterintuitive, as usually this means
to mask/completely disable the unit.
You cannot mask an wants.d/* symlink, only the unit itself, so this is
actually not defined. My understanding is that this is a concept you
would like to introduce rather than a bug. I don't know how/if we
should change this behaviour under the current semantics.
Part of the discussion on #systemd pointed out that the admin should then
- The admin can't retarget a default installed unit without recreating
another unit file
Correct. But is that something we want? I mean, how I would retarget a
unit file is to make a copy, edit the [Install] section and then
"systemctl enable" it. I guess we should not encourage admins to go
fiddling with the symlinks manually?
- There are 2 commands to "disable" an unit: mask for some, disable for
others, this can bring confusion and admins won't know the semantic
difference between the two (and indeed this is rather technical and
unintuitive)
Well, the meaning we have been using so far is that statically enabled
units are things that does not really make sense to disable (which is
different from it being enabled by default), and for all other units
the way to enable/disable them (be it by default or manually) is by
installing symlinks in /etc. If the admin wants to insist to ignore
the "does not make sense to disable part" and really force something
to never start, then masking is the tool for that. Either way, the
admin should never (need to) go poking in /etc manually, but use
systemctl as the interface.
- The status reported with systemctl is still disabled when it's not.
We can probably improve on that. I guess no one really explored the
case of static units with [Install] sections. Even if we end up
thinking of these as bugs, people can still end up with them, so we
should probably make sure our tools report something sensible.
Tested with systemd 216 on fedora 21 and systemd 215 on ubuntu vivid.
It will be great if we can come to some common grounds on how we should
separate admin choices and default distro choices, while still working on
the "remove /etc default distro configuration" . I'm happy to give a hand on
the desired solutions there.
My take on this is: make sure presets are applied on "firstboot"
(which I think they are), so empty /etc works just fine, and then
improve on systemctl to better show the distinction between 'enabled
by default' or 'enabled by choice' (and same for 'disabled').

Cheers,

Tom
Martin Pitt
2014-11-18 13:37:11 UTC
Permalink
Hey Tom,
Post by Tom Gundersen
This I think should be considered a bug in the unit file. If a unit
has a /usr/lib symlink, then it is statically enabled (i.e.,
'enable'/'disable' has no effect), so it should not install symlinks
in /etc, and hence not have an [Install] section. At least with the
current semantics.
Note that these were all just experiments. We just moved a wants.d/
link from /etc/ to /lib and checked the current behaviour.
Post by Tom Gundersen
Post by Didier Roche
- Wrt. the "golden image, /etc reset" approach of reducing base os
installation defaults in /etc, this is another instance of "always needs to
be there" clutter in /etc. If the package default is to start the service,
then it's better to just ship that wants.d/ symlink in the package (and thus
in /usr) instead of always having to create the symlink in /etc at package
install time or after a factory reset.
I get where you are coming from, but presets will give you the same result, no?
By and large yes. Slightly different mechanics, but same eventual
result in /etc/.

The reason for this thread is whether we can get "better", not "same" :-)
Post by Tom Gundersen
Post by Didier Roche
- We are mixing sys admin information and distro default choices in the same
directories, and can't tell apart what is what.
That is true. Could we perhaps improve on systemctl by printing
"enabled (preset)"/"disable (preset)" for units that are in the
default state? I know this does not change the fact that you have
distro-default (via presets) links in /etc, but it should give the
end-user a nicer experienc I guess?
It would at least make it easier for an admin to see what he actually
did change, even though it's looking at systemctl output instead of
just looking at /etc/.
Post by Tom Gundersen
So you are essentially proposing to replace the preset concept?
I don't know, maybe. I see how for some use cases, embedded devices,
custom images etc. presets make sense. But for a large general distro,
any preset other than "enable *" or "disable *" seems unwieldy to mee,
as you don't want to maintain a static list of units anywhere.
Post by Tom Gundersen
enabeld - [Install] section and symlink in /etc/**/*.wants.d/
disabled - [Install] section and no symlink in /etc/**/*.wants.d/
static - no [Install] section and symlink in /usr/lib/**/*.wants.d/
masked - symlink from the unit file-name to /dev/null in /etc
preset (or something like that) - [Install] section and symlink in
/usr/lib/**/*.wants.d/
I'd call this just "enabled". It follows the same "/etc/ trumps /usr"
schema that we have for udev rules, units, etc., i. e. an "enabled"
symlink should be allowed to live in /etc, /usr, and maybe even /run
(haven't though about whether this really makes sense, but perhaps for
full consistency it should be allowed).
Post by Tom Gundersen
unpreset (or something like that) - [Install] section and symlink in
/usr/lib/**/*.wants.d/ and an overriding symlink in /etc pointing at
/dev/null
IMHO this should also just be "disabled" -- /etc/ just overrides /usr/
here. /dev/null symlink is an obvious way to express that; another
would be to put a 0-byte .service file into /etc/systemd/system/ so
that the enabled unit would be a no-op. Perhaps there are different
ways even -- as long as we can clearly express "we want to override
the /usr/lib/**/wants.d/foo.service enablement".
Post by Tom Gundersen
Doing 'enable' on a preset unit will then just delete the symlink to
/dev/null from /etc (if it exists) and doing 'disable' will add it.
This would also entail changing the current logic to check the target
of /**/*.wants.d/ symlinks to see if they point to /dev/null, in which
case they should be ignored.
Did I understand that correctly?
Right. (with the aforementioned variability in the implementation). I
think the admin systemctl enable/disable interface is just fine, and I
see no need to introduce yet another concept/API/interface.
Post by Tom Gundersen
Post by Didier Roche
- If we ln -s /dev/null /etc/<…>/<…>.wants/<unit>, then systemctl status
<unit> will display the unit as being enabled, and it will activated once
the target is reached. This is also counterintuitive, as usually this means
to mask/completely disable the unit.
You cannot mask an wants.d/* symlink, only the unit itself, so this is
actually not defined. My understanding is that this is a concept you
would like to introduce rather than a bug.
Correct. It's the obvious thing that came to my mind, as (as you say)
the current semantics of that is undefined, and we use /dev/null
symlinks for masking already.
Post by Tom Gundersen
Post by Didier Roche
Part of the discussion on #systemd pointed out that the admin should then
- The admin can't retarget a default installed unit without recreating
another unit file
Correct. But is that something we want? I mean, how I would retarget a
unit file is to make a copy, edit the [Install] section and then
"systemctl enable" it. I guess we should not encourage admins to go
fiddling with the symlinks manually?
I'm leaving that to Didier, I'm not entirely sure what he meant with
this. But I think this was just a followup on IRC where the current
implementation was discussed, i. e. as an alternative way around
"systemctl disable for an existing wants.d symlink in /usr doesn't
work".
Post by Tom Gundersen
Post by Didier Roche
- There are 2 commands to "disable" an unit: mask for some, disable for
others, this can bring confusion and admins won't know the semantic
difference between the two (and indeed this is rather technical and
unintuitive)
Well, the meaning we have been using so far is that statically enabled
units are things that does not really make sense to disable (which is
different from it being enabled by default), and for all other units
the way to enable/disable them (be it by default or manually) is by
installing symlinks in /etc.
Right, that's how I understood it as well. I. e. an admin would rarely
go and mask an unit, unless she really knows what she's doing. OTOH
it's perfectly reasonable to disable an unit like apache.
Post by Tom Gundersen
Post by Didier Roche
- The status reported with systemctl is still disabled when it's not.
We can probably improve on that. I guess no one really explored the
case of static units with [Install] sections.
I think they should not be considered static; they are merely "enabled
by default" in the package, as the wants symlink happens to be in /usr
instead of /etc, but other than that they should be exactly the same.
Post by Tom Gundersen
My take on this is: make sure presets are applied on "firstboot"
(which I think they are), so empty /etc works just fine, and then
improve on systemctl to better show the distinction between 'enabled
by default' or 'enabled by choice' (and same for 'disabled').
I guess if the full idea of not requiring the symlinks in /etc in the
first place is rejected, then that would be the next best thing.

Thanks!

Martin
--
Martin Pitt | http://www.piware.de
Ubuntu Developer (www.ubuntu.com) | Debian Developer (www.debian.org)
Lennart Poettering
2014-12-02 00:46:16 UTC
Permalink
Post by Martin Pitt
Post by Tom Gundersen
enabeld - [Install] section and symlink in /etc/**/*.wants.d/
disabled - [Install] section and no symlink in /etc/**/*.wants.d/
static - no [Install] section and symlink in /usr/lib/**/*.wants.d/
masked - symlink from the unit file-name to /dev/null in /etc
preset (or something like that) - [Install] section and symlink in
/usr/lib/**/*.wants.d/
I am not totally opposed to allowing /dev/null symlinks in .wants.d/
subdirs, and considering them a way to override dependencies. Such a
"mask a dependency" concept would be OK.
Post by Martin Pitt
I'd call this just "enabled". It follows the same "/etc/ trumps /usr"
schema that we have for udev rules, units, etc., i. e. an "enabled"
symlink should be allowed to live in /etc, /usr, and maybe even /run
(haven't though about whether this really makes sense, but perhaps for
full consistency it should be allowed).
OK, let me get this right. You want an algorithm like this when
somebody invokes "systemctl enable":

a) if the unit file contains [Install], execute that, done
b) if the unit file does not contain [Install], then delete any
/dev/null symlinks in /etc/systemd/*.{wants,requires}.d/* of the
same name.

Then, "systemctl disable" should do this in your opinion:

a) if the unit file contains [Install] remove all symlinks in
/etc/systemd/*.{wants,requires}.d/* to it.
b) if it doesn't, then *add* new symlinks to /dev/null in all
.{wants,requires}.d/ directories where symlinks exist for it in
/usr?

Did I get this right?

I am not convinced this is really a good idea though, as with this
scheme package changes might reenable a unit that is otherwise
disabled. Also, I kind like the fact that there's currently a clean
error message generated when people try to disable a unit that is part
of the OS itself. The scheme you propose would degrade that case to a
NOP however, right?

Lennart
--
Lennart Poettering, Red Hat
Andrei Borzenkov
2014-12-05 07:58:01 UTC
Permalink
В Tue, 2 Dec 2014 01:46:16 +0100
Post by Lennart Poettering
Post by Martin Pitt
Post by Tom Gundersen
enabeld - [Install] section and symlink in /etc/**/*.wants.d/
disabled - [Install] section and no symlink in /etc/**/*.wants.d/
static - no [Install] section and symlink in /usr/lib/**/*.wants.d/
masked - symlink from the unit file-name to /dev/null in /etc
preset (or something like that) - [Install] section and symlink in
/usr/lib/**/*.wants.d/
I am not totally opposed to allowing /dev/null symlinks in .wants.d/
subdirs, and considering them a way to override dependencies. Such a
"mask a dependency" concept would be OK.
Post by Martin Pitt
I'd call this just "enabled". It follows the same "/etc/ trumps /usr"
schema that we have for udev rules, units, etc., i. e. an "enabled"
symlink should be allowed to live in /etc, /usr, and maybe even /run
(haven't though about whether this really makes sense, but perhaps for
full consistency it should be allowed).
OK, let me get this right. You want an algorithm like this when
a) if the unit file contains [Install], execute that, done
b) if the unit file does not contain [Install], then delete any
/dev/null symlinks in /etc/systemd/*.{wants,requires}.d/* of the
same name.
a) if the unit file contains [Install] remove all symlinks in
/etc/systemd/*.{wants,requires}.d/* to it.
b) if it doesn't, then *add* new symlinks to /dev/null in all
.{wants,requires}.d/ directories where symlinks exist for it in
/usr?
Did I get this right?
That's not how I actually understood it. enable/disable still applies
only to units with [Install] section as it is now. Just that

systemctl disable

means that if there are links in /usr/lib, they are masked in /etc.
I.o. unit foo.service is enabled if

1. [Install] section exists
2. Links from [Install] section are present either in /usr/lib or
in /etc

unit foo.service is disabled if

1. [Install] section exists
2. There are no links from [Install] in /usr/lib or /etc *OR* there are
links in /usr/lib which are masked in /etc.

Units without [Install] section remains static as they are today.

This will allow to cleanly separate distribution default (/usr/lib) and
admin decision (/etc). Also this will allow systemctl list-unit-files to
supply information like

enabled (default)/enabled (admin)

depending on whether link in /usr/lib or /etc exists.

IOW - /usr/lib keeps default state and /etc keeps overrides for default
state.
Post by Lennart Poettering
I am not convinced this is really a good idea though, as with this
scheme package changes might reenable a unit that is otherwise
disabled. Also, I kind like the fact that there's currently a clean
error message generated when people try to disable a unit that is part
of the OS itself. The scheme you propose would degrade that case to a
NOP however, right?
Lennart
Lennart Poettering
2014-12-06 01:58:28 UTC
Permalink
Post by Andrei Borzenkov
That's not how I actually understood it. enable/disable still applies
only to units with [Install] section as it is now. Just that
systemctl disable
means that if there are links in /usr/lib, they are masked in /etc.
I.o. unit foo.service is enabled if
1. [Install] section exists
2. Links from [Install] section are present either in /usr/lib or
in /etc
unit foo.service is disabled if
1. [Install] section exists
2. There are no links from [Install] in /usr/lib or /etc *OR* there are
links in /usr/lib which are masked in /etc.
Units without [Install] section remains static as they are today.
This will allow to cleanly separate distribution default (/usr/lib) and
admin decision (/etc). Also this will allow systemctl list-unit-files to
supply information like
enabled (default)/enabled (admin)
depending on whether link in /usr/lib or /etc exists.
IOW - /usr/lib keeps default state and /etc keeps overrides for default
state.
Hmm, I figure I could live with such a scheme. Not enthusiastic about
the idea, but I see the value, hence I'd merge a good patch for it.

Masking dependency symlinks is certainly OK, the part I am not overly
enthusiastic about is the changes to "systemctl enable" and "systemctl
disable" you propose. But given that behaviour of these commands
wouldn't change unless you actually have symlinks in /usr + [Install]
in the unit file, which doesn't really happen so far, I am fine with it.

Lennart
--
Lennart Poettering, Red Hat
Martin Pitt
2014-12-07 07:39:50 UTC
Permalink
Hello all,

sorry for the late response.
Post by Andrei Borzenkov
That's not how I actually understood it. enable/disable still applies
only to units with [Install] section as it is now. Just that
Correct. I don't see any need to change the behaviour of static units,
and I don't want to change the "visible effect" of systemctl/disable,
nor the current semantics of changing wants/ symlinks in /etc.
Post by Andrei Borzenkov
unit foo.service is disabled if
[...[
2. There are no links from [Install] in /usr/lib or /etc *OR* there are
links in /usr/lib which are masked in /etc.
Indeed the part after the "OR" is the only change that I propose. I. e.

- systemctl enable: If /usr/.../wants/foo.service exists, remove the
/dev/null symlink in /etc/.../wants/foo.service if it exists (if
not, it's already enabled). Otherwise, behave as now.

- systemctl disable: If /usr/.../wants/foo.service exists, create a
/dev/null symlink in /etc/.../wants/foo.service if it doesn't exist
yet (if it does, it's already disabled). Otherwise, behave as now.
Post by Andrei Borzenkov
This will allow to cleanly separate distribution default (/usr/lib) and
admin decision (/etc). Also this will allow systemctl list-unit-files to
supply information like
enabled (default)/enabled (admin)
depending on whether link in /usr/lib or /etc exists.
Exactly.

Thanks,

Martin
--
Martin Pitt | http://www.piware.de
Ubuntu Developer (www.ubuntu.com) | Debian Developer (www.debian.org)
Andrei Borzenkov
2014-12-07 11:39:56 UTC
Permalink
В Sun, 7 Dec 2014 09:39:50 +0200
Post by Martin Pitt
Hello all,
sorry for the late response.
Post by Andrei Borzenkov
That's not how I actually understood it. enable/disable still applies
only to units with [Install] section as it is now. Just that
Correct. I don't see any need to change the behaviour of static units,
and I don't want to change the "visible effect" of systemctl/disable,
nor the current semantics of changing wants/ symlinks in /etc.
Post by Andrei Borzenkov
unit foo.service is disabled if
[...[
2. There are no links from [Install] in /usr/lib or /etc *OR* there are
links in /usr/lib which are masked in /etc.
Indeed the part after the "OR" is the only change that I propose. I. e.
- systemctl enable: If /usr/.../wants/foo.service exists, remove the
/dev/null symlink in /etc/.../wants/foo.service if it exists (if
not, it's already enabled). Otherwise, behave as now.
- systemctl disable: If /usr/.../wants/foo.service exists, create a
/dev/null symlink in /etc/.../wants/foo.service if it doesn't exist
yet (if it does, it's already disabled). Otherwise, behave as now.
I think systemctl enable|disable should always create respective links
in /etc. It makes it obvious that this is admin decision. It also makes
implementation easier. And systemctl reset (or equiv.) would simply
delete any link in /etc thus reverting to (distribution) defaults
in /usr.
Post by Martin Pitt
Post by Andrei Borzenkov
This will allow to cleanly separate distribution default (/usr/lib) and
admin decision (/etc). Also this will allow systemctl list-unit-files to
supply information like
enabled (default)/enabled (admin)
depending on whether link in /usr/lib or /etc exists.
Exactly.
Thanks,
Martin
Martin Pitt
2014-12-07 20:27:16 UTC
Permalink
Hello,
Post by Andrei Borzenkov
Post by Martin Pitt
Indeed the part after the "OR" is the only change that I propose. I. e.
- systemctl enable: If /usr/.../wants/foo.service exists, remove the
/dev/null symlink in /etc/.../wants/foo.service if it exists (if
not, it's already enabled). Otherwise, behave as now.
- systemctl disable: If /usr/.../wants/foo.service exists, create a
/dev/null symlink in /etc/.../wants/foo.service if it doesn't exist
yet (if it does, it's already disabled). Otherwise, behave as now.
I think systemctl enable|disable should always create respective links
in /etc. It makes it obvious that this is admin decision.
Fully agreed, but that's exactly what I proposed, no? Of course it
always acts on /etc, just the kind of symlink it removes/adds is
different depending on whether a unit is already enabled by
/usr/.../wants/foo.service or not.

Martin
--
Martin Pitt | http://www.piware.de
Ubuntu Developer (www.ubuntu.com) | Debian Developer (www.debian.org)
Andrei Borzenkov
2014-12-08 06:08:04 UTC
Permalink
Post by Martin Pitt
Hello,
Post by Andrei Borzenkov
Post by Martin Pitt
Indeed the part after the "OR" is the only change that I propose. I. e.
- systemctl enable: If /usr/.../wants/foo.service exists, remove the
/dev/null symlink in /etc/.../wants/foo.service if it exists (if
not, it's already enabled). Otherwise, behave as now.
- systemctl disable: If /usr/.../wants/foo.service exists, create a
/dev/null symlink in /etc/.../wants/foo.service if it doesn't exist
yet (if it does, it's already disabled). Otherwise, behave as now.
I think systemctl enable|disable should always create respective links
in /etc. It makes it obvious that this is admin decision.
Fully agreed, but that's exactly what I proposed, no?
No quite. Right now "disable" means "delete link"; and I tentatively
think that with proposed scheme "disable" should always create
/dev/null link (or whatever is indication that service is disabled).
Post by Martin Pitt
Of course it
always acts on /etc, just the kind of symlink it removes/adds is
different depending on whether a unit is already enabled by
/usr/.../wants/foo.service or not.
Martin
--
Martin Pitt | http://www.piware.de
Ubuntu Developer (www.ubuntu.com) | Debian Developer (www.debian.org)
Lennart Poettering
2014-12-08 14:32:03 UTC
Permalink
Post by Martin Pitt
Hello all,
sorry for the late response.
Post by Andrei Borzenkov
That's not how I actually understood it. enable/disable still applies
only to units with [Install] section as it is now. Just that
Correct. I don't see any need to change the behaviour of static units,
and I don't want to change the "visible effect" of systemctl/disable,
nor the current semantics of changing wants/ symlinks in /etc.
Post by Andrei Borzenkov
unit foo.service is disabled if
[...[
2. There are no links from [Install] in /usr/lib or /etc *OR* there are
links in /usr/lib which are masked in /etc.
Indeed the part after the "OR" is the only change that I propose. I. e.
- systemctl enable: If /usr/.../wants/foo.service exists, remove the
/dev/null symlink in /etc/.../wants/foo.service if it exists (if
not, it's already enabled). Otherwise, behave as now.
- systemctl disable: If /usr/.../wants/foo.service exists, create a
/dev/null symlink in /etc/.../wants/foo.service if it doesn't exist
yet (if it does, it's already disabled). Otherwise, behave as now.
Sounds OK, would merge a good patch for this.

Thanks,

Lennart
--
Lennart Poettering, Red Hat
Didier Roche
2014-11-18 13:58:17 UTC
Permalink
Post by Tom Gundersen
Hi Didier,
Thanks for your answer Tom and sharing your thoughts on this.
Post by Tom Gundersen
- Duplicate symlinks for the same targets between /etc and units enabled in
/usr/lib for units which are already enabled via /usr/lib, if the admin runs
"enable"
This I think should be considered a bug in the unit file. If a unit
has a /usr/lib symlink, then it is statically enabled (i.e.,
'enable'/'disable' has no effect), so it should not install symlinks
in /etc, and hence not have an [Install] section. At least with the
current semantics.
Shouldn't then systemctl status detects that there is a symlink in /usr
and list it as a static unit instead of disabled? (or even better: warn
that the unit is mis-formatted).
The current "disable" status would let the admin think if he doesn't
know about the implementation that this unit will never be active until
I systemctl start it explicitly, which isn't the case.
Post by Tom Gundersen
- Wrt. the "golden image, /etc reset" approach of reducing base os
installation defaults in /etc, this is another instance of "always needs to
be there" clutter in /etc. If the package default is to start the service,
then it's better to just ship that wants.d/ symlink in the package (and thus
in /usr) instead of always having to create the symlink in /etc at package
install time or after a factory reset.
I get where you are coming from, but presets will give you the same result, no?
Apart from what we discussed on this thread with Martin about the "/etc"
clutterness having distro-specific information and not only system ones,
right.

However, this is kind of a complex case in D/U where we have the policy
to start most of the service on package installation. For instance, if
you apt install docker.io, people using those distros will expect to be
then able to do $ docker run <…> (which starts the docker service
through socket activation).
Post by Tom Gundersen
- We are mixing sys admin information and distro default choices in the same
directories, and can't tell apart what is what.
That is true. Could we perhaps improve on systemctl by printing
"enabled (preset)"/"disable (preset)" for units that are in the
default state? I know this does not change the fact that you have
distro-default (via presets) links in /etc, but it should give the
end-user a nicer experienc I guess?
This would be maybe a nice way for the admin to know what's coming from
a distribution default or not. However, let's say I want to ensure that
ssh will always be available on my server, I would (even if it's in my
server preset) then systemctl enable openssh, no matter whatever future
preset updates does (like disable it in the next batch upgrade).

With a shared distro/admin /etc, we have no way to take that fact into
account and the next one would follow distro policy, right?
Also, after running systemctl enable opensshn, systemctl status openssh
will still say "enabled (preset)" even if the admin wanted to "stick it
for good" as it's part of the preset.
Post by Tom Gundersen
We were thus thinking about having all default distro choices shipping
target symlinks in /usr/lib, and having the administrator overrides this in
/etc via systemctl. This could look similar to masking a unit, i. e. a
symlink "/etc/.../wants.d/foo -> /dev/null" overrides
"/usr/lib/.../wants.d/foo -> ../foo.service", and would be an explicit
representation of "the admin does not want foo.service to autostart" in
/etc.
So you are essentially proposing to replace the preset concept?
enabeld - [Install] section and symlink in /etc/**/*.wants.d/
disabled - [Install] section and no symlink in /etc/**/*.wants.d/
static - no [Install] section and symlink in /usr/lib/**/*.wants.d/
masked - symlink from the unit file-name to /dev/null in /etc
preset (or something like that) - [Install] section and symlink in
/usr/lib/**/*.wants.d/
unpreset (or something like that) - [Install] section and symlink in
/usr/lib/**/*.wants.d/ and an overriding symlink in /etc pointing at
/dev/null
Doing 'enable' on a preset unit will then just delete the symlink to
/dev/null from /etc (if it exists) and doing 'disable' will add it.
This would also entail changing the current logic to check the target
of /**/*.wants.d/ symlinks to see if they point to /dev/null, in which
case they should be ignored.
Did I understand that correctly?
Right, maybe the implementation can diverge a little bit from that, but
the intent would cover most of the admin/distro separation, while
enabling sysadmin to "stick" some of the services disregarding future
distro choices and keeping a clean /etc.
Post by Tom Gundersen
However, we did notice the following: taking an unit, with an [Install]
Yeah, I would not expect this to work with the current semantics, as
it appears to be a contradiction. We can probably improve on the
status-quo even if your proposal is not implemented.
Indeed, this is quite orthogonal, but this whole discussion started
actually when I analyzed those use cases, hence the mention. :)
Post by Tom Gundersen
- systemctl status <unit> will report "disabled", where it's actually
enabled and starting for that unit. This is a bug which should be fixed in
any case, as "disabled" is outright wrong. On IRC it was suggested that
those are "static" units, but then it should say at least that.
I agree, this should be fixed to report them as 'static' (as any state
in /etc apart from masking is irrelevant).
agreed (if we want to keep the current logic of not shipping other kind
of units in /usr)
Post by Tom Gundersen
- systemctl enable <unit> will duplicate the symlink in /etc
I guess this should also be dropped (though the situation here is
weird as it anyway is a noop). Maybe a warning should be printed.
agreed as well, or, this would be a way for the sysadmin to "stick" this
unit/service whatever future distro will choose in the next upgrade.
Post by Tom Gundersen
- If we ln -s /dev/null /etc/<…>/<…>.wants/<unit>, then systemctl status
<unit> will display the unit as being enabled, and it will activated once
the target is reached. This is also counterintuitive, as usually this means
to mask/completely disable the unit.
You cannot mask an wants.d/* symlink, only the unit itself, so this is
actually not defined. My understanding is that this is a concept you
would like to introduce rather than a bug. I don't know how/if we
should change this behaviour under the current semantics.
ack.
Post by Tom Gundersen
Part of the discussion on #systemd pointed out that the admin should then
- The admin can't retarget a default installed unit without recreating
another unit file
Correct. But is that something we want? I mean, how I would retarget a
unit file is to make a copy, edit the [Install] section and then
"systemctl enable" it. I guess we should not encourage admins to go
fiddling with the symlinks manually?
Indeed, this is quite a niche-case, they would rather I think copy it to
/etc and override the [Install] section as you told.
Post by Tom Gundersen
- There are 2 commands to "disable" an unit: mask for some, disable for
others, this can bring confusion and admins won't know the semantic
difference between the two (and indeed this is rather technical and
unintuitive)
Well, the meaning we have been using so far is that statically enabled
units are things that does not really make sense to disable (which is
different from it being enabled by default), and for all other units
the way to enable/disable them (be it by default or manually) is by
installing symlinks in /etc. If the admin wants to insist to ignore
the "does not make sense to disable part" and really force something
to never start, then masking is the tool for that. Either way, the
admin should never (need to) go poking in /etc manually, but use
systemctl as the interface.
Indeed, I'm getting where you are coming from now and see the real
difference you mean with default symlinks in /usr. However, it would
seem weird to me to have to systemctl mask plymouth-quit.service for
instance without knowing the internals of systemd to be able to really
"disable" (I know the term is wrong, just trying to feel how they could
interprete it) a certain class of units.
Post by Tom Gundersen
- The status reported with systemctl is still disabled when it's not.
We can probably improve on that. I guess no one really explored the
case of static units with [Install] sections. Even if we end up
thinking of these as bugs, people can still end up with them, so we
should probably make sure our tools report something sensible.
Agreed, I can open a bug independently of this discussion and work on
this, as it seems we all agree that this status report needs to be
improved even with units not following the current expected semantics.
Post by Tom Gundersen
Tested with systemd 216 on fedora 21 and systemd 215 on ubuntu vivid.
It will be great if we can come to some common grounds on how we should
separate admin choices and default distro choices, while still working on
the "remove /etc default distro configuration" . I'm happy to give a hand on
the desired solutions there.
My take on this is: make sure presets are applied on "firstboot"
(which I think they are), so empty /etc works just fine, and then
improve on systemctl to better show the distinction between 'enabled
by default' or 'enabled by choice' (and same for 'disabled').
Thanks again for your feedback. If the whole proposal is rejected, I
think we'll try to have debian following this as a first step.

Cheers,
Didier
Tom Gundersen
2014-11-18 14:55:13 UTC
Permalink
Post by Tom Gundersen
This I think should be considered a bug in the unit file. If a unit
has a /usr/lib symlink, then it is statically enabled (i.e.,
'enable'/'disable' has no effect), so it should not install symlinks
in /etc, and hence not have an [Install] section. At least with the
current semantics.
Shouldn't then systemctl status detects that there is a symlink in /usr and
list it as a static unit instead of disabled? (or even better: warn that the
unit is mis-formatted).
The current "disable" status would let the admin think if he doesn't know
about the implementation that this unit will never be active until I
systemctl start it explicitly, which isn't the case.
Yeah, that makes sense. Would be happy to take a patch for this.
Post by Tom Gundersen
I get where you are coming from, but presets will give you the same result, no?
Apart from what we discussed on this thread with Martin about the "/etc"
clutterness having distro-specific information and not only system ones,
right.
However, this is kind of a complex case in D/U where we have the policy to
start most of the service on package installation. For instance, if you apt
install docker.io, people using those distros will expect to be then able to
do $ docker run <…> (which starts the docker service through socket
activation).
Hm, not following this last paragraph. Are you saying we are missing
something to do with start-on-install?
This would be maybe a nice way for the admin to know what's coming from a
distribution default or not. However, let's say I want to ensure that ssh
will always be available on my server, I would (even if it's in my server
preset) then systemctl enable openssh, no matter whatever future preset
updates does (like disable it in the next batch upgrade).
With a shared distro/admin /etc, we have no way to take that fact into
account and the next one would follow distro policy, right?
Also, after running systemctl enable opensshn, systemctl status openssh will
still say "enabled (preset)" even if the admin wanted to "stick it for good"
as it's part of the preset.
This is up to the distro I guess, but I would have thought that
presets should only be applied on install-time, and not on upgrade.
Post by Tom Gundersen
Post by Didier Roche
- systemctl enable <unit> will duplicate the symlink in /etc
I guess this should also be dropped (though the situation here is
weird as it anyway is a noop). Maybe a warning should be printed.
agreed as well, or, this would be a way for the sysadmin to "stick" this
unit/service whatever future distro will choose in the next upgrade.
Could be, yeah, but moving from static to opt-in during an upgrade
sounds like a packaging bug to me, so hopefully this situation would
never be encountered in production.
Post by Tom Gundersen
Well, the meaning we have been using so far is that statically enabled
units are things that does not really make sense to disable (which is
different from it being enabled by default), and for all other units
the way to enable/disable them (be it by default or manually) is by
installing symlinks in /etc. If the admin wants to insist to ignore
the "does not make sense to disable part" and really force something
to never start, then masking is the tool for that. Either way, the
admin should never (need to) go poking in /etc manually, but use
systemctl as the interface.
Indeed, I'm getting where you are coming from now and see the real
difference you mean with default symlinks in /usr. However, it would seem
weird to me to have to systemctl mask plymouth-quit.service for instance
without knowing the internals of systemd to be able to really "disable" (I
know the term is wrong, just trying to feel how they could interprete it) a
certain class of units.
Hm, I didn't follow this paragraph, could you rephrase?
Post by Tom Gundersen
Post by Didier Roche
- The status reported with systemctl is still disabled when it's not.
We can probably improve on that. I guess no one really explored the
case of static units with [Install] sections. Even if we end up
thinking of these as bugs, people can still end up with them, so we
should probably make sure our tools report something sensible.
Agreed, I can open a bug independently of this discussion and work on this,
as it seems we all agree that this status report needs to be improved even
with units not following the current expected semantics.
Great!
Post by Tom Gundersen
My take on this is: make sure presets are applied on "firstboot"
(which I think they are), so empty /etc works just fine, and then
improve on systemctl to better show the distinction between 'enabled
by default' or 'enabled by choice' (and same for 'disabled').
Thanks again for your feedback. If the whole proposal is rejected, I think
we'll try to have debian following this as a first step.
Sounds good, but let's see if maybe Zbigniew or Lennart have any
comments on your proposal (if my memory serves me right they did most
of the work in this area).

Cheers,

Tom
Didier Roche
2014-11-18 15:21:34 UTC
Permalink
Post by Tom Gundersen
Post by Didier Roche
Post by Tom Gundersen
I get where you are coming from, but presets will give you the same result, no?
Apart from what we discussed on this thread with Martin about the "/etc"
clutterness having distro-specific information and not only system ones,
right.
However, this is kind of a complex case in D/U where we have the policy to
start most of the service on package installation. For instance, if you apt
install docker.io, people using those distros will expect to be then able to
do $ docker run <…> (which starts the docker service through socket
activation).
Hm, not following this last paragraph. Are you saying we are missing
something to do with start-on-install?
Not at all, I was just presenting the difference between Fedora and D/U
policy for instance, the result with preset will be, as Colin mentioned to:
enable *
disable unit1

The thing I'm afraid of that we won't have a single place to list all
disable units, and they will be in multiple packages, so (as I'll repeat
below), I'm unsure that we would able to only load the preset as once
shot, as we may add some preset files as part of packages later on with
the current structure (to disable more units by default).
Post by Tom Gundersen
Post by Didier Roche
This would be maybe a nice way for the admin to know what's coming from a
distribution default or not. However, let's say I want to ensure that ssh
will always be available on my server, I would (even if it's in my server
preset) then systemctl enable openssh, no matter whatever future preset
updates does (like disable it in the next batch upgrade).
With a shared distro/admin /etc, we have no way to take that fact into
account and the next one would follow distro policy, right?
Also, after running systemctl enable opensshn, systemctl status openssh will
still say "enabled (preset)" even if the admin wanted to "stick it for good"
as it's part of the preset.
This is up to the distro I guess, but I would have thought that
presets should only be applied on install-time, and not on upgrade.
You mean system install time, right? Having it one shot would be more
complex in our case I think as stated above (I guess, we'll have the
disable distributed in multiple packages, not all being installed by
default).
Post by Tom Gundersen
Post by Didier Roche
Post by Tom Gundersen
Post by Didier Roche
- systemctl enable <unit> will duplicate the symlink in /etc
I guess this should also be dropped (though the situation here is
weird as it anyway is a noop). Maybe a warning should be printed.
agreed as well, or, this would be a way for the sysadmin to "stick" this
unit/service whatever future distro will choose in the next upgrade.
Could be, yeah, but moving from static to opt-in during an upgrade
sounds like a packaging bug to me, so hopefully this situation would
never be encountered in production.
It should not happen in production, indeed, but packaging errors happen
and we should maybe be able to recover without having impacts on admins
who systemctl enable this unit in particular for their needs?
Post by Tom Gundersen
Post by Didier Roche
Post by Tom Gundersen
Well, the meaning we have been using so far is that statically enabled
units are things that does not really make sense to disable (which is
different from it being enabled by default), and for all other units
the way to enable/disable them (be it by default or manually) is by
installing symlinks in /etc. If the admin wants to insist to ignore
the "does not make sense to disable part" and really force something
to never start, then masking is the tool for that. Either way, the
admin should never (need to) go poking in /etc manually, but use
systemctl as the interface.
Indeed, I'm getting where you are coming from now and see the real
difference you mean with default symlinks in /usr. However, it would seem
weird to me to have to systemctl mask plymouth-quit.service for instance
without knowing the internals of systemd to be able to really "disable" (I
know the term is wrong, just trying to feel how they could interprete it) a
certain class of units.
Hm, I didn't follow this paragraph, could you rephrase?
I hope this will be a little bit more clear:
Let's say as an admin that I want to disable plymouth-quit.service
(which is a static unit file and symlinked in /usr/lib… on the
multi-user target). Without knowing the systemd internals, my natural
intent would be to use "systemctl disable plymouth-quit.service" which
is no-op in this case on a static unit enabled on the multi-user target
with the symlink shipped by the package. This may be perceived as
unnatural to him to have to use "systemctl mask" to disable it, or am I
just being too pessimistic?
Post by Tom Gundersen
Post by Didier Roche
Post by Tom Gundersen
My take on this is: make sure presets are applied on "firstboot"
(which I think they are), so empty /etc works just fine, and then
improve on systemctl to better show the distinction between 'enabled
by default' or 'enabled by choice' (and same for 'disabled').
Thanks again for your feedback. If the whole proposal is rejected, I think
we'll try to have debian following this as a first step.
Sounds good, but let's see if maybe Zbigniew or Lennart have any
comments on your proposal (if my memory serves me right they did most
of the work in this area).
Sure! Thanks again for your feedback :)

Cheers,
Didier
Tom Gundersen
2014-11-18 16:17:36 UTC
Permalink
Post by Didier Roche
The thing I'm afraid of that we won't have a single place to list all
disable units, and they will be in multiple packages, so (as I'll repeat
below), I'm unsure that we would able to only load the preset as once shot,
as we may add some preset files as part of packages later on with the
current structure (to disable more units by default).
I'm not familiar with Debian packaging, but the way I would imagine
this working would be to call preset once all the packages in your
transaction have been installed. That way, no matter which package
ships the preset files, whatever preset files are installed by the
time your current upgrade/install transaction completes are what will
determine if a certain unit should be enabled.

Of course, if you install first your package, and then in a separate
transaction install some preset files with overrides, these will not
be applied retroactively, but I would fond that behaviour very
surprising to be honest. Of course, it would still be possible to do a
retroactive preset thing with some amount of hacking, but I'm really
not convinced that it makes sense to explicitly support upstream.
Post by Didier Roche
Post by Tom Gundersen
This is up to the distro I guess, but I would have thought that
presets should only be applied on install-time, and not on upgrade.
You mean system install time, right? Having it one shot would be more
complex in our case I think as stated above (I guess, we'll have the disable
distributed in multiple packages, not all being installed by default).
I meant package-install time (which may be different from
system-install). I.e., after every package transaction, do the presets
on all newly installed packages.
Post by Didier Roche
Post by Tom Gundersen
Post by Didier Roche
agreed as well, or, this would be a way for the sysadmin to "stick" this
unit/service whatever future distro will choose in the next upgrade.
Could be, yeah, but moving from static to opt-in during an upgrade
sounds like a packaging bug to me, so hopefully this situation would
never be encountered in production.
It should not happen in production, indeed, but packaging errors happen and
we should maybe be able to recover without having impacts on admins who
systemctl enable this unit in particular for their needs?
What I meant is that it sounds strange for admins to be proactively
enabling static units if the policy is that they should never be
automatically disabled on upgrade. We may still want to make this as
smooth as possible for those who do, but I just doubt it will be a
common thing to do.
Post by Didier Roche
Let's say as an admin that I want to disable plymouth-quit.service (which is
a static unit file and symlinked in /usr/lib… on the multi-user target).
Without knowing the systemd internals, my natural intent would be to use
"systemctl disable plymouth-quit.service" which is no-op in this case on a
static unit enabled on the multi-user target with the symlink shipped by the
package. This may be perceived as unnatural to him to have to use "systemctl
mask" to disable it, or am I just being too pessimistic?
Right, I get it. In this case we should definitely warn when someone
tries to disable a statically enabled unit. We should suggest to the
user that this package is not meant to be disabled, but one can use
masking instead (voiding the warranty, etc, etc).

Cheers,

Tom
Didier Roche
2014-11-18 16:30:58 UTC
Permalink
Post by Tom Gundersen
Post by Didier Roche
Let's say as an admin that I want to disable plymouth-quit.service (which is
a static unit file and symlinked in /usr/lib… on the multi-user target).
Without knowing the systemd internals, my natural intent would be to use
"systemctl disable plymouth-quit.service" which is no-op in this case on a
static unit enabled on the multi-user target with the symlink shipped by the
package. This may be perceived as unnatural to him to have to use "systemctl
mask" to disable it, or am I just being too pessimistic?
Right, I get it. In this case we should definitely warn when someone
tries to disable a statically enabled unit. We should suggest to the
user that this package is not meant to be disabled, but one can use
masking instead (voiding the warranty, etc, etc).
Agreed, this one is as well orthogonal to this discussion anyway and
should be implemented in any case for static units, warning people to
use mask for those cases (voiding the distro warranty as you told :))
/me notes that down as another patch to work on.

Cheers,
Didier
Colin Guthrie
2014-11-18 14:59:18 UTC
Permalink
Hiya,
Post by Didier Roche
This would be maybe a nice way for the admin to know what's coming from
a distribution default or not. However, let's say I want to ensure that
ssh will always be available on my server, I would (even if it's in my
server preset) then systemctl enable openssh, no matter whatever future
preset updates does (like disable it in the next batch upgrade).
For the avoidance of doubt, I believe that running systemctl preset
should only ever happen on *first* install, never on upgrade or such like.

This also avoids any problems here.

(Of course if /etc is nuked, then reapplying the defaults from *.preset
should be done!)
Post by Didier Roche
With a shared distro/admin /etc, we have no way to take that fact into
account and the next one would follow distro policy, right?
Yeah, but that's assuming there *is* a next one. Once things are
installed, the user should *not* be surprised by any action being taken
without their consent on upgrade.

FWIW, it's probably worth considering how you'd handle not changing
users current preferences with regards to enabling/disabling things on
upgrade. I can see this being quite hard for you roll out with your
current suggestions, but you may have this covered already.
Post by Didier Roche
Also, after running systemctl enable opensshn, systemctl status openssh
will still say "enabled (preset)" even if the admin wanted to "stick it
for good" as it's part of the preset.
Not sure what you mean by "stick it for good" here, but my previous
suggestion was to say "enabled [preset: enabled]" or "enabled [preset:
disabled]" accordingly which might be clearer (if a bit longer).
Post by Didier Roche
Post by Tom Gundersen
Doing 'enable' on a preset unit will then just delete the symlink to
/dev/null from /etc (if it exists) and doing 'disable' will add it.
This would also entail changing the current logic to check the target
of /**/*.wants.d/ symlinks to see if they point to /dev/null, in which
case they should be ignored.
Did I understand that correctly?
Right, maybe the implementation can diverge a little bit from that, but
the intent would cover most of the admin/distro separation, while
enabling sysadmin to "stick" some of the services disregarding future
distro choices and keeping a clean /etc.
Again, just to clarify, the current implementation intends that
"systemctl preset myservice.service" is only run on the first
installation of a package, not on upgrades.

There should be no need to "stick" some of the services as distro
choices are only applied at install time, and never on upgrade.
Post by Didier Roche
Post by Tom Gundersen
Post by Didier Roche
- systemctl status <unit> will report "disabled", where it's actually
enabled and starting for that unit. This is a bug which should be fixed in
any case, as "disabled" is outright wrong. On IRC it was suggested that
those are "static" units, but then it should say at least that.
I agree, this should be fixed to report them as 'static' (as any state
in /etc apart from masking is irrelevant).
agreed (if we want to keep the current logic of not shipping other kind
of units in /usr)
Post by Tom Gundersen
Post by Didier Roche
- systemctl enable <unit> will duplicate the symlink in /etc
I guess this should also be dropped (though the situation here is
weird as it anyway is a noop). Maybe a warning should be printed.
agreed as well, or, this would be a way for the sysadmin to "stick" this
unit/service whatever future distro will choose in the next upgrade.
Just to reiterate, the need for "sticking" a unit is currently not
needed, so adding this extra layer of complexity in any future changes
is not something I'd personally like to see. In my mind any package
presets (or distro choices or whatever we should call it) should only
apply on first install and not on future upgrades. I don't want to be
surprised by a change of behaviour on upgrade.


Hope this is useful clarifications.

Cheers!

Col
--
Colin Guthrie
gmane(at)colin.guthr.ie
http://colin.guthr.ie/

Day Job:
Tribalogic Limited http://www.tribalogic.net/
Open Source:
Mageia Contributor http://www.mageia.org/
PulseAudio Hacker http://www.pulseaudio.org/
Trac Hacker http://trac.edgewall.org/
Michael Biebl
2014-11-18 15:09:36 UTC
Permalink
Post by Colin Guthrie
Post by Didier Roche
This would be maybe a nice way for the admin to know what's coming from
a distribution default or not. However, let's say I want to ensure that
ssh will always be available on my server, I would (even if it's in my
server preset) then systemctl enable openssh, no matter whatever future
preset updates does (like disable it in the next batch upgrade).
For the avoidance of doubt, I believe that running systemctl preset
should only ever happen on *first* install, never on upgrade or such like.
And what are you going to do, if the unit file changes?
Say v1 had

[Install]
WantedBy=multi-user.target

and version B has
[Install]
WantedBy=foo.target
--
Why is it that all of the instruments seeking intelligent life in the
universe are pointed away from Earth?
Colin Guthrie
2014-11-18 15:30:31 UTC
Permalink
Post by Michael Biebl
Post by Colin Guthrie
Post by Didier Roche
This would be maybe a nice way for the admin to know what's coming from
a distribution default or not. However, let's say I want to ensure that
ssh will always be available on my server, I would (even if it's in my
server preset) then systemctl enable openssh, no matter whatever future
preset updates does (like disable it in the next batch upgrade).
For the avoidance of doubt, I believe that running systemctl preset
should only ever happen on *first* install, never on upgrade or such like.
And what are you going to do, if the unit file changes?
Say v1 had
[Install]
WantedBy=multi-user.target
and version B has
[Install]
WantedBy=foo.target
Well this is an edge case I'm sure you'll agree.

Ultimately, with this case, doing the preset is wrong anyway. You don't
want the distro choice, you want the "what the user had" choice.

So I'd expect the systemctl preset logic to *not* kick in (which it
won't as it's not the first install of the package), and (in RPM
parliance), I'd have a %triggerun script for when the version before
the change was uninstalled (thus only triggering the fixup script once)
do something like:

if [ -L /etc/systemd/system/multi-user.target.wants/myservice.service ];
then
mkdir -p /etc/systemd/system/foo.target.wants
mv /etc/systemd/system/multi-user.target.wants/myservice.service
/etc/systemd/system/foo.target.wants/
rmdir /etc/systemd/system/multi-user.target.wants >/dev/null
2>/dev/null ||:
fi

Or do it in LUA if I needed/wanted to avoid a shell dependency.

Yes, it's ugly but I doubt very much this kind of special can be easily
captured in a generic structure (or that it makes sense to even if it
could - I'm sure you could always define some way to break any mould!)

Col
--
Colin Guthrie
gmane(at)colin.guthr.ie
http://colin.guthr.ie/

Day Job:
Tribalogic Limited http://www.tribalogic.net/
Open Source:
Mageia Contributor http://www.mageia.org/
PulseAudio Hacker http://www.pulseaudio.org/
Trac Hacker http://trac.edgewall.org/
Michael Biebl
2014-11-18 15:55:27 UTC
Permalink
Post by Colin Guthrie
Post by Michael Biebl
Post by Colin Guthrie
Post by Didier Roche
This would be maybe a nice way for the admin to know what's coming from
a distribution default or not. However, let's say I want to ensure that
ssh will always be available on my server, I would (even if it's in my
server preset) then systemctl enable openssh, no matter whatever future
preset updates does (like disable it in the next batch upgrade).
For the avoidance of doubt, I believe that running systemctl preset
should only ever happen on *first* install, never on upgrade or such like.
And what are you going to do, if the unit file changes?
Say v1 had
[Install]
WantedBy=multi-user.target
and version B has
[Install]
WantedBy=foo.target
Well this is an edge case I'm sure you'll agree.
Actually, in the short period of time (and with the currently still
low number of packages shipping native units) in Debian, this happened
more often then I'd have expected.

So I think we should have a better answer then just saying this is an edge case.
Post by Colin Guthrie
Ultimately, with this case, doing the preset is wrong anyway. You don't
want the distro choice, you want the "what the user had" choice.
You only want to preservce the user choice, if it deviated from the
distro choice. Otherwise the package state should be updated to
reflect the latest distro choice.
--
Why is it that all of the instruments seeking intelligent life in the
universe are pointed away from Earth?
Colin Guthrie
2014-11-18 16:22:18 UTC
Permalink
Post by Michael Biebl
Post by Colin Guthrie
Post by Michael Biebl
Post by Colin Guthrie
Post by Didier Roche
This would be maybe a nice way for the admin to know what's coming from
a distribution default or not. However, let's say I want to ensure that
ssh will always be available on my server, I would (even if it's in my
server preset) then systemctl enable openssh, no matter whatever future
preset updates does (like disable it in the next batch upgrade).
For the avoidance of doubt, I believe that running systemctl preset
should only ever happen on *first* install, never on upgrade or such like.
And what are you going to do, if the unit file changes?
Say v1 had
[Install]
WantedBy=multi-user.target
and version B has
[Install]
WantedBy=foo.target
Well this is an edge case I'm sure you'll agree.
Actually, in the short period of time (and with the currently still
low number of packages shipping native units) in Debian, this happened
more often then I'd have expected.
So I think we should have a better answer then just saying this is an edge case.
I still thing we should still call it an edge case tho' :)

Having a way around it is fine tho'.
Post by Michael Biebl
Post by Colin Guthrie
Ultimately, with this case, doing the preset is wrong anyway. You don't
want the distro choice, you want the "what the user had" choice.
You only want to preservce the user choice, if it deviated from the
distro choice.
Well, depending on implementation that's one and the same thing. With
the current implementation of preset, they *are* the same thing, so I
think my statement is valid.
Post by Michael Biebl
Otherwise the package state should be updated to
reflect the latest distro choice.
Assuming currently implementation, my script did this :)

But I can see why you'd like to encapsulate this better in a more
automated fashion and I don't have a direct answer for this (but then I
don't think the proposed scheme here covered the opposite case either -
i.e. user deviating from distro choice - so IMO it's just as bad!)

Col
--
Colin Guthrie
gmane(at)colin.guthr.ie
http://colin.guthr.ie/

Day Job:
Tribalogic Limited http://www.tribalogic.net/
Open Source:
Mageia Contributor http://www.mageia.org/
PulseAudio Hacker http://www.pulseaudio.org/
Trac Hacker http://trac.edgewall.org/
Andrei Borzenkov
2014-11-19 17:49:51 UTC
Permalink
В Tue, 18 Nov 2014 16:22:18 +0000
Post by Colin Guthrie
Post by Michael Biebl
Post by Colin Guthrie
Post by Michael Biebl
Post by Colin Guthrie
Post by Didier Roche
This would be maybe a nice way for the admin to know what's coming from
a distribution default or not. However, let's say I want to ensure that
ssh will always be available on my server, I would (even if it's in my
server preset) then systemctl enable openssh, no matter whatever future
preset updates does (like disable it in the next batch upgrade).
For the avoidance of doubt, I believe that running systemctl preset
should only ever happen on *first* install, never on upgrade or such like.
And what are you going to do, if the unit file changes?
Say v1 had
[Install]
WantedBy=multi-user.target
and version B has
[Install]
WantedBy=foo.target
Well this is an edge case I'm sure you'll agree.
Actually, in the short period of time (and with the currently still
low number of packages shipping native units) in Debian, this happened
more often then I'd have expected.
So I think we should have a better answer then just saying this is an edge case.
I still thing we should still call it an edge case tho' :)
Having a way around it is fine tho'.
Post by Michael Biebl
Post by Colin Guthrie
Ultimately, with this case, doing the preset is wrong anyway. You don't
want the distro choice, you want the "what the user had" choice.
You only want to preservce the user choice, if it deviated from the
distro choice.
Well, depending on implementation that's one and the same thing. With
the current implementation of preset, they *are* the same thing,
Not really. There is no way to distinguish between unit enabled by
presets and unit enabled by admin.
Post by Colin Guthrie
so I
think my statement is valid.
Post by Michael Biebl
Otherwise the package state should be updated to
reflect the latest distro choice.
Assuming currently implementation, my script did this :)
But I can see why you'd like to encapsulate this better in a more
automated fashion and I don't have a direct answer for this (but then I
don't think the proposed scheme here covered the opposite case either -
i.e. user deviating from distro choice - so IMO it's just as bad!)
Col
Colin Guthrie
2014-11-20 10:18:05 UTC
Permalink
Post by Andrei Borzenkov
В Tue, 18 Nov 2014 16:22:18 +0000
Post by Colin Guthrie
Post by Michael Biebl
Post by Colin Guthrie
Post by Michael Biebl
Post by Colin Guthrie
Post by Didier Roche
This would be maybe a nice way for the admin to know what's coming from
a distribution default or not. However, let's say I want to ensure that
ssh will always be available on my server, I would (even if it's in my
server preset) then systemctl enable openssh, no matter whatever future
preset updates does (like disable it in the next batch upgrade).
For the avoidance of doubt, I believe that running systemctl preset
should only ever happen on *first* install, never on upgrade or such like.
And what are you going to do, if the unit file changes?
Say v1 had
[Install]
WantedBy=multi-user.target
and version B has
[Install]
WantedBy=foo.target
Well this is an edge case I'm sure you'll agree.
Actually, in the short period of time (and with the currently still
low number of packages shipping native units) in Debian, this happened
more often then I'd have expected.
So I think we should have a better answer then just saying this is an edge case.
I still thing we should still call it an edge case tho' :)
Having a way around it is fine tho'.
Post by Michael Biebl
Post by Colin Guthrie
Ultimately, with this case, doing the preset is wrong anyway. You don't
want the distro choice, you want the "what the user had" choice.
You only want to preservce the user choice, if it deviated from the
distro choice.
Well, depending on implementation that's one and the same thing. With
the current implementation of preset, they *are* the same thing,
Not really. There is no way to distinguish between unit enabled by
presets and unit enabled by admin.
Indeed, but is this an important distinction?

If a user installs something knowing the distro policy is to not enable
a service on install they will perhaps quite happily observe this
behaviour (perhaps rebooting several times) and indeed rely on it
(perhaps not wanting it enabled for whatever reason).

If the package is subsequently updated and it's individual policy
changes to enable the service by default (or even if the distro policy
is updated to change to enabling services by default), do you want to
know that the user has not *changed* anything or do you want to know
that the user has *observed* anything? The latter is obviously much
harder to tell!

Personally, I believe that once the package is installed, everything
moves over to user/admin decisions. Regardless of whether the user has
consciously enabled or disabled anything, their system is running in a
particular way and packages or a change of distro policy should not mess
with that later.

So while I agree with your statement, I'm not sure it actually matters.

I certainly strongly disagree with the original statement "You only want
to preservce the user choice, if it deviated from the distro choice." If
the user has *observed* the distro choice in anyway, they are now
relying on it. You cannot and should not go messing with that later.

(Of course there may be valid exceptions for that but these IMO should
be strongly discouraged. In those special cases you'd maybe even want
warnings to be shown to the user before altering anything and perhaps
give the user veto powers. But on the whole I don't think I've yet heard
a good argument for creating an infrastructure that allows to change
things *after* initial install automatically, even if package or distro
policy changes.... after a factory reset I'd agree it should take on the
new defaults, but not on a stateful system during package upgrades)

Again, just my opinion and there may very well be good counter arguments.

Col
--
Colin Guthrie
gmane(at)colin.guthr.ie
http://colin.guthr.ie/

Day Job:
Tribalogic Limited http://www.tribalogic.net/
Open Source:
Mageia Contributor http://www.mageia.org/
PulseAudio Hacker http://www.pulseaudio.org/
Trac Hacker http://trac.edgewall.org/
Lennart Poettering
2014-12-02 00:51:57 UTC
Permalink
Post by Michael Biebl
Post by Colin Guthrie
Post by Didier Roche
This would be maybe a nice way for the admin to know what's coming from
a distribution default or not. However, let's say I want to ensure that
ssh will always be available on my server, I would (even if it's in my
server preset) then systemctl enable openssh, no matter whatever future
preset updates does (like disable it in the next batch upgrade).
For the avoidance of doubt, I believe that running systemctl preset
should only ever happen on *first* install, never on upgrade or such like.
And what are you going to do, if the unit file changes?
Say v1 had
[Install]
WantedBy=multi-user.target
and version B has
[Install]
WantedBy=foo.target
Package installs should probably not try to do something about this
case, just leave things as is.

I mean, let's not forget that admins should be able to define their
own targets and then enabled units in them and disable them
elsewhere. Package upgrades should not manipulate that. The first
installation of a package should enable a unit if that's what the
preset policy says, but from that point on the configuration is admin
configuration and not be changed anymore automatically.

Lennart
--
Lennart Poettering, Red Hat
Uoti Urpala
2014-12-02 18:02:39 UTC
Permalink
Post by Lennart Poettering
Post by Michael Biebl
Post by Colin Guthrie
For the avoidance of doubt, I believe that running systemctl preset
should only ever happen on *first* install, never on upgrade or such like.
And what are you going to do, if the unit file changes?
Say v1 had
[Install]
WantedBy=multi-user.target
and version B has
[Install]
WantedBy=foo.target
Package installs should probably not try to do something about this
case, just leave things as is.
I think this would be a very bad idea. Installing a system and then
upgrading it should give you the same state as installing a newer system
directly; silently leaving outdated configuration in use almost ensures
that systems will fail/degrade over time.
Post by Lennart Poettering
I mean, let's not forget that admins should be able to define their
own targets and then enabled units in them and disable them
elsewhere. Package upgrades should not manipulate that. The first
installation of a package should enable a unit if that's what the
preset policy says, but from that point on the configuration is admin
configuration and not be changed anymore automatically.
It's theoretically possible that the admin could have moved it to a
different target, but that's the exception. The system should still
sanely handle the normal case where the admin has changed nothing, and
in that case leaving the unit in its original target is completely
wrong.

For example, if you move a unit from sysinit.target to multi-user.target
and remove "DefaultDependencies=no" from the .service file, then leaving
the installed symlink for sysinit.target will cause a dependency loop.
Even in cases where the resulting configuration is not so obviously
broken, differences from the behavior of new installs are always
harmful.

If the admin HAS changed the configuration, then silently ignoring
package changes is still not good behavior: it's likely that the admin
should at least check whether the local changes are still required/valid
and fix the setup to match the new package behavior if needed.

So overall, I think the rules for package upgrades should be:
In the default no-local-changes case, package upgrades MUST change
symlinks to match what a new package install would set.
If local configuration changes can be detected, then the admin should be
alerted to the need to check the configuration if possible.
Lennart Poettering
2014-12-05 01:39:09 UTC
Permalink
Post by Uoti Urpala
Post by Lennart Poettering
Post by Michael Biebl
Post by Colin Guthrie
For the avoidance of doubt, I believe that running systemctl preset
should only ever happen on *first* install, never on upgrade or such like.
And what are you going to do, if the unit file changes?
Say v1 had
[Install]
WantedBy=multi-user.target
and version B has
[Install]
WantedBy=foo.target
Package installs should probably not try to do something about this
case, just leave things as is.
I think this would be a very bad idea. Installing a system and then
upgrading it should give you the same state as installing a newer system
directly; silently leaving outdated configuration in use almost ensures
that systems will fail/degrade over time.
Well, things are not that easy.

If distro Foobarix decides one day that from this day on sendmail
should be enabled again by default, what is the "right" upgrade path
for old installs? Should it be enabled now, because that's the new
default for new installs? Or should it stay disabled, since that's
what the user is accustomed to?

I am pretty sure the latter.

I mean, of course, you can play games and try to guess if sendmail was
off when the upgrade took place simply because that used to be the
default, or because the user/admin really didn't want it to run, which
just accidentally happened to be the default. You have a 50/50 chance
to win this guess, which makes the excercise quite moot I'd say.

I'd really be conservative here: optional things that change their
default should be left as is on updates.

Of course, if something starts to be a necessity that wasn't one
strictly necessary then one should do something about this, but
usually in that case this would be a move from "systemctl enable"
units towards statically enabled ones anyway. But again: if something
was optional before, and is optional after, then be conservative,
don't change things...
Post by Uoti Urpala
Post by Lennart Poettering
I mean, let's not forget that admins should be able to define their
own targets and then enabled units in them and disable them
elsewhere. Package upgrades should not manipulate that. The first
installation of a package should enable a unit if that's what the
preset policy says, but from that point on the configuration is admin
configuration and not be changed anymore automatically.
It's theoretically possible that the admin could have moved it to a
different target, but that's the exception. The system should still
sanely handle the normal case where the admin has changed nothing, and
in that case leaving the unit in its original target is completely
wrong.
For example, if you move a unit from sysinit.target to multi-user.target
and remove "DefaultDependencies=no" from the .service file, then leaving
the installed symlink for sysinit.target will cause a dependency loop.
Sure, if you know that changes in your unit files actively break a
previous default, then you should do something about it, but I think
cases like this are best handled with careful, manually written
postinst scripts, that do the right thing in the most defensive
possible way. But blindly enabling all kinds of stuff just because the
upstream default changed is really not a good idea I think.

Lennart
--
Lennart Poettering, Red Hat
Andrei Borzenkov
2014-12-05 07:50:10 UTC
Permalink
В Fri, 5 Dec 2014 02:39:09 +0100
Post by Lennart Poettering
Post by Uoti Urpala
Post by Lennart Poettering
Post by Michael Biebl
Post by Colin Guthrie
For the avoidance of doubt, I believe that running systemctl preset
should only ever happen on *first* install, never on upgrade or such like.
And what are you going to do, if the unit file changes?
Say v1 had
[Install]
WantedBy=multi-user.target
and version B has
[Install]
WantedBy=foo.target
Package installs should probably not try to do something about this
case, just leave things as is.
I think this would be a very bad idea. Installing a system and then
upgrading it should give you the same state as installing a newer system
directly; silently leaving outdated configuration in use almost ensures
that systems will fail/degrade over time.
Well, things are not that easy.
If distro Foobarix decides one day that from this day on sendmail
should be enabled again by default, what is the "right" upgrade path
for old installs? Should it be enabled now, because that's the new
default for new installs? Or should it stay disabled, since that's
what the user is accustomed to?
That's one of the problems today - there is no way to distinguish
between "unit was not enabled due to previous defaults" and "unit was
disabled explicitly by admin". Although I'm afraid even this does not
really solve the issue as it leaves the case of "it was disabled by
default and admin was OK with it" out.

The idea of having default enabled/disabled state in /usr/lib and
letting admin override it in /etc allows to partially solve it while
making packaging really easy - changes to default unit states would
simply mean changing shipped files that is already handled right.
Uoti Urpala
2014-12-05 15:55:39 UTC
Permalink
Post by Lennart Poettering
Post by Uoti Urpala
Post by Lennart Poettering
Post by Michael Biebl
WantedBy=multi-user.target
and version B has
[Install]
WantedBy=foo.target
Package installs should probably not try to do something about this
case, just leave things as is.
I think this would be a very bad idea. Installing a system and then
upgrading it should give you the same state as installing a newer system
directly; silently leaving outdated configuration in use almost ensures
that systems will fail/degrade over time.
Well, things are not that easy.
If distro Foobarix decides one day that from this day on sendmail
should be enabled again by default, what is the "right" upgrade path
for old installs? Should it be enabled now, because that's the new
default for new installs? Or should it stay disabled, since that's
what the user is accustomed to?
The context here was a package changing its install target, not changing
default enable/disable behavior as in your example. The latter is a less
clear-cut case: if the unit has a [Install] section, then presumably the
packager considers both enabled and disabled state supported at least to
some degree, and thus both are explicitly valid choices even on newly
installed systems. By contrast, leaving symlinks from targets that do
not match the [Install] section of the current service file anymore is
more arbitrary reconfiguration, which cannot be expected to work in
general (as in linking arbitrary units from arbitrary targets is not
expected to work), and it's the admin's responsibility to investigate
what he needs to do to make such configurations work and keep them
working.

Keeping such obsolete configuration would mean that systems rot over
time. Package configuration files are not handled that way, and package
startup configuration shouldn't be either, for the same reasons.

Just leaving the symlinks would not give good behavior even in the case
where the admin wants to keep the old target: temporary disable + then
re-enable would now change the target. Perhaps the recommended way to
change targets in local configuration should be to override the
[Install] section, instead of just leaving different symlinks?
Post by Lennart Poettering
units towards statically enabled ones anyway. But again: if something
was optional before, and is optional after, then be conservative,
don't change things...
IMO in the changing-targets case it's not "conservative" at all to
silently leave the system in a state where it has obsolete configuration
which does not match anything supported by the current packaging. Such
behavior is almost 100% guaranteed to break things at some point.
"Conservative" would be something like refusing to upgrade until the
admin resolves possible conflicts manually. If no local configuration
can be detected, using the new packaging defaults has a better chance of
avoiding breakage than leaving obsolete configuration.
Post by Lennart Poettering
Sure, if you know that changes in your unit files actively break a
previous default, then you should do something about it, but I think
cases like this are best handled with careful, manually written
postinst scripts, that do the right thing in the most defensive
possible way. But blindly enabling all kinds of stuff just because the
upstream default changed is really not a good idea I think.
The new defaults could enable more things, or they could disable parts
that are now deemed insecure or unnecessary, or just generally fix bugs.
The sane default assumption is that later package versions are better
than earlier ones, and leaving the system using old default
configuration is worse than new configuration. And that's assuming the
old configuration even works anymore given changes elsewhere.
Zbigniew Jędrzejewski-Szmek
2014-12-08 17:35:07 UTC
Permalink
Post by Uoti Urpala
Just leaving the symlinks would not give good behavior even in the case
where the admin wants to keep the old target: temporary disable + then
re-enable would now change the target. Perhaps the recommended way to
change targets in local configuration should be to override the
[Install] section, instead of just leaving different symlinks?
That'd be quite annoying. Maybe instead systemd-delta should learn
to highlight symlinks which are not specified by [Install] section.

Zbyszek
Didier Roche
2014-11-18 15:40:05 UTC
Permalink
Post by Colin Guthrie
Hiya,
Hey,
Post by Colin Guthrie
Post by Didier Roche
This would be maybe a nice way for the admin to know what's coming from
a distribution default or not. However, let's say I want to ensure that
ssh will always be available on my server, I would (even if it's in my
server preset) then systemctl enable openssh, no matter whatever future
preset updates does (like disable it in the next batch upgrade).
For the avoidance of doubt, I believe that running systemctl preset
should only ever happen on *first* install, never on upgrade or such like.
This also avoids any problems here.
(Of course if /etc is nuked, then reapplying the defaults from *.preset
should be done!)
See my Michael's answer (and my previous one) on the fact that maybe the
preset files would be part of multiple packages (to disable certain
units), and some being only part of packages not installed by default.
Michael's case as well of a unit changing its target on a package
upgrade (as a packaging fix, maybe) is valid as well.
Post by Colin Guthrie
Post by Didier Roche
With a shared distro/admin /etc, we have no way to take that fact into
account and the next one would follow distro policy, right?
Yeah, but that's assuming there *is* a next one. Once things are
installed, the user should *not* be surprised by any action being taken
without their consent on upgrade.
FWIW, it's probably worth considering how you'd handle not changing
users current preferences with regards to enabling/disabling things on
upgrade. I can see this being quite hard for you roll out with your
current suggestions, but you may have this covered already.
Actually, this reminds me some issues we had with gconf in the past in
changing distribution's default and deciphering what was users current
preference or what was distro default behavior.
Gnome-panel was copying its whole distro defaults in ~/.gconf.
Adding/removing some default layouts and settings from the panel was
then unnecessary difficult. Some changes was part of new default
behaviors we wanted that the user never interacted with and was desired
to be changed (because of some applets getting low maintenance,
incompatible with newer technology or duplicates…)
As everything was at the same place, it was difficult to know if the
current value was set because of the previous default, or if the user
explicitly tweaked and then selected it.

I see the same issue with the shared /etc: is this unit enabled for that
target because of one the preset config, or did the admin run "systemctl
enable <unit>" explicitly and want to keep it? I think it's ok to change
distro defaults on upgrade (will be potentially in major version upgrade
of course), not user (admin here) preferences, of course. But we do have
no way to know for sure which is which in the current system.
Post by Colin Guthrie
Post by Didier Roche
Also, after running systemctl enable opensshn, systemctl status openssh
will still say "enabled (preset)" even if the admin wanted to "stick it
for good" as it's part of the preset.
Not sure what you mean by "stick it for good" here, but my previous
disabled]" accordingly which might be clearer (if a bit longer).
Same than in previous case:
I have a preset with
enable docker.socket

systemctl status docker.socket
-> "enabled [preset: enabled]"

systectl enable docker.socket
systemctl status docker.socket
-> "enabled [preset: enabled]"

I guess, it should then just be "enabled". Maybe that will then ask for
a systemctl reset <unit> command or something like that…
Post by Colin Guthrie
Post by Didier Roche
Post by Tom Gundersen
Doing 'enable' on a preset unit will then just delete the symlink to
/dev/null from /etc (if it exists) and doing 'disable' will add it.
This would also entail changing the current logic to check the target
of /**/*.wants.d/ symlinks to see if they point to /dev/null, in which
case they should be ignored.
Did I understand that correctly?
Right, maybe the implementation can diverge a little bit from that, but
the intent would cover most of the admin/distro separation, while
enabling sysadmin to "stick" some of the services disregarding future
distro choices and keeping a clean /etc.
Again, just to clarify, the current implementation intends that
"systemctl preset myservice.service" is only run on the first
installation of a package, not on upgrades.
There should be no need to "stick" some of the services as distro
choices are only applied at install time, and never on upgrade.
Post by Didier Roche
Post by Tom Gundersen
Post by Didier Roche
- systemctl status <unit> will report "disabled", where it's actually
enabled and starting for that unit. This is a bug which should be fixed in
any case, as "disabled" is outright wrong. On IRC it was suggested that
those are "static" units, but then it should say at least that.
I agree, this should be fixed to report them as 'static' (as any state
in /etc apart from masking is irrelevant).
agreed (if we want to keep the current logic of not shipping other kind
of units in /usr)
Post by Tom Gundersen
Post by Didier Roche
- systemctl enable <unit> will duplicate the symlink in /etc
I guess this should also be dropped (though the situation here is
weird as it anyway is a noop). Maybe a warning should be printed.
agreed as well, or, this would be a way for the sysadmin to "stick" this
unit/service whatever future distro will choose in the next upgrade.
Just to reiterate, the need for "sticking" a unit is currently not
needed, so adding this extra layer of complexity in any future changes
is not something I'd personally like to see. In my mind any package
presets (or distro choices or whatever we should call it) should only
apply on first install and not on future upgrades. I don't want to be
surprised by a change of behaviour on upgrade.
I don't reiterate the same arguments again, but yeah, it seems that all
consequences of our discussions are based on the preset usage: having as
a goal on central place installed by default, where we would list to
disable all existing units that needs to be disabled we have throughout
the archive, and be future proof for upgrade (like from a distribution
upgrade which will enable new upstream packages) seems quite hard to
reach out.
Post by Colin Guthrie
Hope this is useful clarifications.
It does, thanks!

Cheers,
Didier
Colin Guthrie
2014-11-21 11:08:44 UTC
Permalink
Hello again!
Post by Didier Roche
Post by Colin Guthrie
Hiya,
Hey,
Post by Colin Guthrie
Post by Didier Roche
This would be maybe a nice way for the admin to know what's coming from
a distribution default or not. However, let's say I want to ensure that
ssh will always be available on my server, I would (even if it's in my
server preset) then systemctl enable openssh, no matter whatever future
preset updates does (like disable it in the next batch upgrade).
For the avoidance of doubt, I believe that running systemctl preset
should only ever happen on *first* install, never on upgrade or such like.
This also avoids any problems here.
(Of course if /etc is nuked, then reapplying the defaults from *.preset
should be done!)
See my Michael's answer (and my previous one) on the fact that maybe the
preset files would be part of multiple packages (to disable certain
units), and some being only part of packages not installed by default.
Michael's case as well of a unit changing its target on a package
upgrade (as a packaging fix, maybe) is valid as well.
I think the distro-wide preset usage would be in a very core package
that is likely installed very early on (perhaps even the package is
required by the one that ships systemctl and thus has to be installed
first).

If you end up shipping random .preset files with the actual packages
containing the units they affect (which isn't recommend as previously
noted, but perhaps you still want to do it that way for some special
cases) then this too will be fine.

I can see some complications here but nothing that isn't manageable.
Post by Didier Roche
Post by Colin Guthrie
Post by Didier Roche
With a shared distro/admin /etc, we have no way to take that fact into
account and the next one would follow distro policy, right?
Yeah, but that's assuming there *is* a next one. Once things are
installed, the user should *not* be surprised by any action being taken
without their consent on upgrade.
FWIW, it's probably worth considering how you'd handle not changing
users current preferences with regards to enabling/disabling things on
upgrade. I can see this being quite hard for you roll out with your
current suggestions, but you may have this covered already.
Actually, this reminds me some issues we had with gconf in the past in
changing distribution's default and deciphering what was users current
preference or what was distro default behavior.
Gnome-panel was copying its whole distro defaults in ~/.gconf.
Adding/removing some default layouts and settings from the panel was
then unnecessary difficult. Some changes was part of new default
behaviors we wanted that the user never interacted with and was desired
to be changed (because of some applets getting low maintenance,
incompatible with newer technology or duplicates…)
As everything was at the same place, it was difficult to know if the
current value was set because of the previous default, or if the user
explicitly tweaked and then selected it.
I see the same issue with the shared /etc: is this unit enabled for that
target because of one the preset config, or did the admin run "systemctl
enable <unit>" explicitly and want to keep it? I think it's ok to change
distro defaults on upgrade (will be potentially in major version upgrade
of course), not user (admin here) preferences, of course.
I would personally disagree with this statement that it's OK to change
the distro defaults on upgrade. As an admin, whether I observe some
behaviour but do not actively reinforce it (e.g. I see that installing
httpd enables it by default and thus my server is working fine, so I
don't need to do "systemctl enable httpd" manually) I now rely on the
distro default. If that was to be changed on upgrade (whether package or
whole distro), I'd personally be really annoyed!

With the goal of being able to reset things (i.e. trashing /etc) if
desired, the admin has a pretty good choice to start again with a clean
slate after a distro upgrade if they so wish. Otherwise I'd very much
expect my system to retain as much state as possible (whether that may
have come from a preset or an active choice is, IMO, irrelevant - it's
how the system was ultimately configured and what the admin now relies
on) over the distro upgrade process.
Post by Didier Roche
But we do have
no way to know for sure which is which in the current system.
Yeah, I accept this is a limitation of the current system. I guess I'm
just making the argument that, IMO, this detail doesn't matter as I
don't see the need to use this information for anything automated anyway.
Post by Didier Roche
Post by Colin Guthrie
Post by Didier Roche
Also, after running systemctl enable opensshn, systemctl status openssh
will still say "enabled (preset)" even if the admin wanted to "stick it
for good" as it's part of the preset.
Not sure what you mean by "stick it for good" here, but my previous
disabled]" accordingly which might be clearer (if a bit longer).
I have a preset with
enable docker.socket
systemctl status docker.socket
-> "enabled [preset: enabled]"
systectl enable docker.socket
systemctl status docker.socket
-> "enabled [preset: enabled]"
I guess, it should then just be "enabled". Maybe that will then ask for
a systemctl reset <unit> command or something like that…
Oh right, so you're very specifically wanting to differentiate from a
systemctl preset call vs a systemctl enable command and somehow
recording that state somewhere. I guess that makes sense with some of
your previous comments. Sorry for not seeing that properly!

FWIW, all I was suggesting with adding the preset information into the
systemctl status would be to report based on current *.preset files as
to what the preset state would be if it were run now, as if the package
was freshly installed. I wasn't suggesting the usage of systemctl enable
be tracked somehow. So the output you simulated above is what I was
expecting to see anyway :)


As noted previously I think it's very wrong to push the enablement
policy into the individual packages (thus I think using /usr is not an
option), so I think it would be very hard to actually track this detail
anyway if both preset info and normal admin info is both stored in /etc
(that being the alternative to using /usr).



But overall, as is the case I'm trying to make, I really don't see much
value in differentiating the manually enabled vs enabled by preset
cases. IMO, that information cannot (or rather should not) be used in
any automated way, although I do concede that it would be "interesting"
to know this detail as an administrator.


This is an interesting discussion, and I'm looking forward to see what
others think too :)

Cheers!

Col
--
Colin Guthrie
gmane(at)colin.guthr.ie
http://colin.guthr.ie/

Day Job:
Tribalogic Limited http://www.tribalogic.net/
Open Source:
Mageia Contributor http://www.mageia.org/
PulseAudio Hacker http://www.pulseaudio.org/
Trac Hacker http://trac.edgewall.org/
Didier Roche
2014-11-28 10:15:37 UTC
Permalink
Post by Colin Guthrie
Hello again!
Hey, trying to revive the topic :)
Post by Colin Guthrie
Post by Didier Roche
Post by Colin Guthrie
Hiya,
Hey,
Post by Colin Guthrie
Post by Didier Roche
This would be maybe a nice way for the admin to know what's coming from
a distribution default or not. However, let's say I want to ensure that
ssh will always be available on my server, I would (even if it's in my
server preset) then systemctl enable openssh, no matter whatever future
preset updates does (like disable it in the next batch upgrade).
For the avoidance of doubt, I believe that running systemctl preset
should only ever happen on *first* install, never on upgrade or such like.
This also avoids any problems here.
(Of course if /etc is nuked, then reapplying the defaults from *.preset
should be done!)
See my Michael's answer (and my previous one) on the fact that maybe the
preset files would be part of multiple packages (to disable certain
units), and some being only part of packages not installed by default.
Michael's case as well of a unit changing its target on a package
upgrade (as a packaging fix, maybe) is valid as well.
I think the distro-wide preset usage would be in a very core package
that is likely installed very early on (perhaps even the package is
required by the one that ships systemctl and thus has to be installed
first).
If you end up shipping random .preset files with the actual packages
containing the units they affect (which isn't recommend as previously
noted, but perhaps you still want to do it that way for some special
cases) then this too will be fine.
I can see some complications here but nothing that isn't manageable.
This is a good news.
Post by Colin Guthrie
Post by Didier Roche
Post by Colin Guthrie
Post by Didier Roche
With a shared distro/admin /etc, we have no way to take that fact into
account and the next one would follow distro policy, right?
Yeah, but that's assuming there *is* a next one. Once things are
installed, the user should *not* be surprised by any action being taken
without their consent on upgrade.
FWIW, it's probably worth considering how you'd handle not changing
users current preferences with regards to enabling/disabling things on
upgrade. I can see this being quite hard for you roll out with your
current suggestions, but you may have this covered already.
Actually, this reminds me some issues we had with gconf in the past in
changing distribution's default and deciphering what was users current
preference or what was distro default behavior.
Gnome-panel was copying its whole distro defaults in ~/.gconf.
Adding/removing some default layouts and settings from the panel was
then unnecessary difficult. Some changes was part of new default
behaviors we wanted that the user never interacted with and was desired
to be changed (because of some applets getting low maintenance,
incompatible with newer technology or duplicates…)
As everything was at the same place, it was difficult to know if the
current value was set because of the previous default, or if the user
explicitly tweaked and then selected it.
I see the same issue with the shared /etc: is this unit enabled for that
target because of one the preset config, or did the admin run "systemctl
enable <unit>" explicitly and want to keep it? I think it's ok to change
distro defaults on upgrade (will be potentially in major version upgrade
of course), not user (admin here) preferences, of course.
I would personally disagree with this statement that it's OK to change
the distro defaults on upgrade. As an admin, whether I observe some
behaviour but do not actively reinforce it (e.g. I see that installing
httpd enables it by default and thus my server is working fine, so I
don't need to do "systemctl enable httpd" manually) I now rely on the
distro default. If that was to be changed on upgrade (whether package or
whole distro), I'd personally be really annoyed!
With the goal of being able to reset things (i.e. trashing /etc) if
desired, the admin has a pretty good choice to start again with a clean
slate after a distro upgrade if they so wish. Otherwise I'd very much
expect my system to retain as much state as possible (whether that may
have come from a preset or an active choice is, IMO, irrelevant - it's
how the system was ultimately configured and what the admin now relies
on) over the distro upgrade process.
That's what we did in multiple cases in ubuntu in particular. I gave in
previous emails some desktop-related email. Another one I didn't mention
is when we changed from gdm to lightdm as the default dm, or gnome-panel
-> unity. If the user selected another dm or another desktop session, we
keep user's preference, if they switched and then switched back, we keep
user's preference as well. We migrate to our new defaults if there was
trace of new user settings.

I guess different settings and policy from different distro, but it's
clearly something that was always not easy to managed and having a clean
/etc will go into that direction in my opinon.
Post by Colin Guthrie
Post by Didier Roche
But we do have
no way to know for sure which is which in the current system.
Yeah, I accept this is a limitation of the current system. I guess I'm
just making the argument that, IMO, this detail doesn't matter as I
don't see the need to use this information for anything automated anyway.
Post by Didier Roche
Post by Colin Guthrie
Post by Didier Roche
Also, after running systemctl enable opensshn, systemctl status openssh
will still say "enabled (preset)" even if the admin wanted to "stick it
for good" as it's part of the preset.
Not sure what you mean by "stick it for good" here, but my previous
disabled]" accordingly which might be clearer (if a bit longer).
I have a preset with
enable docker.socket
systemctl status docker.socket
-> "enabled [preset: enabled]"
systectl enable docker.socket
systemctl status docker.socket
-> "enabled [preset: enabled]"
I guess, it should then just be "enabled". Maybe that will then ask for
a systemctl reset <unit> command or something like that…
Oh right, so you're very specifically wanting to differentiate from a
systemctl preset call vs a systemctl enable command and somehow
recording that state somewhere. I guess that makes sense with some of
your previous comments. Sorry for not seeing that properly!
FWIW, all I was suggesting with adding the preset information into the
systemctl status would be to report based on current *.preset files as
to what the preset state would be if it were run now, as if the package
was freshly installed. I wasn't suggesting the usage of systemctl enable
be tracked somehow. So the output you simulated above is what I was
expecting to see anyway :)
As noted previously I think it's very wrong to push the enablement
policy into the individual packages (thus I think using /usr is not an
option), so I think it would be very hard to actually track this detail
anyway if both preset info and normal admin info is both stored in /etc
(that being the alternative to using /usr).
Yeah, in debian/ubuntu, we would mostly have enable * (which is the same
as having no pragma in the preset file from what I understood) + some
specific disablement anyway.
However, I was thinking recently about unit alias and how that would
work. Let's take display managers as an example.

The distribution comes preinstalled with one dm, enable * -> enable it,
have the Alias=display-manager.service picking the right one.
However, let's say the user installed then another dm, what happens?
Both will be enabled if we systemctl preset <new_service> (as the
discussion was to remove our debian enable <service> that was
conditioned on the postinst). 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?)

We can of course have an ubuntu-desktop.preset which disables all dms by
lightdm, and an ubuntu-gnome.preset which disables all dms but gdm (and
having those settings conflicting with each other), but it's seems that
for every aliases, we need to maintain such a list (as we enable * by
default)?

Shipping distro defaults enablement symlinks in /usr would enable
avoiding that (we need to have package conflicts for lightdm-default and
gdm-default of course), knowing that we will shadow the alias with a new
symlink in /etc if the admin changes his name for instance.

Without regarding the /etc vs /usr discussion, I really want to
experiment with presets instead of our systemctl enable package postinst
snippets (we don't really run that for the record but make manual
symlinks and store default symlinks in another directory). However, I
would appreciate some guidance on a smart way to achieve this in those
kind of complex cases.
It's too late for that change for debian jessie (getting more and more
frozen), but we can pilot that in ubuntu vivid before pushing it to
jessie+1).
Post by Colin Guthrie
But overall, as is the case I'm trying to make, I really don't see much
value in differentiating the manually enabled vs enabled by preset
cases. IMO, that information cannot (or rather should not) be used in
any automated way, although I do concede that it would be "interesting"
to know this detail as an administrator.
I agree if that was the only one aspect of the problem, the other one
(where we started this discussion) was a readable /etc/systemd/ and
really keeping /etc for machine-specific and admin derivations from
distro. Keeping /usr for the distro, and /etc for the admin (as Lennart
told in multiple conferences).
Post by Colin Guthrie
This is an interesting discussion, and I'm looking forward to see what
others think too :)
Same from me, I hope we can see other people jumping from there and
giving their opinions. :)

Cheers,
Didier
Lennart Poettering
2014-12-02 00:59:14 UTC
Permalink
The distribution comes preinstalled with one dm, enable * -> enable it, have
the Alias=display-manager.service picking the right one.
However, let's say the user installed then another dm, what happens? Both
will be enabled if we systemctl preset <new_service> (as the discussion was
to remove our debian enable <service> that was conditioned on the
postinst).
"systemctl preset" will fail if there are already conflicting
symlinks. Hence the first installed DM wins, the second loses.
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"?
We can of course have an ubuntu-desktop.preset which disables all dms by
lightdm, and an ubuntu-gnome.preset which disables all dms but gdm (and
having those settings conflicting with each other), but it's seems that for
every aliases, we need to maintain such a list (as we enable * by
default)?
Not following here. Different flavours of Ubuntu should probably just
ship different preset files. (Or well, the main ubuntu should ship one
that enables lightdm, and then the gnome flavour ship another preset
file, with a lower name, tht overries the lightdm line, and enables
gdm instead).

Lennart
--
Lennart Poettering, Red Hat
Didier Roche
2014-12-02 11:50:46 UTC
Permalink
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)
Post by Lennart Poettering
The distribution comes preinstalled with one dm, enable * -> enable it, have
the Alias=display-manager.service picking the right one.
However, let's say the user installed then another dm, what happens? Both
will be enabled if we systemctl preset <new_service> (as the discussion was
to remove our debian enable <service> that was conditioned on the
postinst).
"systemctl preset" will fail if there are already conflicting
symlinks. Hence the first installed DM wins, the second loses.
Ok, that works with the initial install case then.
However, if lightdm is installed and the admin install gdm, he will get
a prompt (from postinst) asking him which dm to choose. How would you
handle that (without messing manually with the symlinks or systemctl
enable --force in the postinst?). Writing new presets in /etc which
enables the chosen dm and disable other, then reloading preset file to
reset that display-manager.service alias?
Post by Lennart Poettering
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.
Post by Lennart Poettering
We can of course have an ubuntu-desktop.preset which disables all dms by
lightdm, and an ubuntu-gnome.preset which disables all dms but gdm (and
having those settings conflicting with each other), but it's seems that for
every aliases, we need to maintain such a list (as we enable * by
default)?
Not following here. Different flavours of Ubuntu should probably just
ship different preset files. (Or well, the main ubuntu should ship one
that enables lightdm, and then the gnome flavour ship another preset
file, with a lower name, tht overries the lightdm line, and enables
gdm instead).
You meant disable, right? As our default is to enable all services.
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)

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?


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).

Same for enabling a service that is by default disabled: next systemctl
call on reinstall will remove the symlinks (Alias included).


II. if the adminstrator purges the service package, we usually expect
that reinstalling it will reset the service to the default
enablement/disablement state.
So:
<foo.service> enabled by default
1. systemctl disable foo.service
2. apt-get remove --purge foo
3. apt-get install foo
-> foo should be enabled as this is the default state in distro.
This use case works because the previous one doesn't :)

So, I think we should really be able to fix case I. 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?


Cheers,
Didier
Colin Guthrie
2014-12-02 12:37:01 UTC
Permalink
Post by Didier Roche
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)
Post by Lennart Poettering
The distribution comes preinstalled with one dm, enable * -> enable it, have
the Alias=display-manager.service picking the right one.
However, let's say the user installed then another dm, what happens? Both
will be enabled if we systemctl preset <new_service> (as the
discussion was
to remove our debian enable <service> that was conditioned on the
postinst).
"systemctl preset" will fail if there are already conflicting
symlinks. Hence the first installed DM wins, the second loses.
Ok, that works with the initial install case then.
However, if lightdm is installed and the admin install gdm, he will get
a prompt (from postinst) asking him which dm to choose. How would you
handle that (without messing manually with the symlinks or systemctl
enable --force in the postinst?).
If you are giving the user a choice here specifically, then calling
systemctl enable --force is, IMO, the right thing to do.
Post by Didier Roche
Writing new presets in /etc which
enables the chosen dm and disable other, then reloading preset file to
reset that display-manager.service alias?
I would say that the preset file would be in place for the GNOME spin
such that when it was installed, it would be enabled. The GNOME spin's
installer would likely not install lightdm in the first place and thus
gdm would get enabled when it was installed anyway (with your default
enable policy)

That said, as your policy is to enable things by default, you might want
to actually list all the dms as disable in your standard .preset file
and then have a separate .preset file to enable the appropriate dm that
is shipped with your various spins. That way, simply installing a dm is
not enough to enable it via the default policy. This guards against
needing to stop lightdm being installed on the GNOME spin - installing
would be unneeded, but not problematic - and both lightdm and gdm could
both be installed happily and only gdm would be enabled due to preset.
Post by Didier Roche
Post by Lennart Poettering
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
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.
Yeah, I can see this problem. I guess the setup of preset files as I
mentioned above would deal with this.

I guess the problem doesn't exist on Fedora due to it's disable *
default policy and the easiest way to get the same behaviour would be to
just list all dms as disable in your default .preset file and then
enable them all again via drop in as needed (it's not quite as clean but
it's certainly manageable IMO)
Post by Didier Roche
Post by Lennart Poettering
We can of course have an ubuntu-desktop.preset which disables all dms by
lightdm, and an ubuntu-gnome.preset which disables all dms but gdm (and
having those settings conflicting with each other), but it's seems that for
every aliases, we need to maintain such a list (as we enable * by
default)?
Not following here. Different flavours of Ubuntu should probably just
ship different preset files. (Or well, the main ubuntu should ship one
that enables lightdm, and then the gnome flavour ship another preset
file, with a lower name, tht overries the lightdm line, and enables
gdm instead).
You meant disable, right? As our default is to enable all services.
So we need for any services shipping Aliases to have a preset list per
enable lightdm.service
disable kdm.service
disable gdm.service
disable nodm.service
(and whatnot… dm files in distro)
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?
I should read emails to the bottom I guess - seems you see the same
issue here :)

Yeah, I would agree that this is a bit of a pain to maintain the list,
but I don't think it's too hard either. The number of DMs is pretty
bounded, and it likely doesn't change all that often, so I don't think
it'll be too hard to maintain.

I think I've already stated my opinions on the rest of the use cases in
your email, so I'll leave that for others to comment on :)

Cheers!

Col
--
Colin Guthrie
gmane(at)colin.guthr.ie
http://colin.guthr.ie/

Day Job:
Tribalogic Limited http://www.tribalogic.net/
Open Source:
Mageia Contributor http://www.mageia.org/
PulseAudio Hacker http://www.pulseaudio.org/
Trac Hacker http://trac.edgewall.org/
Lennart Poettering
2014-12-05 01:13:10 UTC
Permalink
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)
Post by Lennart Poettering
The distribution comes preinstalled with one dm, enable * -> enable it, have
the Alias=display-manager.service picking the right one.
However, let's say the user installed then another dm, what happens? Both
will be enabled if we systemctl preset <new_service> (as the discussion was
to remove our debian enable <service> that was conditioned on the
postinst).
"systemctl preset" will fail if there are already conflicting
symlinks. Hence the first installed DM wins, the second loses.
Ok, that works with the initial install case then.
However, if lightdm is installed and the admin install gdm, he will get a
prompt (from postinst) asking him which dm to choose. How would you handle
that (without messing manually with the symlinks or systemctl enable --force
in the postinst?). Writing new presets in /etc which enables the chosen dm
and disable other, then reloading preset file to reset that
display-manager.service alias?
Hmm, I am pretty sure interactive updates are a bad idea. But then
again, I know that Debian likes them.

I think, if you install something new that conflicts with something
installed, then you should enable it if the policy says so and if the
existing package isn't enabled already. But if it is already enabled,
or if the policy says no, then leave it alone.

If you really want an UI in the mix here, I'd recommend just altering
the symlinks directly. (I mean, altering the symlinks manually is
completely OK. systemctl enable/disable/preset is simply supposed to
be a nicer helper there, but in no way should be the exclusive way to
access them).
Post by Lennart Poettering
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
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.
Post by Lennart Poettering
We can of course have an ubuntu-desktop.preset which disables all dms by
lightdm, and an ubuntu-gnome.preset which disables all dms but gdm (and
having those settings conflicting with each other), but it's seems that for
every aliases, we need to maintain such a list (as we enable * by
default)?
Not following here. Different flavours of Ubuntu should probably just
ship different preset files. (Or well, the main ubuntu should ship one
that enables lightdm, and then the gnome flavour ship another preset
file, with a lower name, tht overrides the lightdm line, and enables
gdm instead).
You meant disable, right? As our default is to enable all services.
Yeah, "overrides" meant disabling.
So we need for any services shipping Aliases to have a preset list per
enable lightdm.service
disable kdm.service
disable gdm.service
disable nodm.service
(and whatnot… dm files in distro)
Hmm, indeed I guess...
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...
Finally, on the "know what the administrator did on this machine", here are
I. if the administrator removes the service package, we usually keep current
service state (enabled/disabled) on reinstall.
<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.

How does this all precisely work on sysvinit?
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?

Lennart
--
Lennart Poettering, Red Hat
Didier Roche
2014-12-05 10:06:05 UTC
Permalink
Post by Lennart Poettering
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)
Post by Lennart Poettering
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
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.
Post by Lennart Poettering
So we need for any services shipping Aliases to have a preset list per
enable lightdm.service
disable kdm.service
disable gdm.service
disable nodm.service
(and whatnot… dm files in distro)
Hmm, indeed I guess...
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:
[Install]
Alias=display-manager.service

or preset would then generates a warning.
Post by Lennart Poettering
Finally, on the "know what the administrator did on this machine", here are
I. if the administrator removes the service package, we usually keep current
service state (enabled/disabled) on reinstall.
<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?
Post by Lennart Poettering
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 :)
Post by Lennart Poettering
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
file.

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) ;)
Cheers,
Didier
Lennart Poettering
2014-12-05 13:52:53 UTC
Permalink
Post by Didier Roche
Post by Lennart Poettering
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 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?)
[Install]
Alias=display-manager.service
or preset would then generates a warning.
So far this is not how presets work: they are just a database you pass
in as key a service name, and it tells you whether to enable it or
not, in a simple boolean way. It is something where you pass in the
name of a unit you want to enable/disable, and after you got that, you
do that, but you do not verify again the individual steps
enabling/disabling precisely entail.

It also is currently entirely stateless: you could in theory ask a web
server for such a preset question, and it will always tell you the
same answer, because it does *not* take your local configuration and
set of packages into consideration... This kind of "disconnected" logic
I'd really like to keep.

Hmm, what about this proposal:

Whenever the preset db is queried we'll no longer just return the
verdict boolean, but also a numeric overall line number, of the line
we found the verdict on. Then, when "preset-all" is invoked, we
determine all the operations to execute for everything. Then, before
applying them, we check if there are any conflicting operations. If
so, we remove the ones with the higher line number.

In effect this would mean: if you list to DMs as "enable" in the
preset file, and both are to be installed, then the one that is
enabled "earlier" will win in case of "preset-all". To me this appears
quite a natural extension of the logic already in place.
Post by Didier Roche
Post by Lennart Poettering
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.
- 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 :)
To be honest I find the entire stuff with ENABLED=true/false really
questionnable, I think it would be agreat step ahead to get rid of
it. (But then again, I cannot make Debian's decisions there...)
Post by Didier Roche
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).
This sounds quite a limitation. Maybe you can keep a couple of touch files
in /var/lib/ somewhere where you store whether you already applied
"systemctl preset" before?

Lennart
--
Lennart Poettering, Red Hat
Colin Guthrie
2014-12-05 14:39:19 UTC
Permalink
Post by Lennart Poettering
Post by Didier Roche
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).
This sounds quite a limitation. Maybe you can keep a couple of touch files
in /var/lib/ somewhere where you store whether you already applied
"systemctl preset" before?
For what it's worth, this is the technique I used when migrating
sysvinit -> native units.

For a while, we had both sysvinit script and systemd units shipped in
the same package (to allow a choice of init system - but we dropped
support for sysvinit ages ago - in fact the last distro version that
supported this went EOL the other day!).

When the systemd unit was first introduced in the package (assuming the
user was upgrading) we would migrate the enablement state of the
sysvinit script to the systemd unit - if sysvinit was enabled, then so
should the systemd unit; if it was disabled then so should the systemd
unit. We only did this the first time the systemd unit showed up in the
package and touched a file in /var/lib to track this. After this initial
transition, their enablement state (whether it be sysvinit or native)
was in the hands of the admin.

Col
--
Colin Guthrie
gmane(at)colin.guthr.ie
http://colin.guthr.ie/

Day Job:
Tribalogic Limited http://www.tribalogic.net/
Open Source:
Mageia Contributor http://www.mageia.org/
PulseAudio Hacker http://www.pulseaudio.org/
Trac Hacker http://trac.edgewall.org/
Didier Roche
2014-12-05 15:02:49 UTC
Permalink
Post by Lennart Poettering
Post by Didier Roche
Post by Lennart Poettering
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 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?)
[Install]
Alias=display-manager.service
or preset would then generates a warning.
So far this is not how presets work: they are just a database you pass
in as key a service name, and it tells you whether to enable it or
not, in a simple boolean way. It is something where you pass in the
name of a unit you want to enable/disable, and after you got that, you
do that, but you do not verify again the individual steps
enabling/disabling precisely entail.
It also is currently entirely stateless: you could in theory ask a web
server for such a preset question, and it will always tell you the
same answer, because it does *not* take your local configuration and
set of packages into consideration... This kind of "disconnected" logic
I'd really like to keep.
Whenever the preset db is queried we'll no longer just return the
verdict boolean, but also a numeric overall line number, of the line
we found the verdict on. Then, when "preset-all" is invoked, we
determine all the operations to execute for everything. Then, before
applying them, we check if there are any conflicting operations. If
so, we remove the ones with the higher line number.
In effect this would mean: if you list to DMs as "enable" in the
preset file, and both are to be installed, then the one that is
enabled "earlier" will win in case of "preset-all". To me this appears
quite a natural extension of the logic already in place.
And I guess the default behavior (enable *) has a lower priority than
overrides? (enable/disable). Also, I guess you concatenate all preset
files as if it was a single one (ascii ordered?) to build that list.

So, retaking the display-manager (on the principle they all have:
Alias=display-manager.service) example, that would mean:
* ubuntu-desktop would ship 99-defaults with:
enable lightdm

* If someone, install the gnome-ubuntu-desktop metapackage on the same
install, they would get an additional preset file 50-gnome-ubuntu with:
enable gdm

And so, lightdm would be removed on a preset-all call as conflicting
with gdm (due to sharing the same Alias) and having higher line number.

Sounds like a nice way to handle Alias. Happy to have a look at this.
Post by Lennart Poettering
Post by Didier Roche
Post by Lennart Poettering
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.
- 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 :)
To be honest I find the entire stuff with ENABLED=true/false really
questionnable, I think it would be agreat step ahead to get rid of
it. (But then again, I cannot make Debian's decisions there...)
Agreed, I already removed it from some ubuntu-only packages like
whoopsie, xdiagnose… and I'm trying to investigate the right way to get
a systemd-oriented solutions (while still being compatible with older
init system for debian)
Post by Lennart Poettering
Post by Didier Roche
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).
This sounds quite a limitation. Maybe you can keep a couple of touch files
in /var/lib/ somewhere where you store whether you already applied
"systemctl preset" before?
This is possible, but really not encouraged (due to some possibility to
have unpacking or other intermediate states failing).
This would also only "fix" the newly installed case, not the upgrade
with new distro defaults or various purge vs remove ones. That's why I
think some kind of previous state db can help getting all those
requirements met as you propose, and doing some comparisons between
states (only when they deviated from defaults).
Then, we can run preset on packages that matches previous defaults
(meaning: where the admin didn't override the default choice) as a dpkg
trigger (when new units are installed/upgraded and on a new/updated
preset file shipped).
Would that makes sense?

Didier
Lennart Poettering
2014-12-05 15:42:18 UTC
Permalink
Post by Didier Roche
Post by Lennart Poettering
Whenever the preset db is queried we'll no longer just return the
verdict boolean, but also a numeric overall line number, of the line
we found the verdict on. Then, when "preset-all" is invoked, we
determine all the operations to execute for everything. Then, before
applying them, we check if there are any conflicting operations. If
so, we remove the ones with the higher line number.
In effect this would mean: if you list to DMs as "enable" in the
preset file, and both are to be installed, then the one that is
enabled "earlier" will win in case of "preset-all". To me this appears
quite a natural extension of the logic already in place.
And I guess the default behavior (enable *) has a lower priority than
overrides? (enable/disable). Also, I guess you concatenate all preset files
as if it was a single one (ascii ordered?) to build that list.
Yeah, the default policy of "enable *" would have the largest possible
line number, so that any other line number wins.
Post by Didier Roche
enable lightdm
* If someone, install the gnome-ubuntu-desktop metapackage on the same
enable gdm
And so, lightdm would be removed on a preset-all call as conflicting with
gdm (due to sharing the same Alias) and having higher line number.
correct.
Post by Didier Roche
Sounds like a nice way to handle Alias. Happy to have a look at this.
Would love to take a patch for this.
Post by Didier Roche
Post by Lennart Poettering
Post by Didier Roche
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).
This sounds quite a limitation. Maybe you can keep a couple of touch files
in /var/lib/ somewhere where you store whether you already applied
"systemctl preset" before?
This is possible, but really not encouraged (due to some possibility to have
unpacking or other intermediate states failing).
This would also only "fix" the newly installed case, not the upgrade with
new distro defaults or various purge vs remove ones. That's why I think some
kind of previous state db can help getting all those requirements met as you
propose, and doing some comparisons between states (only when they deviated
from defaults).
where the admin didn't override the default choice) as a dpkg trigger (when
new units are installed/upgraded and on a new/updated preset file shipped).
Would that makes sense?
Not sure I grok what you are proposing. I'd be very careful with
keeping yet another layer of service enablement states (even if just
as "history") in systemd upstream.

Lennart
--
Lennart Poettering, Red Hat
Didier Roche
2014-12-10 12:32:13 UTC
Permalink
Post by Lennart Poettering
Post by Didier Roche
This would also only "fix" the newly installed case, not the upgrade with
new distro defaults or various purge vs remove ones. That's why I think some
kind of previous state db can help getting all those requirements met as you
propose, and doing some comparisons between states (only when they deviated
from defaults).
where the admin didn't override the default choice) as a dpkg trigger (when
new units are installed/upgraded and on a new/updated preset file shipped).
Would that makes sense?
Not sure I grok what you are proposing. I'd be very careful with
keeping yet another layer of service enablement states (even if just
as "history") in systemd upstream.
I can clearly understand why you don't want to have a database of
previous default enablement status. (that's what debian/ubuntu is doing
right now in /var, having a bunch of symlinks to keep default state).

There are 3 cases that we want to have supported (ideally with preset-only):

1. upgrade with default policy change:
* foo.service is enabled in a target (with an [Install] section). Preset
says 'enable *' (== no preset stenza) by default.
* sysadmin didn't enable/disable it.
* an upgrade of a package (not necessarily the package containing
foo.service) ships a new preset file with "disable foo.service"
-> We should have then foo.service disabled as per preset choice.

2. upgrade with dependency change:
* foo.service was WantedBy=bar.target. It was enabled by default.
* sysadmin didn't enable/disable it.
* After an upgrade, the unit contains WantedBy=baz.target (still enabled
by default)
-> We have it still enabled by enabled (as per preset choice), with
.wants symlink from baz.target

From those 2 cases, we could say: "just run systemctl preset on every
package upgrade or preset change", however, there is as well this case:

3. upgrade with default changes, but sysadmin overrides:
* foo.service was WantedBy=bar.target. It was enabled by default.
* sysadmin run systemctl disable foo.service (or mask it)
* After an upgrade, the unit contains WantedBy=baz.target (still enabled
by default preset policy)
-> We shouldn't have foo.service enabled back as the admin did disable it.

That's why I was evocating keeping a previous state database to detect
"previous default state == current state", and only run preset on the
package in that case (and new installs).

Is this more clear? Any other idea of on an elegant way of handling
those without having the previous state database? (in an upstream
compatible way, if possible)
Didier

Martin Pitt
2014-12-07 07:26:00 UTC
Permalink
Post by Lennart Poettering
To be honest I find the entire stuff with ENABLED=true/false really
questionnable, I think it would be agreat step ahead to get rid of
it. (But then again, I cannot make Debian's decisions there...)
Indeed it is. It has never really been necessary, as all init systems
have their canonical way of disabling/enabling things: SysV with the
/etc/rc?.d/ symlinks, systemd with the wants/ symlinks, upstart with
empty .override files. And Debian even has a script "update-rc.d
enable|disable foo" which does that for all init systems. So the
ENABLED in /etc/default/foo has always been entirely redundant and
confusing. Fortunately it isn't that widespread, but some packages
need to be cleaned up there.

Anyway, quite a far disgression into distro specific oddities now. :-)
Post by Lennart Poettering
Post by Didier Roche
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).
This sounds quite a limitation. Maybe you can keep a couple of touch files
in /var/lib/ somewhere where you store whether you already applied
"systemctl preset" before?
It's not a limitation, the postinst *can* differ between initial
install and upgrade by looking at $2 (the "most recently configured
version"). If it's empty, it's a new install.

Martin
--
Martin Pitt | http://www.piware.de
Ubuntu Developer (www.ubuntu.com) | Debian Developer (www.debian.org)
Lennart Poettering
2014-12-02 00:29:32 UTC
Permalink
Post by Tom Gundersen
- We are mixing sys admin information and distro default choices in the same
directories, and can't tell apart what is what.
That is true. Could we perhaps improve on systemctl by printing
"enabled (preset)"/"disable (preset)" for units that are in the
default state? I know this does not change the fact that you have
distro-default (via presets) links in /etc, but it should give the
end-user a nicer experienc I guess?
Sounds like a good idea. Added to TODO list.
Post by Tom Gundersen
My take on this is: make sure presets are applied on "firstboot"
(which I think they are), so empty /etc works just fine, and then
improve on systemctl to better show the distinction between 'enabled
by default' or 'enabled by choice' (and same for 'disabled').
Yes systemd applies the presets on firstboot automatically, before
calculating the initial transactions.

Lennart
--
Lennart Poettering, Red Hat
Lennart Poettering
2014-12-02 12:24:30 UTC
Permalink
Post by Lennart Poettering
Post by Tom Gundersen
- We are mixing sys admin information and distro default choices in the same
directories, and can't tell apart what is what.
That is true. Could we perhaps improve on systemctl by printing
"enabled (preset)"/"disable (preset)" for units that are in the
default state? I know this does not change the fact that you have
distro-default (via presets) links in /etc, but it should give the
end-user a nicer experienc I guess?
Sounds like a good idea. Added to TODO list.
Implemented now.

Lennart
--
Lennart Poettering, Red Hat
Lennart Poettering
2014-12-02 00:13:54 UTC
Permalink
Fedora doesn't enable and start all units on package installation: there are
some preset files, based on flavors, which is basically the policy stating
which units to enable/disable by default. Some other units are always
enabled (unless masked), by using symlinks directly shipped with the package
like in /usr/lib/systemd/system/multi-users.target.wants/ for intance.
Contrary to that, Debian/Ubuntu has the policy to enable/start services and
facilities on package installation during postinst. This is done
(indirectly) via "systemctl enable", which creates symlinks in
/etc/systemd/system/*.wants/.
Distros really should use "systemctl preset" for this. It's what it is
for.

If no preset policy is installed "systemctl preset" is actually
equivalent to "systemctl enable", but it allows admins to install
their own policy which then takes effect.

Really, distributions should *not* use "systemctl enable" in
postinst. It breaks presets for zero gain.
knowledgable admins.

If the admin should be able to disable/enable a service during normal
operation as part of his normal workflow then it should *not* be
enabled via symlinks in /usr, but instead carry [Install] and be
enabled by the postinst script via "systemctl preset".
- We are mixing sys admin information and distro default choices in the same
directories, and can't tell apart what is what.
You can actually. There's "systemctl preset-all" for example which
brings the system back into the exact choices of the upstream distro.
We were thus thinking about having all default distro choices shipping
target symlinks in /usr/lib, and having the administrator overrides this in
/etc via systemctl. This could look similar to masking a unit, i. e. a
symlink "/etc/.../wants.d/foo -> /dev/null" overrides
"/usr/lib/.../wants.d/foo -> ../foo.service", and would be an explicit
representation of "the admin does not want foo.service to autostart" in
/etc.
Overriding symlinks with symlinks to different targets is difficult,
as systemd only really cares about the symlink names, and not so much
about the targets.
However, we did notice the following: taking an unit, with an [Install]
- systemctl status <unit> will report "disabled", where it's actually
enabled and starting for that unit. This is a bug which should be fixed in
any case, as "disabled" is outright wrong. On IRC it was suggested that
those are "static" units, but then it should say at least that.
As mentioned above: units that carry [Install] and are also enabled
via /usr/lib/ are broken really. Either you use [Install] and thus ask
systemd to manage the symlinks in /etc for you via commands like
systemctl enable/disable/preset, or you say that systemctl shall not
manage the symlinks and instead create a static on in /usr/lib. But
having a unit that is both managed and unmanaged doesn't really make sense.
- If we ln -s /dev/null /etc/<…>/<…>.wants/<unit>, then systemctl status
<unit> will display the unit as being enabled, and it will activated once
the target is reached. This is also counterintuitive, as usually this means
to mask/completely disable the unit.
Yeah, symlinks in .wants/ are just about creating dependencies, not
about overriding units really...
Part of the discussion on #systemd pointed out that the admin should then
Hmm, "systemctl mask" is really nothing we should advertise to users
or admins. It's a last resort tool. Should not appear in normal workflows.

Lennart
--
Lennart Poettering, Red Hat
Continue reading on narkive:
Loading...