mirror of
https://github.com/compute-blade-community/compute-blade-agent.git
synced 2026-04-16 15:35:42 +02:00
add server version information to output ensure the blade-name is always set --------- Co-authored-by: Cedric Kienzler <cedric@specht-labs.de>
157 lines
5.5 KiB
Go
157 lines
5.5 KiB
Go
package internal_agent
|
|
|
|
import (
|
|
"context"
|
|
"crypto/tls"
|
|
|
|
bladeapiv1alpha1 "github.com/compute-blade-community/compute-blade-agent/api/bladeapi/v1alpha1"
|
|
"github.com/compute-blade-community/compute-blade-agent/pkg/fancontroller"
|
|
"github.com/compute-blade-community/compute-blade-agent/pkg/log"
|
|
grpczap "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging"
|
|
"github.com/sierrasoftworks/humane-errors-go"
|
|
"github.com/spechtlabs/go-otel-utils/otelzap"
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/credentials"
|
|
"google.golang.org/protobuf/types/known/emptypb"
|
|
)
|
|
|
|
// setupGrpcServer initializes and configures the gRPC server with authentication, logging, and server options.
|
|
func (a *computeBladeAgent) setupGrpcServer(ctx context.Context) error {
|
|
listenMode, err := ListenModeFromString(a.config.Listen.GrpcListenMode)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var grpcOpts []grpc.ServerOption
|
|
|
|
if listenMode == ModeTcp && a.config.Listen.GrpcAuthenticated {
|
|
tlsCfg, err := createServerTLSConfig(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
grpcOpts = append(grpcOpts, grpc.Creds(credentials.NewTLS(tlsCfg)))
|
|
|
|
if err := EnsureAuthenticatedBladectlConfig(ctx, a.config.Listen.Grpc, listenMode); err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
if err := EnsureUnauthenticatedBladectlConfig(ctx, a.config.Listen.Grpc, listenMode); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
logger := log.InterceptorLogger(otelzap.L())
|
|
grpcOpts = append(grpcOpts,
|
|
grpc.ChainUnaryInterceptor(grpczap.UnaryServerInterceptor(logger)),
|
|
grpc.ChainStreamInterceptor(grpczap.StreamServerInterceptor(logger)),
|
|
)
|
|
|
|
a.server = grpc.NewServer(grpcOpts...)
|
|
return nil
|
|
}
|
|
|
|
// createServerTLSConfig creates and returns a TLS configuration for a server, enforcing client authentication.
|
|
// It generates or loads the necessary certificates and certificate pools, logging fatal errors if certificate loading fails.
|
|
func createServerTLSConfig(ctx context.Context) (*tls.Config, error) {
|
|
cert, certPool, err := EnsureServerCertificate(ctx)
|
|
if err != nil {
|
|
log.FromContext(ctx).WithError(err).Fatal("failed to load server key pair")
|
|
}
|
|
return &tls.Config{
|
|
Certificates: []tls.Certificate{cert},
|
|
ClientAuth: tls.RequireAndVerifyClientCert,
|
|
ClientCAs: certPool,
|
|
}, nil
|
|
}
|
|
|
|
// EmitEvent dispatches an event to the event handler
|
|
func (a *computeBladeAgent) EmitEvent(ctx context.Context, req *bladeapiv1alpha1.EmitEventRequest) (*emptypb.Empty, error) {
|
|
event, err := fromProto(req.GetEvent())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
select {
|
|
case a.eventChan <- event:
|
|
return &emptypb.Empty{}, nil
|
|
case <-ctx.Done():
|
|
return &emptypb.Empty{}, ctx.Err()
|
|
}
|
|
}
|
|
|
|
// SetFanSpeed sets the fan speed
|
|
func (a *computeBladeAgent) SetFanSpeed(_ context.Context, req *bladeapiv1alpha1.SetFanSpeedRequest) (*emptypb.Empty, error) {
|
|
if a.state.CriticalActive() {
|
|
return &emptypb.Empty{}, humane.New("cannot set fan speed while the blade is in a critical state", "improve cooling on your blade before attempting to overwrite the fan speed")
|
|
}
|
|
|
|
a.fanController.Override(&fancontroller.FanOverrideOpts{Percent: uint8(req.GetPercent())})
|
|
return &emptypb.Empty{}, nil
|
|
}
|
|
|
|
// SetFanSpeedAuto sets the fan speed to automatic mode
|
|
func (a *computeBladeAgent) SetFanSpeedAuto(context.Context, *emptypb.Empty) (*emptypb.Empty, error) {
|
|
a.fanController.Override(nil)
|
|
return &emptypb.Empty{}, nil
|
|
}
|
|
|
|
// SetStealthMode enables/disables the stealth mode
|
|
func (a *computeBladeAgent) SetStealthMode(_ context.Context, req *bladeapiv1alpha1.StealthModeRequest) (*emptypb.Empty, error) {
|
|
if a.state.CriticalActive() {
|
|
return &emptypb.Empty{}, humane.New("cannot set stealth mode while the blade is in a critical state", "improve cooling on your blade before attempting to enable stealth mode again")
|
|
}
|
|
return &emptypb.Empty{}, a.blade.SetStealthMode(req.GetEnable())
|
|
}
|
|
|
|
// GetStatus aggregates the status of the blade
|
|
func (a *computeBladeAgent) GetStatus(_ context.Context, _ *emptypb.Empty) (*bladeapiv1alpha1.StatusResponse, error) {
|
|
rpm, err := a.blade.GetFanRPM()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
temp, err := a.blade.GetTemperature()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
powerStatus, err := a.blade.GetPowerStatus()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
steps := a.fanController.Steps()
|
|
fanCurveSteps := make([]*bladeapiv1alpha1.FanCurveStep, len(steps))
|
|
for idx, step := range steps {
|
|
fanCurveSteps[idx] = &bladeapiv1alpha1.FanCurveStep{
|
|
Temperature: int64(step.Temperature),
|
|
Percent: uint32(step.Percent),
|
|
}
|
|
}
|
|
|
|
versionInfo := &bladeapiv1alpha1.VersionInfo{
|
|
Version: a.agentInfo.Version,
|
|
Commit: a.agentInfo.Commit,
|
|
Date: a.agentInfo.BuildTime.Unix(),
|
|
}
|
|
|
|
return &bladeapiv1alpha1.StatusResponse{
|
|
StealthMode: a.blade.StealthModeActive(),
|
|
IdentifyActive: a.state.IdentifyActive(),
|
|
CriticalActive: a.state.CriticalActive(),
|
|
Temperature: int64(temp),
|
|
FanRpm: int64(rpm),
|
|
FanPercent: uint32(a.fanController.GetFanSpeedPercent(temp)),
|
|
FanSpeedAutomatic: a.fanController.IsAutomaticSpeed(),
|
|
PowerStatus: bladeapiv1alpha1.PowerStatus(powerStatus),
|
|
FanCurveSteps: fanCurveSteps,
|
|
CriticalTemperatureThreshold: int64(a.config.CriticalTemperatureThreshold),
|
|
Version: versionInfo,
|
|
}, nil
|
|
}
|
|
|
|
// WaitForIdentifyConfirm blocks until the identify confirmation process is completed or an error occurs.
|
|
func (a *computeBladeAgent) WaitForIdentifyConfirm(ctx context.Context, _ *emptypb.Empty) (*emptypb.Empty, error) {
|
|
return &emptypb.Empty{}, a.state.WaitForIdentifyConfirm(ctx)
|
|
}
|