1 #pragma once 2 3 #include "config.h" 4 5 #include "types.hpp" 6 7 #include <nlohmann/json.hpp> 8 #include <xyz/openbmc_project/Association/Definitions/server.hpp> 9 10 #include <any> 11 #include <filesystem> 12 13 namespace phosphor 14 { 15 namespace inventory 16 { 17 namespace manager 18 { 19 namespace associations 20 { 21 22 static constexpr auto forwardTypePos = 0; 23 static constexpr auto reverseTypePos = 1; 24 using Types = std::tuple<std::string, std::string>; 25 using Paths = std::vector<std::string>; 26 27 static constexpr auto typesPos = 0; 28 static constexpr auto pathsPos = 1; 29 using EndpointsEntry = std::vector<std::tuple<Types, Paths>>; 30 31 using AssociationMap = std::map<std::string, EndpointsEntry>; 32 33 using AssociationObject = sdbusplus::server::object_t< 34 sdbusplus::xyz::openbmc_project::Association::server::Definitions>; 35 36 using AssociationIfaceMap = 37 std::map<std::string, std::unique_ptr<AssociationObject>>; 38 39 /** 40 * @class Manager 41 * 42 * @brief This class provides the ability to add org.openbmc.Associations 43 * interfaces on inventory D-Bus objects, based on a definition in a 44 * JSON file. 45 * 46 * The purpose for this is to be able to associate other D-Bus paths 47 * with the inventory items they relate to. 48 * 49 * For example, a card temperature sensor D-Bus object can be associated 50 * with the D-Bus object for that card's inventory entry so that some 51 * code can tie them together. 52 */ 53 class Manager 54 { 55 public: 56 struct Condition 57 { 58 std::string path; 59 std::string interface; 60 std::string property; 61 std::vector<InterfaceVariantType> values; 62 std::filesystem::path file; 63 InterfaceVariantType actualValue; 64 }; 65 66 Manager() = delete; 67 ~Manager() = default; 68 Manager(const Manager&) = delete; 69 Manager& operator=(const Manager&) = delete; 70 Manager(Manager&&) = delete; 71 Manager& operator=(Manager&&) = delete; 72 73 /** 74 * @brief Constructor 75 * 76 * @param[in] bus - sdbusplus object 77 * @param[in] jsonPath - path to the JSON File that contains associations 78 */ 79 Manager(sdbusplus::bus_t& bus, const std::string& jsonPath); 80 81 /** 82 * @brief Constructor 83 * 84 * @param[in] bus - sdbusplus object 85 */ 86 explicit Manager(sdbusplus::bus_t& bus) : 87 Manager(bus, ASSOCIATIONS_FILE_PATH) 88 {} 89 90 /** 91 * @brief Creates any association D-Bus interfaces required based on 92 * the JSON associations definition for the object path passed 93 * in. 94 * 95 * Called after PIM creates a new inventory D-Bus interface on objectPath. 96 * 97 * @param[in] objectPath - the D-Bus object path to check for associations 98 * @param[in] deferSignal - whether or not to send a Properties or 99 * ObjectManager signal 100 */ 101 void createAssociations(const std::string& objectPath, bool deferSignal); 102 103 /** 104 * @brief Returned the association configuration. 105 * Used for testing. 106 * 107 * @return AssociationMap& - the association config 108 */ 109 const AssociationMap& getAssociationsConfig() 110 { 111 return _associations; 112 } 113 114 /** 115 * @brief Returns the list of conditions 116 * 117 * @return vector<Condition>& - The conditions 118 */ 119 std::vector<Condition>& getConditions() 120 { 121 return _conditions; 122 } 123 124 /** 125 * @brief Says if there are conditions that need to be met 126 * before an associations file is valid. 127 * 128 * @return bool - If there are pending conditions 129 */ 130 bool pendingCondition() const 131 { 132 return !_conditions.empty(); 133 } 134 135 /** 136 * @brief Checks if a pending condition is satisfied based on the 137 * path, interface, and property value of the object passed 138 * in. 139 * 140 * If it is valid, it will load the associations pointed to 141 * by that condition and erase the _conditions vector as 142 * there are no longer any pending conditions. 143 * 144 * @param[in] objectPath - The D-Bus path of the object to check 145 * @param[in] in object - The interface and properties of the object 146 * 147 * @return bool - If the object matched a condition 148 */ 149 bool conditionMatch(const sdbusplus::message::object_path& objectPath, 150 const Object& object); 151 152 /** 153 * @brief Checks if a pending condition is satisfied based on if the 154 * actualValue field in the condition matches one of the values 155 * in the values field. 156 * 157 * The actualValue field was previously set by code based on the 158 * real property value of the specified interface on the specified 159 * path. 160 * 161 * If it is valid, it will load the associations pointed to 162 * by that condition and erase the _conditions vector as 163 * there are no longer any pending conditions. 164 * 165 * @return bool - If a condition was met 166 */ 167 bool conditionMatch(); 168 169 private: 170 /** 171 * @brief Loads the association JSON into the _associations data 172 * structure. 173 * 174 * @param[in] json - The associations JSON 175 */ 176 void load(const nlohmann::json& json); 177 178 /** 179 * @brief Creates an instance of an org.openbmc.Associations 180 * interface using the passed in properties. 181 * 182 * @param[in] forwardPath - the path of the forward association 183 * @param[in] forwardType - the type of the forward association 184 * @param[in] reversePath - the path of the reverse association 185 * @param[in] reverseType - the type of the reverse association 186 * @param[in] deferSignal - whether or not to send a Properties or 187 * ObjectManager signal 188 */ 189 void createAssociation(const std::string& forwardPath, 190 const std::string& forwardType, 191 const std::string& reversePath, 192 const std::string& reverseType, bool deferSignal); 193 194 /** 195 * @brief Looks for all JSON files in the associations directory that 196 * contain a valid association condition, and loads the 197 * conditions into the _conditions vector. 198 */ 199 bool loadConditions(); 200 201 /** 202 * @brief The map of association data that is loaded from its 203 * JSON definition. Association D-Bus objects will be 204 * created from this data. 205 */ 206 AssociationMap _associations; 207 208 /** 209 * @brief The map of org.openbmc_project.Associations D-Bus 210 * interfaces objects based on their object path. 211 */ 212 AssociationIfaceMap _associationIfaces; 213 214 /** 215 * @brief The sdbusplus bus object. 216 */ 217 sdbusplus::bus_t& _bus; 218 219 /** 220 * @brief The path to the associations JSON File. 221 */ 222 const std::filesystem::path _jsonFile; 223 224 /** 225 * A list of the inventory association paths that have already been handled. 226 */ 227 std::vector<std::string> _handled; 228 229 /** 230 * @brief Conditions that specify when an associations file is valid. 231 */ 232 std::vector<Condition> _conditions; 233 }; 234 235 } // namespace associations 236 } // namespace manager 237 } // namespace inventory 238 } // namespace phosphor 239