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 =
31     sdbusplus::server::object_t<sdbusplus::xyz::openbmc_project::Software::
32                                     server::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_t& bus, const std::string& path) :
48         ActivationBlocksTransitionInherit(bus, path.c_str(),
49                                           action::emit_interface_added),
50         bus(bus)
51     {
52         enableRebootGuard();
53     }
54 
55     ~ActivationBlocksTransition()
56     {
57         disableRebootGuard();
58     }
59 
60   private:
61     sdbusplus::bus_t& bus;
62 
63     /** @brief Enables a Guard that blocks any BMC reboot commands */
64     void enableRebootGuard();
65 
66     /** @brief Disables any guard that was blocking the BMC reboot */
67     void disableRebootGuard();
68 };
69 
70 using ActivationProgressInherit = sdbusplus::server::object_t<
71     sdbusplus::xyz::openbmc_project::Software::server::ActivationProgress>;
72 
73 class ActivationProgress : public ActivationProgressInherit
74 {
75   public:
76     /** @brief Constructs ActivationProgress.
77      *
78      * @param[in] bus    - The Dbus bus object
79      * @param[in] path   - The Dbus object path
80      */
81     ActivationProgress(sdbusplus::bus_t& bus, const std::string& path) :
82         ActivationProgressInherit(bus, path.c_str(),
83                                   action::emit_interface_added)
84     {
85         progress(0);
86     }
87 };
88 
89 using ActivationInherit = sdbusplus::server::object_t<
90     sdbusplus::xyz::openbmc_project::Software::server::ExtendedVersion,
91     sdbusplus::xyz::openbmc_project::Software::server::Activation,
92     sdbusplus::xyz::openbmc_project::Association::server::Definitions,
93     sdbusplus::xyz::openbmc_project::Common::server::FilePath>;
94 
95 /** @class Activation
96  *  @brief OpenBMC activation software management implementation.
97  *  @details A concrete implementation for
98  *  xyz.openbmc_project.Software.Activation DBus API.
99  */
100 class Activation : public ActivationInherit
101 {
102   public:
103     friend class ::TestActivation;
104     using Status = Activations;
105 
106     /** @brief Constructs Activation Software Manager
107      *
108      * @param[in] bus    - The Dbus bus object
109      * @param[in] path   - The Dbus object path
110      * @param[in] versionId  - The software version id
111      * @param[in] extVersion - The extended version
112      * @param[in] activationStatus - The status of Activation
113      * @param[in] assocs - Association objects
114      * @param[in] filePath - The image filesystem path
115      */
116     Activation(sdbusplus::bus_t& bus, const std::string& objPath,
117                const std::string& versionId, const std::string& extVersion,
118                Status activationStatus, const AssociationList& assocs,
119                const std::string& filePath,
120                AssociationInterface* associationInterface,
121                ActivationListener* activationListener) :
122         ActivationInherit(bus, objPath.c_str(),
123                           ActivationInherit::action::defer_emit),
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_t& 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_t& 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