Discussion:
How do I create/destroy instances dynamically when config files appear/disappear?
(too old to reply)
Andrei Borzenkov
2018-03-20 12:47:31 UTC
Permalink
Raw Message
On Tue, Mar 20, 2018 at 12:52 AM, John Ioannidis <systemd-***@tla.org> wrote:
> I want to have a service with several instances, each of which has a
> configuration file; when configuration files appear and disappear, I want
> the corresponding instances to be created and started, and die,
> respectively, and in particular have the running processes corresponding to
> the removed units be killed.
>

There is really no way to do it currently. If instance names are not
known in advance, it is not possible even to dynamically activate
units this way; and there is definitely no way to stop units when come
file goes away.

> I can get them to start the first time, but they do not stop when
> configuration files change. If I systemctl daemon-reload, the links in
> /run/systemd/system-generators get properly adjusted,

generators are simply not the right tool for dynamic changes. There
are path units for activating units when files appear but there are no
corresponding mechanism to stop them.

> but I cannot figure
> out how to tell my service to kill the no-longer-needed processes. If I also
> systemctl reload the service, all existing processes are killed, which is
> absolutely not what I want.
>
> Here is what I've done: what am I doing wrong?
>
> I tried modelling this after what OpenVPN does:
>
> # cat /etc/systemd/system/letters.service
> [Unit]
> Description=Letters service
> After=network.target
>
> [Service]
> Type=oneshot
> RemainAfterExit=yes
> ExecStart=/bin/true
> ExecReload=/bin/true
> WorkingDirectory=/var/tmp/letters
>
> [Install]
> WantedBy=multi-user.target
>
> # cat /etc/systemd/system/***@.service
> [Unit]
> Description=Letters for %i
> PartOf=letters.service
> ReloadPropagatedFrom=letters.service
> Before=systemd-user-sessions.service
> After=syslog.target network-online.target
> Wants=network-online.target
>
> [Service]
> Type=simple
> PrivateTmp=false
> WorkingDirectory=/var/tmp/letters
> ExecStart=/usr/local/bin/letter --daemon --pidfile /run/letters/%i.pid
> PIDFile=/run/letters/%i.pid
> ExecReload=/bin/kill -HUP $MAINPID
> DeviceAllow=/dev/null rw
> ProtectSystem=true
> ProtectHome=true
>
> [Install]
> WantedBy=multi-user.target
>
> # cat /etc/systemd/system-generators/letters
> #!/bin/sh
> exec 2>> /tmp/opg2
> set -eux
> GENDIR="$1"
> WANTDIR="$1/letters.service.wants"
> SERVICEFILE="/lib/systemd/system/***@.service"
> CONFIG_DIR=/var/letters/
> mkdir -p "$WANTDIR"
> for CONFIG in `cd $CONFIG_DIR; ls *.conf 2> /dev/null`; do
> NAME=${CONFIG%%.conf}
> ln -s "$SERVICEFILE" "$WANTDIR/letters@$NAME.service"
> done
> exit 0
>
>
> Now for the fun:
>
> # touch /var/letters/aleph.conf /var/letters/e.conf /var/letters/zeta.conf
> # systemctl daemon-reload
> # ls -l /run/systemd/generator/letters.service.wants
> total 0
> lrwxrwxrwx 1 root root 36 Mar 19 17:37 ***@aleph.service ->
> /lib/systemd/system/***@.service
> lrwxrwxrwx 1 root root 36 Mar 19 17:37 ***@e.service ->
> /lib/systemd/system/***@.service
> lrwxrwxrwx 1 root root 36 Mar 19 17:37 ***@zeta.service ->
> /lib/systemd/system/***@.service
> # systemctl enable letters.service
> Created symlink /etc/systemd/system/multi-user.target.wants/letters.service
> → /etc/systemd/system/letters.service.
> # systemctl start letters.service
> # ps ax | grep lett
> 22853 ? S 0:00 /usr/local/bin/letter --daemon --pidfile
> /run/letters/e.pid
> 22927 ? S 0:00 /usr/local/bin/letter --daemon --pidfile
> /run/letters/aleph.pid
> 22928 ? S 0:00 /usr/local/bin/letter --daemon --pidfile
> /run/letters/zeta.pid
>
> So far so good. This is working as expected. Even better:
>
> # touch /var/letters/tcha.conf
> # systemctl daemon-reload
> # systemctl start letters.service
> # ps ax | grep lett
> 22853 ? S 0:00 /usr/local/bin/letter --daemon --pidfile
> /run/letters/e.pid
> 22927 ? S 0:00 /usr/local/bin/letter --daemon --pidfile
> /run/letters/aleph.pid
> 22928 ? S 0:00 /usr/local/bin/letter --daemon --pidfile
> /run/letters/zeta.pid
> 23083 ? S 0:00 /usr/local/bin/letter --daemon --pidfile
> /run/letters/tcha.pid
>
> But now the trouble begins:
>
> # rm /var/letters/e.conf
> # systemctl daemon-reload
> # ls -l /run/systemd/generator/letters.service.wants
> total 0
> lrwxrwxrwx 1 root root 36 Mar 19 17:44 ***@aleph.service ->
> /lib/systemd/system/***@.service
> lrwxrwxrwx 1 root root 36 Mar 19 17:44 ***@tcha.service ->
> /lib/systemd/system/***@.service
> lrwxrwxrwx 1 root root 36 Mar 19 17:44 ***@zeta.service ->
> /lib/systemd/system/***@.service
>
> The link ***@e.service has been correctly removed, but the
> corresponding process still exists:
> # ps ax | grep e.pid
> 22853 ? S 0:00 /usr/local/bin/letter --daemon --pidfile
> /run/letters/e.pid
>
>
>
>
> _______________________________________________
> systemd-devel mailing list
> systemd-***@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/systemd-devel
>
Lennart Poettering
2018-03-20 16:14:27 UTC
Permalink
Raw Message
On Di, 20.03.18 11:05, John Ioannidis (systemd-***@tla.org) wrote:

> On Tue, Mar 20, 2018 at 8:47 AM, Andrei Borzenkov <***@gmail.com>
> wrote:
>
> > On Tue, Mar 20, 2018 at 12:52 AM, John Ioannidis <systemd-***@tla.org>
> > wrote:
> >
> >
> > > I can get them to start the first time, but they do not stop when
> > > configuration files change. If I systemctl daemon-reload, the links in
> > > /run/systemd/system-generators get properly adjusted,
> >
> > generators are simply not the right tool for dynamic changes. There
> > are path units for activating units when files appear but there are no
> > corresponding mechanism to stop them.
> >
> >
> >
> Interesting... I didn't realize this. How about this as a workaround:
>
> * letters-watcher.path watches /var/letters for any changes, and starts
> (oneshot) letters-watcher.service
>
> * letters-watcher.service scans the configuration file, determines what
> instances it should kill and what it should create, and does so, either by
> invoking systemctl or by talking to DBUS.
>
> (I did a quick-and-dirty POC and it works, I'm wondering if this is the
> right way, for some value of "right")

That sounds like an OK approach. It's definitely intended mode of
operation to use unit instances to quickly start/stop instances
on-the-fly without installing/removing any unit files/symlinks for
them each time. Just install the template unit file, and start/stop
instances off it as needed. That way you don't ever need to change
systemd configuration, and never reload PID 1.

Lennart

--
Lennart Poettering, Red Hat
Loading...