From abead4db9eaf8c64db9492a79f6f1cc28ce5ff6d Mon Sep 17 00:00:00 2001 From: Derek Su Date: Tue, 20 Feb 2024 00:16:26 +0000 Subject: [PATCH] instance: implement log client and server functions Longhorn 7939 Signed-off-by: Derek Su --- pkg/client/instance.go | 72 ++++++++++++++++++++++ pkg/instance/instance.go | 5 ++ pkg/instance/log.go | 126 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 203 insertions(+) create mode 100644 pkg/instance/log.go diff --git a/pkg/client/instance.go b/pkg/client/instance.go index 2164528fd..9be755b21 100644 --- a/pkg/client/instance.go +++ b/pkg/client/instance.go @@ -343,6 +343,78 @@ func (c *InstanceServiceClient) VersionGet() (*meta.VersionOutput, error) { }, nil } +func (c *InstanceServiceClient) LogSetLevel(dataEngine, service, level string) error { + client := c.getControllerServiceClient() + ctx, cancel := context.WithTimeout(context.Background(), types.GRPCServiceTimeout) + defer cancel() + + driver, ok := rpc.DataEngine_value[getDataEngine(dataEngine)] + if !ok { + return fmt.Errorf("failed to set log level: invalid data engine %v", dataEngine) + } + + _, err := client.LogSetLevel(ctx, &rpc.LogSetLevelRequest{ + DataEngine: rpc.DataEngine(driver), + Level: level, + }) + return err +} + +func (c *InstanceServiceClient) LogSetFlags(dataEngine, service, flags string) error { + client := c.getControllerServiceClient() + ctx, cancel := context.WithTimeout(context.Background(), types.GRPCServiceTimeout) + defer cancel() + + driver, ok := rpc.DataEngine_value[getDataEngine(dataEngine)] + if !ok { + return fmt.Errorf("failed to set log flags: invalid data engine %v", dataEngine) + } + + _, err := client.LogSetFlags(ctx, &rpc.LogSetFlagsRequest{ + DataEngine: rpc.DataEngine(driver), + Flags: flags, + }) + return err +} + +func (c *InstanceServiceClient) LogGetLevel(dataEngine, service string) (string, error) { + client := c.getControllerServiceClient() + ctx, cancel := context.WithTimeout(context.Background(), types.GRPCServiceTimeout) + defer cancel() + + driver, ok := rpc.DataEngine_value[getDataEngine(dataEngine)] + if !ok { + return "", fmt.Errorf("failed to get log level: invalid data engine %v", dataEngine) + } + + resp, err := client.LogGetLevel(ctx, &rpc.LogGetLevelRequest{ + DataEngine: rpc.DataEngine(driver), + }) + if err != nil { + return "", err + } + return resp.Level, nil +} + +func (c *InstanceServiceClient) LogGetFlags(dataEngine, service string) (string, error) { + client := c.getControllerServiceClient() + ctx, cancel := context.WithTimeout(context.Background(), types.GRPCServiceTimeout) + defer cancel() + + driver, ok := rpc.DataEngine_value[getDataEngine(dataEngine)] + if !ok { + return "", fmt.Errorf("failed to get log flags: invalid data engine %v", dataEngine) + } + + resp, err := client.LogGetFlags(ctx, &rpc.LogGetFlagsRequest{ + DataEngine: rpc.DataEngine(driver), + }) + if err != nil { + return "", err + } + return resp.Flags, nil +} + func (c *InstanceServiceClient) CheckConnection() error { req := &healthpb.HealthCheckRequest{} _, err := c.health.Check(getContextWithGRPCTimeout(c.ctx), req) diff --git a/pkg/instance/instance.go b/pkg/instance/instance.go index 4de47e490..d11e359c9 100644 --- a/pkg/instance/instance.go +++ b/pkg/instance/instance.go @@ -35,6 +35,11 @@ type InstanceOps interface { InstanceList(map[string]*rpc.InstanceResponse) error InstanceReplace(*rpc.InstanceReplaceRequest) (*rpc.InstanceResponse, error) InstanceLog(*rpc.InstanceLogRequest, rpc.InstanceService_InstanceLogServer) error + + LogSetLevel(context.Context, *rpc.LogSetLevelRequest) (*emptypb.Empty, error) + LogSetFlags(context.Context, *rpc.LogSetFlagsRequest) (*emptypb.Empty, error) + LogGetLevel(context.Context, *rpc.LogGetLevelRequest) (*rpc.LogGetLevelResponse, error) + LogGetFlags(context.Context, *rpc.LogGetFlagsRequest) (*rpc.LogGetFlagsResponse, error) } type V1DataEngineInstanceOps struct { diff --git a/pkg/instance/log.go b/pkg/instance/log.go new file mode 100644 index 000000000..8b8b84b1e --- /dev/null +++ b/pkg/instance/log.go @@ -0,0 +1,126 @@ +package instance + +import ( + "github.com/pkg/errors" + "golang.org/x/net/context" + + grpccodes "google.golang.org/grpc/codes" + grpcstatus "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/emptypb" + + spdkclient "github.com/longhorn/longhorn-spdk-engine/pkg/client" + + rpc "github.com/longhorn/longhorn-instance-manager/pkg/imrpc" +) + +func (s *Server) LogSetLevel(ctx context.Context, req *rpc.LogSetLevelRequest) (resp *emptypb.Empty, err error) { + ops, ok := s.ops[req.DataEngine] + if !ok { + return nil, grpcstatus.Errorf(grpccodes.Unimplemented, "unsupported data engine %v", req.DataEngine) + } + return ops.LogSetLevel(ctx, req) +} + +func (ops V1DataEngineInstanceOps) LogSetLevel(ctx context.Context, req *rpc.LogSetLevelRequest) (resp *emptypb.Empty, err error) { + /* TODO: Implement this */ + return &emptypb.Empty{}, nil +} + +func (ops V2DataEngineInstanceOps) LogSetLevel(ctx context.Context, req *rpc.LogSetLevelRequest) (resp *emptypb.Empty, err error) { + c, err := spdkclient.NewSPDKClient(ops.spdkServiceAddress) + if err != nil { + return nil, grpcstatus.Error(grpccodes.Internal, errors.Wrapf(err, "failed to create SPDK client").Error()) + } + defer c.Close() + + err = c.LogSetLevel(req.Level) + if err != nil { + return nil, grpcstatus.Error(grpccodes.Internal, errors.Wrapf(err, "failed to set log level").Error()) + } + return &emptypb.Empty{}, nil +} + +func (s *Server) LogSetFlags(ctx context.Context, req *rpc.LogSetFlagsRequest) (resp *emptypb.Empty, err error) { + ops, ok := s.ops[req.DataEngine] + if !ok { + return nil, grpcstatus.Errorf(grpccodes.Unimplemented, "unsupported data engine %v", req.DataEngine) + } + return ops.LogSetFlags(ctx, req) +} + +func (ops V1DataEngineInstanceOps) LogSetFlags(ctx context.Context, req *rpc.LogSetFlagsRequest) (resp *emptypb.Empty, err error) { + /* TODO: Implement this */ + return &emptypb.Empty{}, nil +} + +func (ops V2DataEngineInstanceOps) LogSetFlags(ctx context.Context, req *rpc.LogSetFlagsRequest) (resp *emptypb.Empty, err error) { + c, err := spdkclient.NewSPDKClient(ops.spdkServiceAddress) + if err != nil { + return nil, grpcstatus.Error(grpccodes.Internal, errors.Wrapf(err, "failed to create SPDK client").Error()) + } + defer c.Close() + + err = c.LogSetFlags(req.Flags) + if err != nil { + return nil, grpcstatus.Error(grpccodes.Internal, errors.Wrapf(err, "failed to set log flags").Error()) + } + return &emptypb.Empty{}, nil +} + +func (s *Server) LogGetLevel(ctx context.Context, req *rpc.LogGetLevelRequest) (resp *rpc.LogGetLevelResponse, err error) { + ops, ok := s.ops[req.DataEngine] + if !ok { + return nil, grpcstatus.Errorf(grpccodes.Unimplemented, "unsupported data engine %v", req.DataEngine) + } + return ops.LogGetLevel(ctx, req) +} + +func (ops V1DataEngineInstanceOps) LogGetLevel(ctx context.Context, req *rpc.LogGetLevelRequest) (resp *rpc.LogGetLevelResponse, err error) { + /* TODO: Implement this */ + return &rpc.LogGetLevelResponse{}, nil +} + +func (ops V2DataEngineInstanceOps) LogGetLevel(ctx context.Context, req *rpc.LogGetLevelRequest) (resp *rpc.LogGetLevelResponse, err error) { + c, err := spdkclient.NewSPDKClient(ops.spdkServiceAddress) + if err != nil { + return nil, grpcstatus.Error(grpccodes.Internal, errors.Wrapf(err, "failed to create SPDK client").Error()) + } + defer c.Close() + + level, err := c.LogGetLevel() + if err != nil { + return nil, grpcstatus.Error(grpccodes.Internal, errors.Wrapf(err, "failed to get log level").Error()) + } + return &rpc.LogGetLevelResponse{ + Level: level, + }, nil +} + +func (s *Server) LogGetFlags(ctx context.Context, req *rpc.LogGetFlagsRequest) (resp *rpc.LogGetFlagsResponse, err error) { + ops, ok := s.ops[req.DataEngine] + if !ok { + return nil, grpcstatus.Errorf(grpccodes.Unimplemented, "unsupported data engine %v", req.DataEngine) + } + return ops.LogGetFlags(ctx, req) +} + +func (ops V1DataEngineInstanceOps) LogGetFlags(ctx context.Context, req *rpc.LogGetFlagsRequest) (resp *rpc.LogGetFlagsResponse, err error) { + /* TODO: Implement this */ + return &rpc.LogGetFlagsResponse{}, nil +} + +func (ops V2DataEngineInstanceOps) LogGetFlags(ctx context.Context, req *rpc.LogGetFlagsRequest) (resp *rpc.LogGetFlagsResponse, err error) { + c, err := spdkclient.NewSPDKClient(ops.spdkServiceAddress) + if err != nil { + return nil, grpcstatus.Error(grpccodes.Internal, errors.Wrapf(err, "failed to create SPDK client").Error()) + } + defer c.Close() + + flags, err := c.LogGetFlags() + if err != nil { + return nil, grpcstatus.Error(grpccodes.Internal, errors.Wrapf(err, "failed to get log flags").Error()) + } + return &rpc.LogGetFlagsResponse{ + Flags: flags, + }, nil +}