[systemd-devel] Modifying systemd dependency tree during boot

Vivenzio Pagliari vivenzio.pagliari at nokia.com
Fri Sep 18 07:58:20 PDT 2015


Hi,

we face a problem with systemd when we attempt to dynamically add
dependencies to units during bootup. In other words, we want to add services
during boot (by means of some service that is run during boot) and via
"systemctl daemon-reload" we want to notify systemd about this new units and
start them (due to WantedBy dependencies of that newly created units to a
later to be reached target).

In principle, what we have is a system where part of the SW is not (yet)
available at the beginning of boot, when systemd builds up its dependency
tree. During boot, a unit will eventually mount a filesystem where
additional SW is located that shall be started on bootup. It would be
desirable to boot them each as separate systemd units (so we could use e.g.
process supervision etc.).

We tried to have a "scanner service" that comes up after the filesystem is
available. This service will scan a well-known directory in that filesystem
for SW to be started. The scanning procedure would result in the creation of
new service files executing that SW. These services should "hook in" via
[Install] section. When finished with service creation, this "scanner
service" would issue a "systemctl daemon-reload" to make the new
dependencies to the newly created units effective to systemd.


Here an (hopefully not too abstract) example:

1. The target used to "pull in" the dynamically created service units. I
   would use multi-user.target here.
2. The "scanner service", let's call it scanner.service that searches
   programs on the newly available filesystem.
3. The "scanned services"; in my test I made a template and the
   scanner.service will enable instantiations of that, depending on which SW
   is found on the filesystem.


scanner.service:
=========
[Unit]
WantedBy = multi-user.target
Before = multi-user.target
RequiresMountsFor = /path/to/fs

[Service]
Type = oneshot
ExecStart = /usr/bin/scan-for-programs /path/to/fs

scanned at .service:
==========
[Unit]
Description = Program %i from (late) filesystem
WantedBy = multi-user.target
Before= multi-user.target

[Service]
ExecStart = /path/to/fs/%i

*****

The scan-for-programs utility would:
  a. for all found programs in /path/to/fs:
       enable scanned at program.service
  b. call systemctl daemon-reload to make the changes of step a. effective.

[Note: Actually, part a. can also be implemented as a generator which would
be called implicitly by the subsequent daemon-reload, but the end result
remains the same.]

However, these additionally added services are not started, when trying to
reach multi-user.target. After boot, I can see that the dependencies where
added correctly (e.g. doing "systemctl list-dependencies multi-user.target"
lists the newly created services as dependencies, but they remain inactive).

I suspect that something is wrong with this approach, but I do not
understand, what. My assumption is that during boot it is not supported to
fiddle with the "dependency graph" dynamically (i.e. before the boot reaches
its final unit). Is this correct?  If so, is there a rationale for that?

If this approach is wrong, what would be a better systemd-based approach of
solving such a problem of "starting SW that is available only later during
bootup"?

-Vivenzio



More information about the systemd-devel mailing list