Instantiation of handler class
The commit adds implementation of handler class.
Mostly, oem specific implementation has been moved from manager class
to handler class.
Change-Id: Ie2a4ed3f2265b77c260c190809b18b465a81b2f9
Signed-off-by: Sunny Srivastava <sunnsr25@in.ibm.com>
diff --git a/vpd-manager/include/manager.hpp b/vpd-manager/include/manager.hpp
index 94c5693..9de9675 100644
--- a/vpd-manager/include/manager.hpp
+++ b/vpd-manager/include/manager.hpp
@@ -6,6 +6,7 @@
#include "types.hpp"
#include "worker.hpp"
+#include <oem-handler/ibm_handler.hpp>
#include <sdbusplus/asio/object_server.hpp>
namespace vpd
@@ -219,71 +220,6 @@
const std::string& i_expandedLocationCode);
private:
-#ifdef IBM_SYSTEM
- /**
- * @brief API to set timer to detect system VPD over D-Bus.
- *
- * System VPD is required before bus name for VPD-Manager is claimed. Once
- * system VPD is published, VPD for other FRUs should be collected. This API
- * detects id system VPD is already published on D-Bus and based on that
- * triggers VPD collection for rest of the FRUs.
- *
- * Note: Throws exception in case of any failure. Needs to be handled by the
- * caller.
- */
- void SetTimerToDetectSVPDOnDbus();
-
- /**
- * @brief Set timer to detect and set VPD collection status for the system.
- *
- * Collection of FRU VPD is triggered in a separate thread. Resulting in
- * multiple threads at a given time. The API creates a timer which on
- * regular interval will check if all the threads were collected back and
- * sets the status of the VPD collection for the system accordingly.
- *
- * @throw std::runtime_error
- */
- void SetTimerToDetectVpdCollectionStatus();
-
- /**
- * @brief API to register callback for "AssetTag" property change.
- */
- void registerAssetTagChangeCallback();
-
- /**
- * @brief Callback API to be triggered on "AssetTag" property change.
- *
- * @param[in] i_msg - The callback message.
- */
- void processAssetTagChangeCallback(sdbusplus::message_t& i_msg);
-
- /**
- * @brief API to process VPD collection thread failed EEPROMs.
- */
- void processFailedEeproms();
-
- /**
- * @brief API to check and update PowerVS VPD.
- *
- * The API will read the existing data from the DBus and if found
- * different than what has been read from JSON, it will update the VPD with
- * JSON data on hardware and DBus both.
- *
- * @param[in] i_powerVsJsonObj - PowerVS JSON object.
- * @param[out] o_failedPathList - List of path failed to update.
- */
- void checkAndUpdatePowerVsVpd(const nlohmann::json& i_powerVsJsonObj,
- std::vector<std::string>& o_failedPathList);
-
- /**
- * @brief API to handle configuration w.r.t. PowerVS systems.
- *
- * Some FRUs VPD is specific to powerVS system. The API detects the
- * powerVS configuration and updates the VPD accordingly.
- */
- void ConfigurePowerVsSystem();
-#endif
-
/**
* @brief An api to check validity of unexpanded location code.
*
@@ -325,6 +261,9 @@
// Shared pointer to backup and restore class
std::shared_ptr<BackupAndRestore> m_backupAndRestoreObj;
+
+ // Shared pointer to oem specific class.
+ std::shared_ptr<IbmHandler> m_ibmHandler;
};
} // namespace vpd
diff --git a/vpd-manager/oem-handler/ibm_handler.cpp b/vpd-manager/oem-handler/ibm_handler.cpp
index 14ef090..665a7af 100644
--- a/vpd-manager/oem-handler/ibm_handler.cpp
+++ b/vpd-manager/oem-handler/ibm_handler.cpp
@@ -1,6 +1,436 @@
+#include "config.h"
+
#include "ibm_handler.hpp"
+#include "parser.hpp"
+
+#include <utility/dbus_utility.hpp>
+#include <utility/json_utility.hpp>
+#include <utility/vpd_specific_utility.hpp>
+
namespace vpd
{
-// TODO: add implementation
+IbmHandler::IbmHandler(
+ std::shared_ptr<Worker>& o_worker,
+ std::shared_ptr<BackupAndRestore>& o_backupAndRestoreObj,
+ const std::shared_ptr<sdbusplus::asio::dbus_interface>& i_iFace,
+ const std::shared_ptr<boost::asio::io_context>& i_ioCon,
+ const std::shared_ptr<sdbusplus::asio::connection>& i_asioConnection) :
+ m_worker(o_worker), m_backupAndRestoreObj(o_backupAndRestoreObj),
+ m_interface(i_iFace), m_ioContext(i_ioCon),
+ m_asioConnection(i_asioConnection)
+{
+ if (dbusUtility::isChassisPowerOn())
+ {
+ // At power on, less number of FRU(s) needs collection. we can scale
+ // down the threads to reduce CPU utilization.
+ m_worker = std::make_shared<Worker>(INVENTORY_JSON_DEFAULT,
+ constants::VALUE_1);
+ }
+ else
+ {
+ // Initialize with default configuration
+ m_worker = std::make_shared<Worker>(INVENTORY_JSON_DEFAULT);
+ }
+
+ // Set up minimal things that is needed before bus name is claimed.
+ m_worker->performInitialSetup();
+
+ // Get the system config JSON object
+ m_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
+
+ if (!m_sysCfgJsonObj.empty() &&
+ jsonUtility::isBackupAndRestoreRequired(m_sysCfgJsonObj))
+ {
+ try
+ {
+ m_backupAndRestoreObj =
+ std::make_shared<BackupAndRestore>(m_sysCfgJsonObj);
+ }
+ catch (const std::exception& l_ex)
+ {
+ logging::logMessage("Back up and restore instantiation failed. {" +
+ std::string(l_ex.what()) + "}");
+
+ EventLogger::createSyncPel(
+ EventLogger::getErrorType(l_ex), types::SeverityType::Warning,
+ __FILE__, __FUNCTION__, 0, EventLogger::getErrorMsg(l_ex),
+ std::nullopt, std::nullopt, std::nullopt, std::nullopt);
+ }
+ }
+
+ // set callback to detect any asset tag change
+ registerAssetTagChangeCallback();
+
+ // set async timer to detect if system VPD is published on D-Bus.
+ SetTimerToDetectSVPDOnDbus();
+
+ // set async timer to detect if VPD collection is done.
+ SetTimerToDetectVpdCollectionStatus();
+
+ // Instantiate GpioMonitor class
+ m_gpioMonitor =
+ std::make_shared<GpioMonitor>(m_sysCfgJsonObj, m_worker, m_ioContext);
+}
+
+void IbmHandler::registerAssetTagChangeCallback()
+{
+ static std::shared_ptr<sdbusplus::bus::match_t> l_assetMatch =
+ std::make_shared<sdbusplus::bus::match_t>(
+ *m_asioConnection,
+ sdbusplus::bus::match::rules::propertiesChanged(
+ constants::systemInvPath, constants::assetTagInf),
+ [this](sdbusplus::message_t& l_msg) {
+ processAssetTagChangeCallback(l_msg);
+ });
+}
+
+void IbmHandler::processAssetTagChangeCallback(sdbusplus::message_t& i_msg)
+{
+ try
+ {
+ if (i_msg.is_method_error())
+ {
+ throw std::runtime_error(
+ "Error reading callback msg for asset tag.");
+ }
+
+ std::string l_objectPath;
+ types::PropertyMap l_propMap;
+ i_msg.read(l_objectPath, l_propMap);
+
+ const auto& l_itrToAssetTag = l_propMap.find("AssetTag");
+ if (l_itrToAssetTag != l_propMap.end())
+ {
+ if (auto l_assetTag =
+ std::get_if<std::string>(&(l_itrToAssetTag->second)))
+ {
+ // Call Notify to persist the AssetTag
+ types::ObjectMap l_objectMap = {
+ {sdbusplus::message::object_path(constants::systemInvPath),
+ {{constants::assetTagInf, {{"AssetTag", *l_assetTag}}}}}};
+
+ // Notify PIM
+ if (!dbusUtility::callPIM(move(l_objectMap)))
+ {
+ throw std::runtime_error(
+ "Call to PIM failed for asset tag update.");
+ }
+ }
+ }
+ else
+ {
+ throw std::runtime_error(
+ "Could not find asset tag in callback message.");
+ }
+ }
+ catch (const std::exception& l_ex)
+ {
+ // TODO: Log PEL with below description.
+ logging::logMessage("Asset tag callback update failed with error: " +
+ std::string(l_ex.what()));
+ }
+}
+
+void IbmHandler::SetTimerToDetectSVPDOnDbus()
+{
+ try
+ {
+ static boost::asio::steady_timer timer(*m_ioContext);
+
+ // timer for 2 seconds
+ auto asyncCancelled = timer.expires_after(std::chrono::seconds(2));
+
+ (asyncCancelled == 0) ? logging::logMessage("Timer started")
+ : logging::logMessage("Timer re-started");
+
+ timer.async_wait([this](const boost::system::error_code& ec) {
+ if (ec == boost::asio::error::operation_aborted)
+ {
+ throw std::runtime_error(
+ std::string(__FUNCTION__) +
+ ": Timer to detect system VPD collection status was aborted.");
+ }
+
+ if (ec)
+ {
+ throw std::runtime_error(
+ std::string(__FUNCTION__) +
+ ": Timer to detect System VPD collection failed");
+ }
+
+ if (m_worker->isSystemVPDOnDBus())
+ {
+ // cancel the timer
+ timer.cancel();
+
+ // Triggering FRU VPD collection. Setting status to "In
+ // Progress".
+ m_interface->set_property("CollectionStatus",
+ std::string("InProgress"));
+ m_worker->collectFrusFromJson();
+ }
+ });
+ }
+ catch (const std::exception& l_ex)
+ {
+ EventLogger::createAsyncPel(
+ EventLogger::getErrorType(l_ex), types::SeverityType::Critical,
+ __FILE__, __FUNCTION__, 0,
+ std::string("Collection for FRUs failed with reason:") +
+ EventLogger::getErrorMsg(l_ex),
+ std::nullopt, std::nullopt, std::nullopt, std::nullopt);
+ }
+}
+
+void IbmHandler::SetTimerToDetectVpdCollectionStatus()
+{
+ // Keeping max retry for 2 minutes. TODO: Make it configurable based on
+ // system type.
+ static constexpr auto MAX_RETRY = 12;
+
+ static boost::asio::steady_timer l_timer(*m_ioContext);
+ static uint8_t l_timerRetry = 0;
+
+ auto l_asyncCancelled = l_timer.expires_after(std::chrono::seconds(10));
+
+ (l_asyncCancelled == 0)
+ ? logging::logMessage("Collection Timer started")
+ : logging::logMessage("Collection Timer re-started");
+
+ l_timer.async_wait([this](const boost::system::error_code& ec) {
+ if (ec == boost::asio::error::operation_aborted)
+ {
+ throw std::runtime_error(
+ "Timer to detect thread collection status was aborted");
+ }
+
+ if (ec)
+ {
+ throw std::runtime_error(
+ "Timer to detect thread collection failed");
+ }
+
+ if (m_worker->isAllFruCollectionDone())
+ {
+ // cancel the timer
+ l_timer.cancel();
+ processFailedEeproms();
+
+ // update VPD for powerVS system.
+ ConfigurePowerVsSystem();
+
+ std::cout << "m_worker->isSystemVPDOnDBus() completed" << std::endl;
+ m_interface->set_property("CollectionStatus",
+ std::string("Completed"));
+
+ if (m_backupAndRestoreObj)
+ {
+ m_backupAndRestoreObj->backupAndRestore();
+ }
+ }
+ else
+ {
+ auto l_threadCount = m_worker->getActiveThreadCount();
+ if (l_timerRetry == MAX_RETRY)
+ {
+ l_timer.cancel();
+ logging::logMessage("Taking too long. Active thread = " +
+ std::to_string(l_threadCount));
+ }
+ else
+ {
+ l_timerRetry++;
+ logging::logMessage("Collection is in progress for [" +
+ std::to_string(l_threadCount) + "] FRUs.");
+
+ SetTimerToDetectVpdCollectionStatus();
+ }
+ }
+ });
+}
+
+void IbmHandler::checkAndUpdatePowerVsVpd(
+ const nlohmann::json& i_powerVsJsonObj,
+ std::vector<std::string>& o_failedPathList)
+{
+ for (const auto& [l_fruPath, l_recJson] : i_powerVsJsonObj.items())
+ {
+ nlohmann::json l_sysCfgJsonObj{};
+ if (m_worker.get() != nullptr)
+ {
+ l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
+ }
+
+ // The utility method will handle emty JSON case. No explicit
+ // handling required here.
+ auto l_inventoryPath = jsonUtility::getInventoryObjPathFromJson(
+ l_sysCfgJsonObj, l_fruPath);
+
+ // Mark it as failed if inventory path not found in JSON.
+ if (l_inventoryPath.empty())
+ {
+ o_failedPathList.push_back(l_fruPath);
+ continue;
+ }
+
+ // check if the FRU is present
+ if (!dbusUtility::isInventoryPresent(l_inventoryPath))
+ {
+ logging::logMessage(
+ "Inventory not present, skip updating part number. Path: " +
+ l_inventoryPath);
+ continue;
+ }
+
+ // check if the FRU needs CCIN check before updating PN.
+ if (l_recJson.contains("CCIN"))
+ {
+ const auto& l_ccinFromDbus =
+ vpdSpecificUtility::getCcinFromDbus(l_inventoryPath);
+
+ // Not an ideal situation as CCIN can't be empty.
+ if (l_ccinFromDbus.empty())
+ {
+ o_failedPathList.push_back(l_fruPath);
+ continue;
+ }
+
+ std::vector<std::string> l_ccinListFromJson = l_recJson["CCIN"];
+
+ if (find(l_ccinListFromJson.begin(), l_ccinListFromJson.end(),
+ l_ccinFromDbus) == l_ccinListFromJson.end())
+ {
+ // Don't update PN in this case.
+ continue;
+ }
+ }
+
+ for (const auto& [l_recordName, l_kwdJson] : l_recJson.items())
+ {
+ // Record name can't be CCIN, skip processing as it is there for PN
+ // update based on CCIN check.
+ if (l_recordName == constants::kwdCCIN)
+ {
+ continue;
+ }
+
+ for (const auto& [l_kwdName, l_kwdValue] : l_kwdJson.items())
+ {
+ // Is value of type array.
+ if (!l_kwdValue.is_array())
+ {
+ o_failedPathList.push_back(l_fruPath);
+ continue;
+ }
+
+ // Get current FRU Part number.
+ auto l_retVal = dbusUtility::readDbusProperty(
+ constants::pimServiceName, l_inventoryPath,
+ constants::viniInf, constants::kwdFN);
+
+ auto l_ptrToFn = std::get_if<types::BinaryVector>(&l_retVal);
+
+ if (!l_ptrToFn)
+ {
+ o_failedPathList.push_back(l_fruPath);
+ continue;
+ }
+
+ types::BinaryVector l_binaryKwdValue =
+ l_kwdValue.get<types::BinaryVector>();
+ if (l_binaryKwdValue == (*l_ptrToFn))
+ {
+ continue;
+ }
+
+ // Update part number only if required.
+ std::shared_ptr<Parser> l_parserObj =
+ std::make_shared<Parser>(l_fruPath, l_sysCfgJsonObj);
+ if (l_parserObj->updateVpdKeyword(std::make_tuple(
+ l_recordName, l_kwdName, l_binaryKwdValue)) ==
+ constants::FAILURE)
+ {
+ o_failedPathList.push_back(l_fruPath);
+ continue;
+ }
+
+ // update the Asset interface Spare part number explicitly.
+ if (!dbusUtility::callPIM(types::ObjectMap{
+ {l_inventoryPath,
+ {{constants::assetInf,
+ {{"SparePartNumber",
+ std::string(l_binaryKwdValue.begin(),
+ l_binaryKwdValue.end())}}}}}}))
+ {
+ logging::logMessage(
+ "Updating Spare Part Number under Asset interface failed for path [" +
+ l_inventoryPath + "]");
+ }
+
+ // Just needed for logging.
+ std::string l_initialPartNum((*l_ptrToFn).begin(),
+ (*l_ptrToFn).end());
+ std::string l_finalPartNum(l_binaryKwdValue.begin(),
+ l_binaryKwdValue.end());
+ logging::logMessage(
+ "FRU Part number updated for path [" + l_inventoryPath +
+ "]" + "From [" + l_initialPartNum + "]" + " to [" +
+ l_finalPartNum + "]");
+ }
+ }
+ }
+}
+
+void IbmHandler::ConfigurePowerVsSystem()
+{
+ std::vector<std::string> l_failedPathList;
+ try
+ {
+ types::BinaryVector l_imValue = dbusUtility::getImFromDbus();
+ if (l_imValue.empty())
+ {
+ throw DbusException("Invalid IM value read from Dbus");
+ }
+
+ if (!vpdSpecificUtility::isPowerVsConfiguration(l_imValue))
+ {
+ // TODO: Should booting be blocked in case of some
+ // misconfigurations?
+ return;
+ }
+
+ const nlohmann::json& l_powerVsJsonObj =
+ jsonUtility::getPowerVsJson(l_imValue);
+
+ if (l_powerVsJsonObj.empty())
+ {
+ throw std::runtime_error("PowerVS Json not found");
+ }
+
+ checkAndUpdatePowerVsVpd(l_powerVsJsonObj, l_failedPathList);
+
+ if (!l_failedPathList.empty())
+ {
+ throw std::runtime_error(
+ "Part number update failed for following paths: ");
+ }
+ }
+ catch (const std::exception& l_ex)
+ {
+ // TODO log appropriate PEL
+ }
+}
+
+void IbmHandler::processFailedEeproms()
+{
+ if (m_worker.get() != nullptr)
+ {
+ // TODO:
+ // - iterate through list of EEPROMs for which thread creation has
+ // failed
+ // - For each failed EEPROM, trigger VPD collection
+ m_worker->getFailedEepromPaths().clear();
+ }
+}
} // namespace vpd
diff --git a/vpd-manager/oem-handler/ibm_handler.hpp b/vpd-manager/oem-handler/ibm_handler.hpp
index c94b700..35b905e 100644
--- a/vpd-manager/oem-handler/ibm_handler.hpp
+++ b/vpd-manager/oem-handler/ibm_handler.hpp
@@ -1,9 +1,17 @@
#pragma once
+#include "backup_restore.hpp"
+#include "gpio_monitor.hpp"
+#include "worker.hpp"
+
+#include <sdbusplus/asio/object_server.hpp>
+
+#include <memory>
+
namespace vpd
{
/**
- * @brief Class to handle specific use case.
+ * @brief Class to handle OEM specific use case.
*
* Few pre-requisites needs to be taken case specifically, which will be
* encapsulated by this class.
@@ -20,7 +28,103 @@
/**
* @brief Constructor.
+ *
+ * @param[in] o_worker - Reference to worker class object.
+ * @param[in] o_backupAndRestoreObj - Ref to back up and restore class
+ * object.
+ * @param[in] i_iFace - interface to implement.
+ * @param[in] i_ioCon - IO context.
+ * @param[in] i_asioConnection - Dbus Connection.
*/
- IbmHandler() {}
+ IbmHandler(
+ std::shared_ptr<Worker>& o_worker,
+ std::shared_ptr<BackupAndRestore>& o_backupAndRestoreObj,
+ const std::shared_ptr<sdbusplus::asio::dbus_interface>& i_iFace,
+ const std::shared_ptr<boost::asio::io_context>& i_ioCon,
+ const std::shared_ptr<sdbusplus::asio::connection>& i_asioConnection);
+
+ private:
+ /**
+ * @brief API to set timer to detect system VPD over D-Bus.
+ *
+ * System VPD is required before bus name for VPD-Manager is claimed. Once
+ * system VPD is published, VPD for other FRUs should be collected. This API
+ * detects id system VPD is already published on D-Bus and based on that
+ * triggers VPD collection for rest of the FRUs.
+ *
+ * Note: Throws exception in case of any failure. Needs to be handled by the
+ * caller.
+ */
+ void SetTimerToDetectSVPDOnDbus();
+
+ /**
+ * @brief Set timer to detect and set VPD collection status for the system.
+ *
+ * Collection of FRU VPD is triggered in a separate thread. Resulting in
+ * multiple threads at a given time. The API creates a timer which on
+ * regular interval will check if all the threads were collected back and
+ * sets the status of the VPD collection for the system accordingly.
+ *
+ * @throw std::runtime_error
+ */
+ void SetTimerToDetectVpdCollectionStatus();
+
+ /**
+ * @brief API to register callback for "AssetTag" property change.
+ */
+ void registerAssetTagChangeCallback();
+
+ /**
+ * @brief Callback API to be triggered on "AssetTag" property change.
+ *
+ * @param[in] i_msg - The callback message.
+ */
+ void processAssetTagChangeCallback(sdbusplus::message_t& i_msg);
+
+ /**
+ * @brief API to process VPD collection thread failed EEPROMs.
+ */
+ void processFailedEeproms();
+
+ /**
+ * @brief API to check and update PowerVS VPD.
+ *
+ * The API will read the existing data from the DBus and if found
+ * different than what has been read from JSON, it will update the VPD with
+ * JSON data on hardware and DBus both.
+ *
+ * @param[in] i_powerVsJsonObj - PowerVS JSON object.
+ * @param[out] o_failedPathList - List of path failed to update.
+ */
+ void checkAndUpdatePowerVsVpd(const nlohmann::json& i_powerVsJsonObj,
+ std::vector<std::string>& o_failedPathList);
+ /**
+ * @brief API to handle configuration w.r.t. PowerVS systems.
+ *
+ * Some FRUs VPD is specific to powerVS system. The API detects the
+ * powerVS configuration and updates the VPD accordingly.
+ */
+ void ConfigurePowerVsSystem();
+
+ // Parsed system config json object.
+ nlohmann::json m_sysCfgJsonObj{};
+
+ // Shared pointer to worker class
+ std::shared_ptr<Worker>& m_worker;
+
+ // Shared pointer to backup and restore object.
+ std::shared_ptr<BackupAndRestore>& m_backupAndRestoreObj;
+
+ // Shared pointer to GpioMonitor object.
+ std::shared_ptr<GpioMonitor> m_gpioMonitor;
+
+ // Shared pointer to Dbus interface class.
+ const std::shared_ptr<sdbusplus::asio::dbus_interface>& m_interface;
+
+ // Shared pointer to asio context object.
+ const std::shared_ptr<boost::asio::io_context>& m_ioContext;
+
+ // Shared pointer to bus connection.
+ const std::shared_ptr<sdbusplus::asio::connection>& m_asioConnection;
};
} // namespace vpd
diff --git a/vpd-manager/src/manager.cpp b/vpd-manager/src/manager.cpp
index 0df9f80..979078c 100644
--- a/vpd-manager/src/manager.cpp
+++ b/vpd-manager/src/manager.cpp
@@ -43,63 +43,6 @@
try
{
-#ifdef IBM_SYSTEM
- if (dbusUtility::isChassisPowerOn())
- {
- // At power on, less number of FRU(s) needs collection. we can scale
- // down the threads to reduce CPU utilization.
- m_worker = std::make_shared<Worker>(INVENTORY_JSON_DEFAULT,
- constants::VALUE_1);
- }
- else
- {
- // Initialize with default configuration
- m_worker = std::make_shared<Worker>(INVENTORY_JSON_DEFAULT);
- }
-
- // Set up minimal things that is needed before bus name is claimed.
- m_worker->performInitialSetup();
-
- const nlohmann::json& l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
- if (!m_worker->getSysCfgJsonObj().empty() &&
- jsonUtility::isBackupAndRestoreRequired(l_sysCfgJsonObj))
- {
- try
- {
- m_backupAndRestoreObj =
- std::make_shared<BackupAndRestore>(l_sysCfgJsonObj);
- }
- catch (const std::exception& l_ex)
- {
- logging::logMessage(
- "Back up and restore instantiation failed. {" +
- std::string(l_ex.what()) + "}");
-
- EventLogger::createSyncPel(
- EventLogger::getErrorType(l_ex),
- types::SeverityType::Warning, __FILE__, __FUNCTION__, 0,
- EventLogger::getErrorMsg(l_ex), std::nullopt, std::nullopt,
- std::nullopt, std::nullopt);
- }
- }
-
- // set callback to detect any asset tag change
- registerAssetTagChangeCallback();
-
- // set async timer to detect if system VPD is published on D-Bus.
- SetTimerToDetectSVPDOnDbus();
-
- // set async timer to detect if VPD collection is done.
- SetTimerToDetectVpdCollectionStatus();
-
- // Instantiate GpioMonitor class
- m_gpioMonitor = std::make_shared<GpioMonitor>(
- m_worker->getSysCfgJsonObj(), m_worker, m_ioContext);
-
-#endif
- // set callback to detect host state change.
- registerHostStateChangeCallback();
-
// For backward compatibility. Should be depricated.
iFace->register_method(
"WriteKeyword",
@@ -186,6 +129,21 @@
return 0;
},
[this](const auto&) { return m_vpdCollectionStatus; });
+
+ // If required, instantiate OEM specific handler here.
+#ifdef IBM_SYSTEM
+ m_ibmHandler = std::make_shared<IbmHandler>(
+ m_worker, m_backupAndRestoreObj, m_interface, m_ioContext,
+ m_asioConnection);
+
+ // TODO: Move to respective handler class as this is OEM specific. To
+ // move this, collect single FRU VPD API needs to be modified. set
+ // callback to detect host state change.
+ registerHostStateChangeCallback();
+#else
+ m_worker = std::make_shared<Worker>(INVENTORY_JSON_DEFAULT);
+ m_interface->set_property("CollectionStatus", std::string("Completed"));
+#endif
}
catch (const std::exception& e)
{
@@ -199,367 +157,6 @@
}
}
-#ifdef IBM_SYSTEM
-void Manager::registerAssetTagChangeCallback()
-{
- static std::shared_ptr<sdbusplus::bus::match_t> l_assetMatch =
- std::make_shared<sdbusplus::bus::match_t>(
- *m_asioConnection,
- sdbusplus::bus::match::rules::propertiesChanged(
- constants::systemInvPath, constants::assetTagInf),
- [this](sdbusplus::message_t& l_msg) {
- processAssetTagChangeCallback(l_msg);
- });
-}
-
-void Manager::processAssetTagChangeCallback(sdbusplus::message_t& i_msg)
-{
- try
- {
- if (i_msg.is_method_error())
- {
- throw std::runtime_error(
- "Error reading callback msg for asset tag.");
- }
-
- std::string l_objectPath;
- types::PropertyMap l_propMap;
- i_msg.read(l_objectPath, l_propMap);
-
- const auto& l_itrToAssetTag = l_propMap.find("AssetTag");
- if (l_itrToAssetTag != l_propMap.end())
- {
- if (auto l_assetTag =
- std::get_if<std::string>(&(l_itrToAssetTag->second)))
- {
- // Call Notify to persist the AssetTag
- types::ObjectMap l_objectMap = {
- {sdbusplus::message::object_path(constants::systemInvPath),
- {{constants::assetTagInf, {{"AssetTag", *l_assetTag}}}}}};
-
- // Notify PIM
- if (!dbusUtility::callPIM(move(l_objectMap)))
- {
- throw std::runtime_error(
- "Call to PIM failed for asset tag update.");
- }
- }
- }
- else
- {
- throw std::runtime_error(
- "Could not find asset tag in callback message.");
- }
- }
- catch (const std::exception& l_ex)
- {
- // TODO: Log PEL with below description.
- logging::logMessage("Asset tag callback update failed with error: " +
- std::string(l_ex.what()));
- }
-}
-
-void Manager::SetTimerToDetectSVPDOnDbus()
-{
- try
- {
- static boost::asio::steady_timer timer(*m_ioContext);
-
- // timer for 2 seconds
- auto asyncCancelled = timer.expires_after(std::chrono::seconds(2));
-
- (asyncCancelled == 0) ? logging::logMessage("Timer started")
- : logging::logMessage("Timer re-started");
-
- timer.async_wait([this](const boost::system::error_code& ec) {
- if (ec == boost::asio::error::operation_aborted)
- {
- throw std::runtime_error(
- std::string(__FUNCTION__) +
- ": Timer to detect system VPD collection status was aborted.");
- }
-
- if (ec)
- {
- throw std::runtime_error(
- std::string(__FUNCTION__) +
- ": Timer to detect System VPD collection failed");
- }
-
- if (m_worker->isSystemVPDOnDBus())
- {
- // cancel the timer
- timer.cancel();
-
- // Triggering FRU VPD collection. Setting status to "In
- // Progress".
- m_interface->set_property("CollectionStatus",
- std::string("InProgress"));
- m_worker->collectFrusFromJson();
- }
- });
- }
- catch (const std::exception& l_ex)
- {
- EventLogger::createAsyncPel(
- EventLogger::getErrorType(l_ex), types::SeverityType::Critical,
- __FILE__, __FUNCTION__, 0,
- std::string("Collection for FRUs failed with reason:") +
- EventLogger::getErrorMsg(l_ex),
- std::nullopt, std::nullopt, std::nullopt, std::nullopt);
- }
-}
-
-void Manager::SetTimerToDetectVpdCollectionStatus()
-{
- // Keeping max retry for 2 minutes. TODO: Make it configurable based on
- // system type.
- static constexpr auto MAX_RETRY = 12;
-
- static boost::asio::steady_timer l_timer(*m_ioContext);
- static uint8_t l_timerRetry = 0;
-
- auto l_asyncCancelled = l_timer.expires_after(std::chrono::seconds(10));
-
- (l_asyncCancelled == 0)
- ? logging::logMessage("Collection Timer started")
- : logging::logMessage("Collection Timer re-started");
-
- l_timer.async_wait([this](const boost::system::error_code& ec) {
- if (ec == boost::asio::error::operation_aborted)
- {
- throw std::runtime_error(
- "Timer to detect thread collection status was aborted");
- }
-
- if (ec)
- {
- throw std::runtime_error(
- "Timer to detect thread collection failed");
- }
-
- if (m_worker->isAllFruCollectionDone())
- {
- // cancel the timer
- l_timer.cancel();
- processFailedEeproms();
-
- // update VPD for powerVS system.
- ConfigurePowerVsSystem();
-
- m_interface->set_property("CollectionStatus",
- std::string("Completed"));
-
- if (m_backupAndRestoreObj)
- {
- m_backupAndRestoreObj->backupAndRestore();
- }
- }
- else
- {
- auto l_threadCount = m_worker->getActiveThreadCount();
- if (l_timerRetry == MAX_RETRY)
- {
- l_timer.cancel();
- logging::logMessage("Taking too long. Active thread = " +
- std::to_string(l_threadCount));
- }
- else
- {
- l_timerRetry++;
- logging::logMessage("Collection is in progress for [" +
- std::to_string(l_threadCount) + "] FRUs.");
-
- SetTimerToDetectVpdCollectionStatus();
- }
- }
- });
-}
-
-void Manager::checkAndUpdatePowerVsVpd(
- const nlohmann::json& i_powerVsJsonObj,
- std::vector<std::string>& o_failedPathList)
-{
- for (const auto& [l_fruPath, l_recJson] : i_powerVsJsonObj.items())
- {
- nlohmann::json l_sysCfgJsonObj{};
- if (m_worker.get() != nullptr)
- {
- l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
- }
-
- // The utility method will handle emty JSON case. No explicit
- // handling required here.
- auto l_inventoryPath = jsonUtility::getInventoryObjPathFromJson(
- l_sysCfgJsonObj, l_fruPath);
-
- // Mark it as failed if inventory path not found in JSON.
- if (l_inventoryPath.empty())
- {
- o_failedPathList.push_back(l_fruPath);
- continue;
- }
-
- // check if the FRU is present
- if (!dbusUtility::isInventoryPresent(l_inventoryPath))
- {
- logging::logMessage(
- "Inventory not present, skip updating part number. Path: " +
- l_inventoryPath);
- continue;
- }
-
- // check if the FRU needs CCIN check before updating PN.
- if (l_recJson.contains("CCIN"))
- {
- const auto& l_ccinFromDbus =
- vpdSpecificUtility::getCcinFromDbus(l_inventoryPath);
-
- // Not an ideal situation as CCIN can't be empty.
- if (l_ccinFromDbus.empty())
- {
- o_failedPathList.push_back(l_fruPath);
- continue;
- }
-
- std::vector<std::string> l_ccinListFromJson = l_recJson["CCIN"];
-
- if (find(l_ccinListFromJson.begin(), l_ccinListFromJson.end(),
- l_ccinFromDbus) == l_ccinListFromJson.end())
- {
- // Don't update PN in this case.
- continue;
- }
- }
-
- for (const auto& [l_recordName, l_kwdJson] : l_recJson.items())
- {
- // Record name can't be CCIN, skip processing as it is there for PN
- // update based on CCIN check.
- if (l_recordName == constants::kwdCCIN)
- {
- continue;
- }
-
- for (const auto& [l_kwdName, l_kwdValue] : l_kwdJson.items())
- {
- // Is value of type array.
- if (!l_kwdValue.is_array())
- {
- o_failedPathList.push_back(l_fruPath);
- continue;
- }
-
- // Get current FRU Part number.
- auto l_retVal = dbusUtility::readDbusProperty(
- constants::pimServiceName, l_inventoryPath,
- constants::viniInf, constants::kwdFN);
-
- auto l_ptrToFn = std::get_if<types::BinaryVector>(&l_retVal);
-
- if (!l_ptrToFn)
- {
- o_failedPathList.push_back(l_fruPath);
- continue;
- }
-
- types::BinaryVector l_binaryKwdValue =
- l_kwdValue.get<types::BinaryVector>();
- if (l_binaryKwdValue == (*l_ptrToFn))
- {
- continue;
- }
-
- // Update part number only if required.
- if (updateKeyword(
- l_fruPath,
- std::make_tuple(l_recordName, l_kwdName, l_kwdValue)) ==
- constants::FAILURE)
- {
- o_failedPathList.push_back(l_fruPath);
- continue;
- }
-
- // update the Asset interface Spare part number explicitly.
- if (!dbusUtility::callPIM(types::ObjectMap{
- {l_inventoryPath,
- {{constants::assetInf,
- {{"SparePartNumber",
- std::string(l_binaryKwdValue.begin(),
- l_binaryKwdValue.end())}}}}}}))
- {
- logging::logMessage(
- "Updating Spare Part Number under Asset interface failed for path [" +
- l_inventoryPath + "]");
- }
-
- // Just needed for logging.
- std::string l_initialPartNum((*l_ptrToFn).begin(),
- (*l_ptrToFn).end());
- std::string l_finalPartNum(l_binaryKwdValue.begin(),
- l_binaryKwdValue.end());
- logging::logMessage(
- "FRU Part number updated for path [" + l_inventoryPath +
- "]" + "From [" + l_initialPartNum + "]" + " to [" +
- l_finalPartNum + "]");
- }
- }
- }
-}
-
-void Manager::ConfigurePowerVsSystem()
-{
- std::vector<std::string> l_failedPathList;
- try
- {
- types::BinaryVector l_imValue = dbusUtility::getImFromDbus();
- if (l_imValue.empty())
- {
- throw DbusException("Invalid IM value read from Dbus");
- }
-
- if (!vpdSpecificUtility::isPowerVsConfiguration(l_imValue))
- {
- // TODO: Should booting be blocked in case of some
- // misconfigurations?
- return;
- }
-
- const nlohmann::json& l_powerVsJsonObj =
- jsonUtility::getPowerVsJson(l_imValue);
-
- if (l_powerVsJsonObj.empty())
- {
- throw std::runtime_error("PowerVS Json not found");
- }
-
- checkAndUpdatePowerVsVpd(l_powerVsJsonObj, l_failedPathList);
-
- if (!l_failedPathList.empty())
- {
- throw std::runtime_error(
- "Part number update failed for following paths: ");
- }
- }
- catch (const std::exception& l_ex)
- {
- // TODO log appropriate PEL
- }
-}
-
-void Manager::processFailedEeproms()
-{
- if (m_worker.get() != nullptr)
- {
- // TODO:
- // - iterate through list of EEPROMs for which thread creation has
- // failed
- // - For each failed EEPROM, trigger VPD collection
- m_worker->getFailedEepromPaths().clear();
- }
-}
-#endif
-
int Manager::updateKeyword(const types::Path i_vpdPath,
const types::WriteVpdParams i_paramsToWriteData)
{