xref: /openbmc/entity-manager/src/entity_manager/dbus_interface.hpp (revision bc0b05bea374093673a94cfe3b8d455a72f3b9ad)
1 #pragma once
2 
3 #include "configuration.hpp"
4 
5 #include <boost/container/flat_map.hpp>
6 #include <nlohmann/json.hpp>
7 #include <phosphor-logging/lg2.hpp>
8 #include <sdbusplus/asio/connection.hpp>
9 #include <sdbusplus/asio/object_server.hpp>
10 
11 #include <flat_map>
12 #include <vector>
13 
14 namespace dbus_interface
15 {
16 
17 using JsonVariantType =
18     std::variant<std::vector<std::string>, std::vector<double>, std::string,
19                  int64_t, uint64_t, double, int32_t, uint32_t, int16_t,
20                  uint16_t, uint8_t, bool>;
21 
22 class EMDBusInterface
23 {
24   public:
25     EMDBusInterface(boost::asio::io_context& io,
26                     sdbusplus::asio::object_server& objServer,
27                     const std::filesystem::path& schemaDirectory);
28 
29     std::shared_ptr<sdbusplus::asio::dbus_interface> createInterface(
30         const std::string& path, const std::string& interface,
31         const std::string& parent, bool checkNull = false);
32 
33     std::vector<std::weak_ptr<sdbusplus::asio::dbus_interface>>&
34         getDeviceInterfaces(const nlohmann::json& device);
35 
36     void createAddObjectMethod(const std::string& jsonPointerPath,
37                                const std::string& path,
38                                nlohmann::json& systemConfiguration,
39                                const std::string& board);
40 
41     void populateInterfaceFromJson(
42         nlohmann::json& systemConfiguration, const std::string& jsonPointerPath,
43         std::shared_ptr<sdbusplus::asio::dbus_interface>& iface,
44         nlohmann::json& dict,
45         sdbusplus::asio::PropertyPermission permission =
46             sdbusplus::asio::PropertyPermission::readOnly);
47 
48     void createDeleteObjectMethod(
49         const std::string& jsonPointerPath,
50         const std::shared_ptr<sdbusplus::asio::dbus_interface>& iface,
51         nlohmann::json& systemConfiguration);
52 
53   private:
54     void addObject(
55         const std::flat_map<std::string, JsonVariantType, std::less<>>& data,
56         nlohmann::json& systemConfiguration, const std::string& jsonPointerPath,
57         const std::string& path, const std::string& board);
58 
59     // @brief: same as 'addObject', but operates on json
60     void addObjectJson(nlohmann::json& newData,
61                        nlohmann::json& systemConfiguration,
62                        const std::string& jsonPointerPath,
63                        const std::string& path, const std::string& board);
64 
65     boost::asio::io_context& io;
66     sdbusplus::asio::object_server& objServer;
67 
68     boost::container::flat_map<
69         std::string,
70         std::vector<std::weak_ptr<sdbusplus::asio::dbus_interface>>>
71         inventory;
72 
73     const std::filesystem::path schemaDirectory;
74 };
75 
76 void tryIfaceInitialize(
77     std::shared_ptr<sdbusplus::asio::dbus_interface>& iface);
78 
79 template <typename PropertyType>
addArrayToDbus(const std::string & name,const nlohmann::json & array,sdbusplus::asio::dbus_interface * iface,sdbusplus::asio::PropertyPermission permission,nlohmann::json & systemConfiguration,const std::string & jsonPointerString)80 void addArrayToDbus(const std::string& name, const nlohmann::json& array,
81                     sdbusplus::asio::dbus_interface* iface,
82                     sdbusplus::asio::PropertyPermission permission,
83                     nlohmann::json& systemConfiguration,
84                     const std::string& jsonPointerString)
85 {
86     std::vector<PropertyType> values;
87     for (const auto& property : array)
88     {
89         auto ptr = property.get_ptr<const PropertyType*>();
90         if (ptr != nullptr)
91         {
92             values.emplace_back(*ptr);
93         }
94     }
95 
96     if (permission == sdbusplus::asio::PropertyPermission::readOnly)
97     {
98         iface->register_property(name, values);
99     }
100     else
101     {
102         iface->register_property(
103             name, values,
104             [&systemConfiguration,
105              jsonPointerString{std::string(jsonPointerString)}](
106                 const std::vector<PropertyType>& newVal,
107                 std::vector<PropertyType>& val) {
108                 val = newVal;
109                 if (!setJsonFromPointer(jsonPointerString, val,
110                                         systemConfiguration))
111                 {
112                     lg2::error("error setting json field");
113                     return -1;
114                 }
115                 if (!writeJsonFiles(systemConfiguration))
116                 {
117                     lg2::error("error setting json file");
118                     return -1;
119                 }
120                 return 1;
121             });
122     }
123 }
124 
125 template <typename PropertyType>
addProperty(const std::string & name,const PropertyType & value,sdbusplus::asio::dbus_interface * iface,nlohmann::json & systemConfiguration,const std::string & jsonPointerString,sdbusplus::asio::PropertyPermission permission)126 void addProperty(const std::string& name, const PropertyType& value,
127                  sdbusplus::asio::dbus_interface* iface,
128                  nlohmann::json& systemConfiguration,
129                  const std::string& jsonPointerString,
130                  sdbusplus::asio::PropertyPermission permission)
131 {
132     if (permission == sdbusplus::asio::PropertyPermission::readOnly)
133     {
134         iface->register_property(name, value);
135         return;
136     }
137     iface->register_property(
138         name, value,
139         [&systemConfiguration,
140          jsonPointerString{std::string(jsonPointerString)}](
141             const PropertyType& newVal, PropertyType& val) {
142             val = newVal;
143             if (!setJsonFromPointer(jsonPointerString, val,
144                                     systemConfiguration))
145             {
146                 lg2::error("error setting json field");
147                 return -1;
148             }
149             if (!writeJsonFiles(systemConfiguration))
150             {
151                 lg2::error("error setting json file");
152                 return -1;
153             }
154             return 1;
155         });
156 }
157 
158 template <typename PropertyType>
addValueToDBus(const std::string & key,const nlohmann::json & value,sdbusplus::asio::dbus_interface & iface,sdbusplus::asio::PropertyPermission permission,nlohmann::json & systemConfiguration,const std::string & path)159 void addValueToDBus(const std::string& key, const nlohmann::json& value,
160                     sdbusplus::asio::dbus_interface& iface,
161                     sdbusplus::asio::PropertyPermission permission,
162                     nlohmann::json& systemConfiguration,
163                     const std::string& path)
164 {
165     if (value.is_array())
166     {
167         addArrayToDbus<PropertyType>(key, value, &iface, permission,
168                                      systemConfiguration, path);
169     }
170     else
171     {
172         addProperty(key, value.get<PropertyType>(), &iface, systemConfiguration,
173                     path, sdbusplus::asio::PropertyPermission::readOnly);
174     }
175 }
176 
177 } // namespace dbus_interface
178