Patrick Venture | 02e3237 | 2019-08-16 10:50:18 -0700 | [diff] [blame] | 1 | #include "entity_map_json.hpp" |
| 2 | |
Patrick Williams | fbc6c9d | 2023-05-10 07:50:16 -0500 | [diff] [blame^] | 3 | #include <ipmid/types.hpp> |
| 4 | #include <nlohmann/json.hpp> |
| 5 | |
Patrick Venture | 02e3237 | 2019-08-16 10:50:18 -0700 | [diff] [blame] | 6 | #include <exception> |
Patrick Venture | c2b7fc1 | 2019-08-19 11:53:22 -0700 | [diff] [blame] | 7 | #include <fstream> |
Patrick Venture | 87fd2cd | 2019-08-19 12:07:18 -0700 | [diff] [blame] | 8 | #include <memory> |
Patrick Venture | 02e3237 | 2019-08-16 10:50:18 -0700 | [diff] [blame] | 9 | #include <string> |
| 10 | #include <utility> |
| 11 | |
| 12 | namespace ipmi |
| 13 | { |
| 14 | namespace sensor |
| 15 | { |
| 16 | |
Patrick Venture | 87fd2cd | 2019-08-19 12:07:18 -0700 | [diff] [blame] | 17 | EntityInfoMapContainer* EntityInfoMapContainer::getContainer() |
Patrick Venture | 99bf1c4 | 2019-08-23 09:02:13 -0700 | [diff] [blame] | 18 | { |
Patrick Venture | 87fd2cd | 2019-08-19 12:07:18 -0700 | [diff] [blame] | 19 | 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 Venture | 1ad9da8 | 2019-08-19 12:25:54 -0700 | [diff] [blame] | 27 | instance = std::unique_ptr<EntityInfoMapContainer>( |
| 28 | new EntityInfoMapContainer(builtEntityMap)); |
Patrick Venture | 87fd2cd | 2019-08-19 12:07:18 -0700 | [diff] [blame] | 29 | } |
| 30 | |
| 31 | return instance.get(); |
| 32 | } |
| 33 | |
| 34 | const EntityInfoMap& EntityInfoMapContainer::getIpmiEntityRecords() |
| 35 | { |
| 36 | return entityRecords; |
Patrick Venture | 99bf1c4 | 2019-08-23 09:02:13 -0700 | [diff] [blame] | 37 | } |
| 38 | |
Patrick Venture | c2b7fc1 | 2019-08-19 11:53:22 -0700 | [diff] [blame] | 39 | EntityInfoMap 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 Venture | 02e3237 | 2019-08-16 10:50:18 -0700 | [diff] [blame] | 60 | EntityInfoMap 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 |