hardware: push multiple alarm-inventory resources at once
So far we were pushing to sysrepo each alarm-inventory change
separately. Unfortunately this is a computing intensive operations for
large data so we have to optimise it a bit.
This patch modified the class talking to sysrepo about hardware changes.
It now "caches" modifications of resources for an alarm and then pushes
them at once.
There is still a space for a small improvement: After this patch we
create one edit per alarm. This basically gets us with 4 calls (we have
4 alarms) for any change. I think this can be merged into one.
I don't think it is worth doing it now (the alarm-inventory does not
change that much for hardware related alarms). But of course, I can be
wrong.
I had to make some testing changes: all component paths were wrapped by
the COMPONENT macro inside another macro. Now we push more resources at
once and I don't know how to basically call a map function on
__VA_ARGS__ so I am wrapping all the components with COMPONENT manually
inside any macro call.
Change-Id: I9a77dde04e72011a25d6f6e7539fb9b81269e933
diff --git a/src/ietf-hardware/sysrepo/Sysrepo.cpp b/src/ietf-hardware/sysrepo/Sysrepo.cpp
index 4e20e73..8b830ce 100644
--- a/src/ietf-hardware/sysrepo/Sysrepo.cpp
+++ b/src/ietf-hardware/sysrepo/Sysrepo.cpp
@@ -105,18 +105,22 @@
auto [hwStateValues, thresholds, activeSensors, sideLoadedAlarms] = m_hwState->process();
std::set<std::string> deletedComponents;
+ std::vector<std::string> newSensors;
for (const auto& sensorXPath : activeSensors) {
if (!seenSensors.contains(sensorXPath)) {
- auto componentXPath = extractComponentPrefix(sensorXPath);
- alarms::addResourcesToInventory(m_session, ALARM_THRESHOLD_CROSSING_LOW, {componentXPath});
- alarms::addResourcesToInventory(m_session, ALARM_THRESHOLD_CROSSING_HIGH, {componentXPath});
- alarms::addResourcesToInventory(m_session, ALARM_SENSOR_MISSING, {componentXPath});
- alarms::addResourcesToInventory(m_session, ALARM_SENSOR_NONOPERATIONAL, {componentXPath});
+ newSensors.emplace_back(extractComponentPrefix(sensorXPath));
}
}
seenSensors.merge(activeSensors);
+ if (!newSensors.empty()) {
+ alarms::addResourcesToInventory(m_session, ALARM_THRESHOLD_CROSSING_LOW, newSensors);
+ alarms::addResourcesToInventory(m_session, ALARM_THRESHOLD_CROSSING_HIGH, newSensors);
+ alarms::addResourcesToInventory(m_session, ALARM_SENSOR_MISSING, newSensors);
+ alarms::addResourcesToInventory(m_session, ALARM_SENSOR_NONOPERATIONAL, newSensors);
+ }
+
/* Some data readers can stop returning data in some cases (e.g. ejected PSU).
* Prune tree components that were removed before updating to avoid having not current data from previous invocations.
*/
diff --git a/tests/health_systemd-units.cpp b/tests/health_systemd-units.cpp
index fc7929e..48e0856 100644
--- a/tests/health_systemd-units.cpp
+++ b/tests/health_systemd-units.cpp
@@ -22,7 +22,7 @@
using namespace std::chrono_literals;
#define REQUIRE_NEW_ALARM_INVENTORY_UNIT(UNIT) \
- REQUIRE_NEW_ALARM_INVENTORY_RESOURCE(alarmsWatcher, "velia-alarms:systemd-unit-failure", "", UNIT)
+ REQUIRE_NEW_ALARM_INVENTORY_RESOURCE(alarmsWatcher, "velia-alarms:systemd-unit-failure", "", std::set<std::string>{UNIT})
#define REQUIRE_ALARM_RPC(UNIT, SEVERITY, TEXT) \
REQUIRE_NEW_ALARM(alarmsWatcher, "velia-alarms:systemd-unit-failure", "", UNIT, SEVERITY, TEXT)
diff --git a/tests/sysrepo-helpers/alarms.h b/tests/sysrepo-helpers/alarms.h
index 4267388..63e86fb 100644
--- a/tests/sysrepo-helpers/alarms.h
+++ b/tests/sysrepo-helpers/alarms.h
@@ -15,7 +15,13 @@
#include "sysrepo-helpers/rpc.h"
#include "test_log_setup.h"
-inline ValueChanges constructAlarmInventoryChange(const std::string& alarmType,
+enum class EntryAction {
+ Create,
+ Update,
+};
+
+inline ValueChanges constructAlarmInventoryChange(EntryAction action,
+ const std::string& alarmType,
const std::string& alarmQualifier,
const std::set<std::string>& resources,
const std::set<std::string>& severities,
@@ -24,10 +30,12 @@
{
const std::string prefix = "/ietf-alarms:alarms/alarm-inventory/alarm-type[alarm-type-id='" + alarmType + "'][alarm-type-qualifier='" + alarmQualifier + "']";
- ValueChanges ret{
- {prefix + "/alarm-type-id", alarmType},
- {prefix + "/alarm-type-qualifier", alarmQualifier},
- };
+ ValueChanges ret;
+
+ if (action == EntryAction::Create) {
+ ret.emplace(prefix + "/alarm-type-id", alarmType);
+ ret.emplace(prefix + "/alarm-type-qualifier", alarmQualifier);
+ }
if (willClear) {
ret.emplace(prefix + "/will-clear", *willClear ? "true" : "false");
@@ -85,18 +93,12 @@
LR_SIDE_EFFECT(INV.add(ALARM_TYPE, ALARM_QUALIFIER, RESOURCE, SEVERITIES))
#define REQUIRE_NEW_ALARM_INVENTORY_ENTRY(WATCHER, ALARM_TYPE, ALARM_QUALIFIER, RESOURCES, SEVERITIES, WILL_CLEAR, DESCRIPTION) \
- REQUIRE_DATASTORE_CHANGE(WATCHER.datastoreWatcher, \
- constructAlarmInventoryChange(ALARM_TYPE, ALARM_QUALIFIER, RESOURCES, SEVERITIES, WILL_CLEAR, DESCRIPTION)) \
+ REQUIRE_DATASTORE_CHANGE(WATCHER.datastoreWatcher, constructAlarmInventoryChange(EntryAction::Create, ALARM_TYPE, ALARM_QUALIFIER, RESOURCES, SEVERITIES, WILL_CLEAR, DESCRIPTION)) \
.INSERT_INTO_INVENTORY(WATCHER.alarmInventory, ALARM_TYPE, ALARM_QUALIFIER, RESOURCES, SEVERITIES)
-#define REQUIRE_NEW_ALARM_INVENTORY_RESOURCE(WATCHER, ALARM_TYPE, ALARM_QUALIFIER, RESOURCE) \
- REQUIRE_DATASTORE_CHANGE(WATCHER.datastoreWatcher, \
- (ValueChanges{ \
- {"/ietf-alarms:alarms/alarm-inventory/alarm-type" \
- "[alarm-type-id='" ALARM_TYPE "'][alarm-type-qualifier='" ALARM_QUALIFIER "']/resource[1]", \
- RESOURCE}, \
- })) \
- .INSERT_INTO_INVENTORY(WATCHER.alarmInventory, ALARM_TYPE, ALARM_QUALIFIER, (std::set<std::string>{RESOURCE}), (std::set<std::string>{}))
+#define REQUIRE_NEW_ALARM_INVENTORY_RESOURCE(WATCHER, ALARM_TYPE, ALARM_QUALIFIER, RESOURCES) \
+ REQUIRE_DATASTORE_CHANGE(WATCHER.datastoreWatcher, constructAlarmInventoryChange(EntryAction::Update, ALARM_TYPE, ALARM_QUALIFIER, RESOURCES, {}, std::nullopt, std::nullopt)) \
+ .INSERT_INTO_INVENTORY(WATCHER.alarmInventory, ALARM_TYPE, ALARM_QUALIFIER, RESOURCES, (std::set<std::string>{}))
#define REQUIRE_NEW_ALARM(WATCHER, ALARM_TYPE, ALARM_QUALIFIER, RESOURCE, SEVERITY, TEXT) \
REQUIRE_RPC_CALL(WATCHER.rpcWatcher, (Values{ \
diff --git a/tests/sysrepo_ietf-hardware.cpp b/tests/sysrepo_ietf-hardware.cpp
index 43d375f..a859453 100644
--- a/tests/sysrepo_ietf-hardware.cpp
+++ b/tests/sysrepo_ietf-hardware.cpp
@@ -19,8 +19,8 @@
REQUIRE_NEW_ALARM_INVENTORY_ENTRY(alarmWatcher, ALARM_TYPE, "", (std::set<std::string>{}), \
(std::set<std::string>{}), true, DESCRIPTION)
-#define REQUIRE_ALARM_INVENTORY_ADD_RESOURCE(ALARM_TYPE, RESOURCE) \
- REQUIRE_NEW_ALARM_INVENTORY_RESOURCE(alarmWatcher, ALARM_TYPE, "", COMPONENT(RESOURCE))
+#define REQUIRE_ALARM_INVENTORY_ADD_RESOURCES(ALARM_TYPE, ...) \
+ REQUIRE_NEW_ALARM_INVENTORY_RESOURCE(alarmWatcher, ALARM_TYPE, "", (std::set<std::string>{__VA_ARGS__}))
#define REQUIRE_ALARM_RPC(ALARM_TYPE, RESOURCE, SEVERITY, TEXT) \
REQUIRE_NEW_ALARM(alarmWatcher, ALARM_TYPE, "", COMPONENT(RESOURCE), SEVERITY, TEXT)
@@ -143,20 +143,10 @@
REQUIRE_ALARM_INVENTORY_ADD_ALARM("velia-alarms:sensor-missing-alarm", "Sensor is missing.").IN_SEQUENCE(seq1);
REQUIRE_ALARM_INVENTORY_ADD_ALARM("velia-alarms:sensor-nonoperational", "Sensor is flagged as nonoperational.").IN_SEQUENCE(seq1);
- REQUIRE_ALARM_INVENTORY_ADD_RESOURCE("velia-alarms:sensor-low-value-alarm", "ne:power").IN_SEQUENCE(seq1);
- REQUIRE_ALARM_INVENTORY_ADD_RESOURCE("velia-alarms:sensor-high-value-alarm", "ne:power").IN_SEQUENCE(seq1);
- REQUIRE_ALARM_INVENTORY_ADD_RESOURCE("velia-alarms:sensor-missing-alarm", "ne:power").IN_SEQUENCE(seq1);
- REQUIRE_ALARM_INVENTORY_ADD_RESOURCE("velia-alarms:sensor-nonoperational", "ne:power").IN_SEQUENCE(seq1);
-
- REQUIRE_ALARM_INVENTORY_ADD_RESOURCE("velia-alarms:sensor-low-value-alarm", "ne:psu:child").IN_SEQUENCE(seq1);
- REQUIRE_ALARM_INVENTORY_ADD_RESOURCE("velia-alarms:sensor-high-value-alarm", "ne:psu:child").IN_SEQUENCE(seq1);
- REQUIRE_ALARM_INVENTORY_ADD_RESOURCE("velia-alarms:sensor-missing-alarm", "ne:psu:child").IN_SEQUENCE(seq1);
- REQUIRE_ALARM_INVENTORY_ADD_RESOURCE("velia-alarms:sensor-nonoperational", "ne:psu:child").IN_SEQUENCE(seq1);
-
- REQUIRE_ALARM_INVENTORY_ADD_RESOURCE("velia-alarms:sensor-low-value-alarm", "ne:temperature-cpu").IN_SEQUENCE(seq1);
- REQUIRE_ALARM_INVENTORY_ADD_RESOURCE("velia-alarms:sensor-high-value-alarm", "ne:temperature-cpu").IN_SEQUENCE(seq1);
- REQUIRE_ALARM_INVENTORY_ADD_RESOURCE("velia-alarms:sensor-missing-alarm", "ne:temperature-cpu").IN_SEQUENCE(seq1);
- REQUIRE_ALARM_INVENTORY_ADD_RESOURCE("velia-alarms:sensor-nonoperational", "ne:temperature-cpu").IN_SEQUENCE(seq1);
+ REQUIRE_ALARM_INVENTORY_ADD_RESOURCES("velia-alarms:sensor-low-value-alarm", COMPONENT("ne:power"), COMPONENT("ne:psu:child"), COMPONENT("ne:temperature-cpu")).IN_SEQUENCE(seq1);
+ REQUIRE_ALARM_INVENTORY_ADD_RESOURCES("velia-alarms:sensor-high-value-alarm", COMPONENT("ne:power"), COMPONENT("ne:psu:child"), COMPONENT("ne:temperature-cpu")).IN_SEQUENCE(seq1);
+ REQUIRE_ALARM_INVENTORY_ADD_RESOURCES("velia-alarms:sensor-missing-alarm", COMPONENT("ne:power"), COMPONENT("ne:psu:child"), COMPONENT("ne:temperature-cpu")).IN_SEQUENCE(seq1);
+ REQUIRE_ALARM_INVENTORY_ADD_RESOURCES("velia-alarms:sensor-nonoperational", COMPONENT("ne:power"), COMPONENT("ne:psu:child"), COMPONENT("ne:temperature-cpu")).IN_SEQUENCE(seq1);
REQUIRE_DATASTORE_CHANGE(dsChangeHardware, (ValueChanges{
{COMPONENT("ne") "/class", "iana-hardware:chassis"},
@@ -196,7 +186,7 @@
{COMPONENT("ne:temperature-cpu") "/state/oper-state", "enabled"},
}))
.IN_SEQUENCE(seq1);
- REQUIRE_ALARM_INVENTORY_ADD_RESOURCE("velia-alarms:sensor-missing-alarm", "ne:psu").TIMES(AT_LEAST(1));
+ REQUIRE_ALARM_INVENTORY_ADD_RESOURCES("velia-alarms:sensor-missing-alarm", COMPONENT("ne:psu")).TIMES(AT_LEAST(1));
REQUIRE_ALARM_RPC("velia-alarms:sensor-low-value-alarm", "ne:power", "critical", "Sensor value crossed low threshold.").IN_SEQUENCE(seq1);
auto ietfHardwareSysrepo = std::make_shared<velia::ietf_hardware::sysrepo::Sysrepo>(srSess, ietfHardware, 150ms);
@@ -355,15 +345,10 @@
REQUIRE_ALARM_INVENTORY_ADD_ALARM("velia-alarms:sensor-missing-alarm", "Sensor is missing.").IN_SEQUENCE(seq1);
REQUIRE_ALARM_INVENTORY_ADD_ALARM("velia-alarms:sensor-nonoperational", "Sensor is flagged as nonoperational.").IN_SEQUENCE(seq1);
- REQUIRE_ALARM_INVENTORY_ADD_RESOURCE("velia-alarms:sensor-low-value-alarm", "ne:power").IN_SEQUENCE(seq1);
- REQUIRE_ALARM_INVENTORY_ADD_RESOURCE("velia-alarms:sensor-high-value-alarm", "ne:power").IN_SEQUENCE(seq1);
- REQUIRE_ALARM_INVENTORY_ADD_RESOURCE("velia-alarms:sensor-missing-alarm", "ne:power").IN_SEQUENCE(seq1);
- REQUIRE_ALARM_INVENTORY_ADD_RESOURCE("velia-alarms:sensor-nonoperational", "ne:power").IN_SEQUENCE(seq1);
-
- REQUIRE_ALARM_INVENTORY_ADD_RESOURCE("velia-alarms:sensor-low-value-alarm", "ne:temperature-cpu").IN_SEQUENCE(seq1);
- REQUIRE_ALARM_INVENTORY_ADD_RESOURCE("velia-alarms:sensor-high-value-alarm", "ne:temperature-cpu").IN_SEQUENCE(seq1);
- REQUIRE_ALARM_INVENTORY_ADD_RESOURCE("velia-alarms:sensor-missing-alarm", "ne:temperature-cpu").IN_SEQUENCE(seq1);
- REQUIRE_ALARM_INVENTORY_ADD_RESOURCE("velia-alarms:sensor-nonoperational", "ne:temperature-cpu").IN_SEQUENCE(seq1);
+ REQUIRE_ALARM_INVENTORY_ADD_RESOURCES("velia-alarms:sensor-low-value-alarm", COMPONENT("ne:power"), COMPONENT("ne:temperature-cpu")).IN_SEQUENCE(seq1);
+ REQUIRE_ALARM_INVENTORY_ADD_RESOURCES("velia-alarms:sensor-high-value-alarm", COMPONENT("ne:power"), COMPONENT("ne:temperature-cpu")).IN_SEQUENCE(seq1);
+ REQUIRE_ALARM_INVENTORY_ADD_RESOURCES("velia-alarms:sensor-missing-alarm", COMPONENT("ne:power"), COMPONENT("ne:temperature-cpu")).IN_SEQUENCE(seq1);
+ REQUIRE_ALARM_INVENTORY_ADD_RESOURCES("velia-alarms:sensor-nonoperational", COMPONENT("ne:power"), COMPONENT("ne:temperature-cpu")).IN_SEQUENCE(seq1);
REQUIRE_DATASTORE_CHANGE(dsChangeHardware, (ValueChanges{
{COMPONENT("ne") "/class", "iana-hardware:chassis"},
@@ -394,7 +379,7 @@
{COMPONENT("ne:temperature-cpu") "/state/oper-state", "enabled"},
}))
.IN_SEQUENCE(seq1);
- REQUIRE_ALARM_INVENTORY_ADD_RESOURCE("velia-alarms:sensor-missing-alarm", "ne:psu").TIMES(AT_LEAST(1));
+ REQUIRE_ALARM_INVENTORY_ADD_RESOURCES("velia-alarms:sensor-missing-alarm", COMPONENT("ne:psu")).TIMES(AT_LEAST(1));
REQUIRE_ALARM_RPC("velia-alarms:sensor-missing-alarm", "ne:psu", "critical", "PSU missing.").IN_SEQUENCE(seq1);
REQUIRE_ALARM_RPC("velia-alarms:sensor-low-value-alarm", "ne:power", "critical", "Sensor value crossed low threshold.").IN_SEQUENCE(seq1);
@@ -405,10 +390,10 @@
std::string lastChange = directLeafNodeQuery(modulePrefix + "/last-change");
// PSU inserted
- REQUIRE_ALARM_INVENTORY_ADD_RESOURCE("velia-alarms:sensor-low-value-alarm", "ne:psu:child").IN_SEQUENCE(seq1);
- REQUIRE_ALARM_INVENTORY_ADD_RESOURCE("velia-alarms:sensor-high-value-alarm", "ne:psu:child").IN_SEQUENCE(seq1);
- REQUIRE_ALARM_INVENTORY_ADD_RESOURCE("velia-alarms:sensor-missing-alarm", "ne:psu:child").IN_SEQUENCE(seq1);
- REQUIRE_ALARM_INVENTORY_ADD_RESOURCE("velia-alarms:sensor-nonoperational", "ne:psu:child").IN_SEQUENCE(seq1);
+ REQUIRE_ALARM_INVENTORY_ADD_RESOURCES("velia-alarms:sensor-low-value-alarm", COMPONENT("ne:psu:child")).IN_SEQUENCE(seq1);
+ REQUIRE_ALARM_INVENTORY_ADD_RESOURCES("velia-alarms:sensor-high-value-alarm", COMPONENT("ne:psu:child")).IN_SEQUENCE(seq1);
+ REQUIRE_ALARM_INVENTORY_ADD_RESOURCES("velia-alarms:sensor-missing-alarm", COMPONENT("ne:psu:child")).IN_SEQUENCE(seq1);
+ REQUIRE_ALARM_INVENTORY_ADD_RESOURCES("velia-alarms:sensor-nonoperational", COMPONENT("ne:psu:child")).IN_SEQUENCE(seq1);
REQUIRE_DATASTORE_CHANGE(dsChangeHardware, (ValueChanges{
{COMPONENT("ne:psu") "/state/oper-state", "enabled"},
{COMPONENT("ne:psu:child") "/class", "iana-hardware:sensor"},