Add inventory call out in PEL
In case there is any ECC mismatch found while processing a record, a
predictive PEL is being logged. To detect the FRU for which this
happened along with next action to be performed, inventory call out is
being added to the PEL and description is being updated with next
action to be performed.
Change-Id: I92e507fca3b724a42f37ada6fe05b41750a04072
Signed-off-by: Sunny Srivastava <sunnsr25@in.ibm.com>
diff --git a/vpd-manager/include/event_logger.hpp b/vpd-manager/include/event_logger.hpp
index 65399e9..cc5e9d2 100644
--- a/vpd-manager/include/event_logger.hpp
+++ b/vpd-manager/include/event_logger.hpp
@@ -190,14 +190,54 @@
const std::optional<std::string> i_symFru,
const std::optional<std::string> i_procedure);
+ /**
+ * @brief An API to create a synchronus PEL with inventory path callout.
+ *
+ * This API calls phosphor-logging method to create PEL, and also handles
+ * inventory path callout. In case called with EEPROM path, will look for
+ * JSON at symbolic link and if present will fetch inventory path for that
+ * EEPROM.
+ *
+ * Note: In case of any error in fetching JSON or converting the EEPROM
+ * path, the API will log PEL with path passed in callout parameter.
+ * If inventory/EEPROM path is not provided in the callout, it will create
+ * PEL without call out. Currently only one callout is handled in this API.
+ *
+ * @todo: Symbolic FRU and procedure callout needs to be handled in this
+ * API.
+ *
+ * @param[in] i_errorType - Enum to map with event message name.
+ * @param[in] i_severity - Severity of the event.
+ * @param[in] i_fileName - File name.
+ * @param[in] i_funcName - Function name.
+ * @param[in] i_internalRc - Internal return code.
+ * @param[in] i_description - Error description.
+ * @param[in] i_callouts - Callout information.
+ * @param[in] i_userData1 - Additional user data [optional].
+ * @param[in] i_userData2 - Additional user data [optional].
+ * @param[in] i_symFru - Symblolic FRU callout data [optional].
+ * @param[in] i_procedure - Procedure callout data [optional].
+ *
+ */
+ static void createSyncPelWithInvCallOut(
+ const types::ErrorType& i_errorType,
+ const types::SeverityType& i_severity, const std::string& i_fileName,
+ const std::string& i_funcName, const uint8_t i_internalRc,
+ const std::string& i_description,
+ const std::vector<types::InventoryCalloutData>& i_callouts,
+ const std::optional<std::string> i_userData1,
+ const std::optional<std::string> i_userData2,
+ [[maybe_unused]] const std::optional<std::string> i_symFru,
+ [[maybe_unused]] const std::optional<std::string> i_procedure);
+
private:
/**
* @brief API to get error info based on the exception.
*
* @param[in] i_exception - Exception object.
*
- * @return - Valid ExceptionDataMap on success, otherwise map having default
- * value.
+ * @return - Valid ExceptionDataMap on success, otherwise map having
+ * default value.
*/
static types::ExceptionDataMap getExceptionData(
const std::exception& i_exception);
diff --git a/vpd-manager/src/event_logger.cpp b/vpd-manager/src/event_logger.cpp
index a114df5..6b91dc8 100644
--- a/vpd-manager/src/event_logger.cpp
+++ b/vpd-manager/src/event_logger.cpp
@@ -1,3 +1,5 @@
+#include "config.h"
+
#include "event_logger.hpp"
#include "exceptions.hpp"
@@ -5,6 +7,10 @@
#include <systemd/sd-bus.h>
+#include <utility/json_utility.hpp>
+
+#include <filesystem>
+
namespace vpd
{
const std::unordered_map<types::SeverityType, std::string>
@@ -302,6 +308,97 @@
}
}
+void EventLogger::createSyncPelWithInvCallOut(
+ const types::ErrorType& i_errorType, const types::SeverityType& i_severity,
+ const std::string& i_fileName, const std::string& i_funcName,
+ const uint8_t i_internalRc, const std::string& i_description,
+ const std::vector<types::InventoryCalloutData>& i_callouts,
+ const std::optional<std::string> i_userData1,
+ const std::optional<std::string> i_userData2,
+ [[maybe_unused]] const std::optional<std::string> i_symFru,
+ [[maybe_unused]] const std::optional<std::string> i_procedure)
+{
+ try
+ {
+ if (i_callouts.empty())
+ {
+ createSyncPel(i_errorType, i_severity, i_fileName, i_funcName,
+ i_internalRc, i_description, i_userData1, i_userData2,
+ i_symFru, i_procedure);
+ logging::logMessage(
+ "Callout list is empty, creating PEL without call out");
+ return;
+ }
+
+ if (m_errorMsgMap.find(i_errorType) == m_errorMsgMap.end())
+ {
+ throw std::runtime_error("Unsupported error type received");
+ }
+
+ // Path to hold callout inventory path.
+ std::string l_calloutInvPath;
+
+ // check if callout path is a valid inventory path. if not, get the JSON
+ // object to get inventory path.
+ if (std::get<0>(i_callouts[0])
+ .compare(constants::VALUE_0, strlen(constants::pimPath),
+ constants::pimPath) != constants::STR_CMP_SUCCESS)
+ {
+ std::error_code l_ec;
+ // implies json dependent execution.
+ if (std::filesystem::exists(INVENTORY_JSON_SYM_LINK, l_ec))
+ {
+ if (!l_ec)
+ {
+ l_calloutInvPath = jsonUtility::getInventoryObjPathFromJson(
+ jsonUtility::getParsedJson(INVENTORY_JSON_SYM_LINK),
+ std::get<0>(i_callouts[0]));
+ }
+ else
+ {
+ logging::logMessage(
+ "Error finding symlink. Continue with given path");
+ }
+ }
+ }
+
+ if (l_calloutInvPath.empty())
+ {
+ l_calloutInvPath = std::get<0>(i_callouts[0]);
+ }
+
+ const std::map<std::string, std::string> l_additionalData{
+ {"FileName", i_fileName},
+ {"FunctionName", i_funcName},
+ {"DESCRIPTION",
+ (!i_description.empty() ? i_description : "VPD generic error")},
+ {"CALLOUT_INVENTORY_PATH", l_calloutInvPath},
+ {"InteranlRc", std::to_string(i_internalRc)},
+ {"UserData1", ((i_userData1) ? (*i_userData1) : "").c_str()},
+ {"UserData2", ((i_userData2) ? (*i_userData2) : "").c_str()}};
+
+ const std::string& l_severity =
+ (m_severityMap.find(i_severity) != m_severityMap.end()
+ ? m_severityMap.at(i_severity)
+ : m_severityMap.at(types::SeverityType::Informational));
+
+ auto l_bus = sdbusplus::bus::new_default();
+ auto l_method =
+ l_bus.new_method_call(constants::eventLoggingServiceName,
+ constants::eventLoggingObjectPath,
+ constants::eventLoggingInterface, "Create");
+ l_method.append(m_errorMsgMap.at(i_errorType), l_severity,
+ l_additionalData);
+ l_bus.call(l_method);
+ }
+ catch (const std::exception& l_ex)
+ {
+ logging::logMessage(
+ "Sync PEL creation with inventory path failed with error: " +
+ std::string(l_ex.what()));
+ }
+}
+
types::ExceptionDataMap EventLogger::getExceptionData(
const std::exception& i_exception)
{
diff --git a/vpd-manager/src/ipz_parser.cpp b/vpd-manager/src/ipz_parser.cpp
index 828c17c..7b19d22 100644
--- a/vpd-manager/src/ipz_parser.cpp
+++ b/vpd-manager/src/ipz_parser.cpp
@@ -842,11 +842,13 @@
// Log a Predictive PEL, including names and respective error messages
// of all invalid records
- EventLogger::createSyncPel(
- types::ErrorType::InvalidVpdMessage, types::SeverityType::Warning,
+ EventLogger::createSyncPelWithInvCallOut(
+ types::ErrorType::EccCheckFailed, types::SeverityType::Warning,
__FILE__, __FUNCTION__, constants::VALUE_0,
- std::string("Invalid records found while parsing VPD for [" +
- m_vpdFilePath + "]"),
+ std::string(
+ "Check failed for record(s) while parsing VPD. Check user data for reason and list of failed record(s). Re-program VPD."),
+ std::vector{
+ std::make_tuple(m_vpdFilePath, types::CalloutPriority::High)},
l_invalidRecordListString, std::nullopt, std::nullopt,
std::nullopt);