pseq: Add generic failure handling to base class
Use the power sequencer base class to handle failure cases where the
device is not found or a device specific failure can not determined. Add
a error logging convience method. Move the D-Bus object to the base
class.
Signed-off-by: Jim Wright <jlwright@us.ibm.com>
Change-Id: I6f7c2951e83cb892ec0c63018d65d5e241ebe6f0
diff --git a/phosphor-power-sequencer/src/meson.build b/phosphor-power-sequencer/src/meson.build
index 4ea4b9c..590e10e 100644
--- a/phosphor-power-sequencer/src/meson.build
+++ b/phosphor-power-sequencer/src/meson.build
@@ -8,6 +8,7 @@
'power_control_main.cpp',
'power_control.cpp',
'power_interface.cpp',
+ 'power_sequencer_monitor.cpp',
'ucd90320_monitor.cpp',
dependencies: [
libgpiodcxx,
diff --git a/phosphor-power-sequencer/src/power_control.cpp b/phosphor-power-sequencer/src/power_control.cpp
index 9e8b1b4..aa6a8a3 100644
--- a/phosphor-power-sequencer/src/power_control.cpp
+++ b/phosphor-power-sequencer/src/power_control.cpp
@@ -20,8 +20,6 @@
#include "ucd90320_monitor.hpp"
#include <fmt/format.h>
-#include <sys/types.h>
-#include <unistd.h>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/elog.hpp>
@@ -44,12 +42,13 @@
PowerControl::PowerControl(sdbusplus::bus::bus& bus,
const sdeventplus::Event& event) :
PowerObject{bus, POWER_OBJ_PATH, true},
- bus{bus}, match{bus,
- sdbusplus::bus::match::rules::interfacesAdded() +
- sdbusplus::bus::match::rules::sender(
- "xyz.openbmc_project.EntityManager"),
- std::bind(&PowerControl::interfacesAddedHandler, this,
- std::placeholders::_1)},
+ bus{bus}, device{std::make_unique<PowerSequencerMonitor>(bus)},
+ match{bus,
+ sdbusplus::bus::match::rules::interfacesAdded() +
+ sdbusplus::bus::match::rules::sender(
+ "xyz.openbmc_project.EntityManager"),
+ std::bind(&PowerControl::interfacesAddedHandler, this,
+ std::placeholders::_1)},
timer{event, std::bind(&PowerControl::pollPgood, this), pollInterval}
{
// Obtain dbus service name
@@ -157,32 +156,18 @@
log<level::ERR>("ERROR PowerControl: Pgood poll timeout");
inStateTransition = false;
- try
+ if (state)
{
- auto method = bus.new_method_call(
- "xyz.openbmc_project.Logging",
- "/xyz/openbmc_project/logging",
- "xyz.openbmc_project.Logging.Create", "Create");
-
- std::map<std::string, std::string> additionalData;
- // Add PID to AdditionalData
- additionalData.emplace("_PID", std::to_string(getpid()));
-
- method.append(
- state ? "xyz.openbmc_project.Power.Error.PowerOnTimeout"
- : "xyz.openbmc_project.Power.Error.PowerOffTimeout",
- sdbusplus::xyz::openbmc_project::Logging::server::Entry::
- Level::Critical,
- additionalData);
- bus.call_noreply(method);
+ // Time out powering on
+ device->onFailure(true, powerSupplyError);
}
- catch (const std::exception& e)
+ else
{
- log<level::ERR>(
- fmt::format(
- "Unable to log timeout error, state: {}, error {}",
- state, e.what())
- .c_str());
+ // Time out powering off
+ std::map<std::string, std::string> additionalData{};
+ device->logError(
+ "xyz.openbmc_project.Power.Error.PowerOffTimeout",
+ additionalData);
}
return;
@@ -212,6 +197,7 @@
else if (!inStateTransition && (pgoodState == 0))
{
// Not in power off state, not changing state, and power good is off
+ device->onFailure(false, powerSupplyError);
// Power good has failed, call for chassis hard power off
log<level::ERR>("Chassis pgood failure");
diff --git a/phosphor-power-sequencer/src/power_control.hpp b/phosphor-power-sequencer/src/power_control.hpp
index 1bac68c..5bd5e47 100644
--- a/phosphor-power-sequencer/src/power_control.hpp
+++ b/phosphor-power-sequencer/src/power_control.hpp
@@ -75,8 +75,7 @@
/**
* The power sequencer device to monitor.
*/
- std::unique_ptr<PowerSequencerMonitor> device{
- std::make_unique<PowerSequencerMonitor>()};
+ std::unique_ptr<PowerSequencerMonitor> device;
/**
* Indicates if a specific power sequencer device has already been found.
diff --git a/phosphor-power-sequencer/src/power_sequencer_monitor.cpp b/phosphor-power-sequencer/src/power_sequencer_monitor.cpp
new file mode 100644
index 0000000..d56c38d
--- /dev/null
+++ b/phosphor-power-sequencer/src/power_sequencer_monitor.cpp
@@ -0,0 +1,86 @@
+/**
+ * Copyright © 2021 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "power_sequencer_monitor.hpp"
+
+#include <fmt/format.h>
+
+#include <phosphor-logging/elog.hpp>
+#include <phosphor-logging/log.hpp>
+
+#include <exception>
+#include <map>
+
+namespace phosphor::power::sequencer
+{
+
+using namespace phosphor::logging;
+
+PowerSequencerMonitor::PowerSequencerMonitor(sdbusplus::bus::bus& bus) :
+ bus(bus)
+{}
+
+void PowerSequencerMonitor::logError(
+ const std::string& message,
+ std::map<std::string, std::string>& additionalData)
+{
+ try
+ {
+ auto method = bus.new_method_call(
+ "xyz.openbmc_project.Logging", "/xyz/openbmc_project/logging",
+ "xyz.openbmc_project.Logging.Create", "Create");
+
+ // Add PID to AdditionalData
+ additionalData.emplace("_PID", std::to_string(getpid()));
+
+ method.append(message,
+ sdbusplus::xyz::openbmc_project::Logging::server::Entry::
+ Level::Critical,
+ additionalData);
+ bus.call_noreply(method);
+ }
+ catch (const std::exception& e)
+ {
+ log<level::ERR>(
+ fmt::format("Unable to log error, message: {}, error {}", message,
+ e.what())
+ .c_str());
+ }
+}
+
+void PowerSequencerMonitor::onFailure(bool timeout,
+ const std::string& powerSupplyError)
+{
+ std::map<std::string, std::string> additionalData{};
+ if (!powerSupplyError.empty())
+ {
+ // Default to power supply error
+ logError(powerSupplyError, additionalData);
+ }
+ else if (timeout)
+ {
+ // Default to timeout error
+ logError("xyz.openbmc_project.Power.Error.PowerOnTimeout",
+ additionalData);
+ }
+ else
+ {
+ // Default to generic pgood error
+ logError("xyz.openbmc_project.Power.Error.Shutdown", additionalData);
+ }
+}
+
+} // namespace phosphor::power::sequencer
diff --git a/phosphor-power-sequencer/src/power_sequencer_monitor.hpp b/phosphor-power-sequencer/src/power_sequencer_monitor.hpp
index e714d08..944e7ae 100644
--- a/phosphor-power-sequencer/src/power_sequencer_monitor.hpp
+++ b/phosphor-power-sequencer/src/power_sequencer_monitor.hpp
@@ -1,5 +1,10 @@
#pragma once
+#include <sdbusplus/bus.hpp>
+
+#include <map>
+#include <string>
+
namespace phosphor::power::sequencer
{
@@ -10,12 +15,42 @@
class PowerSequencerMonitor
{
public:
- PowerSequencerMonitor() = default;
+ PowerSequencerMonitor() = delete;
PowerSequencerMonitor(const PowerSequencerMonitor&) = delete;
PowerSequencerMonitor& operator=(const PowerSequencerMonitor&) = delete;
PowerSequencerMonitor(PowerSequencerMonitor&&) = delete;
PowerSequencerMonitor& operator=(PowerSequencerMonitor&&) = delete;
virtual ~PowerSequencerMonitor() = default;
+
+ /**
+ * Create a base device object for power sequence monitoring.
+ * @param[in] bus D-Bus bus object
+ */
+ explicit PowerSequencerMonitor(sdbusplus::bus::bus& bus);
+
+ /**
+ * Logs an error using the D-Bus Create method.
+ * @param[in] message Message property of the error log entry
+ * @param[in] additionalData AdditionalData property of the error log entry
+ */
+ void logError(const std::string& message,
+ std::map<std::string, std::string>& additionalData);
+
+ /**
+ * Analyzes the device for errors when the device is
+ * known to be in an error state. A log will be created.
+ * @param[in] timeout if the failure state was determined by timing out
+ * @param[in] powerSupplyError The power supply error to log. A default
+ * std:string, i.e. empty string ("") is passed when there is no power
+ * supply error to log.
+ */
+ virtual void onFailure(bool timeout, const std::string& powerSupplyError);
+
+ protected:
+ /**
+ * The D-Bus bus object
+ */
+ sdbusplus::bus::bus& bus;
};
} // namespace phosphor::power::sequencer
diff --git a/phosphor-power-sequencer/src/ucd90320_monitor.cpp b/phosphor-power-sequencer/src/ucd90320_monitor.cpp
index af04ff0..d7ef7bb 100644
--- a/phosphor-power-sequencer/src/ucd90320_monitor.cpp
+++ b/phosphor-power-sequencer/src/ucd90320_monitor.cpp
@@ -42,13 +42,13 @@
UCD90320Monitor::UCD90320Monitor(sdbusplus::bus::bus& bus, std::uint8_t i2cBus,
std::uint16_t i2cAddress) :
- PowerSequencerMonitor(),
- bus{bus}, match{bus,
- sdbusplus::bus::match::rules::interfacesAdded() +
- sdbusplus::bus::match::rules::sender(
- "xyz.openbmc_project.EntityManager"),
- std::bind(&UCD90320Monitor::interfacesAddedHandler, this,
- std::placeholders::_1)},
+ PowerSequencerMonitor(bus),
+ match{bus,
+ sdbusplus::bus::match::rules::interfacesAdded() +
+ sdbusplus::bus::match::rules::sender(
+ "xyz.openbmc_project.EntityManager"),
+ std::bind(&UCD90320Monitor::interfacesAddedHandler, this,
+ std::placeholders::_1)},
pmbusInterface{
fmt::format("/sys/bus/i2c/devices/{}-{:04x}", i2cBus, i2cAddress)
.c_str(),
diff --git a/phosphor-power-sequencer/src/ucd90320_monitor.hpp b/phosphor-power-sequencer/src/ucd90320_monitor.hpp
index 2453251..97958ce 100644
--- a/phosphor-power-sequencer/src/ucd90320_monitor.hpp
+++ b/phosphor-power-sequencer/src/ucd90320_monitor.hpp
@@ -56,11 +56,6 @@
gpiod::line_bulk lines;
/**
- * The D-Bus bus object
- */
- sdbusplus::bus::bus& bus;
-
- /**
* The match to Entity Manager interfaces added.
*/
sdbusplus::bus::match_t match;