blob: 40087562b1307c7ab86b427d844bf386273054a5 [file] [log] [blame]
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001#pragma once
2
3#include "event_logger.hpp"
4#include "exceptions.hpp"
5#include "logger.hpp"
6#include "types.hpp"
7
8#include <gpiod.hpp>
9#include <nlohmann/json.hpp>
10#include <utility/common_utility.hpp>
11
12#include <fstream>
13#include <type_traits>
14#include <unordered_map>
15
16namespace vpd
17{
18namespace jsonUtility
19{
20
21// forward declaration of API for function map.
22bool processSystemCmdTag(const nlohmann::json& i_parsedConfigJson,
23 const std::string& i_vpdFilePath,
24 const std::string& i_baseAction,
25 const std::string& i_flagToProcess);
26
27// forward declaration of API for function map.
28bool processGpioPresenceTag(
29 const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
30 const std::string& i_baseAction, const std::string& i_flagToProcess);
31
32// forward declaration of API for function map.
33bool procesSetGpioTag(const nlohmann::json& i_parsedConfigJson,
34 const std::string& i_vpdFilePath,
35 const std::string& i_baseAction,
36 const std::string& i_flagToProcess);
37
38// Function pointers to process tags from config JSON.
39typedef bool (*functionPtr)(
40 const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
41 const std::string& i_baseAction, const std::string& i_flagToProcess);
42
43inline std::unordered_map<std::string, functionPtr> funcionMap{
44 {"gpioPresence", processGpioPresenceTag},
45 {"setGpio", procesSetGpioTag},
46 {"systemCmd", processSystemCmdTag}};
47
48/**
49 * @brief API to read VPD offset from JSON file.
50 *
51 * @param[in] i_sysCfgJsonObj - Parsed system config JSON object.
52 * @param[in] i_vpdFilePath - VPD file path.
53 * @return VPD offset if found in JSON, 0 otherwise.
54 */
55inline size_t getVPDOffset(const nlohmann::json& i_sysCfgJsonObj,
56 const std::string& i_vpdFilePath)
57{
58 if (i_vpdFilePath.empty() || (i_sysCfgJsonObj.empty()) ||
59 (!i_sysCfgJsonObj.contains("frus")))
60 {
61 return 0;
62 }
63
64 if (i_sysCfgJsonObj["frus"].contains(i_vpdFilePath))
65 {
66 return i_sysCfgJsonObj["frus"][i_vpdFilePath].at(0).value("offset", 0);
67 }
68
69 const nlohmann::json& l_fruList =
70 i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
71
72 for (const auto& l_fru : l_fruList.items())
73 {
74 const auto l_fruPath = l_fru.key();
75
76 // check if given path is redundant FRU path
77 if (i_vpdFilePath == i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
78 "redundantEeprom", ""))
79 {
80 // Return the offset of redundant EEPROM taken from JSON.
81 return i_sysCfgJsonObj["frus"][l_fruPath].at(0).value("offset", 0);
82 }
83 }
84
85 return 0;
86}
87
88/**
89 * @brief API to parse respective JSON.
90 *
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050091 * @param[in] pathToJson - Path to JSON.
RekhaAparna011ef21002025-02-18 23:47:36 -060092 * @return on success parsed JSON. On failure empty JSON object.
93 *
94 * Note: Caller has to handle it in case an empty JSON object is received.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050095 */
RekhaAparna011ef21002025-02-18 23:47:36 -060096inline nlohmann::json getParsedJson(const std::string& pathToJson) noexcept
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050097{
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050098 try
99 {
RekhaAparna011ef21002025-02-18 23:47:36 -0600100 if (pathToJson.empty())
101 {
102 throw std::runtime_error("Path to JSON is missing");
103 }
104
105 if (!std::filesystem::exists(pathToJson) ||
106 std::filesystem::is_empty(pathToJson))
107 {
Souvik Roy3e9f63c2025-04-23 06:28:17 -0500108 throw std::runtime_error(
109 "File does not exist or empty file: [" + pathToJson + "]");
RekhaAparna011ef21002025-02-18 23:47:36 -0600110 }
111
112 std::ifstream l_jsonFile(pathToJson);
113 if (!l_jsonFile)
114 {
115 throw std::runtime_error(
116 "Failed to access Json path = " + pathToJson);
117 }
118
119 return nlohmann::json::parse(l_jsonFile);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500120 }
RekhaAparna011ef21002025-02-18 23:47:36 -0600121 catch (const std::exception& l_ex)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500122 {
RekhaAparna011ef21002025-02-18 23:47:36 -0600123 logging::logMessage(
124 "Failed to parse JSON file, error: " + std::string(l_ex.what()));
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500125 }
RekhaAparna011ef21002025-02-18 23:47:36 -0600126
127 return nlohmann::json{};
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500128}
129
130/**
131 * @brief Get inventory object path from system config JSON.
132 *
133 * Given either D-bus inventory path/FRU EEPROM path/redundant EEPROM path,
134 * this API returns D-bus inventory path if present in JSON.
135 *
136 * @param[in] i_sysCfgJsonObj - System config JSON object
137 * @param[in] i_vpdPath - Path to where VPD is stored.
138 *
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500139 * @return On success a valid path is returned, on failure an empty string is
RekhaAparna011ef21002025-02-18 23:47:36 -0600140 * returned.
141 *
142 * Note: Caller has to handle it in case an empty string is received.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500143 */
144inline std::string getInventoryObjPathFromJson(
RekhaAparna011ef21002025-02-18 23:47:36 -0600145 const nlohmann::json& i_sysCfgJsonObj,
146 const std::string& i_vpdPath) noexcept
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500147{
RekhaAparna011ef21002025-02-18 23:47:36 -0600148 try
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500149 {
RekhaAparna011ef21002025-02-18 23:47:36 -0600150 if (i_vpdPath.empty())
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500151 {
RekhaAparna011ef21002025-02-18 23:47:36 -0600152 throw std::runtime_error("Path parameter is empty.");
153 }
154
155 if (!i_sysCfgJsonObj.contains("frus"))
156 {
157 throw std::runtime_error("Missing frus tag in system config JSON.");
158 }
159
160 // check if given path is FRU path
161 if (i_sysCfgJsonObj["frus"].contains(i_vpdPath))
162 {
163 return i_sysCfgJsonObj["frus"][i_vpdPath].at(0).value(
164 "inventoryPath", "");
165 }
166
167 const nlohmann::json& l_fruList =
168 i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
169
170 for (const auto& l_fru : l_fruList.items())
171 {
172 const auto l_fruPath = l_fru.key();
173 const auto l_invObjPath =
174 i_sysCfgJsonObj["frus"][l_fruPath].at(0).value("inventoryPath",
175 "");
176
177 // check if given path is redundant FRU path or inventory path
178 if (i_vpdPath == i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
179 "redundantEeprom", "") ||
180 (i_vpdPath == l_invObjPath))
181 {
182 return l_invObjPath;
183 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500184 }
185 }
RekhaAparna011ef21002025-02-18 23:47:36 -0600186 catch (const std::exception& l_ex)
187 {
188 logging::logMessage(
189 "Failed to get inventory object path from json, error: " +
190 std::string(l_ex.what()));
191 }
192
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500193 return std::string();
194}
195
196/**
197 * @brief Process "PostFailAction" defined in config JSON.
198 *
199 * In case there is some error in the processing of "preAction" execution and a
200 * set of procedure needs to be done as a part of post fail action. This base
201 * action can be defined in the config JSON for that FRU and it will be handled
202 * under this API.
203 *
204 * @param[in] i_parsedConfigJson - config JSON
205 * @param[in] i_vpdFilePath - EEPROM file path
206 * @param[in] i_flagToProcess - To identify which flag(s) needs to be processed
207 * under PostFailAction tag of config JSON.
208 * @return - success or failure
209 */
210inline bool executePostFailAction(const nlohmann::json& i_parsedConfigJson,
211 const std::string& i_vpdFilePath,
212 const std::string& i_flagToProcess)
213{
RekhaAparna01c11e8b62025-02-20 00:34:35 -0600214 try
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500215 {
RekhaAparna01c11e8b62025-02-20 00:34:35 -0600216 if (i_parsedConfigJson.empty() || i_vpdFilePath.empty() ||
217 i_flagToProcess.empty())
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500218 {
RekhaAparna01c11e8b62025-02-20 00:34:35 -0600219 throw std::runtime_error(
220 "Invalid parameters. Abort processing for post fail action");
221 }
222
223 if (!(i_parsedConfigJson["frus"][i_vpdFilePath].at(0))["postFailAction"]
224 .contains(i_flagToProcess))
225 {
226 throw std::runtime_error(
227 "Config JSON missing flag " + i_flagToProcess +
228 " to execute post fail action for path = " + i_vpdFilePath);
229 }
230
231 for (const auto& l_tags : (i_parsedConfigJson["frus"][i_vpdFilePath].at(
232 0))["postFailAction"][i_flagToProcess]
233 .items())
234 {
235 auto itrToFunction = funcionMap.find(l_tags.key());
236 if (itrToFunction != funcionMap.end())
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500237 {
RekhaAparna01c11e8b62025-02-20 00:34:35 -0600238 if (!itrToFunction->second(i_parsedConfigJson, i_vpdFilePath,
239 "postFailAction", i_flagToProcess))
240 {
241 return false;
242 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500243 }
244 }
245 }
RekhaAparna01c11e8b62025-02-20 00:34:35 -0600246 catch (const std::exception& l_ex)
247 {
248 logging::logMessage("Execute post fail action failed. Error : " +
249 std::string(l_ex.what()));
250 return false;
251 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500252
253 return true;
254}
255
256/**
257 * @brief Process "systemCmd" tag for a given FRU.
258 *
259 * The API will process "systemCmd" tag if it is defined in the config
260 * JSON for the given FRU.
261 *
262 * @param[in] i_parsedConfigJson - config JSON
263 * @param[in] i_vpdFilePath - EEPROM file path
264 * @param[in] i_baseAction - Base action for which this tag has been called.
265 * @param[in] i_flagToProcess - Flag nested under the base action for which this
266 * tag has been called.
267 * @return Execution status.
268 */
269inline bool processSystemCmdTag(
270 const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
271 const std::string& i_baseAction, const std::string& i_flagToProcess)
272{
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500273 try
274 {
RekhaAparna01c11e8b62025-02-20 00:34:35 -0600275 if (i_vpdFilePath.empty() || i_parsedConfigJson.empty() ||
276 i_baseAction.empty() || i_flagToProcess.empty())
277 {
278 throw std::runtime_error(
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530279 std::string(__FUNCTION__) +
280 " Invalid parameter. Abort processing of processSystemCmd.");
RekhaAparna01c11e8b62025-02-20 00:34:35 -0600281 }
282
283 if (!((i_parsedConfigJson["frus"][i_vpdFilePath].at(
284 0)[i_baseAction][i_flagToProcess]["systemCmd"])
285 .contains("cmd")))
286 {
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530287 throw JsonException(
288 std::string(__FUNCTION__) +
289 " Config JSON missing required information to execute system command for EEPROM " +
RekhaAparna01c11e8b62025-02-20 00:34:35 -0600290 i_vpdFilePath);
291 }
292
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500293 const std::string& l_systemCommand =
294 i_parsedConfigJson["frus"][i_vpdFilePath].at(
295 0)[i_baseAction][i_flagToProcess]["systemCmd"]["cmd"];
296
297 commonUtility::executeCmd(l_systemCommand);
298 return true;
299 }
RekhaAparna01c11e8b62025-02-20 00:34:35 -0600300 catch (const std::exception& l_ex)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500301 {
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530302 EventLogger::createSyncPel(
303 EventLogger::getErrorType(l_ex), types::SeverityType::Informational,
304 __FILE__, __FUNCTION__, 0, EventLogger::getErrorMsg(l_ex),
305 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500306 return false;
307 }
308}
309
310/**
311 * @brief Checks for presence of a given FRU using GPIO line.
312 *
313 * This API returns the presence information of the FRU corresponding to the
314 * given VPD file path by setting the presence pin.
315 *
316 * @param[in] i_parsedConfigJson - config JSON
317 * @param[in] i_vpdFilePath - EEPROM file path
318 * @param[in] i_baseAction - Base action for which this tag has been called.
319 * @param[in] i_flagToProcess - Flag nested under the base action for which this
320 * tag has been called.
321 * @return Execution status.
322 */
323inline bool processGpioPresenceTag(
324 const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
325 const std::string& i_baseAction, const std::string& i_flagToProcess)
326{
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530327 std::string l_presencePinName;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500328 try
329 {
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530330 if (i_vpdFilePath.empty() || i_parsedConfigJson.empty() ||
331 i_baseAction.empty() || i_flagToProcess.empty())
332 {
333 throw std::runtime_error(
334 std::string(__FUNCTION__) +
335 "Invalid parameter. Abort processing of processGpioPresence tag");
336 }
337
338 if (!(((i_parsedConfigJson["frus"][i_vpdFilePath].at(
339 0)[i_baseAction][i_flagToProcess]["gpioPresence"])
340 .contains("pin")) &&
341 ((i_parsedConfigJson["frus"][i_vpdFilePath].at(
342 0)[i_baseAction][i_flagToProcess]["gpioPresence"])
343 .contains("value"))))
344 {
345 throw JsonException(
346 std::string(__FUNCTION__) +
347 "Config JSON missing required information to detect presence for EEPROM " +
348 i_vpdFilePath);
349 }
350
351 // get the pin name
352 l_presencePinName = i_parsedConfigJson["frus"][i_vpdFilePath].at(
353 0)[i_baseAction][i_flagToProcess]["gpioPresence"]["pin"];
354
355 // get the pin value
356 uint8_t l_presencePinValue =
357 i_parsedConfigJson["frus"][i_vpdFilePath].at(
358 0)[i_baseAction][i_flagToProcess]["gpioPresence"]["value"];
359
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500360 gpiod::line l_presenceLine = gpiod::find_line(l_presencePinName);
361
362 if (!l_presenceLine)
363 {
364 throw GpioException("Couldn't find the GPIO line.");
365 }
366
367 l_presenceLine.request({"Read the presence line",
368 gpiod::line_request::DIRECTION_INPUT, 0});
369
370 return (l_presencePinValue == l_presenceLine.get_value());
371 }
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530372 catch (const std::exception& l_ex)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500373 {
Sunny Srivastavac09e2102025-04-23 10:47:06 +0530374 // No need to continue in case of JSON failure or Firmware error
375 // as these are errors internal to the code and in that case the FRU
376 // should not be processed. Any other error is considered as external
377 // error in this case and a try to read the EEPROM should be done.
378 if (EventLogger::getErrorType(l_ex) == types::ErrorType::JsonFailure ||
379 EventLogger::getErrorType(l_ex) == types::ErrorType::FirmwareError)
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530380 {
381 EventLogger::createSyncPel(
382 EventLogger::getErrorType(l_ex),
383 types::SeverityType::Informational, __FILE__, __FUNCTION__, 0,
384 EventLogger::getErrorMsg(l_ex), std::nullopt, std::nullopt,
385 std::nullopt, std::nullopt);
386 return false;
387 }
388
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500389 std::string l_errMsg = "Exception on GPIO line: ";
390 l_errMsg += l_presencePinName;
391 l_errMsg += " Reason: ";
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530392 l_errMsg += l_ex.what();
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500393 l_errMsg += " File: " + i_vpdFilePath + " Pel Logged";
394
395 // ToDo -- Update Internal Rc code.
396 EventLogger::createAsyncPelWithInventoryCallout(
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530397 EventLogger::getErrorType(l_ex), types::SeverityType::Informational,
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500398 {{getInventoryObjPathFromJson(i_parsedConfigJson, i_vpdFilePath),
399 types::CalloutPriority::High}},
400 std::source_location::current().file_name(),
401 std::source_location::current().function_name(), 0, l_errMsg,
402 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
403
404 logging::logMessage(l_errMsg);
405
406 // Except when GPIO pin value is false, we go and try collecting the
407 // FRU VPD as we couldn't able to read GPIO pin value due to some
408 // error/exception. So returning true in error scenario.
409 return true;
410 }
411}
412
413/**
414 * @brief Process "setGpio" tag for a given FRU.
415 *
416 * This API enables the GPIO line.
417 *
418 * @param[in] i_parsedConfigJson - config JSON
419 * @param[in] i_vpdFilePath - EEPROM file path
420 * @param[in] i_baseAction - Base action for which this tag has been called.
421 * @param[in] i_flagToProcess - Flag nested under the base action for which this
422 * tag has been called.
423 * @return Execution status.
424 */
425inline bool procesSetGpioTag(
426 const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
427 const std::string& i_baseAction, const std::string& i_flagToProcess)
428{
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530429 std::string l_pinName;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500430 try
431 {
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530432 if (i_vpdFilePath.empty() || i_parsedConfigJson.empty() ||
433 i_baseAction.empty() || i_flagToProcess.empty())
434 {
435 throw std::runtime_error(
436 std::string(__FUNCTION__) +
437 " Invalid parameter. Abort processing of procesSetGpio.");
438 }
439
440 if (!(((i_parsedConfigJson["frus"][i_vpdFilePath].at(
441 0)[i_baseAction][i_flagToProcess]["setGpio"])
442 .contains("pin")) &&
443 ((i_parsedConfigJson["frus"][i_vpdFilePath].at(
444 0)[i_baseAction][i_flagToProcess]["setGpio"])
445 .contains("value"))))
446 {
447 throw JsonException(
448 std::string(__FUNCTION__) +
449 " Config JSON missing required information to set gpio line for EEPROM " +
450 i_vpdFilePath);
451 }
452
453 l_pinName = i_parsedConfigJson["frus"][i_vpdFilePath].at(
454 0)[i_baseAction][i_flagToProcess]["setGpio"]["pin"];
455
456 // Get the value to set
457 uint8_t l_pinValue = i_parsedConfigJson["frus"][i_vpdFilePath].at(
458 0)[i_baseAction][i_flagToProcess]["setGpio"]["value"];
459
460 logging::logMessage(
461 "Setting GPIO: " + l_pinName + " to " + std::to_string(l_pinValue));
462
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500463 gpiod::line l_outputLine = gpiod::find_line(l_pinName);
464
465 if (!l_outputLine)
466 {
467 throw GpioException("Couldn't find GPIO line.");
468 }
469
470 l_outputLine.request(
471 {"FRU Action", ::gpiod::line_request::DIRECTION_OUTPUT, 0},
472 l_pinValue);
473 return true;
474 }
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530475 catch (const std::exception& l_ex)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500476 {
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530477 if (EventLogger::getErrorType(l_ex) != types::ErrorType::GpioError)
478 {
479 EventLogger::createSyncPel(
480 EventLogger::getErrorType(l_ex),
481 types::SeverityType::Informational, __FILE__, __FUNCTION__, 0,
482 EventLogger::getErrorMsg(l_ex), std::nullopt, std::nullopt,
483 std::nullopt, std::nullopt);
484 }
485 else
486 {
487 std::string l_errMsg = "Exception on GPIO line: ";
488 l_errMsg += l_pinName;
489 l_errMsg += " Reason: ";
490 l_errMsg += l_ex.what();
491 l_errMsg += " File: " + i_vpdFilePath + " Pel Logged";
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500492
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530493 // ToDo -- Update Internal RC code
494 EventLogger::createAsyncPelWithInventoryCallout(
495 EventLogger::getErrorType(l_ex),
496 types::SeverityType::Informational,
497 {{getInventoryObjPathFromJson(i_parsedConfigJson,
498 i_vpdFilePath),
499 types::CalloutPriority::High}},
500 std::source_location::current().file_name(),
501 std::source_location::current().function_name(), 0, l_errMsg,
502 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500503
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530504 logging::logMessage(l_errMsg);
505 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500506
507 return false;
508 }
509}
510
511/**
512 * @brief Process any action, if defined in config JSON.
513 *
514 * If any FRU(s) requires any special handling, then this base action can be
515 * defined for that FRU in the config JSON, processing of which will be handled
516 * in this API.
517 * Examples of action - preAction, PostAction etc.
518 *
519 * @param[in] i_parsedConfigJson - config JSON
520 * @param[in] i_action - Base action to be performed.
521 * @param[in] i_vpdFilePath - EEPROM file path
522 * @param[in] i_flagToProcess - To identify which flag(s) needs to be processed
523 * under PreAction tag of config JSON.
524 * @return - success or failure
525 */
526inline bool executeBaseAction(
527 const nlohmann::json& i_parsedConfigJson, const std::string& i_action,
528 const std::string& i_vpdFilePath, const std::string& i_flagToProcess)
529{
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530530 try
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500531 {
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530532 if (i_flagToProcess.empty() || i_action.empty() ||
533 i_vpdFilePath.empty() || !i_parsedConfigJson.contains("frus"))
534 {
535 throw std::runtime_error(
536 std::string(__FUNCTION__) + " Invalid parameter");
537 }
538
539 if (!i_parsedConfigJson["frus"].contains(i_vpdFilePath))
540 {
541 throw JsonException(std::string(__FUNCTION__) + " File path: " +
542 i_vpdFilePath + " not found in JSON");
543 }
544
545 if (!i_parsedConfigJson["frus"][i_vpdFilePath].at(0).contains(i_action))
546 {
547 throw JsonException(
548 std::string(__FUNCTION__) + " Action [" + i_action +
549 "] not defined for file path:" + i_vpdFilePath);
550 }
551
552 if (!(i_parsedConfigJson["frus"][i_vpdFilePath].at(0))[i_action]
553 .contains(i_flagToProcess))
554 {
555 throw JsonException(
556 std::string(__FUNCTION__) + "Config JSON missing flag [" +
557 i_flagToProcess +
558 "] to execute action for path = " + i_vpdFilePath);
559 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500560 }
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530561 catch (const std::exception& l_ex)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500562 {
Sunny Srivastava0a5fce12025-04-09 11:09:51 +0530563 EventLogger::createSyncPel(
564 EventLogger::getErrorType(l_ex), types::SeverityType::Informational,
565 __FILE__, __FUNCTION__, 0, EventLogger::getErrorMsg(l_ex),
566 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500567 return false;
568 }
569
570 const nlohmann::json& l_tagsJson =
571 (i_parsedConfigJson["frus"][i_vpdFilePath].at(
572 0))[i_action][i_flagToProcess];
573
574 for (const auto& l_tag : l_tagsJson.items())
575 {
576 auto itrToFunction = funcionMap.find(l_tag.key());
577 if (itrToFunction != funcionMap.end())
578 {
579 if (!itrToFunction->second(i_parsedConfigJson, i_vpdFilePath,
580 i_action, i_flagToProcess))
581 {
582 // In case any of the tag fails to execute. Mark action
583 // as failed for that flag.
584 return false;
585 }
586 }
587 }
588
589 return true;
590}
591
592/**
593 * @brief Get redundant FRU path from system config JSON
594 *
595 * Given either D-bus inventory path/FRU path/redundant FRU path, this
596 * API returns the redundant FRU path taken from "redundantEeprom" tag from
597 * system config JSON.
598 *
599 * @param[in] i_sysCfgJsonObj - System config JSON object.
600 * @param[in] i_vpdPath - Path to where VPD is stored.
601 *
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500602 * @return On success return valid path, on failure return empty string.
603 */
604inline std::string getRedundantEepromPathFromJson(
RekhaAparna017fea9f52025-02-17 04:14:02 -0600605 const nlohmann::json& i_sysCfgJsonObj,
606 const std::string& i_vpdPath) noexcept
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500607{
RekhaAparna017fea9f52025-02-17 04:14:02 -0600608 try
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500609 {
RekhaAparna017fea9f52025-02-17 04:14:02 -0600610 if (i_vpdPath.empty())
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500611 {
RekhaAparna017fea9f52025-02-17 04:14:02 -0600612 throw std::runtime_error("Path parameter is empty.");
613 }
614
615 if (!i_sysCfgJsonObj.contains("frus"))
616 {
617 throw std::runtime_error("Missing frus tag in system config JSON.");
618 }
619
620 // check if given path is FRU path
621 if (i_sysCfgJsonObj["frus"].contains(i_vpdPath))
622 {
623 return i_sysCfgJsonObj["frus"][i_vpdPath].at(0).value(
624 "redundantEeprom", "");
625 }
626
627 const nlohmann::json& l_fruList =
628 i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
629
630 for (const auto& l_fru : l_fruList.items())
631 {
632 const std::string& l_fruPath = l_fru.key();
633 const std::string& l_redundantFruPath =
634 i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
635 "redundantEeprom", "");
636
637 // check if given path is inventory path or redundant FRU path
638 if ((i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
639 "inventoryPath", "") == i_vpdPath) ||
640 (l_redundantFruPath == i_vpdPath))
641 {
642 return l_redundantFruPath;
643 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500644 }
645 }
RekhaAparna017fea9f52025-02-17 04:14:02 -0600646 catch (const std::exception& l_ex)
647 {
648 logging::logMessage("Failed to get redundant EEPROM path, error: " +
649 std::string(l_ex.what()));
650 }
651
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500652 return std::string();
653}
654
655/**
656 * @brief Get FRU EEPROM path from system config JSON
657 *
658 * Given either D-bus inventory path/FRU EEPROM path/redundant EEPROM path,
659 * this API returns FRU EEPROM path if present in JSON.
660 *
661 * @param[in] i_sysCfgJsonObj - System config JSON object
662 * @param[in] i_vpdPath - Path to where VPD is stored.
663 *
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500664 * @return On success return valid path, on failure return empty string.
665 */
666inline std::string getFruPathFromJson(const nlohmann::json& i_sysCfgJsonObj,
RekhaAparna017fea9f52025-02-17 04:14:02 -0600667 const std::string& i_vpdPath) noexcept
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500668{
RekhaAparna017fea9f52025-02-17 04:14:02 -0600669 try
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500670 {
RekhaAparna017fea9f52025-02-17 04:14:02 -0600671 if (i_vpdPath.empty())
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500672 {
RekhaAparna017fea9f52025-02-17 04:14:02 -0600673 throw std::runtime_error("Path parameter is empty.");
674 }
675
676 if (!i_sysCfgJsonObj.contains("frus"))
677 {
678 throw std::runtime_error("Missing frus tag in system config JSON.");
679 }
680
681 // check if given path is FRU path
682 if (i_sysCfgJsonObj["frus"].contains(i_vpdPath))
683 {
684 return i_vpdPath;
685 }
686
687 const nlohmann::json& l_fruList =
688 i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
689
690 for (const auto& l_fru : l_fruList.items())
691 {
692 const auto l_fruPath = l_fru.key();
693
694 // check if given path is redundant FRU path or inventory path
695 if (i_vpdPath == i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
696 "redundantEeprom", "") ||
697 (i_vpdPath == i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
698 "inventoryPath", "")))
699 {
700 return l_fruPath;
701 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500702 }
703 }
RekhaAparna017fea9f52025-02-17 04:14:02 -0600704 catch (const std::exception& l_ex)
705 {
706 logging::logMessage("Failed to get FRU path from JSON, error: " +
707 std::string(l_ex.what()));
708 }
709
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500710 return std::string();
711}
712
713/**
714 * @brief An API to check backup and restore VPD is required.
715 *
716 * The API checks if there is provision for backup and restore mentioned in the
717 * system config JSON, by looking "backupRestoreConfigPath" tag.
718 * Checks if the path mentioned is a hardware path, by checking if the file path
719 * exists and size of contents in the path.
720 *
721 * @param[in] i_sysCfgJsonObj - System config JSON object.
722 *
723 * @return true if backup and restore is required, false otherwise.
724 */
725inline bool isBackupAndRestoreRequired(const nlohmann::json& i_sysCfgJsonObj)
726{
727 try
728 {
729 const std::string& l_backupAndRestoreCfgFilePath =
730 i_sysCfgJsonObj.value("backupRestoreConfigPath", "");
731 if (!l_backupAndRestoreCfgFilePath.empty() &&
732 std::filesystem::exists(l_backupAndRestoreCfgFilePath) &&
733 !std::filesystem::is_empty(l_backupAndRestoreCfgFilePath))
734 {
735 return true;
736 }
737 }
738 catch (std::exception& ex)
739 {
740 logging::logMessage(ex.what());
741 }
742 return false;
743}
744
745/** @brief API to check if an action is required for given EEPROM path.
746 *
747 * System config JSON can contain pre-action, post-action etc. like actions
748 * defined for an EEPROM path. The API will check if any such action is defined
749 * for the EEPROM.
750 *
751 * @param[in] i_sysCfgJsonObj - System config JSON object.
752 * @param[in] i_vpdFruPath - EEPROM path.
753 * @param[in] i_action - Action to be checked.
754 * @param[in] i_flowFlag - Denotes the flow w.r.t which the action should be
755 * triggered.
756 * @return - True if action is defined for the flow, false otherwise.
757 */
758inline bool isActionRequired(
759 const nlohmann::json& i_sysCfgJsonObj, const std::string& i_vpdFruPath,
760 const std::string& i_action, const std::string& i_flowFlag)
761{
762 if (i_vpdFruPath.empty() || i_action.empty() || i_flowFlag.empty())
763 {
764 logging::logMessage("Invalid parameters recieved.");
765 return false;
766 }
767
768 if (!i_sysCfgJsonObj.contains("frus"))
769 {
770 logging::logMessage("Invalid JSON object recieved.");
771 return false;
772 }
773
774 if (!i_sysCfgJsonObj["frus"].contains(i_vpdFruPath))
775 {
776 logging::logMessage(
777 "JSON object does not contain EEPROM path " + i_vpdFruPath);
778 return false;
779 }
780
781 if ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0)).contains(i_action))
782 {
783 if ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))[i_action].contains(
784 i_flowFlag))
785 {
786 return true;
787 }
788
789 logging::logMessage("Flow flag: [" + i_flowFlag +
790 "], not found in JSON for path: " + i_vpdFruPath);
791 return false;
792 }
793 return false;
794}
795
796/**
797 * @brief An API to return list of FRUs that needs GPIO polling.
798 *
799 * An API that checks for the FRUs that requires GPIO polling and returns
800 * a list of FRUs that needs polling. Returns an empty list if there are
801 * no FRUs that requires polling.
802 *
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500803 * @param[in] i_sysCfgJsonObj - System config JSON object.
804 *
RekhaAparna017fea9f52025-02-17 04:14:02 -0600805 * @return On success list of FRUs parameters that needs polling. On failure,
806 * empty list.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500807 */
Patrick Williams43fedab2025-02-03 14:28:05 -0500808inline std::vector<std::string> getListOfGpioPollingFrus(
RekhaAparna017fea9f52025-02-17 04:14:02 -0600809 const nlohmann::json& i_sysCfgJsonObj) noexcept
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500810{
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500811 std::vector<std::string> l_gpioPollingRequiredFrusList;
812
RekhaAparna017fea9f52025-02-17 04:14:02 -0600813 try
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500814 {
RekhaAparna017fea9f52025-02-17 04:14:02 -0600815 if (i_sysCfgJsonObj.empty())
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500816 {
RekhaAparna017fea9f52025-02-17 04:14:02 -0600817 throw std::runtime_error("Invalid Parameters");
818 }
819
820 if (!i_sysCfgJsonObj.contains("frus"))
821 {
822 throw std::runtime_error(
823 "Missing frus section in system config JSON");
824 }
825
826 for (const auto& l_fru : i_sysCfgJsonObj["frus"].items())
827 {
828 const auto l_fruPath = l_fru.key();
829
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500830 if (isActionRequired(i_sysCfgJsonObj, l_fruPath, "pollingRequired",
831 "hotPlugging"))
832 {
833 if (i_sysCfgJsonObj["frus"][l_fruPath]
834 .at(0)["pollingRequired"]["hotPlugging"]
835 .contains("gpioPresence"))
836 {
837 l_gpioPollingRequiredFrusList.push_back(l_fruPath);
838 }
839 }
840 }
RekhaAparna017fea9f52025-02-17 04:14:02 -0600841 }
842 catch (const std::exception& l_ex)
843 {
844 logging::logMessage("Failed to get list of GPIO polling FRUs, error: " +
845 std::string(l_ex.what()));
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500846 }
847
848 return l_gpioPollingRequiredFrusList;
849}
850
851/**
852 * @brief Get all related path(s) to update keyword value.
853 *
854 * Given FRU EEPROM path/Inventory path needs keyword's value update, this API
855 * returns tuple of FRU EEPROM path, inventory path and redundant EEPROM path if
856 * exists in the system config JSON.
857 *
858 * Note: If the inventory object path or redundant EEPROM path(s) are not found
859 * in the system config JSON, corresponding fields will have empty value in the
860 * returning tuple.
861 *
862 * @param[in] i_sysCfgJsonObj - System config JSON object.
863 * @param[in,out] io_vpdPath - Inventory object path or FRU EEPROM path.
864 *
865 * @return On success returns tuple of EEPROM path, inventory path & redundant
866 * path, on failure returns tuple with given input path alone.
867 */
868inline std::tuple<std::string, std::string, std::string>
869 getAllPathsToUpdateKeyword(const nlohmann::json& i_sysCfgJsonObj,
870 std::string io_vpdPath)
871{
872 types::Path l_inventoryObjPath;
873 types::Path l_redundantFruPath;
874 try
875 {
876 if (!i_sysCfgJsonObj.empty())
877 {
878 // Get hardware path from system config JSON.
879 const types::Path l_fruPath =
880 jsonUtility::getFruPathFromJson(i_sysCfgJsonObj, io_vpdPath);
881
882 if (!l_fruPath.empty())
883 {
884 io_vpdPath = l_fruPath;
885
886 // Get inventory object path from system config JSON
887 l_inventoryObjPath = jsonUtility::getInventoryObjPathFromJson(
888 i_sysCfgJsonObj, l_fruPath);
889
890 // Get redundant hardware path if present in system config JSON
891 l_redundantFruPath =
892 jsonUtility::getRedundantEepromPathFromJson(i_sysCfgJsonObj,
893 l_fruPath);
894 }
895 }
896 }
897 catch (const std::exception& l_exception)
898 {
899 logging::logMessage(
900 "Failed to get all paths to update keyword value, error " +
901 std::string(l_exception.what()));
902 }
903 return std::make_tuple(io_vpdPath, l_inventoryObjPath, l_redundantFruPath);
904}
905
906/**
907 * @brief An API to get DBus service name.
908 *
909 * Given DBus inventory path, this API returns DBus service name if present in
910 * the JSON.
911 *
912 * @param[in] i_sysCfgJsonObj - System config JSON object.
913 * @param[in] l_inventoryPath - DBus inventory path.
914 *
915 * @return On success returns the service name present in the system config
916 * JSON, otherwise empty string.
917 *
918 * Note: Caller has to handle in case of empty string received.
919 */
920inline std::string getServiceName(const nlohmann::json& i_sysCfgJsonObj,
921 const std::string& l_inventoryPath)
922{
923 try
924 {
925 if (l_inventoryPath.empty())
926 {
927 throw std::runtime_error("Path parameter is empty.");
928 }
929
930 if (!i_sysCfgJsonObj.contains("frus"))
931 {
932 throw std::runtime_error("Missing frus tag in system config JSON.");
933 }
934
935 const nlohmann::json& l_listOfFrus =
936 i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
937
938 for (const auto& l_frus : l_listOfFrus.items())
939 {
940 for (const auto& l_inventoryItem : l_frus.value())
941 {
942 if (l_inventoryPath.compare(l_inventoryItem["inventoryPath"]) ==
943 constants::STR_CMP_SUCCESS)
944 {
945 return l_inventoryItem["serviceName"];
946 }
947 }
948 }
949 throw std::runtime_error(
950 "Inventory path not found in the system config JSON");
951 }
952 catch (const std::exception& l_exception)
953 {
954 logging::logMessage(
955 "Error while getting DBus service name for given path " +
956 l_inventoryPath + ", error: " + std::string(l_exception.what()));
957 // TODO:log PEL
958 }
959 return std::string{};
960}
961
962/**
963 * @brief An API to check if a FRU is tagged as "powerOffOnly"
964 *
965 * Given the system config JSON and VPD FRU path, this API checks if the FRU
966 * VPD can be collected at Chassis Power Off state only.
967 *
968 * @param[in] i_sysCfgJsonObj - System config JSON object.
969 * @param[in] i_vpdFruPath - EEPROM path.
970 * @return - True if FRU VPD can be collected at Chassis Power Off state only.
971 * False otherwise
972 */
973inline bool isFruPowerOffOnly(const nlohmann::json& i_sysCfgJsonObj,
974 const std::string& i_vpdFruPath)
975{
976 if (i_vpdFruPath.empty())
977 {
978 logging::logMessage("FRU path is empty.");
979 return false;
980 }
981
982 if (!i_sysCfgJsonObj.contains("frus"))
983 {
984 logging::logMessage("Missing frus tag in system config JSON.");
985 return false;
986 }
987
988 if (!i_sysCfgJsonObj["frus"].contains(i_vpdFruPath))
989 {
990 logging::logMessage("JSON object does not contain EEPROM path \'" +
991 i_vpdFruPath + "\'");
992 return false;
993 }
994
995 return ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))
996 .contains("powerOffOnly") &&
997 (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0)["powerOffOnly"]));
998}
999
1000/**
1001 * @brief API which tells if the FRU is replaceable at runtime
1002 *
1003 * @param[in] i_sysCfgJsonObj - System config JSON object.
1004 * @param[in] i_vpdFruPath - EEPROM path.
1005 *
1006 * @return true if FRU is replaceable at runtime. false otherwise.
1007 */
1008inline bool isFruReplaceableAtRuntime(const nlohmann::json& i_sysCfgJsonObj,
1009 const std::string& i_vpdFruPath)
1010{
1011 try
1012 {
1013 if (i_vpdFruPath.empty())
1014 {
1015 throw std::runtime_error("Given FRU path is empty.");
1016 }
1017
1018 if (i_sysCfgJsonObj.empty() || (!i_sysCfgJsonObj.contains("frus")))
1019 {
1020 throw std::runtime_error("Invalid system config JSON object.");
1021 }
1022
1023 return ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))
1024 .contains("replaceableAtRuntime") &&
1025 (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(
1026 0)["replaceableAtRuntime"]));
1027 }
1028 catch (const std::exception& l_error)
1029 {
1030 // TODO: Log PEL
1031 logging::logMessage(l_error.what());
1032 }
1033
1034 return false;
1035}
1036
1037/**
1038 * @brief API which tells if the FRU is replaceable at standby
1039 *
1040 * @param[in] i_sysCfgJsonObj - System config JSON object.
1041 * @param[in] i_vpdFruPath - EEPROM path.
1042 *
1043 * @return true if FRU is replaceable at standby. false otherwise.
1044 */
1045inline bool isFruReplaceableAtStandby(const nlohmann::json& i_sysCfgJsonObj,
1046 const std::string& i_vpdFruPath)
1047{
1048 try
1049 {
1050 if (i_vpdFruPath.empty())
1051 {
1052 throw std::runtime_error("Given FRU path is empty.");
1053 }
1054
1055 if (i_sysCfgJsonObj.empty() || (!i_sysCfgJsonObj.contains("frus")))
1056 {
1057 throw std::runtime_error("Invalid system config JSON object.");
1058 }
1059
1060 return ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))
1061 .contains("replaceableAtStandby") &&
1062 (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(
1063 0)["replaceableAtStandby"]));
1064 }
1065 catch (const std::exception& l_error)
1066 {
1067 // TODO: Log PEL
1068 logging::logMessage(l_error.what());
1069 }
1070
1071 return false;
1072}
1073
1074/**
1075 * @brief API to get list of FRUs replaceable at standby from JSON.
1076 *
1077 * The API will return a vector of FRUs inventory path which are replaceable at
1078 * standby.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001079 *
1080 * @param[in] i_sysCfgJsonObj - System config JSON object.
1081 *
RekhaAparna017fea9f52025-02-17 04:14:02 -06001082 * @return - On success, list of FRUs replaceable at standby. On failure, empty
1083 * vector.
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001084 */
Patrick Williams43fedab2025-02-03 14:28:05 -05001085inline std::vector<std::string> getListOfFrusReplaceableAtStandby(
RekhaAparna017fea9f52025-02-17 04:14:02 -06001086 const nlohmann::json& i_sysCfgJsonObj) noexcept
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001087{
1088 std::vector<std::string> l_frusReplaceableAtStandby;
1089
RekhaAparna017fea9f52025-02-17 04:14:02 -06001090 try
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001091 {
RekhaAparna017fea9f52025-02-17 04:14:02 -06001092 if (!i_sysCfgJsonObj.contains("frus"))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001093 {
RekhaAparna017fea9f52025-02-17 04:14:02 -06001094 throw std::runtime_error("Missing frus tag in system config JSON.");
1095 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001096
RekhaAparna017fea9f52025-02-17 04:14:02 -06001097 const nlohmann::json& l_fruList =
1098 i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
1099
1100 for (const auto& l_fru : l_fruList.items())
1101 {
1102 if (i_sysCfgJsonObj["frus"][l_fru.key()].at(0).value(
1103 "replaceableAtStandby", false))
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001104 {
RekhaAparna017fea9f52025-02-17 04:14:02 -06001105 const std::string& l_inventoryObjectPath =
1106 i_sysCfgJsonObj["frus"][l_fru.key()].at(0).value(
1107 "inventoryPath", "");
1108
1109 if (!l_inventoryObjectPath.empty())
1110 {
1111 l_frusReplaceableAtStandby.emplace_back(
1112 l_inventoryObjectPath);
1113 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001114 }
1115 }
1116 }
RekhaAparna017fea9f52025-02-17 04:14:02 -06001117 catch (const std::exception& l_ex)
1118 {
1119 logging::logMessage(
1120 "Failed to get list of FRUs replaceable at standby, error: " +
1121 std::string(l_ex.what()));
1122 }
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001123
1124 return l_frusReplaceableAtStandby;
1125}
1126
Sunny Srivastava022112b2025-02-19 19:53:29 +05301127/**
1128 * @brief API to select powerVS JSON based on system IM.
1129 *
1130 * The API selects respective JSON based on system IM, parse it and return the
1131 * JSON object. Empty JSON will be returned in case of any error. Caller needs
1132 * to handle empty value.
1133 *
1134 * @param[in] i_imValue - IM value of the system.
1135 * @return Parsed JSON object, empty JSON otherwise.
1136 */
1137inline nlohmann::json getPowerVsJson(const types::BinaryVector& i_imValue)
1138{
1139 try
1140 {
1141 if ((i_imValue.at(0) == constants::HEX_VALUE_50) &&
1142 (i_imValue.at(1) == constants::HEX_VALUE_00) &&
1143 (i_imValue.at(2) == constants::HEX_VALUE_30))
1144 {
1145 return jsonUtility::getParsedJson(constants::power_vs_50003_json);
1146 }
1147 else if (i_imValue.at(0) == constants::HEX_VALUE_50 &&
1148 (i_imValue.at(1) == constants::HEX_VALUE_00) &&
1149 (i_imValue.at(2) == constants::HEX_VALUE_10))
1150 {
1151 return jsonUtility::getParsedJson(constants::power_vs_50001_json);
1152 }
1153 return nlohmann::json{};
1154 }
1155 catch (const std::exception& l_ex)
1156 {
1157 return nlohmann::json{};
1158 }
1159}
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001160} // namespace jsonUtility
1161} // namespace vpd