#pragma once #include "config.h" #include "activation_listener.hpp" #include "association_interface.hpp" #include "types.hpp" #include "version.hpp" #include <sdbusplus/server.hpp> #include <xyz/openbmc_project/Association/Definitions/server.hpp> #include <xyz/openbmc_project/Common/FilePath/server.hpp> #include <xyz/openbmc_project/Software/Activation/server.hpp> #include <xyz/openbmc_project/Software/ActivationBlocksTransition/server.hpp> #include <xyz/openbmc_project/Software/ActivationProgress/server.hpp> #include <xyz/openbmc_project/Software/ExtendedVersion/server.hpp> #include <queue> #include <string> class TestActivation; namespace phosphor { namespace software { namespace updater { namespace sdbusRule = sdbusplus::bus::match::rules; using ActivationBlocksTransitionInherit = sdbusplus::server::object_t<sdbusplus::xyz::openbmc_project::Software:: server::ActivationBlocksTransition>; /** @class ActivationBlocksTransition * @brief OpenBMC ActivationBlocksTransition implementation. * @details A concrete implementation for * xyz.openbmc_project.Software.ActivationBlocksTransition DBus API. */ class ActivationBlocksTransition : public ActivationBlocksTransitionInherit { public: ActivationBlocksTransition() = delete; ActivationBlocksTransition(const ActivationBlocksTransition&) = delete; ActivationBlocksTransition& operator=(const ActivationBlocksTransition&) = delete; ActivationBlocksTransition(ActivationBlocksTransition&&) = delete; ActivationBlocksTransition& operator=(ActivationBlocksTransition&&) = delete; /** @brief Constructs ActivationBlocksTransition. * * @param[in] bus - The Dbus bus object * @param[in] path - The Dbus object path */ ActivationBlocksTransition(sdbusplus::bus_t& bus, const std::string& path) : ActivationBlocksTransitionInherit(bus, path.c_str(), action::emit_interface_added), bus(bus) { enableRebootGuard(); } ~ActivationBlocksTransition() override { disableRebootGuard(); } private: sdbusplus::bus_t& bus; /** @brief Enables a Guard that blocks any BMC reboot commands */ void enableRebootGuard(); /** @brief Disables any guard that was blocking the BMC reboot */ void disableRebootGuard(); }; using ActivationProgressInherit = sdbusplus::server::object_t< sdbusplus::xyz::openbmc_project::Software::server::ActivationProgress>; class ActivationProgress : public ActivationProgressInherit { public: /** @brief Constructs ActivationProgress. * * @param[in] bus - The Dbus bus object * @param[in] path - The Dbus object path */ ActivationProgress(sdbusplus::bus_t& bus, const std::string& path) : ActivationProgressInherit(bus, path.c_str(), action::emit_interface_added) { progress(0); } }; using ActivationInherit = sdbusplus::server::object_t< sdbusplus::xyz::openbmc_project::Software::server::ExtendedVersion, sdbusplus::xyz::openbmc_project::Software::server::Activation, sdbusplus::xyz::openbmc_project::Association::server::Definitions, sdbusplus::xyz::openbmc_project::Common::server::FilePath>; /** @class Activation * @brief OpenBMC activation software management implementation. * @details A concrete implementation for * xyz.openbmc_project.Software.Activation DBus API. */ class Activation : public ActivationInherit { public: friend class ::TestActivation; using Status = Activations; /** @brief Constructs Activation Software Manager * * @param[in] bus - The Dbus bus object * @param[in] path - The Dbus object path * @param[in] versionId - The software version id * @param[in] extVersion - The extended version * @param[in] activationStatus - The status of Activation * @param[in] assocs - Association objects * @param[in] filePath - The image filesystem path */ Activation(sdbusplus::bus_t& bus, const std::string& objPath, const std::string& versionId, const std::string& extVersion, Status activationStatus, const AssociationList& assocs, const std::string& filePath, AssociationInterface* associationInterface, ActivationListener* activationListener) : ActivationInherit(bus, objPath.c_str(), ActivationInherit::action::defer_emit), bus(bus), objPath(objPath), versionId(versionId), systemdSignals( bus, sdbusRule::type::signal() + sdbusRule::member("JobRemoved") + sdbusRule::path("/org/freedesktop/systemd1") + sdbusRule::interface("org.freedesktop.systemd1.Manager"), std::bind(&Activation::unitStateChange, this, std::placeholders::_1)), associationInterface(associationInterface), activationListener(activationListener) { // Set Properties. extendedVersion(extVersion); activation(activationStatus); associations(assocs); path(filePath); // Emit deferred signal. emit_object_added(); } /** @brief Overloaded Activation property setter function * * @param[in] value - One of Activation::Activations * * @return Success or exception thrown */ Status activation(Status value) override; /** @brief Activation */ using ActivationInherit::activation; /** @brief Overloaded requestedActivation property setter function * * @param[in] value - One of Activation::RequestedActivations * * @return Success or exception thrown */ RequestedActivations requestedActivation(RequestedActivations value) override; /** @brief Overloaded ExtendedVersion property setter function * * @param[in] value - Extended version value * * @return New value of property */ std::string extendedVersion(std::string value) override; /** @brief Get the object path */ const std::string& getObjectPath() const { return objPath; } /** @brief Get the version ID */ const std::string& getVersionId() const { return versionId; } private: /** @brief Check if systemd state change is relevant to this object * * Instance specific interface to handle the detected systemd state * change * * @param[in] msg - Data associated with subscribed signal * */ void unitStateChange(sdbusplus::message_t& msg); /** * @brief Delete the version from Image Manager and the * untar image from image upload dir. */ void deleteImageManagerObject(); /** @brief Invoke the update service for the PSU * * @param[in] psuInventoryPath - The PSU inventory to be updated. * * @return true if the update starts, and false if it fails. */ bool doUpdate(const std::string& psuInventoryPath); /** @brief Do PSU update one-by-one * * @return true if the update starts, and false if it fails. */ bool doUpdate(); /** @brief Handle an update done event */ void onUpdateDone(); /** @brief Handle an update failure event */ void onUpdateFailed(); /** @brief Start PSU update */ Status startActivation(); /** @brief Finish PSU update */ void finishActivation(); /** @brief Check if the PSU is present */ bool isPresent(const std::string& psuInventoryPath); /** @brief Check if the PSU is compatible with this software*/ bool isCompatible(const std::string& psuInventoryPath); /** @brief Store the updated PSU image to persistent dir */ void storeImage(); /** @brief Construct the systemd service name * * @details Throws an exception if an error occurs * * @param[in] psuInventoryPath - The PSU inventory to be updated. * * @return The escaped string of systemd unit to do the PSU update. */ std::string getUpdateService(const std::string& psuInventoryPath); /** @brief Persistent sdbusplus DBus bus connection */ sdbusplus::bus_t& bus; /** @brief Persistent DBus object path */ std::string objPath; /** @brief Version id */ std::string versionId; /** @brief Used to subscribe to dbus systemd signals */ sdbusplus::bus::match_t systemdSignals; /** @brief The queue of psu objects to be updated */ std::queue<std::string> psuQueue; /** @brief The progress step for each PSU update is done */ uint32_t progressStep; /** @brief The PSU update systemd unit */ std::string psuUpdateUnit; /** @brief The PSU Inventory path of the current updating PSU */ std::string currentUpdatingPsu; /** @brief Persistent ActivationBlocksTransition dbus object */ std::unique_ptr<ActivationBlocksTransition> activationBlocksTransition; /** @brief Persistent ActivationProgress dbus object */ std::unique_ptr<ActivationProgress> activationProgress; /** @brief The AssociationInterface pointer */ AssociationInterface* associationInterface; /** @brief The activationListener pointer */ ActivationListener* activationListener; /** @brief The PSU manufacturer of the software */ std::string manufacturer; /** @brief The PSU model of the software */ std::string model; /** @brief Indicates whether to automatically activate again after current * request finishes */ bool shouldActivateAgain{false}; }; } // namespace updater } // namespace software } // namespace phosphor