package netmap import ( "context" "errors" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/version" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util/response" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" versionsdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" ) type executorSvc struct { version refs.Version state NodeState netInfo NetworkInfo respSvc *response.Service } // NodeState encapsulates information // about current node state. type NodeState interface { // LocalNodeInfo must return current node state // in FrostFS API v2 NodeInfo structure. LocalNodeInfo() *netmapSDK.NodeInfo // ReadCurrentNetMap reads current local network map of the storage node // into the given parameter. Returns any error encountered which prevented // the network map to be read. ReadCurrentNetMap(*netmap.NetMap) error } // NetworkInfo encapsulates source of the // recent information about the FrostFS network. type NetworkInfo interface { // Dump must return recent network information in FrostFS API v2 NetworkInfo structure. // // If protocol version is <=2.9, MillisecondsPerBlock and network config should be unset. Dump(versionsdk.Version) (*netmapSDK.NetworkInfo, error) } func NewExecutionService(s NodeState, v versionsdk.Version, netInfo NetworkInfo, respSvc *response.Service) Server { if s == nil || netInfo == nil || !version.IsValid(v) || respSvc == nil { // this should never happen, otherwise it programmers bug panic("can't create netmap execution service") } res := &executorSvc{ state: s, netInfo: netInfo, respSvc: respSvc, } v.WriteToV2(&res.version) return res } func (s *executorSvc) LocalNodeInfo( _ context.Context, _ *netmap.LocalNodeInfoRequest, ) (*netmap.LocalNodeInfoResponse, error) { ni := s.state.LocalNodeInfo() var nodeInfo netmap.NodeInfo ni.WriteToV2(&nodeInfo) body := new(netmap.LocalNodeInfoResponseBody) body.SetVersion(&s.version) body.SetNodeInfo(&nodeInfo) resp := new(netmap.LocalNodeInfoResponse) resp.SetBody(body) s.respSvc.SetMeta(resp) return resp, nil } func (s *executorSvc) NetworkInfo( _ context.Context, req *netmap.NetworkInfoRequest, ) (*netmap.NetworkInfoResponse, error) { verV2 := req.GetMetaHeader().GetVersion() if verV2 == nil { return nil, errors.New("missing protocol version in meta header") } var ver versionsdk.Version if err := ver.ReadFromV2(*verV2); err != nil { return nil, fmt.Errorf("can't read version: %w", err) } ni, err := s.netInfo.Dump(ver) if err != nil { return nil, err } var niV2 netmap.NetworkInfo ni.WriteToV2(&niV2) body := new(netmap.NetworkInfoResponseBody) body.SetNetworkInfo(&niV2) resp := new(netmap.NetworkInfoResponse) resp.SetBody(body) s.respSvc.SetMeta(resp) return resp, nil } func (s *executorSvc) Snapshot(_ context.Context, _ *netmap.SnapshotRequest) (*netmap.SnapshotResponse, error) { var nm netmap.NetMap err := s.state.ReadCurrentNetMap(&nm) if err != nil { return nil, fmt.Errorf("read current local network map: %w", err) } body := new(netmap.SnapshotResponseBody) body.SetNetMap(&nm) resp := new(netmap.SnapshotResponse) resp.SetBody(body) s.respSvc.SetMeta(resp) return resp, nil }