| // gpowerd is the safe power local agent for BMC. |
| // It implements the SafePowerLocalAgent service, and is responsible for |
| // actuating power cycles on the machine. |
| |
| #include <fmt/format.h> // c NOLINT (c++17 fmt bmc build) |
| #include <grpcpp/grpcpp.h> |
| #include <grpcpp/ext/proto_server_reflection_plugin.h> |
| #include <safepower_agent_config.pb.h> |
| |
| #include <string> |
| #include <csignal> |
| #include <memory> |
| #include <string_view> |
| |
| #include "bmc/auth.h" |
| #include "bmc/daemon_context_bmc.h" |
| #include "safepower_agent.h" |
| #include "safepower_agent.pb.h" |
| #include "state_change_reactor.h" |
| #include "state_updater.h" |
| #include "bmc/machine_configs/setup_configs.h" |
| #include "bmc/state_monitor_bmc.h" |
| #include "bmc/status_macros.h" |
| #include "bmc/register_actions_bmc.h" |
| #include "bmc/proto_reader.h" |
| #include "grpcpp/server_builder.h" |
| |
| #include "grpcpp/security/authorization_policy_provider.h" |
| #include "absl/log/log.h" |
| #include "absl/status/status.h" |
| |
| #include "absl/flags/flag.h" |
| #include "absl/flags/parse.h" |
| #include "absl/log/log.h" |
| #include "absl/log/globals.h" |
| |
| using grpc::Server; |
| using grpc::ServerBuilder; |
| using safepower_agent::StateChangeWriteReactor; |
| using safepower_agent::SafepowerLocalAgentImpl; |
| using safepower_agent::StateUpdater; |
| using safepower_agent::DaemonContextBMC; |
| |
| using ::grpc::experimental::AuthorizationPolicyProviderInterface; |
| |
| const char* address = "[::]:20120"; |
| |
| |
| // The built-in log flags are not being pulled into this code because the cmake |
| // build does not include the flags library for logging, so a local flag was |
| // setup to mitigate this. |
| |
| // Global log verbosity level. Default is 0. |
| ABSL_FLAG(int, v, 0, "Global log verbosity level"); |
| |
| absl::Status main_gpowerd() |
| { |
| DaemonContextBMC daemon_context; |
| safepower_agent_proto::SystemState initialState; |
| auto reactor = |
| std::make_shared<StateUpdater<safepower_agent_proto::SystemState>>( |
| std::move(initialState), true); |
| auto action_context_manager = |
| std::make_unique<safepower_agent::ActionContextManager>(reactor); |
| |
| auto state_monitor = std::make_shared |
| <safepower_agent::StateMonitorBMC>(reactor); |
| |
| RETURN_IF_ERROR(setup_configs::SetupConfigs |
| (*state_monitor, *action_context_manager)); |
| |
| SafepowerLocalAgentImpl safePowerService(std::move(reactor), |
| std::move(action_context_manager)); |
| ServerBuilder builder; |
| |
| ASSIGN_OR_RETURN(std::shared_ptr<grpc::ServerCredentials> |
| creds, auth::GetCredsInfo()); |
| LOG(INFO) << "Credentials loaded"; |
| |
| ASSIGN_OR_RETURN(std::shared_ptr<AuthorizationPolicyProviderInterface> |
| policy, auth::GetAuthPolicy()); |
| LOG(INFO) << "authorization policy loaded"; |
| |
| builder.experimental().SetAuthorizationPolicyProvider(policy); |
| |
| LOG(INFO) << "using address " << address; |
| builder.AddListeningPort(address, creds); |
| |
| /* Listen on the given address with an authentication mechanism. */ |
| builder.RegisterService(&safePowerService); |
| grpc::reflection::InitProtoReflectionServerBuilderPlugin(); |
| |
| std::unique_ptr<Server> server(builder.BuildAndStart()); |
| if (server == nullptr) |
| { |
| // TODO Add logic to restarting safePowerService, while running events |
| // in the scheduler. (Possibly schedule a retry.) |
| LOG(ERROR) << "grpc server failed to start, exiting gPowerD"; |
| return absl::InternalError |
| ("grpc server failed to start, exiting gPowerD"); |
| } |
| |
| // register SIGTERM handler before starting io loop |
| std::signal(SIGTERM, [](int) { |
| LOG(INFO) << "Received SIGTERM, starting shutting down gracefully"; |
| |
| absl::Status status = DaemonContextBMC::Get().scheduler().Shutdown(); |
| if (!status.ok()) { |
| LOG(ERROR) << "SIGTERM, shutting down error : " << status; |
| } |
| }); |
| |
| LOG(INFO) << "gPowerD started"; |
| DaemonContextBMC::Get().get_io_context().run(); |
| LOG(INFO) << "event loop returned"; |
| if (server){ |
| server->Shutdown(gpr_now(GPR_CLOCK_MONOTONIC)); |
| } |
| LOG(INFO) << "gPowerD stopped; grpc server shutdown"; |
| return absl::OkStatus(); |
| } |
| |
| |
| int main(int argc, char** argv) |
| { |
| absl::ParseCommandLine(argc, argv); |
| (void)absl::SetGlobalVLogLevel(absl::GetFlag(FLAGS_v)); |
| absl::Status status = main_gpowerd(); |
| if (!status.ok()){ |
| LOG(ERROR) << "gpowerd exited with status: " << status; |
| return 1; |
| } |
| LOG(INFO) << "gpowerd exited with status: 0 "; |
| return 0; |
| } |