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