| #include "bmcweb_config.h" |
| |
| #include "app.hpp" |
| #include "app_singleton.hpp" |
| #include "cors_preflight.hpp" |
| #include "dbus_monitor.hpp" |
| #include "dbus_singleton.hpp" |
| #include "hostname_monitor.hpp" |
| #include "ibm/management_console_rest.hpp" |
| #include "image_upload.hpp" |
| #include "kvm_websocket.hpp" |
| #include "login_routes.hpp" |
| #include "managed_store.hpp" |
| #include "nbd_proxy.hpp" |
| #include "obmc_console.hpp" |
| #include "openbmc_dbus_rest.hpp" |
| #include "redfish.hpp" |
| #include "redfish_aggregator.hpp" |
| #include "security_headers.hpp" |
| #include "ssl_key_handler.hpp" |
| #include "user_monitor.hpp" |
| #include "vm_websocket.hpp" |
| #include "webassets.hpp" |
| |
| #include <systemd/sd-daemon.h> |
| |
| #ifdef BMCWEB_ENABLE_GRPC |
| #include "absl/flags/flag.h" |
| #include "absl/flags/parse.h" |
| #include "absl/log/globals.h" |
| #include "absl/log/initialize.h" |
| #include "absl/log/log.h" |
| #include "grpc_server.h" |
| |
| // See absl/log/globals.h for detailed instructions |
| ABSL_FLAG( |
| int, stderrthreshold, 1, |
| "Messages logged at or above this level are directed to stderr in addition to other registered log sinks; default to >= absl::LogSeverity::kWarning"); |
| ABSL_FLAG( |
| int, minloglevel, 0, |
| "Messages logged at or above this severity are directed to all registered log sinks or skipped otherwise; default to >= absl::LogSeverity::kInfo"); |
| ABSL_FLAG(absl::optional<int>, httpport, absl::nullopt, |
| "http port to listen on"); |
| |
| // BMCWEB_ENABLE_STATEFUL_BMCWEB: |
| ABSL_FLAG( |
| absl::optional<bool>, stateful, absl::nullopt, |
| "enable stateful bmcweb (stateful-bmcweb) execution of incoming redfish requests"); |
| ABSL_FLAG(absl::optional<int>, stateful_pending_max, absl::nullopt, |
| "stateful - pendingDbusResponsesMax"); |
| ABSL_FLAG(absl::optional<int>, stateful_tfixed_sec, absl::nullopt, |
| "stateful - tfixedThreshold"); |
| ABSL_FLAG(absl::optional<int>, stateful_tgrace_sec, absl::nullopt, |
| "stateful - tgraceThreshold"); |
| ABSL_FLAG(absl::optional<int>, stateful_tlru_sec, absl::nullopt, |
| "stateful - tLRUThreshold"); |
| |
| #endif // BMCWEB_ENABLE_GRPC |
| |
| #ifdef BMCWEB_ENABLE_INSECURE_GRPC |
| #include "grpc_server_insecure.h" |
| #endif |
| |
| #include <boost/asio/io_context.hpp> |
| #include <google/google_service_nvme.hpp> |
| #include <google/google_service_root.hpp> |
| #include <sdbusplus/asio/connection.hpp> |
| #include <sdbusplus/bus.hpp> |
| #include <sdbusplus/server.hpp> |
| |
| #include <exception> |
| #include <memory> |
| #include <string> |
| |
| inline void setupSocket(crow::App& app) |
| { |
| constexpr uint16_t defaultPort = 18080; |
| int listenFd = sd_listen_fds(0); |
| uint16_t portNumber = defaultPort; |
| #ifdef BMCWEB_ENABLE_GRPC |
| portNumber = static_cast<uint16_t>( |
| absl::GetFlag(FLAGS_httpport).value_or(defaultPort)); |
| #endif |
| |
| BMCWEB_LOG_ALWAYS << "setupSocket: defaultPort: " << defaultPort |
| << " portNumber: " << portNumber |
| << " listenFd: " << listenFd; |
| |
| if (1 == listenFd) |
| { |
| BMCWEB_LOG_INFO << "attempting systemd socket activation"; |
| if (sd_is_socket_inet(SD_LISTEN_FDS_START, AF_UNSPEC, SOCK_STREAM, 1, |
| 0) != 0) |
| { |
| BMCWEB_LOG_INFO << "Starting webserver on socket handle " |
| << SD_LISTEN_FDS_START; |
| app.socket(SD_LISTEN_FDS_START); |
| } |
| else |
| { |
| BMCWEB_LOG_ERROR |
| << "bad incoming socket, starting webserver on port " |
| << portNumber; |
| app.port(portNumber); |
| } |
| } |
| else |
| { |
| BMCWEB_LOG_INFO << "Starting webserver on port: " << portNumber; |
| app.port(portNumber); |
| } |
| } |
| |
| static int run() |
| { |
| #ifdef BMCWEB_ENABLE_GRPC |
| auto crowLogLevel = crow::LogLevel::Debug; |
| crow::Logger::setLogLevel(crowLogLevel); |
| const auto minAbslLogLevel = |
| static_cast<absl::LogSeverity>(absl::GetFlag(FLAGS_minloglevel)); |
| BMCWEB_LOG_ALWAYS << "=> minAbslLogLevel: " |
| << static_cast<int>(minAbslLogLevel); |
| switch (minAbslLogLevel) |
| { |
| // unfortunately there is no: absl::LogSeverity::kInfo; so kInfo -> |
| // Debug for now. |
| case absl::LogSeverity::kInfo: |
| crowLogLevel = crow::LogLevel::Debug; |
| break; |
| case absl::LogSeverity::kWarning: |
| crowLogLevel = crow::LogLevel::Warning; |
| break; |
| case absl::LogSeverity::kError: |
| crowLogLevel = crow::LogLevel::Error; |
| break; |
| case absl::LogSeverity::kFatal: |
| crowLogLevel = crow::LogLevel::Critical; |
| break; |
| |
| default: |
| crowLogLevel = crow::LogLevel::Error; |
| break; |
| } |
| BMCWEB_LOG_ALWAYS << "=> crowLogLevel: " << static_cast<int>(crowLogLevel); |
| crow::Logger::setLogLevel(crowLogLevel); |
| #else |
| crow::Logger::setLogLevel(crow::LogLevel::Debug); |
| #endif |
| |
| auto io = std::make_shared<boost::asio::io_context>(); |
| App app(io); |
| crow::globalBmcWebApp = &app; |
| |
| std::shared_ptr<sdbusplus::asio::connection> systemBusPtr = |
| std::make_shared<sdbusplus::asio::connection>(*io); |
| crow::connections::systemBus = &*systemBusPtr; |
| |
| #ifdef BMCWEB_ENABLE_GRPC |
| BMCWEB_LOG_STATEFUL_ALWAYS << "=> stateful: " |
| << absl::GetFlag(FLAGS_stateful).value_or(false); |
| #endif |
| |
| managedStore::ManagedObjectStoreConfig config; |
| // default to the compiler flag: |
| #ifdef BMCWEB_ENABLE_STATEFUL_BMCWEB |
| config.isEnabled = true; |
| #else |
| config.isEnabled = false; |
| #endif |
| |
| #ifdef BMCWEB_ENABLE_GRPC |
| // command line is always higher priority if set: |
| if (absl::GetFlag(FLAGS_stateful).has_value()) |
| { |
| config.isEnabled = absl::GetFlag(FLAGS_stateful).value(); |
| } |
| else |
| #endif |
| { |
| // read the persistent data config: |
| const auto& persistentDataConfig = persistent_data::getConfig(); |
| if (persistentDataConfig.isStatefulEnabled.has_value()) |
| { |
| config.isEnabled = persistentDataConfig.isStatefulEnabled.value(); |
| } |
| } |
| |
| #ifdef BMCWEB_ENABLE_GRPC |
| // other flags: |
| if (absl::GetFlag(FLAGS_stateful_pending_max).has_value()) |
| { |
| config.pendingDbusResponsesMax = |
| static_cast<uint64_t>(absl::GetFlag(FLAGS_stateful_pending_max).value()); |
| } |
| if (absl::GetFlag(FLAGS_stateful_tfixed_sec).has_value()) |
| { |
| config.tfixedThreshold = std::chrono::seconds( |
| absl::GetFlag(FLAGS_stateful_tfixed_sec).value()); |
| } |
| if (absl::GetFlag(FLAGS_stateful_tgrace_sec).has_value()) |
| { |
| config.tgraceThreshold = std::chrono::seconds( |
| absl::GetFlag(FLAGS_stateful_tgrace_sec).value()); |
| } |
| if (absl::GetFlag(FLAGS_stateful_tlru_sec).has_value()) |
| { |
| config.tLRUThreshold = std::chrono::seconds( |
| absl::GetFlag(FLAGS_stateful_tlru_sec).value()); |
| } |
| #endif |
| |
| BMCWEB_LOG_STATEFUL_ALWAYS << "=> ManagedObjectStoreConfig: " |
| << config.toString(); |
| |
| #ifndef BMCWEB_ENABLE_STATEFUL_BMCWEB |
| if (config.isEnabled) |
| { |
| BMCWEB_LOG_WARNING |
| << "ManagedObjectStore can't be enabled without " |
| << "BMCWEB_ENABLE_STATEFUL_BMCWEB; reverting to stateful=0"; |
| config.isEnabled = false; |
| } |
| #endif // BMCWEB_ENABLE_STATEFUL_BMCWEB |
| auto managedObjectStoreSingleton = |
| std::make_shared<managedStore::ManagedObjectStore>(config, *io); |
| managedStore::managedObjectStore = managedObjectStoreSingleton.get(); |
| |
| // Static assets need to be initialized before Authorization, because auth |
| // needs to build the whitelist from the static routes |
| #ifdef BMCWEB_ENABLE_STATIC_HOSTING |
| crow::webassets::requestRoutes(app); |
| #endif |
| |
| #ifdef BMCWEB_ENABLE_KVM |
| crow::obmc_kvm::requestRoutes(app); |
| #endif |
| |
| #ifdef BMCWEB_ENABLE_REDFISH |
| redfish::RedfishService redfish(app); |
| |
| // Create EventServiceManager instance and initialize Config |
| redfish::EventServiceManager::getInstance(); |
| |
| #ifdef BMCWEB_ENABLE_REDFISH_AGGREGATION |
| // Create RedfishAggregator instance and initialize Config |
| redfish::RedfishAggregator::getInstance(); |
| #endif |
| #endif |
| |
| #ifdef BMCWEB_ENABLE_DBUS_REST |
| crow::dbus_monitor::requestRoutes(app); |
| crow::image_upload::requestRoutes(app); |
| crow::openbmc_mapper::requestRoutes(app); |
| #endif |
| |
| #ifdef BMCWEB_ENABLE_HOST_SERIAL_WEBSOCKET |
| crow::obmc_console::requestRoutes(app); |
| #endif |
| |
| #ifdef BMCWEB_ENABLE_VM_WEBSOCKET |
| crow::obmc_vm::requestRoutes(app); |
| #endif |
| |
| #ifdef BMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE |
| crow::ibm_mc::requestRoutes(app); |
| crow::ibm_mc_lock::Lock::getInstance(); |
| #endif |
| |
| #ifdef BMCWEB_ENABLE_GOOGLE_API |
| crow::google_api::requestRoutes(app); |
| crow::google_api::requestGoogleNVMeCollection(app); |
| crow::google_api::requestGoogleNVMe(app); |
| crow::google_api::requestGoogleNVMeController(app); |
| crow::google_api::setupGoogleNVMeFdFetchIOContext(io); |
| crow::google_api::requestGoogleNVMeControllerActionIdentify(app); |
| crow::google_api::requestGoogleNVMeControllerActionLog(app); |
| crow::google_api::requestGoogleNVMeControllerActionCustomNVMeIdentify(app); |
| crow::google_api::requestGoogleNVMeControllerActionAdminNonData(app); |
| #endif |
| |
| #ifdef BMCWEB_ENABLE_MAPPER |
| if (managedStore::managedObjectStore && |
| managedStore::managedObjectStore->isEnabled()) |
| { |
| mapperStart(*io, dbus::utility::interfaceMap, systemBusPtr); |
| } |
| #endif |
| |
| if (bmcwebInsecureDisableXssPrevention != 0) |
| { |
| cors_preflight::requestRoutes(app); |
| } |
| |
| crow::login_routes::requestRoutes(app); |
| |
| setupSocket(app); |
| |
| #ifdef BMCWEB_ENABLE_VM_NBDPROXY |
| crow::nbd_proxy::requestRoutes(app); |
| #endif |
| |
| #ifndef BMCWEB_ENABLE_REDFISH_DBUS_LOG_ENTRIES |
| int rc = redfish::EventServiceManager::startEventLogMonitor(*io); |
| if (rc != 0) |
| { |
| BMCWEB_LOG_ERROR << "Redfish event handler setup failed..."; |
| return rc; |
| } |
| #endif |
| |
| #ifdef BMCWEB_ENABLE_SSL |
| BMCWEB_LOG_INFO << "Start Hostname Monitor Service..."; |
| crow::hostname_monitor::registerHostnameSignal(); |
| #endif |
| |
| bmcweb::registerUserRemovedSignal(); |
| |
| #ifdef BMCWEB_ENABLE_GRPC |
| absl::InitializeLog(); |
| |
| GRPCRedfishService grpc_service(app, io); |
| |
| #ifdef BMCWEB_ENABLE_INSECURE_GRPC |
| InsecureGRPCRedfishService insecure_grpc_service(app, io); |
| #endif |
| |
| #endif |
| app.validate(); |
| app.run(); |
| io->run(); |
| |
| #ifdef BMCWEB_ENABLE_GRPC |
| grpc_service.shutdown(); |
| |
| #ifdef BMCWEB_ENABLE_INSECURE_GRPC |
| insecure_grpc_service.shutdown(); |
| #endif |
| |
| #endif |
| |
| crow::connections::systemBus = nullptr; |
| |
| return 0; |
| } |
| |
| #ifdef BMCWEB_ENABLE_GRPC |
| int main(int argc, char** argv) |
| { |
| absl::ParseCommandLine(argc, argv); |
| absl::SetMinLogLevel(static_cast<absl::LogSeverityAtLeast>( |
| absl::GetFlag(FLAGS_minloglevel))); |
| absl::SetStderrThreshold(static_cast<absl::LogSeverityAtLeast>( |
| absl::GetFlag(FLAGS_stderrthreshold))); |
| #else |
| int main(int /*argc*/, char** /*argv*/) |
| { |
| #endif |
| try |
| { |
| return run(); |
| } |
| catch (const std::exception& e) |
| { |
| BMCWEB_LOG_CRITICAL << "Threw exception to main: " << e.what(); |
| return -1; |
| } |
| catch (...) |
| { |
| BMCWEB_LOG_CRITICAL << "Threw exception to main"; |
| return -1; |
| } |
| } |