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