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