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