1 #pragma once
2 
3 #include "config.h"
4 
5 #include "association_interface.hpp"
6 #include "types.hpp"
7 #include "version.hpp"
8 
9 #include <queue>
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 class TestActivation;
19 
20 namespace phosphor
21 {
22 namespace software
23 {
24 namespace updater
25 {
26 
27 namespace sdbusRule = sdbusplus::bus::match::rules;
28 
29 using ActivationBlocksTransitionInherit = sdbusplus::server::object::object<
30     sdbusplus::xyz::openbmc_project::Software::server::
31         ActivationBlocksTransition>;
32 
33 /** @class ActivationBlocksTransition
34  *  @brief OpenBMC ActivationBlocksTransition implementation.
35  *  @details A concrete implementation for
36  *  xyz.openbmc_project.Software.ActivationBlocksTransition DBus API.
37  */
38 class ActivationBlocksTransition : public ActivationBlocksTransitionInherit
39 {
40   public:
41     /** @brief Constructs ActivationBlocksTransition.
42      *
43      * @param[in] bus    - The Dbus bus object
44      * @param[in] path   - The Dbus object path
45      */
46     ActivationBlocksTransition(sdbusplus::bus::bus& bus,
47                                const std::string& path) :
48         ActivationBlocksTransitionInherit(bus, path.c_str(), true),
49         bus(bus), path(path)
50     {
51         std::vector<std::string> interfaces({interface});
52         bus.emit_interfaces_added(path.c_str(), interfaces);
53     }
54 
55     ~ActivationBlocksTransition()
56     {
57         std::vector<std::string> interfaces({interface});
58         bus.emit_interfaces_removed(path.c_str(), interfaces);
59     }
60 
61   private:
62     // TODO Remove once openbmc/openbmc#1975 is resolved
63     static constexpr auto interface =
64         "xyz.openbmc_project.Software.ActivationBlocksTransition";
65     sdbusplus::bus::bus& bus;
66     std::string path;
67 };
68 
69 using ActivationProgressInherit = sdbusplus::server::object::object<
70     sdbusplus::xyz::openbmc_project::Software::server::ActivationProgress>;
71 
72 class ActivationProgress : public ActivationProgressInherit
73 {
74   public:
75     /** @brief Constructs ActivationProgress.
76      *
77      * @param[in] bus    - The Dbus bus object
78      * @param[in] path   - The Dbus object path
79      */
80     ActivationProgress(sdbusplus::bus::bus& bus, const std::string& path) :
81         ActivationProgressInherit(bus, path.c_str(), true), bus(bus), path(path)
82     {
83         progress(0);
84         std::vector<std::string> interfaces({interface});
85         bus.emit_interfaces_added(path.c_str(), interfaces);
86     }
87 
88     ~ActivationProgress()
89     {
90         std::vector<std::string> interfaces({interface});
91         bus.emit_interfaces_removed(path.c_str(), interfaces);
92     }
93 
94   private:
95     // TODO Remove once openbmc/openbmc#1975 is resolved
96     static constexpr auto interface =
97         "xyz.openbmc_project.Software.ActivationProgress";
98     sdbusplus::bus::bus& bus;
99     std::string path;
100 };
101 
102 using ActivationInherit = sdbusplus::server::object::object<
103     sdbusplus::xyz::openbmc_project::Software::server::ExtendedVersion,
104     sdbusplus::xyz::openbmc_project::Software::server::Activation,
105     sdbusplus::xyz::openbmc_project::Association::server::Definitions,
106     sdbusplus::xyz::openbmc_project::Common::server::FilePath>;
107 
108 /** @class Activation
109  *  @brief OpenBMC activation software management implementation.
110  *  @details A concrete implementation for
111  *  xyz.openbmc_project.Software.Activation DBus API.
112  */
113 class Activation : public ActivationInherit
114 {
115   public:
116     friend class ::TestActivation;
117     using Status = Activations;
118 
119     /** @brief Constructs Activation Software Manager
120      *
121      * @param[in] bus    - The Dbus bus object
122      * @param[in] path   - The Dbus object path
123      * @param[in] versionId  - The software version id
124      * @param[in] extVersion - The extended version
125      * @param[in] activationStatus - The status of Activation
126      * @param[in] assocs - Association objects
127      * @param[in] filePath - The image filesystem path
128      */
129     Activation(sdbusplus::bus::bus& bus, const std::string& objPath,
130                const std::string& versionId, const std::string& extVersion,
131                Status activationStatus, const AssociationList& assocs,
132                AssociationInterface* associationInterface,
133                const std::string& filePath) :
134         ActivationInherit(bus, objPath.c_str(), true),
135         bus(bus), objPath(objPath), versionId(versionId),
136         systemdSignals(
137             bus,
138             sdbusRule::type::signal() + sdbusRule::member("JobRemoved") +
139                 sdbusRule::path("/org/freedesktop/systemd1") +
140                 sdbusRule::interface("org.freedesktop.systemd1.Manager"),
141             std::bind(&Activation::unitStateChange, this,
142                       std::placeholders::_1)),
143         associationInterface(associationInterface)
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::message& 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 comaptible 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      * @param[in] psuInventoryPath - The PSU inventory to be updated.
243      *
244      * @return The escaped string of systemd unit to do the PSU update.
245      */
246     std::string getUpdateService(const std::string& psuInventoryPath);
247 
248     /** @brief Persistent sdbusplus DBus bus connection */
249     sdbusplus::bus::bus& bus;
250 
251     /** @brief Persistent DBus object path */
252     std::string objPath;
253 
254     /** @brief Version id */
255     std::string versionId;
256 
257     /** @brief Used to subscribe to dbus systemd signals */
258     sdbusplus::bus::match_t systemdSignals;
259 
260     /** @brief The queue of psu objects to be updated */
261     std::queue<std::string> psuQueue;
262 
263     /** @brief The progress step for each PSU update is done */
264     uint32_t progressStep;
265 
266     /** @brief The PSU update systemd unit */
267     std::string psuUpdateUnit;
268 
269     /** @brief The PSU Inventory path of the current updating PSU */
270     std::string currentUpdatingPsu;
271 
272     /** @brief Persistent ActivationBlocksTransition dbus object */
273     std::unique_ptr<ActivationBlocksTransition> activationBlocksTransition;
274 
275     /** @brief Persistent ActivationProgress dbus object */
276     std::unique_ptr<ActivationProgress> activationProgress;
277 
278     /** @brief The AssociationInterface pointer */
279     AssociationInterface* associationInterface;
280 
281     /** @brief The PSU manufacturer of the software */
282     std::string manufacturer;
283 
284     /** @brief The PSU model of the software */
285     std::string model;
286 };
287 
288 } // namespace updater
289 } // namespace software
290 } // namespace phosphor
291