1 #pragma once 2 3 #include "config.h" 4 5 #include "activation.hpp" 6 #include "association_interface.hpp" 7 #include "types.hpp" 8 #include "utils.hpp" 9 #include "version.hpp" 10 11 #include <phosphor-logging/log.hpp> 12 #include <sdbusplus/server.hpp> 13 #include <xyz/openbmc_project/Association/Definitions/server.hpp> 14 #include <xyz/openbmc_project/Collection/DeleteAll/server.hpp> 15 16 #include <filesystem> 17 18 class TestItemUpdater; 19 20 namespace phosphor 21 { 22 namespace software 23 { 24 namespace updater 25 { 26 27 class Version; 28 29 using ItemUpdaterInherit = sdbusplus::server::object_t< 30 sdbusplus::xyz::openbmc_project::Association::server::Definitions>; 31 32 namespace MatchRules = sdbusplus::bus::match::rules; 33 34 namespace fs = std::filesystem; 35 36 /** @class ItemUpdater 37 * @brief Manages the activation of the PSU version items. 38 */ 39 class ItemUpdater : 40 public ItemUpdaterInherit, 41 public AssociationInterface, 42 public ActivationListener 43 { 44 friend class ::TestItemUpdater; 45 46 public: 47 /** @brief Constructs ItemUpdater 48 * 49 * @param[in] bus - The D-Bus bus object 50 * @param[in] path - The D-Bus path 51 */ 52 ItemUpdater(sdbusplus::bus_t& bus, const std::string& path) : 53 ItemUpdaterInherit(bus, path.c_str()), bus(bus), 54 versionMatch(bus, 55 MatchRules::interfacesAdded() + 56 MatchRules::path(SOFTWARE_OBJPATH), 57 std::bind(std::mem_fn(&ItemUpdater::createActivation), 58 this, std::placeholders::_1)), 59 psuInterfaceMatch( 60 bus, 61 MatchRules::interfacesAdded() + 62 MatchRules::path("/xyz/openbmc_project/inventory") + 63 MatchRules::sender("xyz.openbmc_project.Inventory.Manager"), 64 std::bind(std::mem_fn(&ItemUpdater::onPSUInterfaceAdded), this, 65 std::placeholders::_1)) 66 { 67 processPSUImageAndSyncToLatest(); 68 } 69 70 /** @brief Deletes version 71 * 72 * @param[in] versionId - Id of the version to delete 73 */ 74 void erase(const std::string& versionId); 75 76 /** @brief Creates an active association to the 77 * newly active software image 78 * 79 * @param[in] path - The path to create the association to. 80 */ 81 void createActiveAssociation(const std::string& path) override; 82 83 /** @brief Add the functional association to the 84 * new "running" PSU images 85 * 86 * @param[in] path - The path to add the association to. 87 */ 88 void addFunctionalAssociation(const std::string& path) override; 89 90 /** @brief Add the updateable association to the 91 * "running" PSU software image 92 * 93 * @param[in] path - The path to create the association. 94 */ 95 void addUpdateableAssociation(const std::string& path) override; 96 97 /** @brief Removes the associations from the provided software image path 98 * 99 * @param[in] path - The path to remove the association from. 100 */ 101 void removeAssociation(const std::string& path) override; 102 103 /** @brief Notify a PSU is updated 104 * 105 * @param[in] versionId - The versionId of the activation 106 * @param[in] psuInventoryPath - The PSU inventory path that is updated 107 */ 108 void onUpdateDone(const std::string& versionId, 109 const std::string& psuInventoryPath) override; 110 111 private: 112 /** @brief Callback function for Software.Version match. 113 * @details Creates an Activation D-Bus object. 114 * 115 * @param[in] msg - Data associated with subscribed signal 116 */ 117 void createActivation(sdbusplus::message_t& msg); 118 119 using Properties = 120 std::map<std::string, utils::UtilsInterface::PropertyType>; 121 122 /** @brief Callback function for PSU inventory match. 123 * @details Update an Activation D-Bus object for PSU inventory. 124 * 125 * @param[in] msg - Data associated with subscribed signal 126 */ 127 void onPsuInventoryChangedMsg(sdbusplus::message_t& msg); 128 129 /** @brief Callback function for PSU inventory match. 130 * @details Update an Activation D-Bus object for PSU inventory. 131 * 132 * @param[in] psuPath - The PSU inventory path 133 * @param[in] properties - The updated properties 134 */ 135 void onPsuInventoryChanged(const std::string& psuPath, 136 const Properties& properties); 137 138 /** @brief Create Activation object */ 139 std::unique_ptr<Activation> createActivationObject( 140 const std::string& path, const std::string& versionId, 141 const std::string& extVersion, Activation::Status activationStatus, 142 const AssociationList& assocs, const std::string& filePath); 143 144 /** @brief Create Version object */ 145 std::unique_ptr<Version> 146 createVersionObject(const std::string& objPath, 147 const std::string& versionId, 148 const std::string& versionString, 149 sdbusplus::xyz::openbmc_project::Software::server:: 150 Version::VersionPurpose versionPurpose); 151 152 /** @brief Create Activation and Version object for PSU inventory 153 * @details If the same version exists for multiple PSUs, just add 154 * related association, instead of creating new objects. 155 * */ 156 void createPsuObject(const std::string& psuInventoryPath, 157 const std::string& psuVersion); 158 159 /** @brief Remove Activation and Version object for PSU inventory 160 * @details If the same version exists for multiple PSUs, just remove 161 * related association. 162 * If the version has no association, the Activation and 163 * Version object will be removed 164 */ 165 void removePsuObject(const std::string& psuInventoryPath); 166 167 /** 168 * @brief Create and populate the active PSU Version. 169 */ 170 void processPSUImage(); 171 172 /** @brief Create PSU Version from stored images */ 173 void processStoredImage(); 174 175 /** @brief Scan a directory and create PSU Version from stored images */ 176 void scanDirectory(const fs::path& p); 177 178 /** @brief Get the versionId of the latest PSU version */ 179 std::optional<std::string> getLatestVersionId(); 180 181 /** @brief Update PSUs to the latest version */ 182 void syncToLatestImage(); 183 184 /** @brief Invoke the activation via DBus */ 185 void invokeActivation(const std::unique_ptr<Activation>& activation); 186 187 /** @brief Callback function for interfaces added signal. 188 * 189 * This method is called when a new interface is added. It updates the 190 * internal status map and process the new PSU if it's present. 191 * 192 * @param[in] msg - Data associated with subscribed signal 193 */ 194 void onPSUInterfaceAdded(sdbusplus::message_t& msg); 195 196 /** 197 * @brief Handles the processing of PSU images. 198 * 199 * This function responsible for invoking the sequence of processing PSU 200 * images, processing stored images, and syncing to the latest firmware 201 * image. 202 */ 203 void processPSUImageAndSyncToLatest(); 204 205 /** @brief Persistent sdbusplus D-Bus bus connection. */ 206 sdbusplus::bus_t& bus; 207 208 /** @brief Persistent map of Activation D-Bus objects and their 209 * version id */ 210 std::map<std::string, std::unique_ptr<Activation>> activations; 211 212 /** @brief Persistent map of Version D-Bus objects and their 213 * version id */ 214 std::map<std::string, std::unique_ptr<Version>> versions; 215 216 /** @brief The reference map of PSU Inventory objects and the 217 * Activation*/ 218 std::map<std::string, const std::unique_ptr<Activation>&> 219 psuPathActivationMap; 220 221 /** @brief sdbusplus signal match for PSU Software*/ 222 sdbusplus::bus::match_t versionMatch; 223 224 /** @brief sdbusplus signal matches for PSU Inventory */ 225 std::vector<sdbusplus::bus::match_t> psuMatches; 226 227 /** @brief This entry's associations */ 228 AssociationList assocs; 229 230 /** @brief A collection of the version strings */ 231 std::set<std::string> versionStrings; 232 233 /** @brief A struct to hold the PSU present status and model */ 234 struct psuStatus 235 { 236 bool present; 237 std::string model; 238 }; 239 240 /** @brief The map of PSU inventory path and the psuStatus 241 * 242 * It is used to handle psu inventory changed event, that only create psu 243 * software object when a PSU is present and the model is retrieved */ 244 std::map<std::string, psuStatus> psuStatusMap; 245 246 /** @brief Signal match for PSU interfaces added. 247 * 248 * This match listens for D-Bus signals indicating new interface has been 249 * added. When such a signal received, it triggers the 250 * `onInterfacesAdded` method to handle the new PSU. 251 */ 252 sdbusplus::bus::match_t psuInterfaceMatch; 253 }; 254 255 } // namespace updater 256 } // namespace software 257 } // namespace phosphor 258