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