health: populate alarms' alarm-inventory container
RFC 8632 says [1] that we MUST populate alarm inventory list with data
about all the alarms that can appear. We don't have many alarms in
velia yet, so this is quite straightforward.
[1] https://www.rfc-editor.org/rfc/rfc8632.html#page-16
Change-Id: Iae1c237cfc0cc54eff835a6c83962598e5bf96ac
diff --git a/src/health/alarms/SystemdUnits.cpp b/src/health/alarms/SystemdUnits.cpp
index c1aac27..241de97 100644
--- a/src/health/alarms/SystemdUnits.cpp
+++ b/src/health/alarms/SystemdUnits.cpp
@@ -12,6 +12,7 @@
namespace {
const auto ALARM_ID = "velia-alarms:systemd-unit-failure";
const auto ALARM_SEVERITY = "critical";
+const auto ALARM_INVENTORY_DESCRIPTION = "The systemd service is considered in failed state.";
}
namespace velia::health {
@@ -27,13 +28,15 @@
utils::ensureModuleImplemented(m_srSession, "sysrepo-ietf-alarms", "2022-02-17");
utils::ensureModuleImplemented(m_srSession, "velia-alarms", "2022-07-12");
+ createOrUpdateAlarmInventoryEntry(m_srSession, ALARM_ID, std::nullopt, {ALARM_SEVERITY}, true, ALARM_INVENTORY_DESCRIPTION);
+
// Subscribe to systemd events. Systemd may not generate signals unless explicitly called
m_proxyManager->callMethod("Subscribe").onInterface(managerIface).withArguments().dontExpectReply();
// Register to a signal introducing new unit
m_proxyManager->uponSignal("UnitNew").onInterface(managerIface).call([&](const std::string& unitName, const sdbus::ObjectPath& unitObjectPath) {
if (m_proxyUnits.find(unitObjectPath) == m_proxyUnits.end()) {
- registerSystemdUnit(connection, unitName, unitObjectPath);
+ registerSystemdUnit(m_srSession, connection, unitName, unitObjectPath);
}
});
m_proxyManager->finishRegistration();
@@ -48,7 +51,7 @@
const auto& unitName = unit.get<0>();
const auto& unitObjectPath = unit.get<6>();
- registerSystemdUnit(connection, unitName, unitObjectPath);
+ registerSystemdUnit(m_srSession, connection, unitName, unitObjectPath);
}
}
@@ -59,8 +62,10 @@
}
/** @brief Registers a systemd unit by its unit name and unit dbus objectpath. */
-void SystemdUnits::registerSystemdUnit(sdbus::IConnection& connection, const std::string& unitName, const sdbus::ObjectPath& unitObjectPath)
+void SystemdUnits::registerSystemdUnit(sysrepo::Session session, sdbus::IConnection& connection, const std::string& unitName, const sdbus::ObjectPath& unitObjectPath)
{
+ addResourceToAlarmInventoryEntry(session, ALARM_ID, std::nullopt, unitName);
+
auto proxyUnit = sdbus::createProxy(connection, m_busName, unitObjectPath);
proxyUnit->uponSignal("PropertiesChanged").onInterface("org.freedesktop.DBus.Properties").call([&, unitName](const std::string& iface, const std::map<std::string, sdbus::Variant>& changed, [[maybe_unused]] const std::vector<std::string>& invalidated) {
if (iface != m_unitIface) {
diff --git a/src/health/alarms/SystemdUnits.h b/src/health/alarms/SystemdUnits.h
index a29ba1f..27f9210 100644
--- a/src/health/alarms/SystemdUnits.h
+++ b/src/health/alarms/SystemdUnits.h
@@ -36,7 +36,7 @@
/** Current unit state. */
std::map<std::string, std::pair<std::string, std::string>> m_unitState;
- void registerSystemdUnit(sdbus::IConnection& connection, const std::string& unitName, const sdbus::ObjectPath& unitObjectPath);
+ void registerSystemdUnit(sysrepo::Session session, sdbus::IConnection& connection, const std::string& unitName, const sdbus::ObjectPath& unitObjectPath);
void onUnitStateChange(const std::string& name, const std::string& activeState, const std::string& nSubState);
};
diff --git a/src/health/alarms/alarms.cpp b/src/health/alarms/alarms.cpp
index e5c6e36..c47dd08 100644
--- a/src/health/alarms/alarms.cpp
+++ b/src/health/alarms/alarms.cpp
@@ -4,11 +4,15 @@
* Written by Tomáš Pecka <tomas.pecka@fit.cvut.cz>
*
*/
+#include <sysrepo-cpp/Enum.hpp>
#include "alarms.h"
+#include "utils/UniqueResource.h"
+#include "utils/libyang.h"
using namespace std::string_literals;
namespace {
+const auto alarmInventory = "/ietf-alarms:alarms/alarm-inventory"s;
const auto alarmRpc = "/sysrepo-ietf-alarms:create-or-update-alarm";
}
@@ -25,4 +29,46 @@
session.sendRPC(inputNode);
}
+
+void createOrUpdateAlarmInventoryEntry(sysrepo::Session session, const std::string& alarmId, const std::optional<std::string>& alarmTypeQualifier, const std::vector<std::string>& severities, bool willClear, const std::string& description)
+{
+ const auto prefix = alarmInventory + "/alarm-type[alarm-type-id='" + alarmId + "'][alarm-type-qualifier='" + alarmTypeQualifier.value_or("") + "']";
+
+ sysrepo::Datastore originalDS;
+ auto restoreDatastore = make_unique_resource(
+ [&]() {
+ originalDS = session.activeDatastore();
+ session.switchDatastore(sysrepo::Datastore::Operational);
+ },
+ [&]() {
+ session.switchDatastore(originalDS);
+ });
+
+ session.setItem(prefix + "/will-clear", willClear ? "true" : "false");
+ session.setItem(prefix + "/description", description);
+
+ for (const auto& severity : severities) {
+ session.setItem(prefix + "/severity-level", severity);
+ }
+
+ session.applyChanges();
+}
+
+void addResourceToAlarmInventoryEntry(sysrepo::Session session, const std::string& alarmId, const std::optional<std::string>& alarmTypeQualifier, const std::string& resource)
+{
+ const auto prefix = alarmInventory + "/alarm-type[alarm-type-id='" + alarmId + "'][alarm-type-qualifier='" + alarmTypeQualifier.value_or("") + "']";
+
+ sysrepo::Datastore originalDS;
+ auto restoreDatastore = make_unique_resource(
+ [&]() {
+ originalDS = session.activeDatastore();
+ session.switchDatastore(sysrepo::Datastore::Operational);
+ },
+ [&]() {
+ session.switchDatastore(originalDS);
+ });
+
+ session.setItem(prefix + "/resource", resource);
+ session.applyChanges();
+}
}
diff --git a/src/health/alarms/alarms.h b/src/health/alarms/alarms.h
index b5cbe73..a10a3db 100644
--- a/src/health/alarms/alarms.h
+++ b/src/health/alarms/alarms.h
@@ -10,4 +10,6 @@
namespace velia::health {
void createOrUpdateAlarm(sysrepo::Session session, const std::string& alarmId, const std::optional<std::string>& alarmQualifierType, const std::string& alarmResource, const std::string& severity, const std::string& alarmText);
+void createOrUpdateAlarmInventoryEntry(sysrepo::Session session, const std::string& alarmId, const std::optional<std::string>& alarmTypeQualifier, const std::vector<std::string>& severities, bool willClear, const std::string& description);
+void addResourceToAlarmInventoryEntry(sysrepo::Session session, const std::string& alarmId, const std::optional<std::string>& alarmTypeQualifier, const std::string& resource);
}