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