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&
47         operator=(const ActivationBlocksTransition&) = delete;
48     ActivationBlocksTransition(ActivationBlocksTransition&&) = delete;
49     ActivationBlocksTransition&
50         operator=(ActivationBlocksTransition&&) = delete;
51 
52     /** @brief Constructs ActivationBlocksTransition.
53      *
54      * @param[in] bus    - The Dbus bus object
55      * @param[in] path   - The Dbus object path
56      */
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 
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      */
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      */
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         auto info = Version::getExtVersionInfo(extVersion);
152         manufacturer = info["manufacturer"];
153         model = info["model"];
154 
155         // Emit deferred signal.
156         emit_object_added();
157     }
158 
159     /** @brief Overloaded Activation property setter function
160      *
161      * @param[in] value - One of Activation::Activations
162      *
163      * @return Success or exception thrown
164      */
165     Status activation(Status value) override;
166 
167     /** @brief Activation */
168     using ActivationInherit::activation;
169 
170     /** @brief Overloaded requestedActivation property setter function
171      *
172      * @param[in] value - One of Activation::RequestedActivations
173      *
174      * @return Success or exception thrown
175      */
176     RequestedActivations
177         requestedActivation(RequestedActivations value) override;
178 
179     /** @brief Get the object path */
180     const std::string& getObjectPath() const
181     {
182         return objPath;
183     }
184 
185     /** @brief Get the version ID */
186     const std::string& getVersionId() const
187     {
188         return versionId;
189     }
190 
191   private:
192     /** @brief Check if systemd state change is relevant to this object
193      *
194      * Instance specific interface to handle the detected systemd state
195      * change
196      *
197      * @param[in]  msg       - Data associated with subscribed signal
198      *
199      */
200     void unitStateChange(sdbusplus::message_t& msg);
201 
202     /**
203      * @brief Delete the version from Image Manager and the
204      *        untar image from image upload dir.
205      */
206     void deleteImageManagerObject();
207 
208     /** @brief Invoke the update service for the PSU
209      *
210      * @param[in] psuInventoryPath - The PSU inventory to be updated.
211      *
212      * @return true if the update starts, and false if it fails.
213      */
214     bool doUpdate(const std::string& psuInventoryPath);
215 
216     /** @brief Do PSU update one-by-one
217      *
218      * @return true if the update starts, and false if it fails.
219      */
220     bool doUpdate();
221 
222     /** @brief Handle an update done event */
223     void onUpdateDone();
224 
225     /** @brief Handle an update failure event */
226     void onUpdateFailed();
227 
228     /** @brief Start PSU update */
229     Status startActivation();
230 
231     /** @brief Finish PSU update */
232     void finishActivation();
233 
234     /** @brief Check if the PSU is compatible with this software*/
235     bool isCompatible(const std::string& psuInventoryPath);
236 
237     /** @brief Store the updated PSU image to persistent dir */
238     void storeImage();
239 
240     /** @brief Construct the systemd service name
241      *
242      *  @details Throws an exception if an error occurs
243      *
244      * @param[in] psuInventoryPath - The PSU inventory to be updated.
245      *
246      * @return The escaped string of systemd unit to do the PSU update.
247      */
248     std::string getUpdateService(const std::string& psuInventoryPath);
249 
250     /** @brief Persistent sdbusplus DBus bus connection */
251     sdbusplus::bus_t& bus;
252 
253     /** @brief Persistent DBus object path */
254     std::string objPath;
255 
256     /** @brief Version id */
257     std::string versionId;
258 
259     /** @brief Used to subscribe to dbus systemd signals */
260     sdbusplus::bus::match_t systemdSignals;
261 
262     /** @brief The queue of psu objects to be updated */
263     std::queue<std::string> psuQueue;
264 
265     /** @brief The progress step for each PSU update is done */
266     uint32_t progressStep;
267 
268     /** @brief The PSU update systemd unit */
269     std::string psuUpdateUnit;
270 
271     /** @brief The PSU Inventory path of the current updating PSU */
272     std::string currentUpdatingPsu;
273 
274     /** @brief Persistent ActivationBlocksTransition dbus object */
275     std::unique_ptr<ActivationBlocksTransition> activationBlocksTransition;
276 
277     /** @brief Persistent ActivationProgress dbus object */
278     std::unique_ptr<ActivationProgress> activationProgress;
279 
280     /** @brief The AssociationInterface pointer */
281     AssociationInterface* associationInterface;
282 
283     /** @brief The activationListener pointer */
284     ActivationListener* activationListener;
285 
286     /** @brief The PSU manufacturer of the software */
287     std::string manufacturer;
288 
289     /** @brief The PSU model of the software */
290     std::string model;
291 };
292 
293 } // namespace updater
294 } // namespace software
295 } // namespace phosphor
296