git.frostfs.info/TrueCloudLab/frostfs-sdk-go@v0.0.0-20241022124111-5361f0ecebd3/client/netmap.go (about) 1 package client 2 3 import ( 4 "context" 5 "fmt" 6 7 v2netmap "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" 8 rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" 9 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" 10 v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" 11 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" 12 apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" 13 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" 14 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" 15 ) 16 17 // PrmEndpointInfo groups parameters of EndpointInfo operation. 18 type PrmEndpointInfo struct { 19 XHeaders []string 20 } 21 22 func (x *PrmEndpointInfo) buildRequest(c *Client) (*v2netmap.LocalNodeInfoRequest, error) { 23 meta := new(v2session.RequestMetaHeader) 24 writeXHeadersToMeta(x.XHeaders, meta) 25 26 req := new(v2netmap.LocalNodeInfoRequest) 27 req.SetBody(new(v2netmap.LocalNodeInfoRequestBody)) 28 c.prepareRequest(req, meta) 29 return req, nil 30 } 31 32 // ResEndpointInfo group resulting values of EndpointInfo operation. 33 type ResEndpointInfo struct { 34 statusRes 35 36 version version.Version 37 38 ni netmap.NodeInfo 39 } 40 41 // LatestVersion returns latest FrostFS API protocol's version in use. 42 func (x ResEndpointInfo) LatestVersion() version.Version { 43 return x.version 44 } 45 46 // NodeInfo returns information about the FrostFS node served on the remote endpoint. 47 func (x ResEndpointInfo) NodeInfo() netmap.NodeInfo { 48 return x.ni 49 } 50 51 // EndpointInfo requests information about the storage node served on the remote endpoint. 52 // 53 // Method can be used as a health check to see if node is alive and responds to requests. 54 // 55 // Any client's internal or transport errors are returned as `error`. 56 // If PrmInit.DisableFrostFSFailuresResolution has been called, unsuccessful 57 // FrostFS status codes are included in the returned result structure, 58 // otherwise, are also returned as `error`. 59 // 60 // Returns an error if parameters are set incorrectly (see PrmEndpointInfo docs). 61 // Context is required and must not be nil. It is used for network communication. 62 // 63 // Exactly one return value is non-nil. Server status return is returned in ResEndpointInfo. 64 // Reflects all internal errors in second return value (transport problems, response processing, etc.). 65 // 66 // Return statuses: 67 // - global (see Client docs). 68 func (c *Client) EndpointInfo(ctx context.Context, prm PrmEndpointInfo) (*ResEndpointInfo, error) { 69 req, err := prm.buildRequest(c) 70 if err != nil { 71 return nil, err 72 } 73 74 if err := signature.SignServiceMessage(&c.prm.Key, req); err != nil { 75 return nil, fmt.Errorf("sign request: %w", err) 76 } 77 78 resp, err := rpcapi.LocalNodeInfo(&c.c, req, client.WithContext(ctx)) 79 if err != nil { 80 return nil, err 81 } 82 83 var res ResEndpointInfo 84 res.st, err = c.processResponse(resp) 85 if err != nil || !apistatus.IsSuccessful(res.st) { 86 return &res, err 87 } 88 89 body := resp.GetBody() 90 91 const fieldVersion = "version" 92 93 verV2 := body.GetVersion() 94 if verV2 == nil { 95 return nil, newErrMissingResponseField(fieldVersion) 96 } 97 if err := res.version.ReadFromV2(*verV2); err != nil { 98 return nil, newErrInvalidResponseField(fieldVersion, err) 99 } 100 101 const fieldNodeInfo = "node info" 102 103 nodeInfoV2 := body.GetNodeInfo() 104 if nodeInfoV2 == nil { 105 return nil, newErrMissingResponseField(fieldNodeInfo) 106 } 107 if err := res.ni.ReadFromV2(*nodeInfoV2); err != nil { 108 return nil, newErrInvalidResponseField(fieldNodeInfo, err) 109 } 110 return &res, nil 111 } 112 113 // PrmNetworkInfo groups parameters of NetworkInfo operation. 114 type PrmNetworkInfo struct { 115 XHeaders []string 116 } 117 118 func (x PrmNetworkInfo) buildRequest(c *Client) (*v2netmap.NetworkInfoRequest, error) { 119 meta := new(v2session.RequestMetaHeader) 120 writeXHeadersToMeta(x.XHeaders, meta) 121 122 var req v2netmap.NetworkInfoRequest 123 req.SetBody(new(v2netmap.NetworkInfoRequestBody)) 124 c.prepareRequest(&req, meta) 125 return &req, nil 126 } 127 128 // ResNetworkInfo groups resulting values of NetworkInfo operation. 129 type ResNetworkInfo struct { 130 statusRes 131 132 info netmap.NetworkInfo 133 } 134 135 // Info returns structured information about the FrostFS network. 136 func (x ResNetworkInfo) Info() netmap.NetworkInfo { 137 return x.info 138 } 139 140 // NetworkInfo requests information about the FrostFS network of which the remote server is a part. 141 // 142 // Any client's internal or transport errors are returned as `error`. 143 // If PrmInit.DisableFrostFSFailuresResolution has been called, unsuccessful 144 // FrostFS status codes are included in the returned result structure, 145 // otherwise, are also returned as `error`. 146 // 147 // Returns an error if parameters are set incorrectly (see PrmNetworkInfo docs). 148 // Context is required and must not be nil. It is used for network communication. 149 // 150 // Exactly one return value is non-nil. Server status return is returned in ResNetworkInfo. 151 // Reflects all internal errors in second return value (transport problems, response processing, etc.). 152 // 153 // Return statuses: 154 // - global (see Client docs). 155 func (c *Client) NetworkInfo(ctx context.Context, prm PrmNetworkInfo) (*ResNetworkInfo, error) { 156 req, err := prm.buildRequest(c) 157 if err != nil { 158 return nil, err 159 } 160 161 if err := signature.SignServiceMessage(&c.prm.Key, req); err != nil { 162 return nil, fmt.Errorf("sign request: %w", err) 163 } 164 165 resp, err := rpcapi.NetworkInfo(&c.c, req, client.WithContext(ctx)) 166 if err != nil { 167 return nil, err 168 } 169 170 var res ResNetworkInfo 171 res.st, err = c.processResponse(resp) 172 if err != nil || !apistatus.IsSuccessful(res.st) { 173 return &res, err 174 } 175 176 const fieldNetInfo = "network info" 177 178 netInfoV2 := resp.GetBody().GetNetworkInfo() 179 if netInfoV2 == nil { 180 return nil, newErrMissingResponseField(fieldNetInfo) 181 } 182 if err := res.info.ReadFromV2(*netInfoV2); err != nil { 183 return nil, newErrInvalidResponseField(fieldNetInfo, err) 184 } 185 return &res, nil 186 } 187 188 // PrmNetMapSnapshot groups parameters of NetMapSnapshot operation. 189 type PrmNetMapSnapshot struct{} 190 191 // ResNetMapSnapshot groups resulting values of NetMapSnapshot operation. 192 type ResNetMapSnapshot struct { 193 statusRes 194 195 netMap netmap.NetMap 196 } 197 198 // NetMap returns current server's local network map. 199 func (x ResNetMapSnapshot) NetMap() netmap.NetMap { 200 return x.netMap 201 } 202 203 // NetMapSnapshot requests current network view of the remote server. 204 // 205 // Any client's internal or transport errors are returned as `error`. 206 // If PrmInit.DisableFrostFSFailuresResolution has been called, unsuccessful 207 // FrostFS status codes are included in the returned result structure, 208 // otherwise, are also returned as `error`. 209 // 210 // Returns an error if parameters are set incorrectly. 211 // Context is required and MUST NOT be nil. It is used for network communication. 212 // 213 // Exactly one return value is non-nil. Server status return is returned in ResNetMapSnapshot. 214 // Reflects all internal errors in second return value (transport problems, response processing, etc.). 215 // 216 // Return statuses: 217 // - global (see Client docs). 218 func (c *Client) NetMapSnapshot(ctx context.Context, _ PrmNetMapSnapshot) (*ResNetMapSnapshot, error) { 219 // form request body 220 var body v2netmap.SnapshotRequestBody 221 222 // form meta header 223 var meta v2session.RequestMetaHeader 224 225 // form request 226 var req v2netmap.SnapshotRequest 227 req.SetBody(&body) 228 c.prepareRequest(&req, &meta) 229 230 err := signature.SignServiceMessage(&c.prm.Key, &req) 231 if err != nil { 232 return nil, fmt.Errorf("sign request: %w", err) 233 } 234 235 resp, err := c.server.netMapSnapshot(ctx, req) 236 if err != nil { 237 return nil, err 238 } 239 240 var res ResNetMapSnapshot 241 res.st, err = c.processResponse(resp) 242 if err != nil || !apistatus.IsSuccessful(res.st) { 243 return &res, err 244 } 245 246 const fieldNetMap = "network map" 247 248 netMapV2 := resp.GetBody().NetMap() 249 if netMapV2 == nil { 250 return nil, newErrMissingResponseField(fieldNetMap) 251 } 252 253 err = res.netMap.ReadFromV2(*netMapV2) 254 if err != nil { 255 return nil, newErrInvalidResponseField(fieldNetMap, err) 256 } 257 258 return &res, nil 259 }