1 #include "validator.hpp" 2 3 #include "model.hpp" 4 5 #include <phosphor-logging/lg2.hpp> 6 7 #include <iostream> 8 9 namespace validator 10 { 11 using namespace phosphor::power::util; 12 constexpr auto supportedConfIntf = 13 "xyz.openbmc_project.Configuration.SupportedConfiguration"; 14 const auto objectPath = "/"; 15 16 bool PSUUpdateValidator::areAllPsuSameModel() 17 { 18 try 19 { 20 targetPsuModel = model::getModel(bus, psuPath); 21 psuPaths = getPSUInventoryPaths(bus); 22 for (const auto& path : psuPaths) 23 { 24 auto thisPsuModel = model::getModel(bus, path); 25 // All PSUs must have same model 26 if (targetPsuModel != thisPsuModel) 27 { 28 lg2::error( 29 "PSU models do not match, targetPsuModel= {TARGET}, thisPsuModel= {THISPSU}", 30 "TARGET", targetPsuModel, "THISPSU", thisPsuModel); 31 return false; 32 } 33 } 34 } 35 catch (const std::exception& e) 36 { 37 lg2::error("Failed to get all PSUs from EM, error {ERROR}", "ERROR", e); 38 return false; 39 } 40 return true; 41 } 42 43 bool PSUUpdateValidator::countPresentPsus() 44 { 45 auto psuPaths = getPSUInventoryPaths(bus); 46 for (const auto& path : psuPaths) 47 { 48 auto present = false; 49 try 50 { 51 getProperty(INVENTORY_IFACE, PRESENT_PROP, path, 52 INVENTORY_MGR_IFACE, bus, present); 53 if (present) 54 { 55 if (!isItFunctional(path)) 56 { 57 lg2::error("PSU {PATH} is not functional", "PATH", path); 58 return false; 59 } 60 61 presentPsuCount++; 62 } 63 } 64 catch (const std::exception& e) 65 { 66 lg2::error("Failed to get PSU present status, error {ERR} ", "ERR", 67 e); 68 return false; 69 } 70 } 71 return true; 72 } 73 74 bool PSUUpdateValidator::getRequiredPsus() 75 { 76 try 77 { 78 supportedObjects = getSubTree(bus, objectPath, supportedConfIntf, 0); 79 } 80 catch (std::exception& e) 81 { 82 lg2::error("Failed to retrieve supported configuration"); 83 return false; 84 } 85 for (const auto& [objPath, services] : supportedObjects) 86 { 87 if (objPath.empty() || services.empty()) 88 { 89 continue; 90 } 91 92 std::string service = services.begin()->first; 93 try 94 { 95 properties = 96 getAllProperties(bus, objPath, supportedConfIntf, service); 97 } 98 catch (const std::exception& e) 99 { 100 lg2::error( 101 "Failed to get all PSU {PSUPATH} properties error: {ERR}", 102 "PSUPATH", objPath, "ERR", e); 103 return false; 104 } 105 auto propertyModel = properties.find("SupportedModel"); 106 if (propertyModel == properties.end()) 107 { 108 continue; 109 } 110 try 111 { 112 auto supportedModel = std::get<std::string>(propertyModel->second); 113 if ((supportedModel.empty()) || (supportedModel != targetPsuModel)) 114 { 115 continue; 116 } 117 } 118 catch (const std::bad_variant_access& e) 119 { 120 lg2::error("Failed to get supportedModel, error: {ERR}", "ERR", e); 121 } 122 123 try 124 { 125 auto redundantCountProp = properties.find("RedundantCount"); 126 if (redundantCountProp != properties.end()) 127 { 128 redundantCount = static_cast<int>( 129 std::get<uint64_t>(redundantCountProp->second)); 130 break; 131 } 132 } 133 catch (const std::bad_variant_access& e) 134 { 135 lg2::error("Redundant type mismatch, error: {ERR}", "ERR", e); 136 } 137 } 138 return true; 139 } 140 141 bool PSUUpdateValidator::isItFunctional(const std::string& path) 142 { 143 try 144 { 145 bool isFunctional = false; 146 getProperty(OPERATIONAL_STATE_IFACE, FUNCTIONAL_PROP, path, 147 INVENTORY_MGR_IFACE, bus, isFunctional); 148 return isFunctional; 149 } 150 catch (const std::exception& e) 151 { 152 lg2::error("Failed to get PSU fault status, error {ERR} ", "ERR", e); 153 return false; 154 } 155 } 156 157 bool PSUUpdateValidator::validToUpdate() 158 { 159 if (areAllPsuSameModel() && countPresentPsus() && getRequiredPsus()) 160 { 161 if (presentPsuCount >= redundantCount) 162 { 163 return true; 164 } 165 } 166 return false; 167 } 168 } // namespace validator 169