[systemd-devel] Special targets - should they Want or be WantedBy?

Lennart Poettering lennart at poettering.net
Thu Mar 17 16:34:19 PDT 2011


On Sat, 12.03.11 13:00, Andrey Borzenkov (arvidjaar at mail.ru) wrote:

> The problem is not limited to syslog and applies to all special
> targets that serve as "virtual provides"
> 
> Actually I think design should be reversed. The service that
> implements this virtual provide (syslog, network, rpcbind, smtp, ...)
> should pull in special target. This way you ensure
> 
> - when service that provides functionality is started, corresponding
> virtual target is started as indication, that functionality is
> available
> 
> - if there is no service with requested functionality, target is not
> available. In other words - target is not faked to be started unless
> functionality is available. This allows easy and logical check,
> whether syslog (rpcbind, network, ...) was really provided by any
> service - if unit is not started, it was not. To round this off,
> specials should also refuse manual activation.

So, Kay and I discussed this yesterday, and we came to the conclusion
that Andrey's proposal is the right thing to do. It should be the
specific implementations which pull in the generic targets and *not* the
other way round. This might be surprising at first, but Andrey, Kay and
I think this makes most sense.

Here's an attempt of a longer explanation for this:

First of all most of these special targets should eventually go away
without replacement. They exist primarily to provide compatibility with
SysV/LSB where generic facility names were a crucial requirement for
ordering things properly. However, in a world with socket and bus
activation this is not necessary anymore. If all services are socket and
bus activatable, then all clients can just use them without the need to
wait for anything explicitly. Currently existing targets of this kind are at least:
nss-lookup.target, http-daemon.target, dbus.target,
mail-transfer-agent.target, rpcbind.target, rtc-set.target,
syslog.target.

Of these dbus.target can probably be retired right now, since we only
support bus activated dbus daemons. And syslog.target probably soon
too, since all relevant syslog implementations have been patched by
now. And rpcbind very likely too soon.

Then there is network.target. This is a bit more complex case. $network
in LSB headers is mostly use to synchronize services to the point where
"the network is up". I generally believe that the idea that such a point
in tim exists is just broken. Networks aren't static beasts
anymore. They come and go. Machines move. Machines are reconfigured all
the time. An application which is written in a way that it expects the
network to be up from the moment it is started to the moment it exits is
just broken. That's 90's style hacking, but in 2011 network software
should acknowledge that things have changed and subscribe to netlink so
that they follow network changes and can be started at any
time. Thankfully a lot of software does that correctly now. However, we
have to acknowledge that a lot of software still doesn't, for example
stuff like ntpdate. For that reason we probably need to keep
network.target for a while, even if it's mostly an indication of software
sucking and not so much an indication of excellence on sw design.

So, now let's have a close look at network.target,
NetworkManager.service and network.service (i.e. the classic Fedora
network init scripts. The ordering between these units is pretty clear:
network.target should be AFTER the other two, and that's about it. But
what about the requirement deps? The obvious choice would be to make
network.target require (or want) the two services. But that would mean
that any start transaction that includes network.target would also
include the two services. And is this really what we want? No, clearly
not I would say. network.target is supposed to be used to order the
various network setup systems against the various network consuming
services, but it shouldn't mean that just to enforce this ordering
having apache.service in your transaction also causes you to have *all*
the configured network setup implementations in it as well. i.e. if at
boot NM and the old network scripts got started, and then the user
stopped NM (but didn't disable it), then starting apache should
definitely *not* start NM again. And hence there should *not* be a
wants/requires dep from network.target on NM.service nor
network.service.

But what about the other direction? We definitely want network.target in
the boot transaction if NM or network.service is part of it too. Because
only then the network consuming services can be synchronized
properly. Hence we want those two services pull in network.target, as a
signal "Hey, we implement this, and when it is up, you can use it".

So, here's what I am going to do now:

a) Modify the Description= strings of the various target units where
   this applies to make clear that they exist for SysV/LSB compat only.

b) Remove dbus.target

c) Add a Wants+Before to syslog.socket on syslog.target. Since the
   socket is already enough to make logging possible this is all that is
   needed.

d) fix the systemd code which parses LSB headers to interpret Provides
   like this.

e) patch NM upstream and NTP in F15 to add the necessary dependencies.

And Andrey, thanks a lot for pointing us to this problem and the
solution!

Questions? Anything we didn't think about?

Lennart

-- 
Lennart Poettering - Red Hat, Inc.


More information about the systemd-devel mailing list