1 #pragma once 2 3 #include "config.h" 4 5 #include "activation_listener.hpp" 6 #include "association_interface.hpp" 7 #include "types.hpp" 8 #include "version.hpp" 9 10 #include <queue> 11 #include <sdbusplus/server.hpp> 12 #include <xyz/openbmc_project/Association/Definitions/server.hpp> 13 #include <xyz/openbmc_project/Common/FilePath/server.hpp> 14 #include <xyz/openbmc_project/Software/Activation/server.hpp> 15 #include <xyz/openbmc_project/Software/ActivationBlocksTransition/server.hpp> 16 #include <xyz/openbmc_project/Software/ActivationProgress/server.hpp> 17 #include <xyz/openbmc_project/Software/ExtendedVersion/server.hpp> 18 19 class TestActivation; 20 21 namespace phosphor 22 { 23 namespace software 24 { 25 namespace updater 26 { 27 28 namespace sdbusRule = sdbusplus::bus::match::rules; 29 30 using ActivationBlocksTransitionInherit = sdbusplus::server::object::object< 31 sdbusplus::xyz::openbmc_project::Software::server:: 32 ActivationBlocksTransition>; 33 34 /** @class ActivationBlocksTransition 35 * @brief OpenBMC ActivationBlocksTransition implementation. 36 * @details A concrete implementation for 37 * xyz.openbmc_project.Software.ActivationBlocksTransition DBus API. 38 */ 39 class ActivationBlocksTransition : public ActivationBlocksTransitionInherit 40 { 41 public: 42 /** @brief Constructs ActivationBlocksTransition. 43 * 44 * @param[in] bus - The Dbus bus object 45 * @param[in] path - The Dbus object path 46 */ 47 ActivationBlocksTransition(sdbusplus::bus::bus& bus, 48 const std::string& path) : 49 ActivationBlocksTransitionInherit(bus, path.c_str(), true), 50 bus(bus), path(path) 51 { 52 std::vector<std::string> interfaces({interface}); 53 bus.emit_interfaces_added(path.c_str(), interfaces); 54 enableRebootGuard(); 55 } 56 57 ~ActivationBlocksTransition() 58 { 59 std::vector<std::string> interfaces({interface}); 60 bus.emit_interfaces_removed(path.c_str(), interfaces); 61 disableRebootGuard(); 62 } 63 64 private: 65 // TODO Remove once openbmc/openbmc#1975 is resolved 66 static constexpr auto interface = 67 "xyz.openbmc_project.Software.ActivationBlocksTransition"; 68 sdbusplus::bus::bus& bus; 69 std::string path; 70 71 /** @brief Enables a Guard that blocks any BMC reboot commands */ 72 void enableRebootGuard(); 73 74 /** @brief Disables any guard that was blocking the BMC reboot */ 75 void disableRebootGuard(); 76 }; 77 78 using ActivationProgressInherit = sdbusplus::server::object::object< 79 sdbusplus::xyz::openbmc_project::Software::server::ActivationProgress>; 80 81 class ActivationProgress : public ActivationProgressInherit 82 { 83 public: 84 /** @brief Constructs ActivationProgress. 85 * 86 * @param[in] bus - The Dbus bus object 87 * @param[in] path - The Dbus object path 88 */ 89 ActivationProgress(sdbusplus::bus::bus& bus, const std::string& path) : 90 ActivationProgressInherit(bus, path.c_str(), true), bus(bus), path(path) 91 { 92 progress(0); 93 std::vector<std::string> interfaces({interface}); 94 bus.emit_interfaces_added(path.c_str(), interfaces); 95 } 96 97 ~ActivationProgress() 98 { 99 std::vector<std::string> interfaces({interface}); 100 bus.emit_interfaces_removed(path.c_str(), interfaces); 101 } 102 103 private: 104 // TODO Remove once openbmc/openbmc#1975 is resolved 105 static constexpr auto interface = 106 "xyz.openbmc_project.Software.ActivationProgress"; 107 sdbusplus::bus::bus& bus; 108 std::string path; 109 }; 110 111 using ActivationInherit = sdbusplus::server::object::object< 112 sdbusplus::xyz::openbmc_project::Software::server::ExtendedVersion, 113 sdbusplus::xyz::openbmc_project::Software::server::Activation, 114 sdbusplus::xyz::openbmc_project::Association::server::Definitions, 115 sdbusplus::xyz::openbmc_project::Common::server::FilePath>; 116 117 /** @class Activation 118 * @brief OpenBMC activation software management implementation. 119 * @details A concrete implementation for 120 * xyz.openbmc_project.Software.Activation DBus API. 121 */ 122 class Activation : public ActivationInherit 123 { 124 public: 125 friend class ::TestActivation; 126 using Status = Activations; 127 128 /** @brief Constructs Activation Software Manager 129 * 130 * @param[in] bus - The Dbus bus object 131 * @param[in] path - The Dbus object path 132 * @param[in] versionId - The software version id 133 * @param[in] extVersion - The extended version 134 * @param[in] activationStatus - The status of Activation 135 * @param[in] assocs - Association objects 136 * @param[in] filePath - The image filesystem path 137 */ 138 Activation(sdbusplus::bus::bus& bus, const std::string& objPath, 139 const std::string& versionId, const std::string& extVersion, 140 Status activationStatus, const AssociationList& assocs, 141 const std::string& filePath, 142 AssociationInterface* associationInterface, 143 ActivationListener* activationListener) : 144 ActivationInherit(bus, objPath.c_str(), true), 145 bus(bus), objPath(objPath), versionId(versionId), 146 systemdSignals( 147 bus, 148 sdbusRule::type::signal() + sdbusRule::member("JobRemoved") + 149 sdbusRule::path("/org/freedesktop/systemd1") + 150 sdbusRule::interface("org.freedesktop.systemd1.Manager"), 151 std::bind(&Activation::unitStateChange, this, 152 std::placeholders::_1)), 153 associationInterface(associationInterface), 154 activationListener(activationListener) 155 { 156 // Set Properties. 157 extendedVersion(extVersion); 158 activation(activationStatus); 159 associations(assocs); 160 path(filePath); 161 162 auto info = Version::getExtVersionInfo(extVersion); 163 manufacturer = info["manufacturer"]; 164 model = info["model"]; 165 166 // Emit deferred signal. 167 emit_object_added(); 168 } 169 170 /** @brief Overloaded Activation property setter function 171 * 172 * @param[in] value - One of Activation::Activations 173 * 174 * @return Success or exception thrown 175 */ 176 Status activation(Status value) override; 177 178 /** @brief Activation */ 179 using ActivationInherit::activation; 180 181 /** @brief Overloaded requestedActivation property setter function 182 * 183 * @param[in] value - One of Activation::RequestedActivations 184 * 185 * @return Success or exception thrown 186 */ 187 RequestedActivations 188 requestedActivation(RequestedActivations value) override; 189 190 /** @brief Get the object path */ 191 const std::string& getObjectPath() const 192 { 193 return objPath; 194 } 195 196 /** @brief Get the version ID */ 197 const std::string& getVersionId() const 198 { 199 return versionId; 200 } 201 202 private: 203 /** @brief Check if systemd state change is relevant to this object 204 * 205 * Instance specific interface to handle the detected systemd state 206 * change 207 * 208 * @param[in] msg - Data associated with subscribed signal 209 * 210 */ 211 void unitStateChange(sdbusplus::message::message& msg); 212 213 /** 214 * @brief Delete the version from Image Manager and the 215 * untar image from image upload dir. 216 */ 217 void deleteImageManagerObject(); 218 219 /** @brief Invoke the update service for the PSU 220 * 221 * @param[in] psuInventoryPath - The PSU inventory to be updated. 222 * 223 * @return true if the update starts, and false if it fails. 224 */ 225 bool doUpdate(const std::string& psuInventoryPath); 226 227 /** @brief Do PSU update one-by-one 228 * 229 * @return true if the update starts, and false if it fails. 230 */ 231 bool doUpdate(); 232 233 /** @brief Handle an update done event */ 234 void onUpdateDone(); 235 236 /** @brief Handle an update failure event */ 237 void onUpdateFailed(); 238 239 /** @brief Start PSU update */ 240 Status startActivation(); 241 242 /** @brief Finish PSU update */ 243 void finishActivation(); 244 245 /** @brief Check if the PSU is comaptible with this software*/ 246 bool isCompatible(const std::string& psuInventoryPath); 247 248 /** @brief Store the updated PSU image to persistent dir */ 249 void storeImage(); 250 251 /** @brief Construct the systemd service name 252 * 253 * @param[in] psuInventoryPath - The PSU inventory to be updated. 254 * 255 * @return The escaped string of systemd unit to do the PSU update. 256 */ 257 std::string getUpdateService(const std::string& psuInventoryPath); 258 259 /** @brief Persistent sdbusplus DBus bus connection */ 260 sdbusplus::bus::bus& bus; 261 262 /** @brief Persistent DBus object path */ 263 std::string objPath; 264 265 /** @brief Version id */ 266 std::string versionId; 267 268 /** @brief Used to subscribe to dbus systemd signals */ 269 sdbusplus::bus::match_t systemdSignals; 270 271 /** @brief The queue of psu objects to be updated */ 272 std::queue<std::string> psuQueue; 273 274 /** @brief The progress step for each PSU update is done */ 275 uint32_t progressStep; 276 277 /** @brief The PSU update systemd unit */ 278 std::string psuUpdateUnit; 279 280 /** @brief The PSU Inventory path of the current updating PSU */ 281 std::string currentUpdatingPsu; 282 283 /** @brief Persistent ActivationBlocksTransition dbus object */ 284 std::unique_ptr<ActivationBlocksTransition> activationBlocksTransition; 285 286 /** @brief Persistent ActivationProgress dbus object */ 287 std::unique_ptr<ActivationProgress> activationProgress; 288 289 /** @brief The AssociationInterface pointer */ 290 AssociationInterface* associationInterface; 291 292 /** @brief The activationListener pointer */ 293 ActivationListener* activationListener; 294 295 /** @brief The PSU manufacturer of the software */ 296 std::string manufacturer; 297 298 /** @brief The PSU model of the software */ 299 std::string model; 300 }; 301 302 } // namespace updater 303 } // namespace software 304 } // namespace phosphor 305