chassis-psu: ChassisManager class to manage chassis PSUs
Introduced the ChassisManager class to detect chassis and manage power
supply devices associated with chassis using D-Bus interfaces. This
includes:
- Subscribing to Entity Manager interface changes
- Implementing timers to validate power supply presence and status
- Scan the system for new chassis; if a chassis is new, add it to the
chassis list.
- Adding event loop integration for continuous monitoring
- Analysis of power supply status and error logging.
Test:
- On simulation system, verified chassis and their power supplies are
added to the chassis list, with each power supply correctly linked
to its corresponding chassis.
- Verified the power supplies in each chassis based on analysis
performed at the specified time interval.
Note: There are some commented code indicates future implementation,
please ignore for now, as they will be implemented soon.
Change-Id: I80c271783e71f668ca1405f7aca80c8ec112f531
Signed-off-by: Faisal Awada <faisal@us.ibm.com>
diff --git a/phosphor-power-supply/chassis_manager.cpp b/phosphor-power-supply/chassis_manager.cpp
new file mode 100644
index 0000000..710b5dc
--- /dev/null
+++ b/phosphor-power-supply/chassis_manager.cpp
@@ -0,0 +1,145 @@
+#include "config.h"
+
+#include "chassis_manager.hpp"
+
+#include <phosphor-logging/lg2.hpp>
+using namespace phosphor::logging;
+
+namespace phosphor::power::chassis_manager
+{
+using namespace phosphor::power::util;
+constexpr auto managerBusName =
+ "xyz.openbmc_project.Power.MultiChassisPSUMonitor";
+constexpr auto IBMCFFPSInterface =
+ "xyz.openbmc_project.Configuration.IBMCFFPSConnector";
+constexpr auto supportedConfIntf =
+ "xyz.openbmc_project.Configuration.SupportedConfiguration";
+
+ChassisManager::ChassisManager(sdbusplus::bus_t& bus,
+ const sdeventplus::Event& e) :
+ bus(bus), eventLoop(e)
+{
+ // Subscribe to InterfacesAdded before doing a property read, otherwise
+ // the interface could be created after the read attempt but before the
+ // match is created.
+ entityManagerIfacesAddedMatch = std::make_unique<sdbusplus::bus::match_t>(
+ bus,
+ sdbusplus::bus::match::rules::interfacesAdded() +
+ sdbusplus::bus::match::rules::sender(
+ "xyz.openbmc_project.EntityManager"),
+ std::bind(&ChassisManager::entityManagerIfaceAdded, this,
+ std::placeholders::_1));
+
+ initializeChassisList();
+
+ // Request the bus name before the analyze() function, which is the one that
+ // determines the brownout condition and sets the status d-bus property.
+ bus.request_name(managerBusName);
+
+ using namespace sdeventplus;
+ auto interval = std::chrono::milliseconds(1000);
+ timer = std::make_unique<utility::Timer<ClockId::Monotonic>>(
+ e, std::bind(&ChassisManager::analyze, this), interval);
+}
+
+void ChassisManager::entityManagerIfaceAdded(sdbusplus::message_t& msg)
+{
+ try
+ {
+ phosphor::power::chassis::Chassis* chassisMatchPtr = nullptr;
+ sdbusplus::message::object_path objPath;
+ std::map<std::string, std::map<std::string, util::DbusVariant>>
+ interfaces;
+ msg.read(objPath, interfaces);
+
+ std::string objPathStr = objPath;
+
+ auto itInterface = interfaces.find(supportedConfIntf);
+ if (itInterface != interfaces.cend())
+ {
+ lg2::info("InterfacesAdded supportedConfIntf- objPathStr= {OBJ}",
+ "OBJ", objPathStr);
+ auto myChassisId = getParentEMUniqueId(bus, objPathStr);
+ chassisMatchPtr = getMatchingChassisPtr(myChassisId);
+ if (chassisMatchPtr)
+ {
+ lg2::debug("InterfacesAdded for: {SUPPORTED_CONFIGURATION}",
+ "SUPPORTED_CONFIGURATION", supportedConfIntf);
+ // Future implementation
+ // chassisMatchPtr->supportedConfigurationInterfaceAdded(
+ // itInterface->second);
+ }
+ }
+ itInterface = interfaces.find(IBMCFFPSInterface);
+ if (itInterface != interfaces.cend())
+ {
+ lg2::debug("InterfacesAdded IBMCFFPSInterface- objPathStr= {OBJ}",
+ "OBJ", objPathStr);
+ auto myChassisId = getParentEMUniqueId(bus, objPathStr);
+ chassisMatchPtr = getMatchingChassisPtr(myChassisId);
+ if (chassisMatchPtr)
+ {
+ lg2::info("InterfacesAdded for: {IBMCFFPSINTERFACE}",
+ "IBMCFFPSINTERFACE", IBMCFFPSInterface);
+ // Future implementation
+ // chassisMatchPtr->psuInterfaceAdded(itInterface->second);
+ }
+ }
+ if (chassisMatchPtr != nullptr)
+ {
+ lg2::debug(
+ "InterfacesAdded validatePsuConfigAndInterfacesProcessed()");
+ // Future implementation
+ // chassisMatchPtr->validatePsuConfigAndInterfacesProcessed();
+ }
+ }
+ catch (const std::exception& e)
+ {
+ // Ignore, the property may be of a different type than expected.
+ }
+}
+
+phosphor::power::chassis::Chassis* ChassisManager::getMatchingChassisPtr(
+ uint64_t chassisId)
+{
+ for (const auto& chassisPtr : listOfChassis)
+ {
+ if (chassisPtr->getChassisId() == chassisId)
+ {
+ return chassisPtr.get();
+ }
+ }
+ lg2::debug("Chassis ID {ID} not found", "ID", chassisId);
+ return nullptr;
+}
+
+void ChassisManager::analyze()
+{
+ for (const auto& chassis : listOfChassis)
+ {
+ chassis->analyze();
+ }
+}
+
+void ChassisManager::initializeChassisList()
+{
+ try
+ {
+ auto chassisPathList = getChassisInventoryPaths(bus);
+ for (const auto& chassisPath : chassisPathList)
+ {
+ lg2::info(
+ "ChassisManager::initializeChassisList chassisPath= {CHASSIS_PATH}",
+ "CHASSIS_PATH", chassisPath);
+ auto chassis = std::make_unique<phosphor::power::chassis::Chassis>(
+ bus, chassisPath, eventLoop);
+ listOfChassis.push_back(std::move(chassis));
+ }
+ }
+ catch (const sdbusplus::exception_t& e)
+ {
+ lg2::error("Failed to initialize chassis list, error: {ERROR}", "ERROR",
+ e);
+ }
+}
+} // namespace phosphor::power::chassis_manager