Discussion:
How to properly write an "umbrella" unit
(too old to reply)
Alexandre Detiste
2015-07-21 12:13:12 UTC
Permalink
This works as designed. Unfortunately, my Distribution's build tools
don't handle package-provided targets too well, and I feel that using
a target here is kind of wrong anyway.
Hi,

Package-provided targets works well,
but by default debhelper will try to enable everything.

You'd need to overide dh_systemd_enable & dh_systemd_start:

https://sources.debian.net/src/systemd-cron/1.5.2-1/debian/rules/

| override_dh_systemd_enable:
| # Only enable cron.target, it pulls in all the others via .timer files.
| dh_systemd_enable cron.target
|
| override_dh_systemd_start:
| # Only start cron.target, it pulls in all the others via .timer files.
| dh_systemd_start cron.target
Can I write my nifty.target as a service? I have seen in this case
nifty.service files with Exec=/bin/true to basically create a no-op
service, but that's ugly.
PostgreSQL does that for some reason:
https://sources.debian.net/src/postgresql-common/169/systemd/postgresql.service/
How would one handle this situation in the clear, recommended way?
Can't help for this.

Greets,

Alexandre
Colin Guthrie
2015-07-21 12:40:31 UTC
Permalink
Hi,
I am trying to systemd'ize a daemon which is useful to be run in two
instances. It is usually the case that both instances need to be
started and stopped simultaneously, and the local admin would want a
_single_ command to start and stop both instances. Therefore, an
"umbrella" is needed.
[Unit]
Description=nifty Server (all protocols)
After=network.target
[Install]
WantedBy=multi-user.target
[Unit]
Description=nifty Server for IPv4 (niftyd4.conf)
After=network.target
PartOf=nifty.target
[Service]
ExecStart=/usr/sbin/niftyd -f -4 -q -cf /etc/nifty/niftyd4.conf
[Install]
WantedBy=nifty.target
[Unit]
Description=nifty Server for IPv6
After=network.target
PartOf=nifty.target
[Service]
ExecStart=/usr/sbin/niftyd -f -6 -q -cf /etc/nifty/niftyd6.conf
[Install]
WantedBy=nifty.target
This works as designed. Unfortunately, my Distribution's build tools
don't handle package-provided targets too well, and I feel that using
a target here is kind of wrong anyway.
In this case, I'd perhaps recommend NOT including [Install] sections fir
your two .service files and instead make your "make install" action
write symlinks into /usr/lib/systemd/system/nifty.target.wants.d/ thus
the user could never disable the individual components of your daemon
themselves and thus not need to rely on distro scripts to create them at
install time.

Your package install script would still have to enable (or preset) the
nifty.target however.

This might or might not be desirable overall (in the example above, I
can imagine someone still wanting to disable only the IPv6 component for
example!).

Col
--
Colin Guthrie
colin(at)mageia.org
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/
Dimitri John Ledkov
2015-07-21 13:20:39 UTC
Permalink
Heya,
Hi,
I am trying to systemd'ize a daemon which is useful to be run in two
instances. It is usually the case that both instances need to be
started and stopped simultaneously, and the local admin would want a
_single_ command to start and stop both instances. Therefore, an
"umbrella" is needed.
Imho targets are ugly =)

I'd do a ***@.service
with:
ExecStart=.... -%I -cf /etc/nifty/niftyd%I.conf

And then people can do e.g.:
systemctl enable ***@4.service ***@6.service
systemctl start nifty@*.service
systemctl stop nifty@*.service

And the install section would have e.g. default instance name 4, and
wanted by multi-user target.

And such service should be trivial to integrate into any maintainer scripts.
--
Regards,

Dimitri.
Pura Vida!

https://clearlinux.org
Open Source Technology Center
Intel Corporation (UK) Ltd. - Co. Reg. #1134945 - Pipers Way, Swindon SN3 1RJ.
Michael Biebl
2015-07-21 19:42:38 UTC
Permalink
Have a look at the openvpn package in Debian. It implements something
like you have in mind.
There are multiple ***@.service instances and a single
openvpn.service which can be used by the admin to start/stop/restart
them.
Hi,
I am trying to systemd'ize a daemon which is useful to be run in two
instances. It is usually the case that both instances need to be
started and stopped simultaneously, and the local admin would want a
_single_ command to start and stop both instances. Therefore, an
"umbrella" is needed.
[Unit]
Description=nifty Server (all protocols)
After=network.target
[Install]
WantedBy=multi-user.target
[Unit]
Description=nifty Server for IPv4 (niftyd4.conf)
After=network.target
PartOf=nifty.target
[Service]
ExecStart=/usr/sbin/niftyd -f -4 -q -cf /etc/nifty/niftyd4.conf
[Install]
WantedBy=nifty.target
[Unit]
Description=nifty Server for IPv6
After=network.target
PartOf=nifty.target
[Service]
ExecStart=/usr/sbin/niftyd -f -6 -q -cf /etc/nifty/niftyd6.conf
[Install]
WantedBy=nifty.target
This works as designed. Unfortunately, my Distribution's build tools
don't handle package-provided targets too well, and I feel that using
a target here is kind of wrong anyway.
Can I write my nifty.target as a service? I have seen in this case
nifty.service files with Exec=/bin/true to basically create a no-op
service, but that's ugly.
instances from a single shell command?
How would one handle this situation in the clear, recommended way?
Greetings
Marc
--
-----------------------------------------------------------------------------
Marc Haber | "I don't trust Computers. They | Mailadresse im Header
Leimen, Germany | lose things." Winona Ryder | Fon: *49 6224 1600402
Nordisch by Nature | How to make an American Quilt | Fax: *49 6224 1600421
_______________________________________________
systemd-devel mailing list
http://lists.freedesktop.org/mailman/listinfo/systemd-devel
--
Why is it that all of the instruments seeking intelligent life in the
universe are pointed away from Earth?
Lennart Poettering
2015-07-22 17:15:32 UTC
Permalink
Hi,
I am trying to systemd'ize a daemon which is useful to be run in two
instances. It is usually the case that both instances need to be
started and stopped simultaneously, and the local admin would want a
_single_ command to start and stop both instances. Therefore, an
"umbrella" is needed.
[Unit]
Description=nifty Server (all protocols)
After=network.target
Unrelated to the actual topic of this thread: this line above usually
doesn't do what people assume it does: It does not start the daemon
after the network is up -- which is what most folks might think --,
that's what network-online.target is for. Also, most daemons actually
don't need the network to be up, and it is bad style to make daemons
wait for external events such as DHCP events anyway. Hence, don't use
this. The primary effect of ordering something after network.target is
actually at shut down, since it ensures that the service is stopped
before the network is turned off.) It is usually a good to remove
such lines, unless you really really know you need it. In this case
the target should definitely not list this, if at all the services
should, but probably not even they.
This works as designed. Unfortunately, my Distribution's build tools
don't handle package-provided targets too well, and I feel that using
a target here is kind of wrong anyway.
Going for a target for this sounds like the right choice, and if your
distro cannot support that nicely, it really should be improved to
support it.
Can I write my nifty.target as a service? I have seen in this case
nifty.service files with Exec=/bin/true to basically create a no-op
service, but that's ugly.
That's a hack. A target is for grouping things, they basically are
services without processes attached to them. You really should use
targets for this, and not misuse services.
instances from a single shell command?
You can also group instances with a target unit nicely. But the way to
group things is via target units, nothing else.
How would one handle this situation in the clear, recommended way?
The way you already did it!

Lennart
--
Lennart Poettering, Red Hat
Michael Biebl
2015-07-22 18:28:33 UTC
Permalink
Post by Lennart Poettering
Can I write my nifty.target as a service? I have seen in this case
nifty.service files with Exec=/bin/true to basically create a no-op
service, but that's ugly.
That's a hack. A target is for grouping things, they basically are
services without processes attached to them. You really should use
targets for this, and not misuse services.
Afaik, there is no way to have a .target reloaded and that reload
request propagated to all services in that target.

Say you have foo.target consisting of bar.service and baz.service,
how can you achieve that
systemctl reload foo.target propagates that reload request to {bar,baz}.service?

Michael
--
Why is it that all of the instruments seeking intelligent life in the
universe are pointed away from Earth?
Lennart Poettering
2015-07-22 18:41:22 UTC
Permalink
Post by Michael Biebl
Post by Lennart Poettering
Can I write my nifty.target as a service? I have seen in this case
nifty.service files with Exec=/bin/true to basically create a no-op
service, but that's ugly.
That's a hack. A target is for grouping things, they basically are
services without processes attached to them. You really should use
targets for this, and not misuse services.
Afaik, there is no way to have a .target reloaded and that reload
request propagated to all services in that target.
Say you have foo.target consisting of bar.service and baz.service,
how can you achieve that
systemctl reload foo.target propagates that reload request to {bar,baz}.service?
You cannot do that right now, and I am not sure you should be able to,
after all the operation does not really apply to target units.

I do see your usecase though...

Humm...

Maybe we can change the manager core to propagate Reload() calls
for unit type that do not support it natively to other units listed in
PropagateReloadsTo= and then become a NOP.

Or in other words: invoking reload on a target that knows no
PropagateReloadsTo= should continue to return an error. But if such
deps are defined, it should become a silent NOP and propagate the
event.

Could you file an RFP issue on github asking for this? [or even better,
send a PR with a patch... ;-) ]

Lennart
--
Lennart Poettering, Red Hat
Daurnimator
2015-07-23 00:41:16 UTC
Permalink
Post by Lennart Poettering
Maybe we can change the manager core to propagate Reload() calls
for unit type that do not support it natively to other units listed in
PropagateReloadsTo= and then become a NOP.
Or in other words: invoking reload on a target that knows no
PropagateReloadsTo= should continue to return an error. But if such
deps are defined, it should become a silent NOP and propagate the
event.
Could you file an RFP issue on github asking for this? [or even better,
send a PR with a patch... ;-) ]
ReloadPropagatedFrom= would seem to be more useful here.

Why should reloading a target error in the first place? ==> why not just a NOP?
Lennart Poettering
2015-07-23 01:09:40 UTC
Permalink
Post by Daurnimator
Post by Lennart Poettering
Maybe we can change the manager core to propagate Reload() calls
for unit type that do not support it natively to other units listed in
PropagateReloadsTo= and then become a NOP.
Or in other words: invoking reload on a target that knows no
PropagateReloadsTo= should continue to return an error. But if such
deps are defined, it should become a silent NOP and propagate the
event.
Could you file an RFP issue on github asking for this? [or even better,
send a PR with a patch... ;-) ]
ReloadPropagatedFrom= would seem to be more useful here.
Well, ReloadPropagateFrom= is the inverse of PropagateReloadsTo=. If
there is a dep of the first kind from A to B, there's always a dep of
the second kind from B to A, and vice versa.
Post by Daurnimator
Why should reloading a target error in the first place? ==> why not just a NOP?
Hides bugs? reloading a target makes no sense, unless you use it for
reload propagation. Hence we should generate an error.

Lennart
--
Lennart Poettering, Red Hat
Krzysztof Kotlenga
2015-07-24 09:07:07 UTC
Permalink
Post by Lennart Poettering
Post by Daurnimator
Post by Lennart Poettering
Maybe we can change the manager core to propagate Reload() calls
for unit type that do not support it natively to other units
listed in PropagateReloadsTo= and then become a NOP.
Or in other words: invoking reload on a target that knows no
PropagateReloadsTo= should continue to return an error. But if
such deps are defined, it should become a silent NOP and
propagate the event.
Could you file an RFP issue on github asking for this? [or even
better, send a PR with a patch... ;-) ]
ReloadPropagatedFrom= would seem to be more useful here.
Well, ReloadPropagateFrom= is the inverse of PropagateReloadsTo=. If
there is a dep of the first kind from A to B, there's always a dep of
the second kind from B to A, and vice versa.
Post by Daurnimator
Why should reloading a target error in the first place? ==> why not just a NOP?
Hides bugs? reloading a target makes no sense, unless you use it for
reload propagation.
But stopping and restarting a target already makes sense if you use
PartOf=foo.target.

Unfortunately one cannot specify ConsistsOf in a unit file, which
is a really annoying limitation.
--
kjk
Lennart Poettering
2015-07-24 13:00:58 UTC
Permalink
Post by Krzysztof Kotlenga
Unfortunately one cannot specify ConsistsOf in a unit file, which
is a really annoying limitation.
That limitation exists for a reason: systemd loads unit files lazily:
only units that are referenced by some other unit are loaded. Thus,
just sticking a unit file somewhere, and writing ConsistsOf= into it,
would generally not work, since the dep would never be considered
unless you also have a dep from something else on it. To avoid this
confusion we simply don't support it at all.

(Only way to make this work would be by allowing ConsistsOf= deps via
.consistsof subdirs with symlinks like we support it for .wants, and
then have ConsistsOf= in the [Install] section, if you follow what I
mean).

Lennart
--
Lennart Poettering, Red Hat
Krzysztof Kotlenga
2015-07-24 16:20:07 UTC
Permalink
Post by Lennart Poettering
Post by Krzysztof Kotlenga
Unfortunately one cannot specify ConsistsOf in a unit file, which
is a really annoying limitation.
only units that are referenced by some other unit are loaded.
By reference you mean a reference that causes a unit file to be loaded
like Wants? I understand that ConsistsOf is not (would not be) such
a reference, but TBH I don't quite understand why.

Is this something to do with "positive" and "inverse" dependencies and
PartOf being already a positive one? (I'm staring at the UnitDependency
enum).

I kinda understand it was made this way mainly or even only with
instance units in mind. Correct?
Post by Lennart Poettering
Thus, just sticking a unit file somewhere, and writing ConsistsOf=
into it, would generally not work, since the dep would never be
considered unless you also have a dep from something else on it. To
avoid this confusion we simply don't support it at all.
What I've actually tried after learning about PartOf some time ago:

# foo.target
[Unit]
Wants=a.service b.service c.service
ConsistsOf=a.service b.service c.service

so I can start/stop/restart a bunch of services with systemctl. Both
lists in one place, so it would be hard to forget about something while
making changes. Single file to edit - neat. Just perfect - that's what
I thought until a moment later.
Post by Lennart Poettering
(Only way to make this work would be by allowing ConsistsOf= deps via
.consistsof subdirs with symlinks like we support it for .wants, and
then have ConsistsOf= in the [Install] section, if you follow what I
mean).
.consistsof and [Install]/PartOf would sound reasonable, just
like .wants and [Install]/WantedBy. [Install]/ConsistsOf seems wrong.

But how will this solve anything? Is .wants different from Wants?
--
kjk
Continue reading on narkive:
Loading...