psu-ng: Create errors for detected faults
Add in a function for creating errors using the Create D-Bus call.
Update the analyze function to create errors when faults are found.
We would want to log a fault per power supply, so move the faultLogged
concept down to the PowerSupply object itself.
Signed-off-by: Brandon Wyman <bjwyman@gmail.com>
Change-Id: I94d22b2b8a495abde87fb921c9177c6d25225ef7
diff --git a/meson.build b/meson.build
index eef6b82..7d90fa3 100644
--- a/meson.build
+++ b/meson.build
@@ -40,6 +40,7 @@
pthread = dependency('threads')
stdplus = dependency('stdplus')
boost = dependency('boost')
+fmt = dependency('fmt')
systemd = dependency('systemd')
servicedir = systemd.get_pkgconfig_variable('systemdsystemunitdir')
diff --git a/phosphor-power-supply/meson.build b/phosphor-power-supply/meson.build
index 342e4e4..fa83ae7 100644
--- a/phosphor-power-supply/meson.build
+++ b/phosphor-power-supply/meson.build
@@ -11,6 +11,7 @@
dependencies: [
sdbusplus,
sdeventplus,
+ fmt,
],
include_directories: '..',
install: true,
diff --git a/phosphor-power-supply/power_supply.cpp b/phosphor-power-supply/power_supply.cpp
index 97acd6d..ab1caf9 100644
--- a/phosphor-power-supply/power_supply.cpp
+++ b/phosphor-power-supply/power_supply.cpp
@@ -129,6 +129,7 @@
inputFault = false;
mfrFault = false;
vinUVFault = false;
+ faultLogged = false;
// The PMBus device driver does not allow for writing CLEAR_FAULTS
// directly. However, the pmbus hwmon device driver code will send a
diff --git a/phosphor-power-supply/power_supply.hpp b/phosphor-power-supply/power_supply.hpp
index c94871f..f1220fd 100644
--- a/phosphor-power-supply/power_supply.hpp
+++ b/phosphor-power-supply/power_supply.hpp
@@ -152,6 +152,22 @@
}
/**
+ * @brief Return whether a fault has been logged for this power supply
+ */
+ bool isFaultLogged() const
+ {
+ return faultLogged;
+ }
+
+ /**
+ * @brief Called when a fault for this power supply has been logged.
+ */
+ void setFaultLogged()
+ {
+ faultLogged = true;
+ }
+
+ /**
* @brief Returns true if INPUT fault occurred.
*/
bool hasInputFault() const
@@ -190,6 +206,9 @@
/** @brief True if a fault has already been found and not cleared */
bool faultFound = false;
+ /** @brief True if an error for a fault has already been logged. */
+ bool faultLogged = false;
+
/** @brief True if bit 5 of STATUS_WORD high byte is on. */
bool inputFault = false;
diff --git a/phosphor-power-supply/psu_manager.cpp b/phosphor-power-supply/psu_manager.cpp
index 0fcd566..c84201e 100644
--- a/phosphor-power-supply/psu_manager.cpp
+++ b/phosphor-power-supply/psu_manager.cpp
@@ -2,6 +2,10 @@
#include "utility.hpp"
+#include <fmt/format.h>
+#include <sys/types.h>
+#include <unistd.h>
+
using namespace phosphor::logging;
namespace phosphor::power::manager
@@ -125,6 +129,44 @@
}
}
+void PSUManager::createError(
+ const std::string& faultName,
+ const std::map<std::string, std::string>& additionalData)
+{
+ using namespace sdbusplus::xyz::openbmc_project;
+ constexpr auto loggingObjectPath = "/xyz/openbmc_project/logging";
+ constexpr auto loggingCreateInterface =
+ "xyz.openbmc_project.Logging.Create";
+
+ try
+ {
+ auto service =
+ util::getService(loggingObjectPath, loggingCreateInterface, bus);
+
+ if (service.empty())
+ {
+ log<level::ERR>("Unable to get logging manager service");
+ return;
+ }
+
+ auto method = bus.new_method_call(service.c_str(), loggingObjectPath,
+ loggingCreateInterface, "Create");
+
+ auto level = Logging::server::Entry::Level::Error;
+ method.append(faultName, level, additionalData);
+
+ auto reply = bus.call(method);
+ }
+ catch (std::exception& e)
+ {
+ log<level::ERR>(
+ fmt::format(
+ "Failed creating event log for fault {} due to error {}",
+ faultName, e.what())
+ .c_str());
+ }
+}
+
void PSUManager::analyze()
{
for (auto& psu : psus)
@@ -135,21 +177,45 @@
for (auto& psu : psus)
{
// TODO: Fault priorities #918
- if (!faultLogged && psu->isFaulted())
+ if (!psu->isFaultLogged() && psu->isFaulted())
{
- if (psu->hasInputFault())
- {
- // TODO: Create error log
- }
+ std::map<std::string, std::string> additionalData;
+ additionalData["_PID"] = std::to_string(getpid());
+ additionalData["STATUS_WORD"] =
+ std::to_string(psu->getStatusWord());
- if (psu->hasMFRFault())
+ if ((psu->hasInputFault() || psu->hasVINUVFault()))
{
- // TODO: Create error log
+ /* The power supply location might be needed if the input fault
+ * is due to a problem with the power supply itself. Include the
+ * inventory path with a call out priority of low.
+ */
+ additionalData["CALLOUT_INVENTORY_PATH"] =
+ psu->getInventoryPath();
+ additionalData["CALLOUT_PRIORITY"] = "L";
+ createError(
+ "xyz.openbmc_project.Power.PowerSupply.Error.InputFault",
+ additionalData);
+ psu->setFaultLogged();
}
-
- if (psu->hasVINUVFault())
+ else if (psu->hasMFRFault())
{
- // TODO: Create error log
+ /* This can represent a variety of faults that result in calling
+ * out the power supply for replacement:
+ * Output OverCurrent, Output Under Voltage, and potentially
+ * other faults.
+ *
+ * Also plan on putting specific fault in AdditionalData,
+ * along with register names and register values
+ * (STATUS_WORD, STATUS_MFR, etc.).*/
+
+ additionalData["CALLOUT_INVENTORY_PATH"] =
+ psu->getInventoryPath();
+
+ createError("xyz.openbmc_project.Power.PowerSupply.Error.Fault",
+ additionalData);
+
+ psu->setFaultLogged();
}
}
}
diff --git a/phosphor-power-supply/psu_manager.hpp b/phosphor-power-supply/psu_manager.hpp
index ca8fd05..06d7c82 100644
--- a/phosphor-power-supply/psu_manager.hpp
+++ b/phosphor-power-supply/psu_manager.hpp
@@ -121,8 +121,6 @@
{
psu->clearFaults();
}
-
- faultLogged = false;
}
private:
@@ -139,16 +137,24 @@
timer;
/**
+ * Create an error
+ *
+ * @param[in] faultName - 'name' message for the BMC error log entry
+ * @param[in] additionalData - The AdditionalData property for the error
+ */
+ void createError(const std::string& faultName,
+ const std::map<std::string, std::string>& additionalData);
+
+ /**
* Analyze the status of each of the power supplies.
+ *
+ * Log errors for faults, when and where appropriate.
*/
void analyze();
/** @brief True if the power is on. */
bool powerOn = false;
- /** @brief True if fault logged. Clear in clearFaults(). */
- bool faultLogged = false;
-
/** @brief Used as part of subscribing to power on state changes*/
std::string powerService;