--- /dev/null
+#!/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))
'header-ifdef.py',
'hvsupport.py',
'hyperv_wmi_generator.py',
+ 'merge-systemd-units.py',
'meson-dist.py',
'meson-gen-authors.py',
'meson-gen-def.py',
# * sockets - array of additional sockets (optional, default [ 'main', 'ro', 'admin' ])
# * service_in - service source file (optional, default remote/libvirtd.service.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 '')
virt_daemon_units = []
'initconfdir': initconfdir,
'name': unit['name'],
'service': unit['service'],
+ 'SERVICE': unit['service'].to_upper(),
'sockprefix': unit.get('sockprefix', unit['service']),
'deps': unit.get('deps', ''),
'sockmode': sockmode,
service_in = unit.get('service_in', service_in_default)
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(
input: service_in,
output: service_out,
socket_in = unit.get('socket_@0@_in'.format(socket), socket_in_default)
socket_out = '@0@-@1@.socket'.format(unit['service'], socket)
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(
input: socket_in,
output: socket_out,
--- /dev/null
+[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
--- /dev/null
+[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
--- /dev/null
+[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
--- /dev/null
+[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
--- /dev/null
+[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
--- /dev/null
+[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