Merge pull request #108 from glance-/systemd

Add Systemd integration to aes67-daemon
This commit is contained in:
Andrea Bondavalli 2023-02-03 13:48:21 +01:00 committed by GitHub
commit f77db79869
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 119 additions and 0 deletions

View File

@ -11,6 +11,8 @@ option(WITH_AVAHI "Include mDNS support via Avahi" OFF)
option(FAKE_DRIVER "Use fake driver instead of RAVENNA" OFF)
set(CMAKE_CXX_STANDARD 17)
option(WITH_SYSTEMD "Include systemd notify and watchdog support" OFF)
# ravena lkm _should_ be provided by the CLI. Nonetheless, we should be able
# to find it in system dirs too...
if (NOT RAVENNNA_ALSA_LKM_DIR)
@ -54,3 +56,9 @@ if(WITH_AVAHI)
include_directories(aes67-daemon ${AVAHI_INCLUDE_DIRS})
target_link_libraries(aes67-daemon ${AVAHI_LIBRARIES})
endif()
if(WITH_SYSTEMD)
MESSAGE(STATUS "WITH_SYSTEMD")
add_definitions(-D_USE_SYSTEMD_)
target_link_libraries(aes67-daemon systemd)
endif()

View File

@ -31,6 +31,10 @@
#include "rtsp_server.hpp"
#include "session_manager.hpp"
#ifdef _USE_SYSTEMD_
#include <systemd/sd-daemon.h>
#endif
namespace po = boost::program_options;
namespace postyle = boost::program_options::command_line_style;
namespace logging = boost::log;
@ -64,6 +68,11 @@ int main(int argc, char* argv[]) {
int unix_style = postyle::unix_style | postyle::short_allow_next;
bool driver_restart(true);
#ifdef _USE_SYSTEMD_
// with which interval we should pet the dog
uint64_t current_watchdog_usec;
#endif
po::variables_map vm;
try {
po::store(po::command_line_parser(argc, argv)
@ -98,6 +107,17 @@ int main(int argc, char* argv[]) {
std::string filename = vm["config"].as<std::string>();
#ifdef _USE_SYSTEMD_
sd_watchdog_enabled(0, &current_watchdog_usec);
if (current_watchdog_usec > 0) {
// Inform systemd that if we're not petting the dog in 5s we're bust.
sd_notify(0, "WATCHDOG_USEC=5000000");
current_watchdog_usec = 5000000;
}
#endif
while (!is_terminated() && rc == EXIT_SUCCESS) {
/* load configuration from file */
auto config = Config::parse(filename, driver_restart);
@ -112,6 +132,11 @@ int main(int argc, char* argv[]) {
log_init(*config);
if (config->get_ip_addr_str().empty()) {
#ifdef _USE_SYSTEMD_
if (current_watchdog_usec > 0)
sd_notify(0, "WATCHDOG=1");
sd_notify(0, "STATUS=no IP address, waiting ...");
#endif
BOOST_LOG_TRIVIAL(info) << "main:: no IP address, waiting ...";
std::this_thread::sleep_for(std::chrono::seconds(1));
continue;
@ -159,7 +184,22 @@ int main(int argc, char* argv[]) {
session_manager->load_status();
BOOST_LOG_TRIVIAL(debug) << "main:: init done, entering loop...";
#ifdef _USE_SYSTEMD_
// To be able to use sd_notify at all have to set service NotifyAccess
// (e.g. to main)
sd_notify(0, "READY=1"); // If service Type=notify the service is only
// considered ready once we send this (this is
// independent of watchdog capability)
sd_notify(0, "STATUS=Working");
#endif
while (!is_terminated()) {
#ifdef _USE_SYSTEMD_
if (current_watchdog_usec > 0)
sd_notify(0, "WATCHDOG=1");
#endif
auto [ip_addr, ip_str] = get_interface_ip(config->get_interface_name());
if (config->get_ip_addr_str() != ip_str) {
BOOST_LOG_TRIVIAL(warning)
@ -175,6 +215,15 @@ int main(int argc, char* argv[]) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
#ifdef _USE_SYSTEMD_
if (is_terminated()) {
sd_notify(0, "STOPPING=1");
sd_notify(0, "STATUS=Stopping");
} else {
sd_notify(0, "RELOADING=1");
sd_notify(0, "STATUS=Restarting");
}
#endif
/* save session status to file */
session_manager->save_status();

View File

@ -0,0 +1,2 @@
#Type Name ID GECOS Home directory Shell
u aes67-daemon - "AES67 daemon user"

View File

@ -0,0 +1,60 @@
[Unit]
Description=AES67 daemon service
Before=multi-user.target
After=network.target
[Service]
Type=notify
# Will be adjusted by service during startup
WatchdogSec=10
# Run as separate user created via sysusers.d
User=aes67-daemon
ExecStart=/usr/local/bin/aes67-daemon
# Security filters.
CapabilityBoundingSet=
DevicePolicy=closed
LockPersonality=yes
MemoryDenyWriteExecute=yes
NoNewPrivileges=yes
PrivateDevices=yes
PrivateMounts=yes
PrivateTmp=yes
PrivateUsers=yes
# interface::get_mac_from_arp_cache() reads from /proc/net/arp
ProcSubset=all
ProtectClock=yes
ProtectControlGroups=yes
ProtectHome=yes
ProtectHostname=yes
ProtectKernelLogs=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
ProtectProc=invisible
ProtectSystem=strict
RemoveIPC=yes
RestrictAddressFamilies=AF_INET AF_NETLINK AF_UNIX
RestrictNamespaces=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
SystemCallArchitectures=native
SystemCallFilter=~@clock
SystemCallFilter=~@cpu-emulation
SystemCallFilter=~@debug
SystemCallFilter=~@module
SystemCallFilter=~@mount
SystemCallFilter=~@obsolete
SystemCallFilter=~@privileged
SystemCallFilter=~@raw-io
SystemCallFilter=~@reboot
SystemCallFilter=~@resources
SystemCallFilter=~@swap
UMask=077
# Paths matching daemon.conf
ReadWritePaths=/etc/daemon.conf
ReadWritePaths=/etc/status.json
[Install]
WantedBy=multi-user.target