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