mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 13:45:38 +00:00
systemd: Introduce common templates
We already use templating to generate sockets, which are all based off libvirtd's. Push the idea further, and extend it to cover services as well. This is more challenging, as the various modular daemons each have their own needs in terms of what system services needs to be available before they can be started, which other components of libvirt they depend on, and so on. In order to make this sort of per-service tweaks possible, we introduce a Python script that can merge two systemd units together. The script is aware of the semantics of systemd's unit definition format, so it can intelligently merge sections together. This generic systemd unit merging mechanism will also supersede the extremely ad-hoc @deps@ variable, which is currently used in a single scenario. Signed-off-by: Andrea Bolognani <abologna@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
parent
80ee76218c
commit
e86390c9b4
94
scripts/merge-systemd-units.py
Executable file
94
scripts/merge-systemd-units.py
Executable file
@ -0,0 +1,94 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Copyright (C) 2023 Red Hat, Inc.
|
||||||
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
SECTIONS = [
|
||||||
|
"[Unit]",
|
||||||
|
"[Service]",
|
||||||
|
"[Socket]",
|
||||||
|
"[Install]",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def parse_unit(unit_path):
|
||||||
|
unit = {}
|
||||||
|
current_section = "[Invalid]"
|
||||||
|
|
||||||
|
with open(unit_path) as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
|
||||||
|
if line == "":
|
||||||
|
continue
|
||||||
|
|
||||||
|
if line[0] == "[" and line[-1] == "]":
|
||||||
|
if line not in SECTIONS:
|
||||||
|
print("Unknown section {}".format(line))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
current_section = line
|
||||||
|
continue
|
||||||
|
|
||||||
|
if current_section not in unit:
|
||||||
|
unit[current_section] = []
|
||||||
|
|
||||||
|
unit[current_section].append(line)
|
||||||
|
|
||||||
|
if "[Invalid]" in unit:
|
||||||
|
print("Contents found outside of any section")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
return unit
|
||||||
|
|
||||||
|
|
||||||
|
def format_unit(unit):
|
||||||
|
lines = []
|
||||||
|
|
||||||
|
for section in SECTIONS:
|
||||||
|
if section not in unit:
|
||||||
|
continue
|
||||||
|
|
||||||
|
lines.append(section)
|
||||||
|
|
||||||
|
for line in unit[section]:
|
||||||
|
lines.append(line)
|
||||||
|
|
||||||
|
lines.append("")
|
||||||
|
|
||||||
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
|
def merge_units(base, extra):
|
||||||
|
merged = {}
|
||||||
|
|
||||||
|
for section in SECTIONS:
|
||||||
|
if section in extra and section not in base:
|
||||||
|
print("Section {} in extra but not in base".format(section))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if section not in base:
|
||||||
|
continue
|
||||||
|
|
||||||
|
merged[section] = base[section]
|
||||||
|
|
||||||
|
if section not in extra:
|
||||||
|
continue
|
||||||
|
|
||||||
|
merged[section].extend(extra[section])
|
||||||
|
|
||||||
|
return merged
|
||||||
|
|
||||||
|
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print("usage: {} BASE EXTRA".format(sys.argv[0]))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
base = parse_unit(sys.argv[1])
|
||||||
|
extra = parse_unit(sys.argv[2])
|
||||||
|
|
||||||
|
merged = merge_units(base, extra)
|
||||||
|
|
||||||
|
sys.stdout.write(format_unit(merged))
|
@ -19,6 +19,7 @@ scripts = [
|
|||||||
'header-ifdef.py',
|
'header-ifdef.py',
|
||||||
'hvsupport.py',
|
'hvsupport.py',
|
||||||
'hyperv_wmi_generator.py',
|
'hyperv_wmi_generator.py',
|
||||||
|
'merge-systemd-units.py',
|
||||||
'meson-dist.py',
|
'meson-dist.py',
|
||||||
'meson-gen-authors.py',
|
'meson-gen-authors.py',
|
||||||
'meson-gen-def.py',
|
'meson-gen-def.py',
|
||||||
|
@ -203,6 +203,8 @@ libvirtd_socket_admin_in = files('remote' / 'libvirtd-admin.socket.in')
|
|||||||
# * sockets - array of additional sockets (optional, default [ 'main', 'ro', 'admin' ])
|
# * sockets - array of additional sockets (optional, default [ 'main', 'ro', 'admin' ])
|
||||||
# * service_in - service source file (optional, default remote/libvirtd.service.in)
|
# * service_in - service source file (optional, default remote/libvirtd.service.in)
|
||||||
# * socket_$name_in - additional socket source files (optional, default remote/libvirtd.socket.in )
|
# * socket_$name_in - additional socket source files (optional, default remote/libvirtd.socket.in )
|
||||||
|
# * service_extra_in - unit to merge with service_in (optional, default None)
|
||||||
|
# * socket_extra_in - unit to merge with socket_$name_in (optional, default None)
|
||||||
# * deps - socket dependencies (optional, default '')
|
# * deps - socket dependencies (optional, default '')
|
||||||
virt_daemon_units = []
|
virt_daemon_units = []
|
||||||
|
|
||||||
@ -817,6 +819,7 @@ if conf.has('WITH_LIBVIRTD')
|
|||||||
'initconfdir': initconfdir,
|
'initconfdir': initconfdir,
|
||||||
'name': unit['name'],
|
'name': unit['name'],
|
||||||
'service': unit['service'],
|
'service': unit['service'],
|
||||||
|
'SERVICE': unit['service'].to_upper(),
|
||||||
'sockprefix': unit.get('sockprefix', unit['service']),
|
'sockprefix': unit.get('sockprefix', unit['service']),
|
||||||
'deps': unit.get('deps', ''),
|
'deps': unit.get('deps', ''),
|
||||||
'sockmode': sockmode,
|
'sockmode': sockmode,
|
||||||
@ -825,6 +828,15 @@ if conf.has('WITH_LIBVIRTD')
|
|||||||
service_in = unit.get('service_in', service_in_default)
|
service_in = unit.get('service_in', service_in_default)
|
||||||
service_out = '@0@.service'.format(unit['service'])
|
service_out = '@0@.service'.format(unit['service'])
|
||||||
|
|
||||||
|
if 'service_extra_in' in unit
|
||||||
|
service_in = configure_file(
|
||||||
|
input: [ service_in, unit['service_extra_in'] ],
|
||||||
|
output: '@0@.in'.format(service_out),
|
||||||
|
command: [ merge_systemd_units_prog, '@INPUT0@', '@INPUT1@' ],
|
||||||
|
capture: true,
|
||||||
|
)
|
||||||
|
endif
|
||||||
|
|
||||||
configure_file(
|
configure_file(
|
||||||
input: service_in,
|
input: service_in,
|
||||||
output: service_out,
|
output: service_out,
|
||||||
@ -843,6 +855,16 @@ if conf.has('WITH_LIBVIRTD')
|
|||||||
socket_in = unit.get('socket_@0@_in'.format(socket), socket_in_default)
|
socket_in = unit.get('socket_@0@_in'.format(socket), socket_in_default)
|
||||||
socket_out = '@0@-@1@.socket'.format(unit['service'], socket)
|
socket_out = '@0@-@1@.socket'.format(unit['service'], socket)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if 'socket_extra_in' in unit
|
||||||
|
socket_in = configure_file(
|
||||||
|
input: [ socket_in, unit['socket_extra_in'] ],
|
||||||
|
output: '@0@.in'.format(socket_out),
|
||||||
|
command: [ merge_systemd_units_prog, '@INPUT0@', '@INPUT1@' ],
|
||||||
|
capture: true,
|
||||||
|
)
|
||||||
|
endif
|
||||||
|
|
||||||
configure_file(
|
configure_file(
|
||||||
input: socket_in,
|
input: socket_in,
|
||||||
output: socket_out,
|
output: socket_out,
|
||||||
|
13
src/virtd-admin.socket.in
Normal file
13
src/virtd-admin.socket.in
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=@name@ admin socket
|
||||||
|
Before=@service@.service
|
||||||
|
BindsTo=@service@.socket
|
||||||
|
After=@service@.socket
|
||||||
|
|
||||||
|
[Socket]
|
||||||
|
ListenStream=@runstatedir@/libvirt/@sockprefix@-admin-sock
|
||||||
|
Service=@service@.service
|
||||||
|
SocketMode=0600
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=sockets.target
|
13
src/virtd-ro.socket.in
Normal file
13
src/virtd-ro.socket.in
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=@name@ local read-only socket
|
||||||
|
Before=@service@.service
|
||||||
|
BindsTo=@service@.socket
|
||||||
|
After=@service@.socket
|
||||||
|
|
||||||
|
[Socket]
|
||||||
|
ListenStream=@runstatedir@/libvirt/@sockprefix@-sock-ro
|
||||||
|
Service=@service@.service
|
||||||
|
SocketMode=0666
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=sockets.target
|
12
src/virtd-tcp.socket.in
Normal file
12
src/virtd-tcp.socket.in
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=@name@ non-TLS IP socket
|
||||||
|
Before=@service@.service
|
||||||
|
BindsTo=@service@.socket
|
||||||
|
After=@service@.socket
|
||||||
|
|
||||||
|
[Socket]
|
||||||
|
ListenStream=16509
|
||||||
|
Service=@service@.service
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=sockets.target
|
12
src/virtd-tls.socket.in
Normal file
12
src/virtd-tls.socket.in
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=@name@ TLS IP socket
|
||||||
|
Before=@service@.service
|
||||||
|
BindsTo=@service@.socket
|
||||||
|
After=@service@.socket
|
||||||
|
|
||||||
|
[Socket]
|
||||||
|
ListenStream=16514
|
||||||
|
Service=@service@.service
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=sockets.target
|
25
src/virtd.service.in
Normal file
25
src/virtd.service.in
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=@name@ daemon
|
||||||
|
Conflicts=libvirtd.service
|
||||||
|
Requires=@service@.socket
|
||||||
|
Requires=@service@-ro.socket
|
||||||
|
Requires=@service@-admin.socket
|
||||||
|
After=network.target
|
||||||
|
After=dbus.service
|
||||||
|
After=apparmor.service
|
||||||
|
Documentation=man:@service@(8)
|
||||||
|
Documentation=https://libvirt.org
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=notify
|
||||||
|
Environment=@SERVICE@_ARGS="--timeout 120"
|
||||||
|
EnvironmentFile=-@initconfdir@/@service@
|
||||||
|
ExecStart=@sbindir@/@service@ $@SERVICE@_ARGS
|
||||||
|
ExecReload=/bin/kill -HUP $MAINPID
|
||||||
|
Restart=on-failure
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
Also=@service@.socket
|
||||||
|
Also=@service@-ro.socket
|
||||||
|
Also=@service@-admin.socket
|
12
src/virtd.socket.in
Normal file
12
src/virtd.socket.in
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=@name@ local socket
|
||||||
|
Before=@service@.service
|
||||||
|
|
||||||
|
[Socket]
|
||||||
|
ListenStream=@runstatedir@/libvirt/@sockprefix@-sock
|
||||||
|
Service=@service@.service
|
||||||
|
SocketMode=@sockmode@
|
||||||
|
RemoveOnStop=yes
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=sockets.target
|
Loading…
Reference in New Issue
Block a user