| #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 |