Tomáš Pecka | 6a2334b | 2022-07-12 13:57:54 +0200 | [diff] [blame] | 1 | /* |
| 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áš Pecka | 1d2b95c | 2023-05-11 16:01:46 +0200 | [diff] [blame] | 14 | #include "health/SystemdUnits.h" |
Tomáš Pecka | 8e5a2d3 | 2022-08-22 17:48:58 +0200 | [diff] [blame] | 15 | #include "pretty_printers.h" |
Tomáš Pecka | 6a2334b | 2022-07-12 13:57:54 +0200 | [diff] [blame] | 16 | #include "test_log_setup.h" |
Tomáš Pecka | b80a7e3 | 2024-01-24 15:04:14 +0100 | [diff] [blame] | 17 | #include "tests/sysrepo-helpers/alarms.h" |
Tomáš Pecka | c164ca6 | 2024-01-24 13:38:03 +0100 | [diff] [blame] | 18 | #include "tests/sysrepo-helpers/common.h" |
Tomáš Pecka | 6a2334b | 2022-07-12 13:57:54 +0200 | [diff] [blame] | 19 | #include "utils/log-init.h" |
| 20 | #include "utils/log.h" |
| 21 | |
| 22 | using namespace std::chrono_literals; |
| 23 | |
Jan Kundrát | c151151 | 2024-01-15 13:47:28 +0100 | [diff] [blame] | 24 | #define REQUIRE_NEW_ALARM_INVENTORY_UNIT(UNIT) \ |
Tomáš Pecka | 52d5046 | 2024-01-31 13:37:29 +0100 | [diff] [blame^] | 25 | REQUIRE_NEW_ALARM_INVENTORY_RESOURCES(alarmsWatcher, (std::set<std::string>{"velia-alarms:systemd-unit-failure"}), std::set<std::string>{UNIT}) |
Jan Kundrát | c151151 | 2024-01-15 13:47:28 +0100 | [diff] [blame] | 26 | |
| 27 | #define REQUIRE_ALARM_RPC(UNIT, SEVERITY, TEXT) \ |
Tomáš Pecka | 4163c0c | 2024-01-31 13:21:03 +0100 | [diff] [blame] | 28 | REQUIRE_NEW_ALARM(alarmsWatcher, "velia-alarms:systemd-unit-failure", UNIT, SEVERITY, TEXT) |
Tomáš Pecka | 6a2334b | 2022-07-12 13:57:54 +0200 | [diff] [blame] | 29 | |
Tomáš Pecka | 6a2334b | 2022-07-12 13:57:54 +0200 | [diff] [blame] | 30 | TEST_CASE("systemd unit state monitoring (alarms)") |
| 31 | { |
| 32 | TEST_INIT_LOGS; |
| 33 | TEST_SYSREPO_INIT; |
Tomáš Pecka | 6fcb759 | 2024-01-24 14:42:14 +0100 | [diff] [blame] | 34 | TEST_SYSREPO_INIT_CLIENT; |
Tomáš Pecka | 6a2334b | 2022-07-12 13:57:54 +0200 | [diff] [blame] | 35 | 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áš Pecka | 6a2334b | 2022-07-12 13:57:54 +0200 | [diff] [blame] | 45 | |
Tomáš Pecka | b80a7e3 | 2024-01-24 15:04:14 +0100 | [diff] [blame] | 46 | client.switchDatastore(sysrepo::Datastore::Operational); |
| 47 | AlarmWatcher alarmsWatcher(client); |
| 48 | |
Tomáš Pecka | ca85a6d | 2024-01-24 16:55:44 +0100 | [diff] [blame] | 49 | REQUIRE_NEW_ALARM_INVENTORY_ENTRY(alarmsWatcher, |
| 50 | "velia-alarms:systemd-unit-failure", |
Tomáš Pecka | ca85a6d | 2024-01-24 16:55:44 +0100 | [diff] [blame] | 51 | (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áš Pecka | b80a7e3 | 2024-01-24 15:04:14 +0100 | [diff] [blame] | 55 | |
Tomáš Pecka | 6fcb759 | 2024-01-24 14:42:14 +0100 | [diff] [blame] | 56 | REQUIRE_ALARM_RPC("unit1.service", "cleared", "systemd unit state: (active, running)"); |
Tomáš Pecka | 6a2334b | 2022-07-12 13:57:54 +0200 | [diff] [blame] | 57 | server.createUnit(*serverConnection, "unit1.service", "/org/freedesktop/systemd1/unit/unit1", "active", "running"); |
Tomáš Pecka | b80a7e3 | 2024-01-24 15:04:14 +0100 | [diff] [blame] | 58 | |
Tomáš Pecka | 6fcb759 | 2024-01-24 14:42:14 +0100 | [diff] [blame] | 59 | REQUIRE_ALARM_RPC("unit2.service", "critical", "systemd unit state: (activating, auto-restart)"); |
Tomáš Pecka | 6a2334b | 2022-07-12 13:57:54 +0200 | [diff] [blame] | 60 | server.createUnit(*serverConnection, "unit2.service", "/org/freedesktop/systemd1/unit/unit2", "activating", "auto-restart"); |
Tomáš Pecka | b80a7e3 | 2024-01-24 15:04:14 +0100 | [diff] [blame] | 61 | |
Tomáš Pecka | 6fcb759 | 2024-01-24 14:42:14 +0100 | [diff] [blame] | 62 | REQUIRE_ALARM_RPC("unit3.service", "critical", "systemd unit state: (failed, failed)"); |
Tomáš Pecka | 6a2334b | 2022-07-12 13:57:54 +0200 | [diff] [blame] | 63 | 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áš Pecka | 6fcb759 | 2024-01-24 14:42:14 +0100 | [diff] [blame] | 67 | REQUIRE_ALARM_RPC("unit2.service", "cleared", "systemd unit state: (active, running)"); |
| 68 | REQUIRE_ALARM_RPC("unit3.service", "cleared", "systemd unit state: (active, running)"); |
Tomáš Pecka | b80a7e3 | 2024-01-24 15:04:14 +0100 | [diff] [blame] | 69 | REQUIRE_NEW_ALARM_INVENTORY_UNIT("unit4.service"); |
Tomáš Pecka | 6fcb759 | 2024-01-24 14:42:14 +0100 | [diff] [blame] | 70 | 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áš Pecka | 6a2334b | 2022-07-12 13:57:54 +0200 | [diff] [blame] | 77 | |
| 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áš Pecka | 457016b | 2023-07-12 15:18:09 +0200 | [diff] [blame] | 89 | std::this_thread::sleep_for(250ms); |
Tomáš Pecka | 6a2334b | 2022-07-12 13:57:54 +0200 | [diff] [blame] | 90 | |
| 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áš Pecka | 6a2334b | 2022-07-12 13:57:54 +0200 | [diff] [blame] | 100 | systemdSimulator.join(); |
| 101 | waitForCompletionAndBitMore(seq1); |
Tomáš Pecka | 6a2334b | 2022-07-12 13:57:54 +0200 | [diff] [blame] | 102 | } |