Discussion:
[systemd-devel] Behavior of BindsTo when stopping a service
Amit Saha
2018-01-26 02:11:40 UTC
Permalink
Hello,

I have a systemd service - drainconnections which I want to to make sure
finishes stopping before systemd starts stopping another service. What I
also want is to if I stop supervisord service, drainconnections should be
stopped first.

It seems like BindsTo is what I need for establishing the coupling between
the two units. The following unit file describes drainconnections:


[Unit]
Description=Drain Connections
After=supervisord.service
BindsTo=supervisord.service

[Service]
Type=oneshot
RemainAfterExit=True
ExecStart=/bin/true
ExecStop=/usr/bin/touch /var/shuttingdown1
ExecStop=/usr/bin/sleep 60
ExecStop=/usr/bin/touch /var/shuttingdown2

[Install]
WantedBy=multi-user.target


In addition, I also needed to add BindsTo=drainconnections to the
supervisord service.

Things work as desired for me considering the above configuration.

Am I on the right track here? Thanks in advance.

Best Wishes,
Amit.
Andrei Borzenkov
2018-01-27 19:22:56 UTC
Permalink
Post by Amit Saha
Hello,
I have a systemd service - drainconnections which I want to to make sure
finishes stopping before systemd starts stopping another service. What I
also want is to if I stop supervisord service, drainconnections should be
stopped first.
It seems like BindsTo is what I need for establishing the coupling between
the two units.
If your description of services relationship is accurate and complete,
BindsTo is too strong here; you really need just PartsOf.
Post by Amit Saha
[Unit]
Description=Drain Connections
After=supervisord.service
BindsTo=supervisord.service
[Service]
Type=oneshot
RemainAfterExit=True
ExecStart=/bin/true
I think recent sytsemd relaxes requirement, so you can omit ExecStart here.
Post by Amit Saha
ExecStop=/usr/bin/touch /var/shuttingdown1
ExecStop=/usr/bin/sleep 60
ExecStop=/usr/bin/touch /var/shuttingdown2
[Install]
WantedBy=multi-user.target
In addition, I also needed to add BindsTo=drainconnections to the
supervisord service.
This will create dependency loop with your unit definition shown above.
Post by Amit Saha
Things work as desired for me considering the above configuration.
Am I on the right track here? Thanks in advance.
Best Wishes,
Amit.
_______________________________________________
systemd-devel mailing list
https://lists.freedesktop.org/mailman/listinfo/systemd-devel
Amit Saha
2018-01-27 23:11:41 UTC
Permalink
Post by Amit Saha
Post by Amit Saha
Hello,
I have a systemd service - drainconnections which I want to to make sure
finishes stopping before systemd starts stopping another service. What I
also want is to if I stop supervisord service, drainconnections should be
stopped first.
It seems like BindsTo is what I need for establishing the coupling
between
Post by Amit Saha
the two units.
If your description of services relationship is accurate and complete,
BindsTo is too strong here; you really need just PartsOf.
Thanks. PartOf looks like something more suitable. Would having PartOf in
supervisord obey the before after relationship setup by drainconnections
service?

I will give it a shot.
Post by Amit Saha
Post by Amit Saha
[Unit]
Description=Drain Connections
After=supervisord.service
BindsTo=supervisord.service
[Service]
Type=oneshot
RemainAfterExit=True
ExecStart=/bin/true
I think recent sytsemd relaxes requirement, so you can omit ExecStart here.
Thanks.
Post by Amit Saha
Post by Amit Saha
ExecStop=/usr/bin/touch /var/shuttingdown1
ExecStop=/usr/bin/sleep 60
ExecStop=/usr/bin/touch /var/shuttingdown2
[Install]
WantedBy=multi-user.target
In addition, I also needed to add BindsTo=drainconnections to the
supervisord service.
This will create dependency loop with your unit definition shown above.
Wouldn’t the Before/After take care of breaking the dependency loop? That
seems to be what I observed.
Post by Amit Saha
Post by Amit Saha
Things work as desired for me considering the above configuration.
Am I on the right track here? Thanks in advance.
Best Wishes,
Amit.
_______________________________________________
systemd-devel mailing list
https://lists.freedesktop.org/mailman/listinfo/systemd-devel
Andrei Borzenkov
2018-01-28 06:04:00 UTC
Permalink
Post by Amit Saha
Post by Amit Saha
Post by Amit Saha
Hello,
I have a systemd service - drainconnections which I want to to make sure
finishes stopping before systemd starts stopping another service. What I
also want is to if I stop supervisord service, drainconnections should be
stopped first.
It seems like BindsTo is what I need for establishing the coupling
between
Post by Amit Saha
the two units.
If your description of services relationship is accurate and complete,
BindsTo is too strong here; you really need just PartsOf.
Thanks. PartOf looks like something more suitable. Would having PartOf in
supervisord obey the before after relationship setup by drainconnections
service?
PartsOf (like BindsTo) is orthogonal to After/Before. PartsOf/BindsTo
define what to do, After/Before define when to do.
Post by Amit Saha
I will give it a shot.
Post by Amit Saha
Post by Amit Saha
[Unit]
Description=Drain Connections
After=supervisord.service
BindsTo=supervisord.service
...
Post by Amit Saha
Post by Amit Saha
Post by Amit Saha
In addition, I also needed to add BindsTo=drainconnections to the
supervisord service.
This will create dependency loop with your unit definition shown above.
Wouldn’t the Before/After take care of breaking the dependency loop? That
seems to be what I observed.
Probably I had to elaborate. If you need full BindsTo semantic (which is
superset of Requires) it only works as documented if you also have
corresponding After/Before which creates loop. Otherwise Requires part
is mostly useless. If you are only interested in propagating stop
request and "stopping on surprise removal" part of BindsTo then this is
probably OK, but this will make your units definitions rather confusing.
Amit Saha
2018-01-28 09:50:58 UTC
Permalink
Post by Andrei Borzenkov
Post by Amit Saha
Post by Amit Saha
Post by Amit Saha
Hello,
I have a systemd service - drainconnections which I want to to make
sure
Post by Amit Saha
Post by Amit Saha
Post by Amit Saha
finishes stopping before systemd starts stopping another service. What
I
Post by Amit Saha
Post by Amit Saha
Post by Amit Saha
also want is to if I stop supervisord service, drainconnections should
be
Post by Amit Saha
Post by Amit Saha
Post by Amit Saha
stopped first.
It seems like BindsTo is what I need for establishing the coupling
between
Post by Amit Saha
the two units.
If your description of services relationship is accurate and complete,
BindsTo is too strong here; you really need just PartsOf.
Thanks. PartOf looks like something more suitable. Would having PartOf in
supervisord obey the before after relationship setup by drainconnections
service?
PartsOf (like BindsTo) is orthogonal to After/Before. PartsOf/BindsTo
define what to do, After/Before define when to do.
Post by Amit Saha
I will give it a shot.
Thanks. Tried it and that is how it works.
Post by Andrei Borzenkov
Post by Amit Saha
Post by Amit Saha
Post by Amit Saha
[Unit]
Description=Drain Connections
After=supervisord.service
BindsTo=supervisord.service
...
Post by Amit Saha
Post by Amit Saha
Post by Amit Saha
In addition, I also needed to add BindsTo=drainconnections to the
supervisord service.
This will create dependency loop with your unit definition shown above.
Wouldn’t the Before/After take care of breaking the dependency loop? That
seems to be what I observed.
Probably I had to elaborate. If you need full BindsTo semantic (which is
superset of Requires) it only works as documented if you also have
corresponding After/Before which creates loop. Otherwise Requires part
is mostly useless. If you are only interested in propagating stop
request and "stopping on surprise removal" part of BindsTo then this is
probably OK, but this will make your units definitions rather confusing.
Thanks, I think your suggestion of using PartOf is more suitable for my use
case here - which is basically making sure that I can do some work before
systemd shuts down the system (killing supervisord) and use After/Before to
ensure the when.

This is my current unit file:

[Unit]
Description=Drain Connections
After=supervisord.service
PartOf=supervisord.service

[Service]
Type=oneshot
RemainAfterExit=True
ExecStart=/bin/true
ExecStop=/usr/bin/touch /var/shuttingdown1
ExecStop=/usr/bin/sleep 60
ExecStop=/usr/bin/touch /var/shuttingdown2

[Install]
WantedBy=multi-user.target


It looks like I added the BindsTo=drainconnectins.service to supervisord as
well for a use case where during shutdown, if supervisord was stopped
first, it would first stop drainconnections.service. But I don't need that
- since systemd figures out it needs to first stop drainconnections.service
before it stops supervisord.

I think the only change I would make to the supervisord configuration is so
that it always starts drainconnections.service when it's started.
Loading...