blob: 5bf878b1cecca20d7ad5639a5768f71fd83174a9 [file] [log] [blame]
Tomáš Pecka6a2334b2022-07-12 13:57:54 +02001/*
2 * Copyright (C) 2020 - 2022 CESNET, https://photonics.cesnet.cz/
3 *
4 * Written by Tomáš Pecka <tomas.pecka@cesnet.cz>
5 *
6 */
7
8#include "trompeloeil_doctest.h"
9#include <sysrepo-cpp/Connection.hpp>
10#include <sysrepo-cpp/Enum.hpp>
11#include <sysrepo-cpp/Subscription.hpp>
12#include <thread>
13#include "dbus-helpers/dbus_systemd_server.h"
Tomáš Pecka1d2b95c2023-05-11 16:01:46 +020014#include "health/SystemdUnits.h"
Tomáš Pecka8e5a2d32022-08-22 17:48:58 +020015#include "pretty_printers.h"
Tomáš Pecka6a2334b2022-07-12 13:57:54 +020016#include "test_log_setup.h"
Tomáš Peckab80a7e32024-01-24 15:04:14 +010017#include "tests/sysrepo-helpers/alarms.h"
Tomáš Peckac164ca62024-01-24 13:38:03 +010018#include "tests/sysrepo-helpers/common.h"
Tomáš Pecka6a2334b2022-07-12 13:57:54 +020019#include "utils/log-init.h"
20#include "utils/log.h"
21
22using namespace std::chrono_literals;
23
Jan Kundrátc1511512024-01-15 13:47:28 +010024#define REQUIRE_NEW_ALARM_INVENTORY_UNIT(UNIT) \
Tomáš Pecka52d50462024-01-31 13:37:29 +010025 REQUIRE_NEW_ALARM_INVENTORY_RESOURCES(alarmsWatcher, (std::set<std::string>{"velia-alarms:systemd-unit-failure"}), std::set<std::string>{UNIT})
Jan Kundrátc1511512024-01-15 13:47:28 +010026
27#define REQUIRE_ALARM_RPC(UNIT, SEVERITY, TEXT) \
Tomáš Pecka4163c0c2024-01-31 13:21:03 +010028 REQUIRE_NEW_ALARM(alarmsWatcher, "velia-alarms:systemd-unit-failure", UNIT, SEVERITY, TEXT)
Tomáš Pecka6a2334b2022-07-12 13:57:54 +020029
Tomáš Pecka6a2334b2022-07-12 13:57:54 +020030TEST_CASE("systemd unit state monitoring (alarms)")
31{
32 TEST_INIT_LOGS;
33 TEST_SYSREPO_INIT;
Tomáš Pecka6fcb7592024-01-24 14:42:14 +010034 TEST_SYSREPO_INIT_CLIENT;
Tomáš Pecka6a2334b2022-07-12 13:57:54 +020035 trompeloeil::sequence seq1;
36
37 // Create and setup separate connections for both client and server to simulate real-world server-client architecture.
38 // Also this doesn't work one a single dbus connection.
39 auto clientConnection = sdbus::createSessionBusConnection();
40 auto serverConnection = sdbus::createSessionBusConnection();
41 clientConnection->enterEventLoopAsync();
42 serverConnection->enterEventLoopAsync();
43
44 auto server = DbusSystemdServer(*serverConnection);
Tomáš Pecka6a2334b2022-07-12 13:57:54 +020045
Tomáš Peckab80a7e32024-01-24 15:04:14 +010046 client.switchDatastore(sysrepo::Datastore::Operational);
47 AlarmWatcher alarmsWatcher(client);
48
Tomáš Peckaca85a6d2024-01-24 16:55:44 +010049 REQUIRE_NEW_ALARM_INVENTORY_ENTRY(alarmsWatcher,
50 "velia-alarms:systemd-unit-failure",
Tomáš Peckaca85a6d2024-01-24 16:55:44 +010051 (std::set<std::string>{"unit1.service", "unit2.service", "unit3.service"}),
52 (std::set<std::string>{"critical"}),
53 true,
54 "The systemd service is considered in failed state.");
Tomáš Peckab80a7e32024-01-24 15:04:14 +010055
Tomáš Pecka6fcb7592024-01-24 14:42:14 +010056 REQUIRE_ALARM_RPC("unit1.service", "cleared", "systemd unit state: (active, running)");
Tomáš Pecka6a2334b2022-07-12 13:57:54 +020057 server.createUnit(*serverConnection, "unit1.service", "/org/freedesktop/systemd1/unit/unit1", "active", "running");
Tomáš Peckab80a7e32024-01-24 15:04:14 +010058
Tomáš Pecka6fcb7592024-01-24 14:42:14 +010059 REQUIRE_ALARM_RPC("unit2.service", "critical", "systemd unit state: (activating, auto-restart)");
Tomáš Pecka6a2334b2022-07-12 13:57:54 +020060 server.createUnit(*serverConnection, "unit2.service", "/org/freedesktop/systemd1/unit/unit2", "activating", "auto-restart");
Tomáš Peckab80a7e32024-01-24 15:04:14 +010061
Tomáš Pecka6fcb7592024-01-24 14:42:14 +010062 REQUIRE_ALARM_RPC("unit3.service", "critical", "systemd unit state: (failed, failed)");
Tomáš Pecka6a2334b2022-07-12 13:57:54 +020063 server.createUnit(*serverConnection, "unit3.service", "/org/freedesktop/systemd1/unit/unit3", "failed", "failed");
64
65 auto systemdAlarms = std::make_shared<velia::health::SystemdUnits>(srSess, *clientConnection, serverConnection->getUniqueName(), "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "org.freedesktop.systemd1.Unit");
66
Tomáš Pecka6fcb7592024-01-24 14:42:14 +010067 REQUIRE_ALARM_RPC("unit2.service", "cleared", "systemd unit state: (active, running)");
68 REQUIRE_ALARM_RPC("unit3.service", "cleared", "systemd unit state: (active, running)");
Tomáš Peckab80a7e32024-01-24 15:04:14 +010069 REQUIRE_NEW_ALARM_INVENTORY_UNIT("unit4.service");
Tomáš Pecka6fcb7592024-01-24 14:42:14 +010070 REQUIRE_ALARM_RPC("unit4.service", "critical", "systemd unit state: (failed, failed)");
71 REQUIRE_ALARM_RPC("unit3.service", "critical", "systemd unit state: (activating, auto-restart)");
72 REQUIRE_ALARM_RPC("unit3.service", "cleared", "systemd unit state: (active, running)");
73 REQUIRE_ALARM_RPC("unit3.service", "critical", "systemd unit state: (failed, failed)");
74 REQUIRE_ALARM_RPC("unit3.service", "critical", "systemd unit state: (activating, auto-restart)");
75 REQUIRE_ALARM_RPC("unit3.service", "cleared", "systemd unit state: (active, running)");
76 REQUIRE_ALARM_RPC("unit4.service", "cleared", "systemd unit state: (active, running)");
Tomáš Pecka6a2334b2022-07-12 13:57:54 +020077
78 std::thread systemdSimulator([&] {
79 server.changeUnitState("/org/freedesktop/systemd1/unit/unit2", "active", "running");
80 server.changeUnitState("/org/freedesktop/systemd1/unit/unit3", "active", "running");
81
82 // In case we obtain a notifications that unit changed state from (X,Y) to (X,Y), do not trigger any events.
83 server.changeUnitState("/org/freedesktop/systemd1/unit/unit3", "active", "running");
84
85 // add new unit with failed/failed, DbusSystemdInput should receive UnitNew signal and monitor this unit too
86 server.createUnit(*serverConnection, "unit4.service", "/org/freedesktop/systemd1/unit/unit4", "failed", "failed");
87
88 // Sleep for a while; the rest of the code might be too fast and we need to be sure that we pick up event for (failed, failed) before the state of unit4 is changed in the DBus server
Tomáš Pecka457016b2023-07-12 15:18:09 +020089 std::this_thread::sleep_for(250ms);
Tomáš Pecka6a2334b2022-07-12 13:57:54 +020090
91 server.changeUnitState("/org/freedesktop/systemd1/unit/unit3", "activating", "auto-restart");
92 server.changeUnitState("/org/freedesktop/systemd1/unit/unit3", "active", "running");
93 server.changeUnitState("/org/freedesktop/systemd1/unit/unit3", "failed", "failed");
94 server.changeUnitState("/org/freedesktop/systemd1/unit/unit3", "activating", "auto-restart");
95 server.changeUnitState("/org/freedesktop/systemd1/unit/unit3", "active", "running");
96
97 server.changeUnitState("/org/freedesktop/systemd1/unit/unit4", "active", "running");
98 });
99
Tomáš Pecka6a2334b2022-07-12 13:57:54 +0200100 systemdSimulator.join();
101 waitForCompletionAndBitMore(seq1);
Tomáš Pecka6a2334b2022-07-12 13:57:54 +0200102}