package client import ( "context" "fmt" v2netmap "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap" rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" ) // PrmEndpointInfo groups parameters of EndpointInfo operation. type PrmEndpointInfo struct { XHeaders []string } func (x *PrmEndpointInfo) buildRequest(c *Client) (*v2netmap.LocalNodeInfoRequest, error) { meta := new(v2session.RequestMetaHeader) writeXHeadersToMeta(x.XHeaders, meta) req := new(v2netmap.LocalNodeInfoRequest) req.SetBody(new(v2netmap.LocalNodeInfoRequestBody)) c.prepareRequest(req, meta) return req, nil } // ResEndpointInfo group resulting values of EndpointInfo operation. type ResEndpointInfo struct { statusRes version version.Version ni netmap.NodeInfo } // LatestVersion returns latest FrostFS API protocol's version in use. func (x ResEndpointInfo) LatestVersion() version.Version { return x.version } // NodeInfo returns information about the FrostFS node served on the remote endpoint. func (x ResEndpointInfo) NodeInfo() netmap.NodeInfo { return x.ni } // EndpointInfo requests information about the storage node served on the remote endpoint. // // Method can be used as a health check to see if node is alive and responds to requests. // // Any client's internal or transport errors are returned as `error`. // If PrmInit.DisableFrostFSFailuresResolution has been called, unsuccessful // FrostFS status codes are included in the returned result structure, // otherwise, are also returned as `error`. // // Returns an error if parameters are set incorrectly (see PrmEndpointInfo docs). // Context is required and must not be nil. It is used for network communication. // // Exactly one return value is non-nil. Server status return is returned in ResEndpointInfo. // Reflects all internal errors in second return value (transport problems, response processing, etc.). // // Return statuses: // - global (see Client docs). func (c *Client) EndpointInfo(ctx context.Context, prm PrmEndpointInfo) (*ResEndpointInfo, error) { req, err := prm.buildRequest(c) if err != nil { return nil, err } if err := signature.SignServiceMessage(&c.prm.Key, req); err != nil { return nil, fmt.Errorf("sign request: %w", err) } resp, err := rpcapi.LocalNodeInfo(&c.c, req, client.WithContext(ctx)) if err != nil { return nil, err } var res ResEndpointInfo res.st, err = c.processResponse(resp) if err != nil || !apistatus.IsSuccessful(res.st) { return &res, err } body := resp.GetBody() const fieldVersion = "version" verV2 := body.GetVersion() if verV2 == nil { return nil, newErrMissingResponseField(fieldVersion) } if err := res.version.ReadFromV2(*verV2); err != nil { return nil, newErrInvalidResponseField(fieldVersion, err) } const fieldNodeInfo = "node info" nodeInfoV2 := body.GetNodeInfo() if nodeInfoV2 == nil { return nil, newErrMissingResponseField(fieldNodeInfo) } if err := res.ni.ReadFromV2(*nodeInfoV2); err != nil { return nil, newErrInvalidResponseField(fieldNodeInfo, err) } return &res, nil } // PrmNetworkInfo groups parameters of NetworkInfo operation. type PrmNetworkInfo struct { XHeaders []string } func (x PrmNetworkInfo) buildRequest(c *Client) (*v2netmap.NetworkInfoRequest, error) { meta := new(v2session.RequestMetaHeader) writeXHeadersToMeta(x.XHeaders, meta) var req v2netmap.NetworkInfoRequest req.SetBody(new(v2netmap.NetworkInfoRequestBody)) c.prepareRequest(&req, meta) return &req, nil } // ResNetworkInfo groups resulting values of NetworkInfo operation. type ResNetworkInfo struct { statusRes info netmap.NetworkInfo } // Info returns structured information about the FrostFS network. func (x ResNetworkInfo) Info() netmap.NetworkInfo { return x.info } // NetworkInfo requests information about the FrostFS network of which the remote server is a part. // // Any client's internal or transport errors are returned as `error`. // If PrmInit.DisableFrostFSFailuresResolution has been called, unsuccessful // FrostFS status codes are included in the returned result structure, // otherwise, are also returned as `error`. // // Returns an error if parameters are set incorrectly (see PrmNetworkInfo docs). // Context is required and must not be nil. It is used for network communication. // // Exactly one return value is non-nil. Server status return is returned in ResNetworkInfo. // Reflects all internal errors in second return value (transport problems, response processing, etc.). // // Return statuses: // - global (see Client docs). func (c *Client) NetworkInfo(ctx context.Context, prm PrmNetworkInfo) (*ResNetworkInfo, error) { req, err := prm.buildRequest(c) if err != nil { return nil, err } if err := signature.SignServiceMessage(&c.prm.Key, req); err != nil { return nil, fmt.Errorf("sign request: %w", err) } resp, err := rpcapi.NetworkInfo(&c.c, req, client.WithContext(ctx)) if err != nil { return nil, err } var res ResNetworkInfo res.st, err = c.processResponse(resp) if err != nil || !apistatus.IsSuccessful(res.st) { return &res, err } const fieldNetInfo = "network info" netInfoV2 := resp.GetBody().GetNetworkInfo() if netInfoV2 == nil { return nil, newErrMissingResponseField(fieldNetInfo) } if err := res.info.ReadFromV2(*netInfoV2); err != nil { return nil, newErrInvalidResponseField(fieldNetInfo, err) } return &res, nil } // PrmNetMapSnapshot groups parameters of NetMapSnapshot operation. type PrmNetMapSnapshot struct{} // ResNetMapSnapshot groups resulting values of NetMapSnapshot operation. type ResNetMapSnapshot struct { statusRes netMap netmap.NetMap } // NetMap returns current server's local network map. func (x ResNetMapSnapshot) NetMap() netmap.NetMap { return x.netMap } // NetMapSnapshot requests current network view of the remote server. // // Any client's internal or transport errors are returned as `error`. // If PrmInit.DisableFrostFSFailuresResolution has been called, unsuccessful // FrostFS status codes are included in the returned result structure, // otherwise, are also returned as `error`. // // Returns an error if parameters are set incorrectly. // Context is required and MUST NOT be nil. It is used for network communication. // // Exactly one return value is non-nil. Server status return is returned in ResNetMapSnapshot. // Reflects all internal errors in second return value (transport problems, response processing, etc.). // // Return statuses: // - global (see Client docs). func (c *Client) NetMapSnapshot(ctx context.Context, _ PrmNetMapSnapshot) (*ResNetMapSnapshot, error) { // form request body var body v2netmap.SnapshotRequestBody // form meta header var meta v2session.RequestMetaHeader // form request var req v2netmap.SnapshotRequest req.SetBody(&body) c.prepareRequest(&req, &meta) err := signature.SignServiceMessage(&c.prm.Key, &req) if err != nil { return nil, fmt.Errorf("sign request: %w", err) } resp, err := c.server.netMapSnapshot(ctx, req) if err != nil { return nil, err } var res ResNetMapSnapshot res.st, err = c.processResponse(resp) if err != nil || !apistatus.IsSuccessful(res.st) { return &res, err } const fieldNetMap = "network map" netMapV2 := resp.GetBody().NetMap() if netMapV2 == nil { return nil, newErrMissingResponseField(fieldNetMap) } err = res.netMap.ReadFromV2(*netMapV2) if err != nil { return nil, newErrInvalidResponseField(fieldNetMap, err) } return &res, nil }