Adding systemd unit files in OpenStack packages

Ansgar Burchardt ansgar at debian.org
Mon Jul 7 12:21:58 BST 2014


Hi,

I'm mostly a systemd user myself, but have read through a reasonable
part of the documentation. So hopefully I can answer some of your questions.

On 07/06/2014 15:33, Thomas Goirand wrote:
> Let's take an example with keystone. Currently, there's the following
> init.d sysv-rc script LSB header:
> 
> # Required-Start:    $network $local_fs $remote_fs
> # Required-Stop:     $remote_fs

Except for $network, these dependencies should be included in default
dependencies, i.e. you don't need to do anything for them.

The replacement for $network depends on what exactly is needed and I'm
not entirely sure myself of the semantics. Maybe someone else could
explain this part.

> # Should-Start:      mysql postgresql slapd rabbitmq-server ntp
> # Should-Stop:       mysql postgresql slapd rabbitmq-server ntp
> 
> How does this translate into a systemd unit? Especially, it'd be nice to
> have mysql socket activation, but the service may be remote, so it
> shouldn't be forced, but just be there if mysqld is local.

For service with socket activation, there should be no need for an
explicit dependency.

For other dependencies, I believe that Should-Start: foo translates to
After=foo.service. The Should-Stop is then implied.

> Then another example. With nova-compute, I have the following:
> 
> [ -r /etc/default/openstack ] && . /etc/default/openstack
> [ -r /etc/default/$NAME ] && . /etc/default/$NAME
> 
> [ "x$USE_SYSLOG" = "xyes" ] && DAEMON_ARGS="$DAEMON_ARGS --use-syslog"
> [ "x$USE_LOGFILE" != "xno" ] && DAEMON_ARGS="$DAEMON_ARGS \
> 	--log-file /var/log/nova/$NAME.log"
> 
> The idea is that, by default, nova-compute only logs to a file. That is,
> unless someone configures /etc/default/nova-compute. It is also possible
> configure it globally in /etc/default/openstack (with the same
> directives). How do I do this in a systemd unit file?

I think they probably should log to the journal by default. If the admin
wants to change this, he can override the ExecStart= option to pass
different options to the executable.

Just let the daemon write to stdout/stderr and set
StandardOutput=journal if it has no built-in support for logging the the
journal itself.

systemd can do variable substitution, but logic like "if USE_SYSLOG=yes,
then append --use-syslog to startup options" isn't directly supported.
It is however considered better style not to rely on these features.

> The daemon currently are started with start-stop-daemon. I do:
> 
> NAME=nova-compute
> DAEMON=/usr/bin/$NAME
> DAEMON_ARGS="--config-file=/etc/nova/nova.conf"
> PIDFILE=/var/run/$NAME.pid
> 
> [...]
> 
> do_start() {
>         start-stop-daemon --start --background --quiet --chuid \
> 		${NOVA_USER}:nova --make-pidfile --pidfile $PIDFILE \
> 		--startas $DAEMON --test > /dev/null \
>                 || return 1
>
> As per above, the daemon doesn't fork by itself. Should I also do a PID
> file with systemd, or is there a better way, with supervision?

systemd can track the daemon and any child processes without a PID file.

> How do I do the restart on crash?

Restart=on-failure will restart the service if it exists with non-zero
in addition to the on-abort conditions. Restart=on-abort will restart
the process only when it exists due to an uncaught signal (one can
whitelist signals). Finally, Restart=always will always restart the
service if the daemon exits for any reason.

The detailed semantics are described in systemd.service(5).

> Is there a way to send an email to root upon
> crash of the daemon, or is this still not implemented in systemd?

I don't think systemd can do this and believe it might not be its role
either. But one can probably obtain this information for the journal.

> How do I implement waiting for libvirtd socket, so that compute starts
> after that?

Hmm, ideally use socket activation for that as well? Otherwise
After=libvirt-bin.service

A full .service file for nova might look like this:

+---
| [Unit]
| Description=Nova Compute server
| Documentation=man:nova-compute(8) http://example.com/nova.html
| After=libvirt-bin.service keystone.service
|
| [Service]
| ExecStart=/usr/bin/nova-compute --config-file=/etc/nova/nova.conf
| Restart=always
| User=nova
| Group=nova (defaults to default group of the user)
| StandardOutput=journal
| StandardError=inherit (actually the default)
|
| [Install]
| WantedBy=multi-user.target
+---

The Unit and Install sections are documented in systemd.unit(5), the
Service section in systemd.service(5), with the options related to
execution in systemd.exec(5).

You can install the .service file with dh-systemd which will also take
care of the necessary bits in the maintainer scripts.

I noticed that the init script for nova-compute also sets up a directory
for locks. In systemd this is handled by systemd-tmpfiles:

+---
| d /run/lock/nova 0755 nova nova
+---[ debian/nova-compute.tmpfile ]

dh-systemd will then install the file to
/usr/lib/tmpfiles.d/nova-compute.conf. Note that I changed
/var/lock/nova to /run/lock/nova. See tmpfiles.d(5) for details on the
syntax.

Ansgar





More information about the Pkg-systemd-maintainers mailing list