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