Listener:Implement Present property callback
This commit implements Present property callback in Listener. For
hotPluggable FRUs whose present property is toggled by external
application based on their actual presence detection, vpd-manager needs
to monitor "Present" property and collect/delete FRU VPD accordingly.
Test:
```
- On Everest system, toggle Present property of fan0 from busctl
- Observer callback getting triggered
```
Change-Id: Ia558306417adf18155b5b363fc9caa797bda250f
Signed-off-by: Souvik Roy <souvikroyofficial10@gmail.com>
diff --git a/vpd-manager/include/listener.hpp b/vpd-manager/include/listener.hpp
index 719c21d..f387d5e 100644
--- a/vpd-manager/include/listener.hpp
+++ b/vpd-manager/include/listener.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include "types.hpp"
#include "worker.hpp"
#include <sdbusplus/asio/object_server.hpp>
@@ -80,5 +81,8 @@
// Shared pointer to bus connection.
const std::shared_ptr<sdbusplus::asio::connection>& m_asioConnection;
+
+ // Map of inventory path to Present property match object
+ types::FruPresenceMatchObjectMap m_fruPresenceMatchObjectMap;
};
} // namespace vpd
diff --git a/vpd-manager/include/types.hpp b/vpd-manager/include/types.hpp
index 1ea8f09..31d0085 100644
--- a/vpd-manager/include/types.hpp
+++ b/vpd-manager/include/types.hpp
@@ -204,5 +204,7 @@
using InvalidRecordEntry = std::pair<Record,ErrorType>;
/* List of invalid record entries*/
using InvalidRecordList = std::vector<InvalidRecordEntry>;
+/* Map of inventory path -> Present property match object */
+using FruPresenceMatchObjectMap = std::map<Path, std::shared_ptr<sdbusplus::bus::match::match>>;
} // namespace types
} // namespace vpd
diff --git a/vpd-manager/include/utility/json_utility.hpp b/vpd-manager/include/utility/json_utility.hpp
index 9a78b68..4bf3846 100644
--- a/vpd-manager/include/utility/json_utility.hpp
+++ b/vpd-manager/include/utility/json_utility.hpp
@@ -1158,5 +1158,45 @@
return nlohmann::json{};
}
}
+
+/**
+ * @brief API to get list of FRUs for which "monitorPresence" is true.
+ *
+ * @param[in] i_sysCfgJsonObj - System config JSON object.
+ *
+ * @return On success, returns list of FRUs for which "monitorPresence" is true,
+ * empty list on error.
+ */
+inline std::vector<types::Path> getFrusWithPresenceMonitoring(
+ const nlohmann::json& i_sysCfgJsonObj) noexcept
+{
+ std::vector<types::Path> l_frusWithPresenceMonitoring;
+ try
+ {
+ if (!i_sysCfgJsonObj.contains("frus"))
+ {
+ throw JsonException("Missing frus tag in system config JSON.");
+ }
+
+ const nlohmann::json& l_listOfFrus =
+ i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
+
+ for (const auto& l_aFru : l_listOfFrus)
+ {
+ if (l_aFru.at(0).value("monitorPresence", false))
+ {
+ l_frusWithPresenceMonitoring.emplace_back(
+ l_aFru.at(0).value("inventoryPath", ""));
+ }
+ }
+ }
+ catch (const std::exception& l_ex)
+ {
+ logging::logMessage(
+ "Failed to get list of FRUs with presence monitoring, error: " +
+ std::string(l_ex.what()));
+ }
+ return l_frusWithPresenceMonitoring;
+}
} // namespace jsonUtility
} // namespace vpd
diff --git a/vpd-manager/src/listener.cpp b/vpd-manager/src/listener.cpp
index a95be64..49825fd 100644
--- a/vpd-manager/src/listener.cpp
+++ b/vpd-manager/src/listener.cpp
@@ -1,7 +1,9 @@
#include "listener.hpp"
+#include "constants.hpp"
#include "event_logger.hpp"
#include "utility/dbus_utility.hpp"
+#include "utility/json_utility.hpp"
namespace vpd
{
@@ -167,11 +169,24 @@
{
try
{
- /* TODO:
- - iterate through all FRUs.
- - if FRU is runtime replaceable and we do not handle presence for
- the FRU, register a Present property change callback.
- */
+ // get list of FRUs for which presence monitoring is required
+ const auto& l_listOfFrus = jsonUtility::getFrusWithPresenceMonitoring(
+ m_worker->getSysCfgJsonObj());
+
+ for (const auto& l_inventoryPath : l_listOfFrus)
+ {
+ std::shared_ptr<sdbusplus::bus::match_t> l_fruPresenceMatch =
+ std::make_shared<sdbusplus::bus::match_t>(
+ *m_asioConnection,
+ sdbusplus::bus::match::rules::propertiesChanged(
+ l_inventoryPath, constants::inventoryItemInf),
+ [this](sdbusplus::message_t& i_msg) {
+ presentPropertyChangeCallback(i_msg);
+ });
+
+ // save the match object to map
+ m_fruPresenceMatchObjectMap[l_inventoryPath] = l_fruPresenceMatch;
+ }
}
catch (const std::exception& l_ex)
{
@@ -195,14 +210,29 @@
"Error reading callback message for Present property change");
}
- const auto& l_objectPath = i_msg.get_path();
- (void)l_objectPath;
- /*TODO:
- - read "Present" property
- - if "Present" property = true, trigger "collectSingleFruVpd" for the
- FRU
- - if "Present" property = false, trigger "deleteFruVpd" for the FRU
- */
+ std::string l_interface;
+ types::PropertyMap l_propMap;
+ i_msg.read(l_interface, l_propMap);
+
+ const std::string l_objectPath{i_msg.get_path()};
+
+ const auto l_itr = l_propMap.find("Present");
+ if (l_itr == l_propMap.end())
+ {
+ // Present is not found in the callback message
+ return;
+ }
+
+ if (auto l_present = std::get_if<bool>(&(l_itr->second)))
+ {
+ *l_present ? m_worker->collectSingleFruVpd(l_objectPath)
+ : m_worker->deleteFruVpd(l_objectPath);
+ }
+ else
+ {
+ throw DbusException(
+ "Invalid type recieved in variant for present property");
+ }
}
catch (const std::exception& l_ex)
{