Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
Joachim Nilsson committed 2016-01-05 21:11:27 +01:00
1 parent aa1da0e9f2
commit 5b28fed321
1 file changed
+89 -63
+89 -63
View File
@@ -1,99 +1,125 @@
# Finit Conditions Finit Conditions
================
In addition to runlevels, Finit supports user-defined conditions that ![Condition state machine](../images/cond-statem.jpg "Condition state machine")
services can declare a dependency on. The conditions are specified in
angle brackets on the service stanza. Multiple conditions may be
specified, separated by commas. Conditions are AND-ed together during
evaluation, i.e. all conditions must be satisfied in order for the
service to be able to run.
##### Example:
``` Table of Contents
service [2345] <svc/sbin/setupd,svc/sbin/zebra> /sbin/netd -- Network monitor -----------------
* [Introduction](#introduction)
* [Triggering](#triggering)
* [Built-in Conditions](#built-in--conditions)
* [Debugging](#debugging)
* [Internals](#internals)
Introduction
------------
In addition to runlevels, services can declare user-defined conditions
as dependencies. Conditions are specified within angle brackets (<>) in
the service stanza. Multiple conditions may be specified separated by
comma. Conditions are AND'ed during evaluation, i.e. all conditions
must be satisfied in order for a service to run.
**Example:**
```shell
service [2345] <svc/sbin/setupd,svc/sbin/zebra> /sbin/netd -- Network monitor
``` ```
In this example the `netd` daemon will not be started until both In this example the Network monitor daemon `netd` is not started until
`svc/sbin/setupd` and `svc/sbin/zebra` are satisfied. both the `svc/sbin/setupd` *and* `svc/sbin/zebra` conditions are
satisfied. An `svc` condition is satisfied by the corresponding
service's pidfile being created.
## Triggering Triggering
----------
Conditions are triggered by using the `emit` sub-command of the Conditions are triggered by using the `emit` command of the `initctl`
`initctl` command. control tool.
* To set a condition, use: `initctl emit +your/cond/here`. * `initctl emit +your/cond/here`
* To clear a condition, use: `initctl emit -your/cond/here`.
A condition will retain its current state until the next To set a condition
reconfiguration or runlevel change. At that point, all set conditions
will transition into the `flux` state, meaning that the condition's * `initctl emit -your/cond/here`
state is unknown. The rationale for this can be found in the
[Internals](#internals) section. Thus, after a reconfiguration, it is To clear a condition
up to the "owner" of the condition to convey the new (or possibly
unchanged) state of it. Conditions retain their current state until the next reconfiguration or
runlevel change. At that point all set conditions transition into the
`flux` state, meaning the condition's state is unknown. (See
[Internals](#internals) for the rationale behind this.) Thus, after a
reconfiguration it is up to the "owner" of the condition to convey the
new (or possibly unchanged) state of it.
## Built-in Conditions Built-in Conditions
-------------------
Finit is distributed with the `pidfile`-plugin. If enabled, it will Finit is distributed with the `pidfile`-plugin. If enabled, it will
watch `/var/run/` for pidfiles created by services that is controls watch `/var/run/` for pidfiles created by services that it controls
and set a corresponding condition in the `svc/` namespace. and set a corresponding condition in the `svc/` namespace.
Thus, if Finit starts the `/sbin/netd` daemon and it creates For example, if Finit starts the `/sbin/netd` daemon and it creates the
`/var/run/netd.pid`, the condition `svc/sbin/netd` will be set. If the file `/var/run/netd.pid`, the condition `svc/sbin/netd` is satisfied.
file is removed, the condition will be cleared. If the file is removed, the condition is cleared.
## Debugging Debugging
---------
If a service is not being started when it ought to be, the problem If a service is not being started as it should, the problem might be
might be that one of its conditions are not in the expected that one of its conditions are not in the expected state. Use the
state. This is indicated when running `initctl status` by the service command `initctl status` to inspect service status. Services in the
being in the `ready` state. `ready` state are pending a condition.
In that situation, running `initctl cond show` will reveal which of In that situation, running `initctl cond show` reveals which of the
the conditions that are not in the `on` state. conditions that are not satisfied. Listed as `off` below.
##### Example: **Example:**
``` ```shell
~ # initctl cond show ~ # initctl cond show
PID Service Status Condition (+ on, ~ flux, - off) PID Service Status Condition (+ on, ~ flux, - off)
==================================================================================== ===============================================================================
1419 /sbin/netd on <+svc/sbin/setupd,+svc/sbin/zebra> 1419 /sbin/netd on <+svc/sbin/setupd,+svc/sbin/zebra>
0 /sbin/udhcpc off <-net/vlan1/exist> 0 /sbin/udhcpc off <-net/vlan1/exist>
``` ```
Here we can see that `netd` is allowed to run since both of its Here we can see that `netd` is allowed to run since both its conditions
conditions are in the `on` state, as indicated by the are in the `on` state, as indicated by the `+`-prefix. `udhcpc` however
`+`-prefix. `udhcpc` is not allowed to run since `net/vlan1/exist` is is not allowed to run since `net/vlan1/exist` condition is not satsifed.
in the `off` state, indicated by the `-`-prefix. As indicated by the `-`-prefix.
## Internals Internals
---------
A condition is always in one of three states: A condition is always in one of three states:
* `on`: The condition is asserted. * `on`: The condition is asserted.
* `off`: The condition is deasserted. * `off`: The condition is deasserted.
* `flux`: The conditions state is unknown. * `flux`: The conditions state is unknown.
All conditions that have not explicitly been set are interpreted as All conditions that have not explicitly been set are interpreted as
being in the `off` state. being in the `off` state.
When a reconfiguration is requested, Finit will transition all When a reconfiguration is requested, Finit transitions all conditions to
conditions to the `flux` state. As a result, any service that depends the `flux` state. As a result, services that depend on a condition are
on the condition will be sent a SIGSTOP. Once the new state of the sent `SIGSTOP`. Once the new state of the condition is asserted, the
condition becomes known the service will receive a SIGCONT. Then if service receives `SIGCONT`. If the condition is no longer satisfied the
the condition is no longer satisfied the service will be stopped, service will then be stopped, otherwise no further action is taken.
otherwise no action needs to be taken.
This minimizes the number of services that have to be restarted This STOP/CONT handling minimizes the number of unnecessary service
needlessly, just because the depending service was sent a SIGHUP for restarts that would otherwise occur because a depending service was sent
example. `SIGHUP` for example.
Therefore, any plugin that supplies Finit with conditions must ensure Therefore, any plugin that supplies Finit with conditions must ensure
that their state is updated after each reconfiguration. This can be that their state is updated after each reconfiguration. This can be
done by binding to the `HOOK_SVC_RECONF`-hook. Look at done by binding to the `HOOK_SVC_RECONF` hook. For an example of how
`plugins/pidfile.c` too see an example of this. to do this, see `plugins/pidfile.c`.