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