blob: 9286dc7bdf8b4fc6b72e0891475322f4f6138a25 [file] [log] [blame]
/**
* Copyright © 2022 IBM Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "config.h"
#ifndef CONTROL_USE_JSON
#include "manager.hpp"
#include <CLI/CLI.hpp>
#else
#include "../utils/flight_recorder.hpp"
#include "json/manager.hpp"
#endif
#include "dbus_paths.hpp"
#include "sdbusplus.hpp"
#include "sdeventplus.hpp"
#include <phosphor-logging/log.hpp>
#include <sdbusplus/bus.hpp>
#include <sdeventplus/event.hpp>
#include <sdeventplus/source/signal.hpp>
#include <stdplus/signal.hpp>
#include <fstream>
using namespace phosphor::fan::control;
using namespace phosphor::logging;
#ifdef CONTROL_USE_JSON
void dumpFlightRecorder()
{
nlohmann::json data;
phosphor::fan::control::json::FlightRecorder::instance().dump(data);
std::ofstream file{json::Manager::dumpFile};
file << std::setw(4) << data;
}
#endif
int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
{
auto event = phosphor::fan::util::SDEventPlus::getEvent();
#ifndef CONTROL_USE_JSON
CLI::App app{"Phosphor Fan Control"};
bool init = false;
bool control = false;
app.add_flag("-i,--init", init, "Sets fans to full speed, delays, exits");
app.add_flag("-c,--control", control, "Start fan control algorithm");
app.require_option();
try
{
app.parse(argc, argv);
}
catch (const CLI::Error& e)
{
return app.exit(e);
}
Mode mode;
if (init)
{
mode = Mode::init;
}
else if (control)
{
mode = Mode::control;
}
#endif
// Attach the event object to the bus object so we can
// handle both sd_events (for the timers) and dbus signals.
phosphor::fan::util::SDBusPlus::getBus().attach_event(
event.get(), SD_EVENT_PRIORITY_NORMAL);
try
{
#ifdef CONTROL_USE_JSON
phosphor::fan::control::json::FlightRecorder::instance().log(
"main", "Startup");
json::Manager manager(event);
// Handle loading fan control's config file(s)
phosphor::fan::JsonConfig config(
std::bind(&json::Manager::load, &manager));
// Enable SIGHUP handling to reload JSON configs
stdplus::signal::block(SIGHUP);
sdeventplus::source::Signal signal(
event, SIGHUP,
std::bind(&json::Manager::sighupHandler, &manager,
std::placeholders::_1, std::placeholders::_2));
// Enable SIGUSR1 handling to dump the flight recorder
stdplus::signal::block(SIGUSR1);
sdeventplus::source::Signal sigUsr1(
event, SIGUSR1,
std::bind(&json::Manager::dumpDebugData, &manager,
std::placeholders::_1, std::placeholders::_2));
phosphor::fan::util::SDBusPlus::getBus().request_name(CONTROL_BUSNAME);
#else
Manager manager(phosphor::fan::util::SDBusPlus::getBus(), event, mode);
// Init mode will just set fans to max and delay
if (mode == Mode::init)
{
manager.doInit(event);
return 0;
}
#endif
return event.loop();
}
// Log the useful metadata on these exceptions and let the app
// return 1 so it is restarted without a core dump.
catch (const phosphor::fan::util::DBusServiceError& e)
{
log<level::ERR>("Uncaught DBus service lookup failure exception",
entry("PATH=%s", e.path.c_str()),
entry("INTERFACE=%s", e.interface.c_str()));
}
catch (const phosphor::fan::util::DBusMethodError& e)
{
log<level::ERR>("Uncaught DBus method failure exception",
entry("BUSNAME=%s", e.busName.c_str()),
entry("PATH=%s", e.path.c_str()),
entry("INTERFACE=%s", e.interface.c_str()),
entry("METHOD=%s", e.method.c_str()));
}
catch (const phosphor::fan::util::DBusPropertyError& e)
{
log<level::ERR>("Uncaught DBus property access failure exception",
entry("BUSNAME=%s", e.busName.c_str()),
entry("PATH=%s", e.path.c_str()),
entry("INTERFACE=%s", e.interface.c_str()),
entry("PROPERTY=%s", e.property.c_str()));
}
catch (std::exception& e)
{
#ifdef CONTROL_USE_JSON
phosphor::fan::control::json::FlightRecorder::instance().log(
"main", "Unexpected exception exit");
dumpFlightRecorder();
#endif
throw;
}
#ifdef CONTROL_USE_JSON
phosphor::fan::control::json::FlightRecorder::instance().log(
"main", "Abnormal exit");
dumpFlightRecorder();
#endif
return 1;
}