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