1 #include <ipmid/entity_map_json.hpp> 2 #include <ipmid/types.hpp> 3 #include <nlohmann/json.hpp> 4 5 #include <exception> 6 #include <fstream> 7 #include <memory> 8 #include <string> 9 #include <utility> 10 11 namespace ipmi 12 { 13 namespace sensor 14 { 15 16 EntityInfoMapContainer* EntityInfoMapContainer::getContainer() 17 { 18 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(); 26 instance = std::unique_ptr<EntityInfoMapContainer>( 27 new EntityInfoMapContainer(builtEntityMap)); 28 } 29 30 return instance.get(); 31 } 32 33 const EntityInfoMap& EntityInfoMapContainer::getIpmiEntityRecords() 34 { 35 return entityRecords; 36 } 37 38 EntityInfoMap 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 59 EntityInfoMap 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 120