#include "validator.hpp" #include "model.hpp" #include #include namespace validator { using namespace phosphor::power::util; constexpr auto supportedConfIntf = "xyz.openbmc_project.Configuration.SupportedConfiguration"; 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(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( std::get(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