xref: /openbmc/phosphor-power/tools/power-utils/validator.cpp (revision bdc18bd4def8d0d721a60ab8775d2d2a3c293bf5)
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 
areAllPsuSameModel()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 
countPresentPsus()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 
getRequiredPsus()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 
isItFunctional(const std::string & path)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 
validToUpdate()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