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