blob: 7942be9b1abe61a2b097aa85952daea1ec2f07d6 [file] [log] [blame] [edit]
#include "validator.hpp"
#include "model.hpp"
#include <phosphor-logging/lg2.hpp>
#include <iostream>
namespace validator
{
using namespace phosphor::power::util;
constexpr auto supportedConfIntf =
"xyz.openbmc_project.Configuration.SupportedConfiguration";
const auto IBMCFFPSInterface =
"xyz.openbmc_project.Configuration.IBMCFFPSConnector";
const auto objectPath = "/";
bool PSUUpdateValidator::areAllPsuSameModel()
{
try
{
targetPsuModel = model::getModel(bus, psuPath);
psuPaths = getPSUInventoryPaths(bus);
for (const auto& path : psuPaths)
{
auto thisPsuModel = model::getModel(bus, path);
// All PSUs must have same model
if (targetPsuModel != thisPsuModel)
{
lg2::error(
"PSU models do not match, targetPsuModel= {TARGET}, thisPsuModel= {THISPSU}",
"TARGET", targetPsuModel, "THISPSU", thisPsuModel);
return false;
}
}
}
catch (const std::exception& e)
{
lg2::error("Failed to get all PSUs from EM, error {ERROR}", "ERROR", e);
return false;
}
return true;
}
bool PSUUpdateValidator::countPresentPsus()
{
auto psuPaths = getPSUInventoryPaths(bus);
for (const auto& path : psuPaths)
{
auto present = false;
try
{
getProperty(INVENTORY_IFACE, PRESENT_PROP, path,
INVENTORY_MGR_IFACE, bus, present);
if (present)
{
if (!isItFunctional(path))
{
lg2::error("PSU {PATH} is not functional", "PATH", path);
return false;
}
presentPsuCount++;
}
}
catch (const std::exception& e)
{
lg2::error("Failed to get PSU present status, error {ERR} ", "ERR",
e);
return false;
}
}
return true;
}
bool PSUUpdateValidator::getRequiredPsus()
{
try
{
supportedObjects = getSubTree(bus, objectPath, supportedConfIntf, 0);
}
catch (std::exception& e)
{
lg2::error("Failed to retrieve supported configuration");
return false;
}
for (const auto& [objPath, services] : supportedObjects)
{
if (objPath.empty() || services.empty())
{
continue;
}
std::string service = services.begin()->first;
try
{
properties =
getAllProperties(bus, objPath, supportedConfIntf, service);
}
catch (const std::exception& e)
{
lg2::error(
"Failed to get all PSU {PSUPATH} properties error: {ERR}",
"PSUPATH", objPath, "ERR", e);
return false;
}
auto propertyModel = properties.find("SupportedModel");
if (propertyModel == properties.end())
{
continue;
}
try
{
auto supportedModel = std::get<std::string>(propertyModel->second);
if ((supportedModel.empty()) || (supportedModel != targetPsuModel))
{
continue;
}
}
catch (const std::bad_variant_access& e)
{
lg2::error("Failed to get supportedModel, error: {ERR}", "ERR", e);
}
try
{
auto redundantCountProp = properties.find("RedundantCount");
if (redundantCountProp != properties.end())
{
redundantCount = static_cast<int>(
std::get<uint64_t>(redundantCountProp->second));
break;
}
}
catch (const std::bad_variant_access& e)
{
lg2::error("Redundant type mismatch, error: {ERR}", "ERR", e);
}
}
return true;
}
bool PSUUpdateValidator::isItFunctional(const std::string& path)
{
try
{
bool isFunctional = false;
getProperty(OPERATIONAL_STATE_IFACE, FUNCTIONAL_PROP, path,
INVENTORY_MGR_IFACE, bus, isFunctional);
return isFunctional;
}
catch (const std::exception& e)
{
lg2::error("Failed to get PSU fault status, error {ERR} ", "ERR", e);
return false;
}
}
bool PSUUpdateValidator::validToUpdate()
{
if (areAllPsuSameModel() && countPresentPsus() && getRequiredPsus())
{
if (presentPsuCount >= redundantCount)
{
return true;
}
}
return false;
}
} // namespace validator