blob: 76d0a302b8211a008238f398f98f328294a92bf8 [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 <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;
}