xref: /openbmc/bmcweb/src/webserver_cli.cpp (revision a553291f)
1bd1299b7SAushim Nagarkatti #include "boost_formatters.hpp"
2bd1299b7SAushim Nagarkatti #include "logging.hpp"
3bd1299b7SAushim Nagarkatti 
4bd1299b7SAushim Nagarkatti #include <CLI/CLI.hpp>
5bd1299b7SAushim Nagarkatti #include <boost/asio/io_context.hpp>
6bd1299b7SAushim Nagarkatti #include <sdbusplus/asio/connection.hpp>
7bd1299b7SAushim Nagarkatti 
8*a553291fSAushim Nagarkatti #include <algorithm>
9*a553291fSAushim Nagarkatti #include <array>
10*a553291fSAushim Nagarkatti #include <cctype>
1141fe81c2SEd Tanous #include <memory>
12bd1299b7SAushim Nagarkatti #include <string>
13bd1299b7SAushim Nagarkatti 
14bd1299b7SAushim Nagarkatti // Override default log option:
cliLogLevel(const std::string & logLevel)15bd1299b7SAushim Nagarkatti static void cliLogLevel(const std::string& logLevel)
16bd1299b7SAushim Nagarkatti {
17bd1299b7SAushim Nagarkatti     crow::getBmcwebCurrentLoggingLevel() = crow::getLogLevelFromName(logLevel);
18bd1299b7SAushim Nagarkatti }
19bd1299b7SAushim Nagarkatti 
20*a553291fSAushim Nagarkatti static constexpr std::array<std::string, 7> levels{
21*a553291fSAushim Nagarkatti     "DISABLED", "CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG", "ENABLED"};
22*a553291fSAushim Nagarkatti 
23*a553291fSAushim Nagarkatti // Check if debug level is valid
validateLogLevel(std::string & input)24*a553291fSAushim Nagarkatti static std::string validateLogLevel(std::string& input)
25*a553291fSAushim Nagarkatti {
26*a553291fSAushim Nagarkatti     std::transform(input.begin(), input.end(), input.begin(), ::toupper);
27*a553291fSAushim Nagarkatti     const std::string* iter = std::ranges::find(levels, input);
28*a553291fSAushim Nagarkatti     if (iter == levels.end())
29*a553291fSAushim Nagarkatti     {
30*a553291fSAushim Nagarkatti         return {"Invalid log level"};
31*a553291fSAushim Nagarkatti     }
32*a553291fSAushim Nagarkatti     return {};
33*a553291fSAushim Nagarkatti }
34*a553291fSAushim Nagarkatti 
helpMsg()35*a553291fSAushim Nagarkatti static std::string helpMsg()
36*a553291fSAushim Nagarkatti {
37*a553291fSAushim Nagarkatti     std::string help = "\nLog levels to choose from:\n";
38*a553291fSAushim Nagarkatti     for (const std::string& prompt : levels)
39*a553291fSAushim Nagarkatti     {
40*a553291fSAushim Nagarkatti         std::string level = prompt;
41*a553291fSAushim Nagarkatti         std::transform(level.begin(), level.end(), level.begin(), ::tolower);
42*a553291fSAushim Nagarkatti         help.append(level + "\n");
43*a553291fSAushim Nagarkatti     }
44*a553291fSAushim Nagarkatti     return help;
45*a553291fSAushim Nagarkatti }
46*a553291fSAushim Nagarkatti 
main(int argc,char ** argv)47bd1299b7SAushim Nagarkatti int main(int argc, char** argv) noexcept(false)
48bd1299b7SAushim Nagarkatti {
49bd1299b7SAushim Nagarkatti     CLI::App app("BMCWeb SetLogLevel CLI");
50bd1299b7SAushim Nagarkatti 
51bd1299b7SAushim Nagarkatti     cliLogLevel("INFO");
52bd1299b7SAushim Nagarkatti 
53bd1299b7SAushim Nagarkatti     // Define sdbus interfaces:
54bd1299b7SAushim Nagarkatti     std::string service = "xyz.openbmc_project.bmcweb";
55bd1299b7SAushim Nagarkatti     std::string path = "/xyz/openbmc_project/bmcweb";
56bd1299b7SAushim Nagarkatti     std::string iface = "xyz.openbmc_project.bmcweb";
57bd1299b7SAushim Nagarkatti     std::string method = "SetLogLevel";
58bd1299b7SAushim Nagarkatti 
59bd1299b7SAushim Nagarkatti     std::string loglevel;
60*a553291fSAushim Nagarkatti     app.require_subcommand(1);
61*a553291fSAushim Nagarkatti 
62*a553291fSAushim Nagarkatti     const CLI::Validator levelValidator =
63*a553291fSAushim Nagarkatti         CLI::Validator(validateLogLevel, "valid level");
64*a553291fSAushim Nagarkatti 
65*a553291fSAushim Nagarkatti     CLI::App* sub = app.add_subcommand("loglevel", "Set bmcweb log level");
66*a553291fSAushim Nagarkatti     sub->add_option("level", loglevel, helpMsg())
67*a553291fSAushim Nagarkatti         ->required()
68*a553291fSAushim Nagarkatti         ->check(levelValidator);
69bd1299b7SAushim Nagarkatti 
70bd1299b7SAushim Nagarkatti     CLI11_PARSE(app, argc, argv)
71bd1299b7SAushim Nagarkatti 
72*a553291fSAushim Nagarkatti     std::transform(loglevel.begin(), loglevel.end(), loglevel.begin(),
73*a553291fSAushim Nagarkatti                    ::toupper);
74bd1299b7SAushim Nagarkatti     // Set up dbus connection:
75bd1299b7SAushim Nagarkatti     boost::asio::io_context io;
76bd1299b7SAushim Nagarkatti     auto conn = std::make_shared<sdbusplus::asio::connection>(io);
77bd1299b7SAushim Nagarkatti 
78bd1299b7SAushim Nagarkatti     // Attempt to async_call to set logging level
79bd1299b7SAushim Nagarkatti     conn->async_method_call(
80*a553291fSAushim Nagarkatti         [&io, &loglevel](boost::system::error_code& ec) mutable {
81bd1299b7SAushim Nagarkatti             if (ec)
82bd1299b7SAushim Nagarkatti             {
83bd1299b7SAushim Nagarkatti                 BMCWEB_LOG_ERROR("SetLogLevel returned error with {}", ec);
84bd1299b7SAushim Nagarkatti                 return;
85bd1299b7SAushim Nagarkatti             }
86*a553291fSAushim Nagarkatti             BMCWEB_LOG_INFO("logging level changed to: {}", loglevel);
87bd1299b7SAushim Nagarkatti             io.stop();
88bd1299b7SAushim Nagarkatti         },
89bd1299b7SAushim Nagarkatti         service, path, iface, method, loglevel);
90bd1299b7SAushim Nagarkatti 
91bd1299b7SAushim Nagarkatti     io.run();
92bd1299b7SAushim Nagarkatti 
93bd1299b7SAushim Nagarkatti     return 0;
94bd1299b7SAushim Nagarkatti }
95