blob: d00fcf07d30ba3c0befeb0f62b5f9bf031c05f8f [file] [log] [blame]
Patrick Venture02e32372019-08-16 10:50:18 -07001#include "entity_map_json.hpp"
2
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -05003#include <ipmid/types.hpp>
4#include <nlohmann/json.hpp>
5
Patrick Venture02e32372019-08-16 10:50:18 -07006#include <exception>
Patrick Venturec2b7fc12019-08-19 11:53:22 -07007#include <fstream>
Patrick Venture87fd2cd2019-08-19 12:07:18 -07008#include <memory>
Patrick Venture02e32372019-08-16 10:50:18 -07009#include <string>
10#include <utility>
11
12namespace ipmi
13{
14namespace sensor
15{
16
Patrick Venture87fd2cd2019-08-19 12:07:18 -070017EntityInfoMapContainer* EntityInfoMapContainer::getContainer()
Patrick Venture99bf1c42019-08-23 09:02:13 -070018{
Patrick Venture87fd2cd2019-08-19 12:07:18 -070019 static std::unique_ptr<EntityInfoMapContainer> instance;
20
21 if (!instance)
22 {
23 /* TODO: With multi-threading this would all need to be locked so
24 * the first thread to hit it would set it up.
25 */
26 EntityInfoMap builtEntityMap = buildEntityMapFromFile();
Patrick Venture1ad9da82019-08-19 12:25:54 -070027 instance = std::unique_ptr<EntityInfoMapContainer>(
28 new EntityInfoMapContainer(builtEntityMap));
Patrick Venture87fd2cd2019-08-19 12:07:18 -070029 }
30
31 return instance.get();
32}
33
34const EntityInfoMap& EntityInfoMapContainer::getIpmiEntityRecords()
35{
36 return entityRecords;
Patrick Venture99bf1c42019-08-23 09:02:13 -070037}
38
Patrick Venturec2b7fc12019-08-19 11:53:22 -070039EntityInfoMap buildEntityMapFromFile()
40{
41 const char* entityMapJsonFilename =
42 "/usr/share/ipmi-providers/entity-map.json";
43 EntityInfoMap builtMap;
44
45 std::ifstream mapFile(entityMapJsonFilename);
46 if (!mapFile.is_open())
47 {
48 return builtMap;
49 }
50
51 auto data = nlohmann::json::parse(mapFile, nullptr, false);
52 if (data.is_discarded())
53 {
54 return builtMap;
55 }
56
57 return buildJsonEntityMap(data);
58}
59
Patrick Venture02e32372019-08-16 10:50:18 -070060EntityInfoMap buildJsonEntityMap(const nlohmann::json& data)
61{
62 EntityInfoMap builtMap;
63
64 if (data.type() != nlohmann::json::value_t::array)
65 {
66 return builtMap;
67 }
68
69 try
70 {
71 for (const auto& entry : data)
72 {
73 /* It's an array entry with the following fields: id,
74 * containerEntityId, containerEntityInstance, isList, isLinked,
75 * entities[4]
76 */
77 EntityInfo obj;
78 Id recordId = entry.at("id").get<Id>();
79 obj.containerEntityId =
80 entry.at("containerEntityId").get<uint8_t>();
81 obj.containerEntityInstance =
82 entry.at("containerEntityInstance").get<uint8_t>();
83 obj.isList = entry.at("isList").get<bool>();
84 obj.isLinked = entry.at("isLinked").get<bool>();
85
86 auto jsonEntities = entry.at("entities");
87
88 if (jsonEntities.type() != nlohmann::json::value_t::array)
89 {
90 throw std::runtime_error(
91 "Invalid type for entities entry, must be array");
92 }
93 if (jsonEntities.size() != obj.containedEntities.size())
94 {
95 throw std::runtime_error(
96 "Entities must be in pairs of " +
97 std::to_string(obj.containedEntities.size()));
98 }
99
100 for (std::size_t i = 0; i < obj.containedEntities.size(); i++)
101 {
102 obj.containedEntities[i] = std::make_pair(
103 jsonEntities[i].at("id").get<uint8_t>(),
104 jsonEntities[i].at("instance").get<uint8_t>());
105 }
106
107 builtMap.insert({recordId, obj});
108 }
109 }
110 catch (const std::exception& e)
111 {
112 /* If any entry is invalid, the entire file cannot be trusted. */
113 builtMap.clear();
114 }
115
116 return builtMap;
117}
118
119} // namespace sensor
120} // namespace ipmi