blob: 98dcb20330993c4c06da549d2031bab2d934a668 [file] [log] [blame]
Matthew Barthc95c5272020-06-15 19:51:13 -05001/**
Mike Capps7b34ee02022-05-04 14:16:12 -04002 * Copyright © 2022 IBM Corporation
Matthew Barthc95c5272020-06-15 19:51:13 -05003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Matthew Barthc95c5272020-06-15 19:51:13 -050016#include "system.hpp"
17
18#include "fan.hpp"
19#include "fan_defs.hpp"
20#include "tach_sensor.hpp"
21#include "trust_manager.hpp"
22#include "types.hpp"
Mike Cappsfdcd5db2021-05-20 12:47:10 -040023#include "utility.hpp"
Matthew Barthc95c5272020-06-15 19:51:13 -050024#ifdef MONITOR_USE_JSON
Mike Cappsb4379a12021-10-11 14:18:06 -040025#include "json_config.hpp"
Matthew Barthc95c5272020-06-15 19:51:13 -050026#include "json_parser.hpp"
27#endif
28
Matt Spinlerc8d3c512021-01-06 14:22:25 -060029#include "config.h"
30
Matt Spinlerbb449c12021-06-14 11:45:28 -060031#include "hwmon_ffdc.hpp"
32
Matthew Barthc95c5272020-06-15 19:51:13 -050033#include <nlohmann/json.hpp>
Matthew Barthd06905c2020-06-12 08:13:06 -050034#include <phosphor-logging/log.hpp>
Matthew Barthc95c5272020-06-15 19:51:13 -050035#include <sdbusplus/bus.hpp>
Patrick Williamscb356d42022-07-22 19:26:53 -050036#include <sdbusplus/bus/match.hpp>
Matthew Barthc95c5272020-06-15 19:51:13 -050037#include <sdeventplus/event.hpp>
Matthew Barthd06905c2020-06-12 08:13:06 -050038#include <sdeventplus/source/signal.hpp>
Matthew Barthc95c5272020-06-15 19:51:13 -050039
40namespace phosphor::fan::monitor
41{
42
43using json = nlohmann::json;
Matt Spinlerf13b42e2020-10-26 15:29:49 -050044using Severity = sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level;
45
Matthew Barthd06905c2020-06-12 08:13:06 -050046using namespace phosphor::logging;
Matthew Barthc95c5272020-06-15 19:51:13 -050047
Patrick Williamscb356d42022-07-22 19:26:53 -050048System::System(Mode mode, sdbusplus::bus_t& bus,
Matthew Barthc95c5272020-06-15 19:51:13 -050049 const sdeventplus::Event& event) :
50 _mode(mode),
Matt Spinlerc8d3c512021-01-06 14:22:25 -060051 _bus(bus), _event(event),
52 _powerState(std::make_unique<PGoodState>(
Matt Spinlere892e392020-10-14 13:21:31 -050053 bus, std::bind(std::mem_fn(&System::powerStateChanged), this,
Matt Spinlerc8d3c512021-01-06 14:22:25 -060054 std::placeholders::_1))),
55 _thermalAlert(bus, THERMAL_ALERT_OBJPATH)
Matt Spinler7d135642021-02-04 12:44:17 -060056{}
Matt Spinlere892e392020-10-14 13:21:31 -050057
Matthew Barth823bc492021-06-21 14:19:09 -050058void System::start()
Matt Spinler7d135642021-02-04 12:44:17 -060059{
Mike Cappsb4379a12021-10-11 14:18:06 -040060 namespace match = sdbusplus::bus::match;
61
62 // must be done before service detection
Patrick Williamscb356d42022-07-22 19:26:53 -050063 _inventoryMatch = std::make_unique<sdbusplus::bus::match_t>(
Mike Cappsb4379a12021-10-11 14:18:06 -040064 _bus, match::rules::nameOwnerChanged(util::INVENTORY_SVC),
65 std::bind(&System::inventoryOnlineCb, this, std::placeholders::_1));
66
67 bool invServiceRunning = util::SDBusPlus::callMethodAndRead<bool>(
68 _bus, "org.freedesktop.DBus", "/org/freedesktop/DBus",
69 "org.freedesktop.DBus", "NameHasOwner", util::INVENTORY_SVC);
70
71 if (invServiceRunning)
72 {
73 _inventoryMatch.reset();
74
75 if (!_loaded)
76 {
77 load();
78 }
79 }
80}
81
82void System::load()
83{
Matthew Barthc95c5272020-06-15 19:51:13 -050084 json jsonObj = json::object();
85#ifdef MONITOR_USE_JSON
Mike Cappsb4379a12021-10-11 14:18:06 -040086 try
87 {
Mike Capps808d7fe2022-06-13 10:12:16 -040088 jsonObj = getJsonObj();
Matthew Barthc95c5272020-06-15 19:51:13 -050089#endif
Mike Cappsb4379a12021-10-11 14:18:06 -040090 auto trustGrps = getTrustGroups(jsonObj);
91 auto fanDefs = getFanDefinitions(jsonObj);
92 // Retrieve and set trust groups within the trust manager
93 setTrustMgr(getTrustGroups(jsonObj));
94 // Clear/set configured fan definitions
95 _fans.clear();
96 _fanHealth.clear();
97 // Retrieve fan definitions and create fan objects to be monitored
98 setFans(fanDefs);
99 setFaultConfig(jsonObj);
100 log<level::INFO>("Configuration loaded");
101
102 _loaded = true;
103#ifdef MONITOR_USE_JSON
104 }
105 catch (const phosphor::fan::NoConfigFound&)
106 {}
107#endif
Matt Spinlere892e392020-10-14 13:21:31 -0500108
Matt Spinlere892e392020-10-14 13:21:31 -0500109 if (_powerState->isPowerOn())
110 {
Matt Spinler752f24e2022-07-06 15:57:54 -0500111 // Fans could be missing on startup, so check the power off rules.
112 // Tach sensors default to functional, so they wouldn't cause a power
113 // off here.
Matt Spinlere892e392020-10-14 13:21:31 -0500114 std::for_each(_powerOffRules.begin(), _powerOffRules.end(),
115 [this](auto& rule) {
Matt Spinlere892e392020-10-14 13:21:31 -0500116 rule->check(PowerRuleState::runtime, _fanHealth);
117 });
118 }
Mike Cappsfdcd5db2021-05-20 12:47:10 -0400119
Mike Cappsb4379a12021-10-11 14:18:06 -0400120 subscribeSensorsToServices();
Mike Cappsfdcd5db2021-05-20 12:47:10 -0400121}
122
Mike Capps25f03272021-09-13 13:38:44 -0400123void System::subscribeSensorsToServices()
Mike Cappsfdcd5db2021-05-20 12:47:10 -0400124{
Mike Capps25f03272021-09-13 13:38:44 -0400125 namespace match = sdbusplus::bus::match;
126
Mike Cappsb4379a12021-10-11 14:18:06 -0400127 _sensorMatch.clear();
128
Mike Cappsfdcd5db2021-05-20 12:47:10 -0400129 SensorMapType sensorMap;
130
131 // build a list of all interfaces, always including the value interface
132 // using set automatically guards against duplicates
133 std::set<std::string> unique_interfaces{util::FAN_SENSOR_VALUE_INTF};
134
135 for (const auto& fan : _fans)
136 {
137 for (const auto& sensor : fan->sensors())
138 {
139 unique_interfaces.insert(sensor->getInterface());
140 }
141 }
142 // convert them to vector to pass into getSubTreeRaw
143 std::vector<std::string> interfaces(unique_interfaces.begin(),
144 unique_interfaces.end());
145
Mike Capps25f03272021-09-13 13:38:44 -0400146 try
Mike Cappsfdcd5db2021-05-20 12:47:10 -0400147 {
Mike Capps25f03272021-09-13 13:38:44 -0400148 // get service information for all service names that are
149 // hosting these interfaces
150 auto serviceObjects = util::SDBusPlus::getSubTreeRaw(
151 _bus, FAN_SENSOR_PATH, interfaces, 0);
152
153 for (const auto& fan : _fans)
Mike Cappsfdcd5db2021-05-20 12:47:10 -0400154 {
Mike Capps25f03272021-09-13 13:38:44 -0400155 // For every sensor in each fan
156 for (const auto& sensor : fan->sensors())
Mike Cappsfdcd5db2021-05-20 12:47:10 -0400157 {
Mike Capps25f03272021-09-13 13:38:44 -0400158 const auto itServ = serviceObjects.find(sensor->name());
Mike Cappsfdcd5db2021-05-20 12:47:10 -0400159
Mike Capps25f03272021-09-13 13:38:44 -0400160 if (serviceObjects.end() == itServ || itServ->second.empty())
161 {
162 getLogger().log(
163 fmt::format("Fan sensor entry {} not found in D-Bus",
164 sensor->name()),
165 Logger::error);
166 continue;
167 }
168
169 for (const auto& [serviceName, unused] : itServ->second)
170 {
171 // associate service name with sensor
172 sensorMap[serviceName].insert(sensor);
173 }
Mike Cappsfdcd5db2021-05-20 12:47:10 -0400174 }
175 }
Mike Cappsfdcd5db2021-05-20 12:47:10 -0400176
Mike Capps25f03272021-09-13 13:38:44 -0400177 // only create 1 match per service
178 for (const auto& [serviceName, unused] : sensorMap)
179 {
180 // map its service name to the sensor
Patrick Williamscb356d42022-07-22 19:26:53 -0500181 _sensorMatch.emplace_back(std::make_unique<sdbusplus::bus::match_t>(
Mike Capps25f03272021-09-13 13:38:44 -0400182 _bus, match::rules::nameOwnerChanged(serviceName),
183 std::bind(&System::tachSignalOffline, this,
184 std::placeholders::_1, sensorMap)));
185 }
186 }
187 catch (const util::DBusError&)
188 {
189 // catch exception from getSubTreeRaw() when fan sensor paths don't
190 // exist yet
191 }
Matthew Barthd06905c2020-06-12 08:13:06 -0500192}
193
Patrick Williamscb356d42022-07-22 19:26:53 -0500194void System::inventoryOnlineCb(sdbusplus::message_t& msg)
Mike Cappsb4379a12021-10-11 14:18:06 -0400195{
196 namespace match = sdbusplus::bus::match;
197
198 std::string iface;
199 msg.read(iface);
200
201 if (util::INVENTORY_INTF != iface)
202 {
203 return;
204 }
205
206 std::string oldName;
207 msg.read(oldName);
208
209 std::string newName;
210 msg.read(newName);
211
212 // newName should never be empty since match was reset on the first
213 // nameOwnerChanged signal received from the service.
214 if (!_loaded && !newName.empty())
215 {
216 load();
217 }
218
219 // cancel any further notifications about the service state
220 _inventoryMatch.reset();
221}
222
Matthew Barthd06905c2020-06-12 08:13:06 -0500223void System::sighupHandler(sdeventplus::source::Signal&,
224 const struct signalfd_siginfo*)
225{
226 try
Matthew Barthc95c5272020-06-15 19:51:13 -0500227 {
Mike Cappsb4379a12021-10-11 14:18:06 -0400228 load();
Matthew Barthd06905c2020-06-12 08:13:06 -0500229 }
Mike Cappsb4379a12021-10-11 14:18:06 -0400230 catch (std::runtime_error& re)
Matthew Barthd06905c2020-06-12 08:13:06 -0500231 {
232 log<level::ERR>("Error reloading config, no config changes made",
233 entry("LOAD_ERROR=%s", re.what()));
Matthew Barthc95c5272020-06-15 19:51:13 -0500234 }
235}
236
237const std::vector<CreateGroupFunction>
Mike Capps808d7fe2022-06-13 10:12:16 -0400238 System::getTrustGroups([[maybe_unused]] const json& jsonObj)
Matthew Barthc95c5272020-06-15 19:51:13 -0500239{
240#ifdef MONITOR_USE_JSON
241 return getTrustGrps(jsonObj);
242#else
243 return trustGroups;
244#endif
245}
246
Matthew Barthd06905c2020-06-12 08:13:06 -0500247void System::setTrustMgr(const std::vector<CreateGroupFunction>& groupFuncs)
248{
249 _trust = std::make_unique<trust::Manager>(groupFuncs);
250}
251
Mike Capps808d7fe2022-06-13 10:12:16 -0400252const std::vector<FanDefinition>
253 System::getFanDefinitions([[maybe_unused]] const json& jsonObj)
Matthew Barthc95c5272020-06-15 19:51:13 -0500254{
255#ifdef MONITOR_USE_JSON
256 return getFanDefs(jsonObj);
257#else
258 return fanDefinitions;
259#endif
260}
261
Matthew Barthd06905c2020-06-12 08:13:06 -0500262void System::setFans(const std::vector<FanDefinition>& fanDefs)
263{
264 for (const auto& fanDef : fanDefs)
265 {
266 // Check if a condition exists on the fan
267 auto condition = std::get<conditionField>(fanDef);
268 if (condition)
269 {
270 // Condition exists, skip adding fan if it fails
271 if (!(*condition)(_bus))
272 {
273 continue;
274 }
275 }
276 _fans.emplace_back(
Matt Spinlerb0412d02020-10-12 16:53:52 -0500277 std::make_unique<Fan>(_mode, _bus, _event, _trust, fanDef, *this));
Matt Spinlerb63aa092020-10-14 09:45:11 -0500278
279 updateFanHealth(*(_fans.back()));
Matthew Barthd06905c2020-06-12 08:13:06 -0500280 }
281}
282
Mike Cappsfdcd5db2021-05-20 12:47:10 -0400283// callback indicating a service went [on|off]line.
284// Determine on/offline status, set all sensors for that service
285// to new state
286//
Patrick Williamscb356d42022-07-22 19:26:53 -0500287void System::tachSignalOffline(sdbusplus::message_t& msg,
Mike Cappsfdcd5db2021-05-20 12:47:10 -0400288 SensorMapType const& sensorMap)
289{
290 std::string serviceName, oldOwner, newOwner;
291
292 msg.read(serviceName);
293 msg.read(oldOwner);
294 msg.read(newOwner);
295
296 // true if sensor server came back online, false -> went offline
297 bool hasOwner = !newOwner.empty() && oldOwner.empty();
298
299 std::string stateStr(hasOwner ? "online" : "offline");
300 getLogger().log(fmt::format("Changing sensors for service {} to {}",
301 serviceName, stateStr),
302 Logger::info);
303
304 auto sensorItr(sensorMap.find(serviceName));
305
306 if (sensorItr != sensorMap.end())
307 {
308 // set all sensors' owner state to not-owned
309 for (auto& sensor : sensorItr->second)
310 {
311 sensor->setOwner(hasOwner);
312 sensor->getFan().process(*sensor);
313 }
314 }
315}
316
Matt Spinlerb63aa092020-10-14 09:45:11 -0500317void System::updateFanHealth(const Fan& fan)
318{
319 std::vector<bool> sensorStatus;
320 for (const auto& sensor : fan.sensors())
321 {
322 sensorStatus.push_back(sensor->functional());
323 }
324
325 _fanHealth[fan.getName()] =
326 std::make_tuple(fan.present(), std::move(sensorStatus));
327}
328
Matt Spinler4283c5d2021-03-01 15:56:00 -0600329void System::fanStatusChange(const Fan& fan, bool skipRulesCheck)
Matt Spinlerb63aa092020-10-14 09:45:11 -0500330{
331 updateFanHealth(fan);
Matt Spinlere892e392020-10-14 13:21:31 -0500332
Matt Spinler4283c5d2021-03-01 15:56:00 -0600333 if (_powerState->isPowerOn() && !skipRulesCheck)
Matt Spinlere892e392020-10-14 13:21:31 -0500334 {
335 std::for_each(_powerOffRules.begin(), _powerOffRules.end(),
336 [this](auto& rule) {
337 rule->check(PowerRuleState::runtime, _fanHealth);
338 });
339 }
340}
341
Mike Capps808d7fe2022-06-13 10:12:16 -0400342void System::setFaultConfig([[maybe_unused]] const json& jsonObj)
Matt Spinlere892e392020-10-14 13:21:31 -0500343{
344#ifdef MONITOR_USE_JSON
345 std::shared_ptr<PowerInterfaceBase> powerInterface =
Matt Spinlerba3ee9a2021-01-06 14:45:50 -0600346 std::make_shared<PowerInterface>(_thermalAlert);
Matt Spinlere892e392020-10-14 13:21:31 -0500347
Matt Spinlerac1efc12020-10-27 10:20:11 -0500348 PowerOffAction::PrePowerOffFunc func =
349 std::bind(std::mem_fn(&System::logShutdownError), this);
350
351 _powerOffRules = getPowerOffRules(jsonObj, powerInterface, func);
Matt Spinlerf13b42e2020-10-26 15:29:49 -0500352
353 _numNonfuncSensorsBeforeError = getNumNonfuncRotorsBeforeError(jsonObj);
Matt Spinlere892e392020-10-14 13:21:31 -0500354#endif
355}
356
357void System::powerStateChanged(bool powerStateOn)
358{
Matt Spinler7d135642021-02-04 12:44:17 -0600359 std::for_each(_fans.begin(), _fans.end(), [powerStateOn](auto& fan) {
360 fan->powerStateChanged(powerStateOn);
361 });
362
Matt Spinlere892e392020-10-14 13:21:31 -0500363 if (powerStateOn)
364 {
Mike Cappsb4379a12021-10-11 14:18:06 -0400365 if (!_loaded)
Matt Spinler7d135642021-02-04 12:44:17 -0600366 {
367 log<level::ERR>("No conf file found at power on");
Matthew Barthba53d3e2021-02-24 07:48:37 -0600368 throw std::runtime_error("No conf file found at power on");
Matt Spinler7d135642021-02-04 12:44:17 -0600369 }
370
Matt Spinlerbb449c12021-06-14 11:45:28 -0600371 // If no fan has its sensors on D-Bus, then there is a problem
372 // with the fan controller. Log an error and shut down.
373 if (std::all_of(_fans.begin(), _fans.end(), [](const auto& fan) {
374 return fan->numSensorsOnDBusAtPowerOn() == 0;
375 }))
376 {
377 handleOfflineFanController();
378 return;
379 }
380
Mike Capps25f03272021-09-13 13:38:44 -0400381 if (_sensorMatch.empty())
382 {
383 subscribeSensorsToServices();
384 }
385
Matt Spinlere892e392020-10-14 13:21:31 -0500386 std::for_each(_powerOffRules.begin(), _powerOffRules.end(),
387 [this](auto& rule) {
388 rule->check(PowerRuleState::atPgood, _fanHealth);
389 });
390 std::for_each(_powerOffRules.begin(), _powerOffRules.end(),
391 [this](auto& rule) {
392 rule->check(PowerRuleState::runtime, _fanHealth);
393 });
394 }
395 else
396 {
Matt Spinlerc8d3c512021-01-06 14:22:25 -0600397 _thermalAlert.enabled(false);
398
Matt Spinlere892e392020-10-14 13:21:31 -0500399 // Cancel any in-progress power off actions
400 std::for_each(_powerOffRules.begin(), _powerOffRules.end(),
401 [this](auto& rule) { rule->cancel(); });
402 }
Matt Spinlerb63aa092020-10-14 09:45:11 -0500403}
404
Matt Spinlerf13b42e2020-10-26 15:29:49 -0500405void System::sensorErrorTimerExpired(const Fan& fan, const TachSensor& sensor)
406{
407 std::string fanPath{util::INVENTORY_PATH + fan.getName()};
408
409 getLogger().log(
410 fmt::format("Creating event log for faulted fan {} sensor {}", fanPath,
411 sensor.name()),
412 Logger::error);
413
414 // In order to know if the event log should have a severity of error or
415 // informational, count the number of existing nonfunctional sensors and
416 // compare it to _numNonfuncSensorsBeforeError.
417 size_t nonfuncSensors = 0;
418 for (const auto& fan : _fans)
419 {
420 for (const auto& s : fan->sensors())
421 {
422 // Don't count nonfunctional sensors that still have their
423 // error timer running as nonfunctional since they haven't
424 // had event logs created for those errors yet.
425 if (!s->functional() && !s->errorTimerRunning())
426 {
427 nonfuncSensors++;
428 }
429 }
430 }
431
432 Severity severity = Severity::Error;
433 if (nonfuncSensors < _numNonfuncSensorsBeforeError)
434 {
435 severity = Severity::Informational;
436 }
437
438 auto error =
439 std::make_unique<FanError>("xyz.openbmc_project.Fan.Error.Fault",
440 fanPath, sensor.name(), severity);
441
442 auto sensorData = captureSensorData();
443 error->commit(sensorData);
444
Matt Spinlerac1efc12020-10-27 10:20:11 -0500445 // Save the error so it can be committed again on a power off.
446 _lastError = std::move(error);
Matt Spinlerf13b42e2020-10-26 15:29:49 -0500447}
448
Matt Spinler27f6b682020-10-27 08:43:37 -0500449void System::fanMissingErrorTimerExpired(const Fan& fan)
450{
451 std::string fanPath{util::INVENTORY_PATH + fan.getName()};
452
453 getLogger().log(
454 fmt::format("Creating event log for missing fan {}", fanPath),
455 Logger::error);
456
457 auto error = std::make_unique<FanError>(
458 "xyz.openbmc_project.Fan.Error.Missing", fanPath, "", Severity::Error);
459
460 auto sensorData = captureSensorData();
461 error->commit(sensorData);
462
Matt Spinlerac1efc12020-10-27 10:20:11 -0500463 // Save the error so it can be committed again on a power off.
464 _lastError = std::move(error);
465}
466
467void System::logShutdownError()
468{
469 if (_lastError)
470 {
471 getLogger().log("Re-committing previous fan error before power off");
472
473 // Still use the latest sensor data
474 auto sensorData = captureSensorData();
Matt Spinlerf435eb12021-05-11 14:44:25 -0500475 _lastError->commit(sensorData, true);
Matt Spinlerac1efc12020-10-27 10:20:11 -0500476 }
Matt Spinler27f6b682020-10-27 08:43:37 -0500477}
478
Matt Spinlerf13b42e2020-10-26 15:29:49 -0500479json System::captureSensorData()
480{
481 json data;
482
483 for (const auto& fan : _fans)
484 {
485 for (const auto& sensor : fan->sensors())
486 {
487 json values;
488 values["present"] = fan->present();
489 values["functional"] = sensor->functional();
490 values["tach"] = sensor->getInput();
Mike Capps7b34ee02022-05-04 14:16:12 -0400491
Matt Spinlerf13b42e2020-10-26 15:29:49 -0500492 if (sensor->hasTarget())
493 {
494 values["target"] = sensor->getTarget();
495 }
496
Mike Capps7b34ee02022-05-04 14:16:12 -0400497 // convert between string/json to remove newlines
498 values["prev_tachs"] = json(sensor->getPrevTach()).dump();
499
500 if (sensor->hasTarget())
501 {
502 values["prev_targets"] = json(sensor->getPrevTarget()).dump();
503 }
504
Matt Spinler87f9adc2022-08-11 13:17:09 -0500505 if (sensor->getMethod() == MethodMode::count)
506 {
507 values["ticks"] = sensor->getCounter();
508 }
Matt Spinlerf13b42e2020-10-26 15:29:49 -0500509 data["sensors"][sensor->name()] = values;
510 }
511 }
512
513 return data;
514}
515
Matt Spinlerbb449c12021-06-14 11:45:28 -0600516void System::handleOfflineFanController()
517{
518 getLogger().log("The fan controller appears to be offline. Shutting down.",
519 Logger::error);
520
521 auto ffdc = collectHwmonFFDC();
522
523 FanError error{"xyz.openbmc_project.Fan.Error.FanControllerOffline",
524 Severity::Critical};
525 error.commit(ffdc, true);
526
527 PowerInterface::executeHardPowerOff();
Mike Capps683a96c2022-04-27 16:46:06 -0400528
529 createBmcDump();
530}
531
532/**
533 * @brief Create a BMC Dump
534 */
535void System::createBmcDump() const
536{
537 try
538 {
539 util::SDBusPlus::callMethod(
540 "xyz.openbmc_project.Dump.Manager", "/xyz/openbmc_project/dump/bmc",
541 "xyz.openbmc_project.Dump.Create", "CreateDump",
542 std::vector<
543 std::pair<std::string, std::variant<std::string, uint64_t>>>());
544 }
Mike Capps477b13b2022-07-11 10:45:46 -0400545 catch (const std::exception& e)
546 {
547 getLogger().log(
548 fmt::format("Caught exception while creating BMC dump: {}",
549 e.what()),
550 Logger::error);
551 }
Matt Spinlerbb449c12021-06-14 11:45:28 -0600552}
553
Matthew Barthc95c5272020-06-15 19:51:13 -0500554} // namespace phosphor::fan::monitor