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( 55 bus, 56 MatchRules::interfacesAdded() + MatchRules::path(SOFTWARE_OBJPATH), 57 std::bind(std::mem_fn(&ItemUpdater::createActivation), this, 58 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> createVersionObject( 146 const std::string& objPath, const std::string& versionId, 147 const std::string& versionString, 148 sdbusplus::xyz::openbmc_project::Software::server::Version:: 149 VersionPurpose versionPurpose); 150 151 /** @brief Create Activation and Version object for PSU inventory 152 * @details If the same version exists for multiple PSUs, just add 153 * related association, instead of creating new objects. 154 * */ 155 void createPsuObject(const std::string& psuInventoryPath, 156 const std::string& psuVersion); 157 158 /** @brief Remove Activation and Version object for PSU inventory 159 * @details If the same version exists for multiple PSUs, just remove 160 * related association. 161 * If the version has no association, the Activation and 162 * Version object will be removed 163 */ 164 void removePsuObject(const std::string& psuInventoryPath); 165 166 /** 167 * @brief Create and populate the active PSU Version. 168 */ 169 void processPSUImage(); 170 171 /** @brief Create PSU Version from stored images */ 172 void processStoredImage(); 173 174 /** @brief Scan a directory and create PSU Version from stored images */ 175 void scanDirectory(const fs::path& p); 176 177 /** @brief Get the versionId of the latest PSU version */ 178 std::optional<std::string> getLatestVersionId(); 179 180 /** @brief Update PSUs to the latest version */ 181 void syncToLatestImage(); 182 183 /** @brief Invoke the activation via DBus */ 184 void invokeActivation(const std::unique_ptr<Activation>& activation); 185 186 /** @brief Callback function for interfaces added signal. 187 * 188 * This method is called when a new interface is added. It updates the 189 * internal status map and process the new PSU if it's present. 190 * 191 * @param[in] msg - Data associated with subscribed signal 192 */ 193 void onPSUInterfaceAdded(sdbusplus::message_t& msg); 194 195 /** 196 * @brief Handles the processing of PSU images. 197 * 198 * This function responsible for invoking the sequence of processing PSU 199 * images, processing stored images, and syncing to the latest firmware 200 * image. 201 */ 202 void processPSUImageAndSyncToLatest(); 203 204 /** @brief Persistent sdbusplus D-Bus bus connection. */ 205 sdbusplus::bus_t& bus; 206 207 /** @brief Persistent map of Activation D-Bus objects and their 208 * version id */ 209 std::map<std::string, std::unique_ptr<Activation>> activations; 210 211 /** @brief Persistent map of Version D-Bus objects and their 212 * version id */ 213 std::map<std::string, std::unique_ptr<Version>> versions; 214 215 /** @brief The reference map of PSU Inventory objects and the 216 * Activation*/ 217 std::map<std::string, const std::unique_ptr<Activation>&> 218 psuPathActivationMap; 219 220 /** @brief sdbusplus signal match for PSU Software*/ 221 sdbusplus::bus::match_t versionMatch; 222 223 /** @brief sdbusplus signal matches for PSU Inventory */ 224 std::vector<sdbusplus::bus::match_t> psuMatches; 225 226 /** @brief This entry's associations */ 227 AssociationList assocs; 228 229 /** @brief A collection of the version strings */ 230 std::set<std::string> versionStrings; 231 232 /** @brief A struct to hold the PSU present status and model */ 233 struct psuStatus 234 { 235 bool present; 236 std::string model; 237 }; 238 239 /** @brief The map of PSU inventory path and the psuStatus 240 * 241 * It is used to handle psu inventory changed event, that only create psu 242 * software object when a PSU is present and the model is retrieved */ 243 std::map<std::string, psuStatus> psuStatusMap; 244 245 /** @brief Signal match for PSU interfaces added. 246 * 247 * This match listens for D-Bus signals indicating new interface has been 248 * added. When such a signal received, it triggers the 249 * `onInterfacesAdded` method to handle the new PSU. 250 */ 251 sdbusplus::bus::match_t psuInterfaceMatch; 252 }; 253 254 } // namespace updater 255 } // namespace software 256 } // namespace phosphor 257