blob: 7d9eabec62372ff154b7e5993b28512231ffb393 [file] [log] [blame]
// 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 <csignal>
#include <memory>
#include <string>
#include <utility>
#include "action_context.h"
#include "bmc/auth.h"
#include "bmc/daemon_context_bmc.h"
#include "bmc/machine_configs/setup_configs.h"
#include "bmc/state_monitor_bmc.h"
#include "safepower_agent_config.pb.h"
#include "safepower_agent.h"
#include "state_updater.h"
#include "absl/flags/flag.h"
#include "absl/flags/parse.h"
#include "absl/log/globals.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "grpc/support/time.h"
#include "grpcpp/ext/proto_server_reflection_plugin.h"
#include "grpcpp/security/authorization_policy_provider.h"
#include "grpcpp/security/server_credentials.h"
#include "grpcpp/server.h"
#include "grpcpp/server_builder.h"
#include "bmc/status_macros.h"
using grpc::Server;
using grpc::ServerBuilder;
using safepower_agent::DaemonContextBMC;
using safepower_agent::SafepowerLocalAgentImpl;
using safepower_agent::StateUpdater;
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").OnUpdate([] {
absl::SetGlobalVLogLevel(absl::GetFlag(FLAGS_v));
});
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;
std::shared_ptr<grpc::ServerCredentials> creds = nullptr;
#ifdef INSECURE_MODE
creds = grpc::InsecureServerCredentials(); // NOLINT if the image is
// build in insecure mode, build the grpc server with
// insecure credentials
LOG(WARNING) << "Using insecure credentials";
#else
LOG(INFO) << "Using secure credentials";
ASSIGN_OR_RETURN(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);
#endif // INSECURE_MODE
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);
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;
}