[#946] ir: Refactor usage of NeoFS API client

The client needs of the IR application are very limited and rarely change.
Interface changes of the client library should not affect the operation of
various application packages, if they do not change their requirements for
the provided functionality. To localize the use of the base client and
facilitate further support, an auxiliary package is implemented that will
only be used by the IR application.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
Leonard Lyubich 2021-10-27 15:12:05 +03:00 committed by LeL
parent 49c9dbfba8
commit 88e37ea372
7 changed files with 416 additions and 66 deletions

View file

@ -12,6 +12,8 @@ import (
"github.com/nspcc-dev/neofs-api-go/pkg/storagegroup"
clientcore "github.com/nspcc-dev/neofs-node/pkg/core/client"
coreObject "github.com/nspcc-dev/neofs-node/pkg/core/object"
neofsapiclient "github.com/nspcc-dev/neofs-node/pkg/innerring/internal/client"
auditproc "github.com/nspcc-dev/neofs-node/pkg/innerring/processors/audit"
"github.com/nspcc-dev/neofs-node/pkg/network/cache"
"github.com/nspcc-dev/neofs-node/pkg/services/audit"
"github.com/nspcc-dev/neofs-node/pkg/services/object_manager/placement"
@ -82,7 +84,7 @@ func (c *ClientCache) getSG(ctx context.Context, addr *object.Address, nm *netma
return nil, fmt.Errorf("parse client node info: %w", err)
}
cli, err := c.Get(info)
cli, err := c.getWrappedClient(info)
if err != nil {
c.log.Warn("can't setup remote connection",
zap.String("error", err.Error()))
@ -91,12 +93,15 @@ func (c *ClientCache) getSG(ctx context.Context, addr *object.Address, nm *netma
}
cctx, cancel := context.WithTimeout(ctx, c.sgTimeout)
obj, err := cli.GetObject(cctx, getParams, client.WithKey(c.key))
// NOTE: we use the function which does not verify object integrity (checksums, signature),
// but it would be useful to do as part of a data audit.
payload, err := neofsapiclient.GetObjectPayload(cctx, cli, addr)
cancel()
if err != nil {
c.log.Warn("can't get storage group object",
c.log.Warn("can't get payload of storage group object",
zap.String("error", err.Error()))
continue
@ -104,7 +109,7 @@ func (c *ClientCache) getSG(ctx context.Context, addr *object.Address, nm *netma
sg := storagegroup.New()
err = sg.Unmarshal(obj.Payload())
err = sg.Unmarshal(payload)
if err != nil {
return nil, fmt.Errorf("can't parse storage group payload: %w", err)
}
@ -117,23 +122,10 @@ func (c *ClientCache) getSG(ctx context.Context, addr *object.Address, nm *netma
// GetHeader requests node from the container under audit to return object header by id.
func (c *ClientCache) GetHeader(task *audit.Task, node *netmap.Node, id *object.ID, relay bool) (*object.Object, error) {
raw := true
ttl := uint32(1)
if relay {
ttl = 10 // todo: instead of hardcode value we can set TTL based on container length
raw = false
}
objAddress := new(object.Address)
objAddress.SetContainerID(task.ContainerID())
objAddress.SetObjectID(id)
headParams := new(client.ObjectHeaderParams)
headParams.WithRawFlag(raw)
headParams.WithMainFields()
headParams.WithAddress(objAddress)
var info clientcore.NodeInfo
err := clientcore.NodeInfoFromRawNetmapElement(&info, node)
@ -141,15 +133,21 @@ func (c *ClientCache) GetHeader(task *audit.Task, node *netmap.Node, id *object.
return nil, fmt.Errorf("parse client node info: %w", err)
}
cli, err := c.Get(info)
cli, err := c.getWrappedClient(info)
if err != nil {
return nil, fmt.Errorf("can't setup remote connection with %s: %w", info.AddressGroup(), err)
}
cctx, cancel := context.WithTimeout(task.AuditContext(), c.headTimeout)
head, err := cli.GetObjectHeader(cctx, headParams,
client.WithTTL(ttl),
client.WithKey(c.key))
var obj *object.Object
if relay {
// todo: function sets hardcoded TTL value, but instead we can set TTL based on container length
obj, err = neofsapiclient.GetObjectHeaderFromContainer(cctx, cli, objAddress)
} else {
obj, err = neofsapiclient.GetRawObjectHeaderLocally(cctx, cli, objAddress)
}
cancel()
@ -157,7 +155,7 @@ func (c *ClientCache) GetHeader(task *audit.Task, node *netmap.Node, id *object.
return nil, fmt.Errorf("object head error: %w", err)
}
return head, nil
return obj, nil
}
// GetRangeHash requests node from the container under audit to return Tillich-Zemor hash of the
@ -167,11 +165,6 @@ func (c *ClientCache) GetRangeHash(task *audit.Task, node *netmap.Node, id *obje
objAddress.SetContainerID(task.ContainerID())
objAddress.SetObjectID(id)
rangeParams := new(client.RangeChecksumParams)
rangeParams.WithAddress(objAddress)
rangeParams.WithRangeList(rng)
rangeParams.WithSalt(nil) // it MUST be nil for correct hash concatenation in PDP game
var info clientcore.NodeInfo
err := clientcore.NodeInfoFromRawNetmapElement(&info, node)
@ -179,15 +172,14 @@ func (c *ClientCache) GetRangeHash(task *audit.Task, node *netmap.Node, id *obje
return nil, fmt.Errorf("parse client node info: %w", err)
}
cli, err := c.Get(info)
cli, err := c.getWrappedClient(info)
if err != nil {
return nil, fmt.Errorf("can't setup remote connection with %s: %w", info.AddressGroup(), err)
}
cctx, cancel := context.WithTimeout(task.AuditContext(), c.rangeTimeout)
result, err := cli.ObjectPayloadRangeTZ(cctx, rangeParams,
client.WithTTL(1),
client.WithKey(c.key))
h, err := neofsapiclient.HashObjectRange(cctx, cli, objAddress, rng)
cancel()
@ -195,7 +187,41 @@ func (c *ClientCache) GetRangeHash(task *audit.Task, node *netmap.Node, id *obje
return nil, fmt.Errorf("object rangehash error: %w", err)
}
// client guarantees that request and response have equal amount of ranges
return result[0][:], nil
return h, nil
}
func (c *ClientCache) getWrappedClient(info clientcore.NodeInfo) (neofsapiclient.Client, error) {
// can be also cached
var cInternal neofsapiclient.Client
cli, err := c.Get(info)
if err != nil {
return cInternal, fmt.Errorf("could not get API client from cache")
}
cInternal.WrapBasicClient(cli)
cInternal.SetPrivateKey(c.key)
return cInternal, nil
}
func (c ClientCache) ListSG(dst *auditproc.SearchSGDst, prm auditproc.SearchSGPrm) error {
cli, err := c.getWrappedClient(prm.NodeInfo())
if err != nil {
return fmt.Errorf("could not get API client from cache")
}
var cliPrm neofsapiclient.SearchSGPrm
cliPrm.SetContext(prm.Context())
cliPrm.SetContainerID(prm.CID())
res, err := cli.SearchSG(cliPrm)
if err != nil {
return err
}
dst.WriteIDList(res.IDList())
return nil
}