psutil: Add PSU Event Log Reporting Methods
This commit introduces new methods in the Updater class to log errors
and create Platform Event Logs for PSU failures and I2C-related
issues. The following methods are added:
- createServiceableEventLog:
Creates a serviceable Platform Event Log using
xyz.openbmc_project.Logging.Create. Takes an error name, severity, and
additional data as parameters. Retrieves the logging service and calls
the D-Bus method to create the log.
- getI2CAdditionalData:
Retrieves I2C-related callout data, including I2C bus ID, address, and
error number. Formats the ID and address as hexadecimal strings and
returns them as a map.
- callOutI2CEventLog:
Reports a Event Log for I2C failures. Collects PSU inventory path,
priority, and I2C-specific callout data. Merges any additional
provided data and creates a Event Log.
- callOutPsuEventLog:
Reports a Event Log for general PSU failures. Includes PSU inventory
callout information and priority.
- callOutSWEventLog:
Reports Event Log for software-related PSU file issues.Logs errors
using predefined PSU firmware file issue messages. These changes
improve fault logging and troubleshooting capabilities in PSU
management by ensuring proper logging and event recording.
- callOutGoodEventLog:
Reports a successful PSU firmware update Event Log along with the
firmware level.
- Added accessor functions to provide control over Event logging,
allowing:
- Enabling/disabling Event logging at runtime.
- Tracking if Event Log has been logged in the current session.
Accessor functions:
- enableEventLogging()
- disableEventLogging()
- isEventLogEnabled()
- enableEventLoggedThisSession()
- isEventLoggedThisSession()
Test:
Verified each function correctly generates Event Log in openBmc. The
test was conducted by writing a standalone test program that:
1 - Calls createServiceableEventLog() with various error names,
severity levels, and additionalData then check the generated Event Log.
2 - Calls getI2CAdditionalData() and verifies the returned data
contains the correct I2C bus ID, Address and error number.
3 - Calls callOutI2CEventLog() with simulated I2C error and checks the
generated Event Log.
4 - Calls callOutPsuEventLog() and callOutSWEventLog() with different
input data and verifies the correct error messages are logged.
Change-Id: Id52b3e1c0b2a3b09ae3ac5d93bc53e02d335d6c7
Signed-off-by: Faisal Awada <faisal@us.ibm.com>
diff --git a/tools/power-utils/updater.cpp b/tools/power-utils/updater.cpp
index 7da839f..16e225f 100644
--- a/tools/power-utils/updater.cpp
+++ b/tools/power-utils/updater.cpp
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
#include "updater.hpp"
#include "aei_updater.hpp"
@@ -20,13 +21,16 @@
#include "types.hpp"
#include "utility.hpp"
#include "utils.hpp"
+#include "version.hpp"
#include <phosphor-logging/lg2.hpp>
+#include <xyz/openbmc_project/Logging/Create/client.hpp>
#include <chrono>
#include <fstream>
-#include <thread>
-#include <vector>
+#include <iostream>
+#include <map>
+#include <string>
using namespace phosphor::logging;
namespace util = phosphor::power::util;
@@ -169,7 +173,7 @@
}
catch (const std::ios_base::failure& e)
{
- lg2::error("Error reading firmware: {ERROR}", "ERROR", e.what());
+ lg2::error("Error reading firmware: {ERROR}", "ERROR", e);
readDataBytes.clear();
}
return readDataBytes;
@@ -220,7 +224,7 @@
catch (const fs::filesystem_error& e)
{
lg2::error("Failed to get canonical path DEVPATH= {PATH}, ERROR= {ERR}",
- "PATH", devPath, "ERR", e.what());
+ "PATH", devPath, "ERR", e);
}
}
@@ -380,4 +384,105 @@
auto [id, addr] = utils::parseDeviceName(devName);
i2c = i2c::create(id, addr);
}
+
+void Updater::createServiceableEventLog(
+ const std::string& errorName, const std::string& severity,
+ std::map<std::string, std::string>& additionalData)
+{
+ if (!isEventLogEnabled() || isEventLoggedThisSession())
+ {
+ return;
+ }
+
+ using namespace sdbusplus::xyz::openbmc_project;
+ using LoggingCreate =
+ sdbusplus::client::xyz::openbmc_project::logging::Create<>;
+ enableEventLoggedThisSession();
+ try
+ {
+ additionalData["_PID"] = std::to_string(getpid());
+ auto method = bus.new_method_call(LoggingCreate::default_service,
+ LoggingCreate::instance_path,
+ LoggingCreate::interface, "Create");
+ method.append(errorName, severity, additionalData);
+
+ bus.call(method);
+ }
+ catch (const sdbusplus::exception::SdBusError& e)
+ {
+ lg2::error(
+ "Failed creating event log for fault {ERROR_NAME}, error {ERR}",
+ "ERROR_NAME", errorName, "ERR", e);
+ }
+ disableEventLogging();
+}
+
+std::map<std::string, std::string> Updater::getI2CAdditionalData()
+{
+ std::map<std::string, std::string> additionalData;
+ auto [id, addr] = utils::parseDeviceName(getDevName());
+ std::string hexIdString = std::format("0x{:x}", id);
+ std::string hexAddrString = std::format("0x{:x}", addr);
+
+ additionalData["CALLOUT_IIC_BUS"] = hexIdString;
+ additionalData["CALLOUT_IIC_ADDR"] = hexAddrString;
+ return additionalData;
+}
+
+/*
+ * callOutI2CEventLog calls out FRUs in the following order:
+ * 1 - PSU high priority
+ * 2 - CALLOUT_IIC_BUS
+ */
+void Updater::callOutI2CEventLog(
+ std::map<std::string, std::string> extraAdditionalData,
+ const std::string& exceptionString, const int errorCode)
+{
+ std::map<std::string, std::string> additionalData = {
+ {"CALLOUT_INVENTORY_PATH", getPsuInventoryPath()}};
+ additionalData.merge(extraAdditionalData);
+ additionalData.merge(getI2CAdditionalData());
+ additionalData["CALLOUT_ERRNO"] = std::to_string(errorCode);
+ if (!exceptionString.empty())
+ {
+ additionalData["I2C_EXCEPTION"] = exceptionString;
+ }
+ createServiceableEventLog(FW_UPDATE_FAILED_MSG, ERROR_SEVERITY,
+ additionalData);
+}
+
+/*
+ * callOutPsuEventLog calls out PSU and system planar
+ */
+void Updater::callOutPsuEventLog(
+ std::map<std::string, std::string> extraAdditionalData)
+{
+ std::map<std::string, std::string> additionalData = {
+ {"CALLOUT_INVENTORY_PATH", getPsuInventoryPath()}};
+ additionalData.merge(extraAdditionalData);
+ createServiceableEventLog(updater::FW_UPDATE_FAILED_MSG,
+ updater::ERROR_SEVERITY, additionalData);
+}
+
+/*
+ * callOutSWEventLog calls out the BMC0001 procedure.
+ */
+void Updater::callOutSWEventLog(
+ std::map<std::string, std::string> additionalData)
+{
+ createServiceableEventLog(updater::PSU_FW_FILE_ISSUE_MSG,
+ updater::ERROR_SEVERITY, additionalData);
+}
+
+/*
+ * callOutGoodEventLog calls out a successful firmware update.
+ */
+void Updater::callOutGoodEventLog()
+{
+ std::map<std::string, std::string> additionalData = {
+ {"SUCCESSFUL_PSU_UPDATE", getPsuInventoryPath()},
+ {"FIRMWARE_VERSION", version::getVersion(bus, getPsuInventoryPath())}};
+ createServiceableEventLog(updater::FW_UPDATE_SUCCESS_MSG,
+ updater::INFORMATIONAL_SEVERITY, additionalData);
+}
} // namespace updater