xref: /openbmc/openpower-vpd-parser/vpd-manager/src/listener.cpp (revision b198eb5dd37c203e73c99e3318e8da913c3186ce)
1 #include "listener.hpp"
2 
3 #include "constants.hpp"
4 #include "event_logger.hpp"
5 #include "utility/dbus_utility.hpp"
6 #include "utility/json_utility.hpp"
7 
8 namespace vpd
9 {
Listener(const std::shared_ptr<Worker> & i_worker,const std::shared_ptr<sdbusplus::asio::connection> & i_asioConnection)10 Listener::Listener(
11     const std::shared_ptr<Worker>& i_worker,
12     const std::shared_ptr<sdbusplus::asio::connection>& i_asioConnection) :
13     m_worker(i_worker), m_asioConnection(i_asioConnection)
14 {}
15 
registerHostStateChangeCallback() const16 void Listener::registerHostStateChangeCallback() const noexcept
17 {
18     try
19     {
20         static std::shared_ptr<sdbusplus::bus::match_t> l_hostState =
21             std::make_shared<sdbusplus::bus::match_t>(
22                 *m_asioConnection,
23                 sdbusplus::bus::match::rules::propertiesChanged(
24                     constants::hostObjectPath, constants::hostInterface),
25                 [this](sdbusplus::message_t& i_msg) {
26                     hostStateChangeCallBack(i_msg);
27                 });
28     }
29     catch (const std::exception& l_ex)
30     {
31         logging::logMessage(
32             "Register Host state change callback failed, reason: " +
33             std::string(l_ex.what()));
34     }
35 }
36 
hostStateChangeCallBack(sdbusplus::message_t & i_msg) const37 void Listener::hostStateChangeCallBack(
38     sdbusplus::message_t& i_msg) const noexcept
39 {
40     try
41     {
42         if (i_msg.is_method_error())
43         {
44             throw std::runtime_error(
45                 "Error reading callback message for host state");
46         }
47 
48         std::string l_objectPath;
49         types::PropertyMap l_propMap;
50         i_msg.read(l_objectPath, l_propMap);
51 
52         const auto l_itr = l_propMap.find("CurrentHostState");
53 
54         if (l_itr == l_propMap.end())
55         {
56             // CurrentHostState is not found in the callback message
57             return;
58         }
59 
60         if (auto l_hostState = std::get_if<std::string>(&(l_itr->second)))
61         {
62             // implies system is moving from standby to power on state
63             if (*l_hostState == "xyz.openbmc_project.State.Host.HostState."
64                                 "TransitioningToRunning")
65             {
66                 // TODO: check for all the essential FRUs in the system.
67 
68                 if (m_worker.get() != nullptr)
69                 {
70                     // Perform recollection.
71                     m_worker->performVpdRecollection();
72                 }
73                 else
74                 {
75                     logging::logMessage(
76                         "Failed to get worker object, Abort re-collection");
77                 }
78             }
79         }
80         else
81         {
82             throw std::runtime_error(
83                 "Invalid type recieved in variant for host state.");
84         }
85     }
86     catch (const std::exception& l_ex)
87     {
88         EventLogger::createSyncPel(
89             EventLogger::getErrorType(l_ex), types::SeverityType::Informational,
90             __FILE__, __FUNCTION__, 0,
91             "Host state change callback failed, reason: " +
92                 std::string(l_ex.what()),
93             std::nullopt, std::nullopt, std::nullopt, std::nullopt);
94     }
95 }
96 
registerAssetTagChangeCallback() const97 void Listener::registerAssetTagChangeCallback() const noexcept
98 {
99     try
100     {
101         static std::shared_ptr<sdbusplus::bus::match_t> l_assetMatch =
102             std::make_shared<sdbusplus::bus::match_t>(
103                 *m_asioConnection,
104                 sdbusplus::bus::match::rules::propertiesChanged(
105                     constants::systemInvPath, constants::assetTagInf),
106                 [this](sdbusplus::message_t& l_msg) {
107                     assetTagChangeCallback(l_msg);
108                 });
109     }
110     catch (const std::exception& l_ex)
111     {
112         logging::logMessage(
113             "Register AssetTag change callback failed, reason: " +
114             std::string(l_ex.what()));
115     }
116 }
117 
assetTagChangeCallback(sdbusplus::message_t & i_msg) const118 void Listener::assetTagChangeCallback(
119     sdbusplus::message_t& i_msg) const noexcept
120 {
121     try
122     {
123         if (i_msg.is_method_error())
124         {
125             throw std::runtime_error(
126                 "Error reading callback msg for asset tag.");
127         }
128 
129         std::string l_objectPath;
130         types::PropertyMap l_propMap;
131         i_msg.read(l_objectPath, l_propMap);
132 
133         const auto& l_itrToAssetTag = l_propMap.find("AssetTag");
134         if (l_itrToAssetTag != l_propMap.end())
135         {
136             if (auto l_assetTag =
137                     std::get_if<std::string>(&(l_itrToAssetTag->second)))
138             {
139                 // Call Notify to persist the AssetTag
140                 types::ObjectMap l_objectMap = {
141                     {sdbusplus::message::object_path(constants::systemInvPath),
142                      {{constants::assetTagInf, {{"AssetTag", *l_assetTag}}}}}};
143 
144                 // Notify PIM
145                 if (!dbusUtility::callPIM(move(l_objectMap)))
146                 {
147                     throw std::runtime_error(
148                         "Call to PIM failed for asset tag update.");
149                 }
150             }
151         }
152         else
153         {
154             throw std::runtime_error(
155                 "Could not find asset tag in callback message.");
156         }
157     }
158     catch (const std::exception& l_ex)
159     {
160         EventLogger::createSyncPel(
161             EventLogger::getErrorType(l_ex), types::SeverityType::Informational,
162             __FILE__, __FUNCTION__, 0,
163             "AssetTag update failed, reason: " + std::string(l_ex.what()),
164             std::nullopt, std::nullopt, std::nullopt, std::nullopt);
165     }
166 }
167 
registerPresenceChangeCallback()168 void Listener::registerPresenceChangeCallback() noexcept
169 {
170     try
171     {
172         // get list of FRUs for which presence monitoring is required
173         const auto& l_listOfFrus = jsonUtility::getFrusWithPresenceMonitoring(
174             m_worker->getSysCfgJsonObj());
175 
176         for (const auto& l_inventoryPath : l_listOfFrus)
177         {
178             std::shared_ptr<sdbusplus::bus::match_t> l_fruPresenceMatch =
179                 std::make_shared<sdbusplus::bus::match_t>(
180                     *m_asioConnection,
181                     sdbusplus::bus::match::rules::propertiesChanged(
182                         l_inventoryPath, constants::inventoryItemInf),
183                     [this](sdbusplus::message_t& i_msg) {
184                         presentPropertyChangeCallback(i_msg);
185                     });
186 
187             // save the match object to map
188             m_fruPresenceMatchObjectMap[l_inventoryPath] = l_fruPresenceMatch;
189         }
190     }
191     catch (const std::exception& l_ex)
192     {
193         EventLogger::createSyncPel(
194             EventLogger::getErrorType(l_ex), types::SeverityType::Informational,
195             __FILE__, __FUNCTION__, 0,
196             "Register presence change callback failed, reason: " +
197                 std::string(l_ex.what()),
198             std::nullopt, std::nullopt, std::nullopt, std::nullopt);
199     }
200 }
201 
presentPropertyChangeCallback(sdbusplus::message_t & i_msg) const202 void Listener::presentPropertyChangeCallback(
203     sdbusplus::message_t& i_msg) const noexcept
204 {
205     try
206     {
207         if (i_msg.is_method_error())
208         {
209             throw DbusException(
210                 "Error reading callback message for Present property change");
211         }
212 
213         std::string l_interface;
214         types::PropertyMap l_propMap;
215         i_msg.read(l_interface, l_propMap);
216 
217         const std::string l_objectPath{i_msg.get_path()};
218 
219         const auto l_itr = l_propMap.find("Present");
220         if (l_itr == l_propMap.end())
221         {
222             // Present is not found in the callback message
223             return;
224         }
225 
226         if (auto l_present = std::get_if<bool>(&(l_itr->second)))
227         {
228             *l_present ? m_worker->collectSingleFruVpd(l_objectPath)
229                        : m_worker->deleteFruVpd(l_objectPath);
230         }
231         else
232         {
233             throw DbusException(
234                 "Invalid type recieved in variant for present property");
235         }
236     }
237     catch (const std::exception& l_ex)
238     {
239         EventLogger::createSyncPel(
240             EventLogger::getErrorType(l_ex), types::SeverityType::Informational,
241             __FILE__, __FUNCTION__, 0,
242             "Process presence change callback failed, reason: " +
243                 std::string(l_ex.what()),
244             std::nullopt, std::nullopt, std::nullopt, std::nullopt);
245     }
246 }
247 
248 } // namespace vpd
249