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