1 #pragma once
2 
3 #include "types.hpp"
4 
5 #include <experimental/any>
6 #include <sdbusplus/bus.hpp>
7 #include <set>
8 #include <string>
9 #include <vector>
10 
11 namespace utils
12 {
13 
14 class UtilsInterface;
15 
16 using AssociationList = phosphor::software::updater::AssociationList;
17 // Due to a libstdc++ bug, we got compile error using std::any with gmock.
18 // A temporary workaround is to use std::experimental::any.
19 // See details in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90415
20 using std::experimental::any;
21 using std::experimental::any_cast;
22 
23 /**
24  * @brief Get the implementation of UtilsInterface
25  */
26 const UtilsInterface& getUtils();
27 
28 /**
29  * @brief Get PSU inventory object path from DBus
30  */
31 std::vector<std::string> getPSUInventoryPath(sdbusplus::bus::bus& bus);
32 
33 /** @brief Get service name from object path and interface
34  *
35  * @param[in] bus          - The Dbus bus object
36  * @param[in] path         - The Dbus object path
37  * @param[in] interface    - The Dbus interface
38  *
39  * @return The name of the service
40  */
41 std::string getService(sdbusplus::bus::bus& bus, const char* path,
42                        const char* interface);
43 
44 /** @brief Get all the service names from object path and interface
45  *
46  * @param[in] bus          - The Dbus bus object
47  * @param[in] path         - The Dbus object path
48  * @param[in] interface    - The Dbus interface
49  *
50  * @return The name of the services
51  */
52 std::vector<std::string> getServices(sdbusplus::bus::bus& bus, const char* path,
53                                      const char* interface);
54 
55 /** @brief The template function to get property from the requested dbus path
56  *
57  * @param[in] bus          - The Dbus bus object
58  * @param[in] service      - The Dbus service name
59  * @param[in] path         - The Dbus object path
60  * @param[in] interface    - The Dbus interface
61  * @param[in] propertyName - The property name to get
62  *
63  * @return The value of the property
64  */
65 template <typename T>
66 T getProperty(sdbusplus::bus::bus& bus, const char* service, const char* path,
67               const char* interface, const char* propertyName);
68 
69 /**
70  * @brief Calculate the version id from the version string.
71  *
72  * @details The version id is a unique 8 hexadecimal digit id
73  *          calculated from the version string.
74  *
75  * @param[in] version - The image version string (e.g. v1.99.10-19).
76  *
77  * @return The id.
78  */
79 std::string getVersionId(const std::string& version);
80 
81 /** @brief Get version of PSU specified by the inventory path
82  *
83  * @param[in] inventoryPath - The PSU inventory object path
84  *
85  * @return The version string, or empry string if it fails to get the version
86  */
87 std::string getVersion(const std::string& inventoryPath);
88 
89 /** @brief Get latest version from the PSU versions
90  *
91  * @param[in] versions - The list of the versions
92  *
93  * @return The latest version string
94  */
95 std::string getLatestVersion(const std::set<std::string>& versions);
96 
97 /** @brief Check if the PSU is associated
98  *
99  * @param[in] psuInventoryPath - The PSU inventory path
100  * @param[in] assocs - The list of associations
101  *
102  * @return true if the psu is in the association list
103  */
104 bool isAssociated(const std::string& psuInventoryPath,
105                   const AssociationList& assocs);
106 
107 /**
108  * @brief The interface for utils
109  */
110 class UtilsInterface
111 {
112   public:
113     // For now the code needs to get property for Present and Version
114     using PropertyType = sdbusplus::message::variant<std::string, bool>;
115 
116     virtual ~UtilsInterface() = default;
117 
118     virtual std::vector<std::string>
119         getPSUInventoryPath(sdbusplus::bus::bus& bus) const = 0;
120 
121     virtual std::string getService(sdbusplus::bus::bus& bus, const char* path,
122                                    const char* interface) const = 0;
123 
124     virtual std::vector<std::string>
125         getServices(sdbusplus::bus::bus& bus, const char* path,
126                     const char* interface) const = 0;
127 
128     virtual std::string getVersionId(const std::string& version) const = 0;
129 
130     virtual std::string getVersion(const std::string& inventoryPath) const = 0;
131 
132     virtual std::string
133         getLatestVersion(const std::set<std::string>& versions) const = 0;
134 
135     virtual bool isAssociated(const std::string& psuInventoryPath,
136                               const AssociationList& assocs) const = 0;
137 
138     virtual any getPropertyImpl(sdbusplus::bus::bus& bus, const char* service,
139                                 const char* path, const char* interface,
140                                 const char* propertyName) const = 0;
141 
142     template <typename T>
143     T getProperty(sdbusplus::bus::bus& bus, const char* service,
144                   const char* path, const char* interface,
145                   const char* propertyName) const
146     {
147         any result =
148             getPropertyImpl(bus, service, path, interface, propertyName);
149         auto value = any_cast<PropertyType>(result);
150         return sdbusplus::message::variant_ns::get<T>(value);
151     }
152 };
153 
154 class Utils : public UtilsInterface
155 {
156   public:
157     std::vector<std::string>
158         getPSUInventoryPath(sdbusplus::bus::bus& bus) const override;
159 
160     std::string getService(sdbusplus::bus::bus& bus, const char* path,
161                            const char* interface) const override;
162 
163     std::vector<std::string> getServices(sdbusplus::bus::bus& bus,
164                                          const char* path,
165                                          const char* interface) const override;
166 
167     std::string getVersionId(const std::string& version) const override;
168 
169     std::string getVersion(const std::string& inventoryPath) const override;
170 
171     std::string
172         getLatestVersion(const std::set<std::string>& versions) const override;
173 
174     bool isAssociated(const std::string& psuInventoryPath,
175                       const AssociationList& assocs) const override;
176 
177     any getPropertyImpl(sdbusplus::bus::bus& bus, const char* service,
178                         const char* path, const char* interface,
179                         const char* propertyName) const override;
180 };
181 
182 inline std::string getService(sdbusplus::bus::bus& bus, const char* path,
183                               const char* interface)
184 {
185     return getUtils().getService(bus, path, interface);
186 }
187 
188 inline std::vector<std::string> getServices(sdbusplus::bus::bus& bus,
189                                             const char* path,
190                                             const char* interface)
191 {
192     return getUtils().getServices(bus, path, interface);
193 }
194 
195 inline std::vector<std::string> getPSUInventoryPath(sdbusplus::bus::bus& bus)
196 {
197     return getUtils().getPSUInventoryPath(bus);
198 }
199 
200 inline std::string getVersionId(const std::string& version)
201 {
202     return getUtils().getVersionId(version);
203 }
204 
205 inline std::string getVersion(const std::string& inventoryPath)
206 {
207     return getUtils().getVersion(inventoryPath);
208 }
209 
210 inline std::string getLatestVersion(const std::set<std::string>& versions)
211 {
212     return getUtils().getLatestVersion(versions);
213 }
214 
215 inline bool isAssociated(const std::string& psuInventoryPath,
216                          const AssociationList& assocs)
217 {
218     return getUtils().isAssociated(psuInventoryPath, assocs);
219 }
220 
221 template <typename T>
222 T getProperty(sdbusplus::bus::bus& bus, const char* service, const char* path,
223               const char* interface, const char* propertyName)
224 {
225     return getUtils().getProperty<T>(bus, service, path, interface,
226                                      propertyName);
227 }
228 
229 } // namespace utils
230