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