2019-01-24 20:15:10 +00:00
|
|
|
// Copyright (C) 2019 Storj Labs, Inc.
|
2018-06-19 15:00:15 +01:00
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
|
|
|
package overlay
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
|
2018-09-11 05:52:14 +01:00
|
|
|
"github.com/zeebo/errs"
|
2018-11-19 20:39:25 +00:00
|
|
|
|
2019-01-30 20:47:21 +00:00
|
|
|
"storj.io/storj/pkg/identity"
|
2018-09-18 05:39:06 +01:00
|
|
|
"storj.io/storj/pkg/pb"
|
2018-11-29 18:39:27 +00:00
|
|
|
"storj.io/storj/pkg/storj"
|
|
|
|
"storj.io/storj/pkg/transport"
|
2018-06-19 15:00:15 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
// Client is the interface that defines an overlay client.
|
|
|
|
//
|
|
|
|
// Choose returns a list of storage NodeID's that fit the provided criteria.
|
|
|
|
// limit is the maximum number of nodes to be returned.
|
|
|
|
// space is the storage and bandwidth requested consumption in bytes.
|
|
|
|
//
|
|
|
|
// Lookup finds a Node with the provided identifier.
|
2018-09-11 05:52:14 +01:00
|
|
|
|
|
|
|
// ClientError creates class of errors for stack traces
|
|
|
|
var ClientError = errs.Class("Client Error")
|
|
|
|
|
|
|
|
//Client implements the Overlay Client interface
|
2018-06-19 15:00:15 +01:00
|
|
|
type Client interface {
|
2018-10-15 18:42:36 +01:00
|
|
|
Choose(ctx context.Context, op Options) ([]*pb.Node, error)
|
2018-11-29 18:39:27 +00:00
|
|
|
Lookup(ctx context.Context, nodeID storj.NodeID) (*pb.Node, error)
|
|
|
|
BulkLookup(ctx context.Context, nodeIDs storj.NodeIDList) ([]*pb.Node, error)
|
2018-06-19 15:00:15 +01:00
|
|
|
}
|
|
|
|
|
2018-12-20 13:57:54 +00:00
|
|
|
// client is the overlay concrete implementation of the client interface
|
|
|
|
type client struct {
|
|
|
|
conn pb.OverlayClient
|
2018-06-19 15:00:15 +01:00
|
|
|
}
|
|
|
|
|
2018-10-15 18:42:36 +01:00
|
|
|
// Options contains parameters for selecting nodes
|
|
|
|
type Options struct {
|
2018-12-04 20:18:26 +00:00
|
|
|
Amount int
|
|
|
|
Space int64
|
2018-12-11 17:30:14 +00:00
|
|
|
Bandwidth int64
|
2018-12-04 20:18:26 +00:00
|
|
|
Uptime float64
|
|
|
|
UptimeCount int64
|
|
|
|
AuditSuccess float64
|
|
|
|
AuditCount int64
|
|
|
|
Excluded storj.NodeIDList
|
2018-10-15 18:42:36 +01:00
|
|
|
}
|
|
|
|
|
2018-12-20 13:57:54 +00:00
|
|
|
// NewClient returns a new intialized Overlay Client
|
2019-01-30 20:47:21 +00:00
|
|
|
func NewClient(identity *identity.FullIdentity, address string) (Client, error) {
|
2018-12-22 04:51:42 +00:00
|
|
|
tc := transport.NewClient(identity, &Cache{}) // add overlay to transport client as observer
|
2018-11-06 17:49:17 +00:00
|
|
|
conn, err := tc.DialAddress(context.Background(), address)
|
2018-06-19 15:00:15 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2018-08-03 14:15:52 +01:00
|
|
|
|
2018-12-20 13:57:54 +00:00
|
|
|
return &client{
|
|
|
|
conn: pb.NewOverlayClient(conn),
|
2018-06-19 15:00:15 +01:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2018-11-19 20:39:25 +00:00
|
|
|
// NewClientFrom returns a new overlay.Client from a connection
|
2018-12-20 13:57:54 +00:00
|
|
|
func NewClientFrom(conn pb.OverlayClient) Client { return &client{conn} }
|
2018-11-19 20:39:25 +00:00
|
|
|
|
2018-12-20 13:57:54 +00:00
|
|
|
// a compiler trick to make sure *client implements Client
|
|
|
|
var _ Client = (*client)(nil)
|
2018-07-23 21:05:02 +01:00
|
|
|
|
2018-12-20 13:57:54 +00:00
|
|
|
// Choose returns nodes based on Options
|
|
|
|
func (client *client) Choose(ctx context.Context, op Options) ([]*pb.Node, error) {
|
2018-11-29 18:39:27 +00:00
|
|
|
var exIDs storj.NodeIDList
|
|
|
|
exIDs = append(exIDs, op.Excluded...)
|
2018-06-19 15:00:15 +01:00
|
|
|
// TODO(coyle): We will also need to communicate with the reputation service here
|
2018-12-20 13:57:54 +00:00
|
|
|
resp, err := client.conn.FindStorageNodes(ctx, &pb.FindStorageNodesRequest{
|
2018-10-15 18:42:36 +01:00
|
|
|
Opts: &pb.OverlayOptions{
|
2018-12-17 21:05:05 +00:00
|
|
|
Amount: int64(op.Amount),
|
|
|
|
Restrictions: &pb.NodeRestrictions{FreeDisk: op.Space, FreeBandwidth: op.Bandwidth},
|
2018-10-15 18:42:36 +01:00
|
|
|
ExcludedNodes: exIDs,
|
|
|
|
},
|
2018-08-01 15:15:38 +01:00
|
|
|
})
|
2018-06-19 15:00:15 +01:00
|
|
|
if err != nil {
|
2018-08-03 14:15:52 +01:00
|
|
|
return nil, Error.Wrap(err)
|
2018-06-19 15:00:15 +01:00
|
|
|
}
|
|
|
|
|
2018-08-01 15:15:38 +01:00
|
|
|
return resp.GetNodes(), nil
|
2018-06-19 15:00:15 +01:00
|
|
|
}
|
|
|
|
|
2018-09-11 05:52:14 +01:00
|
|
|
// Lookup provides a Node with the given ID
|
2018-12-20 13:57:54 +00:00
|
|
|
func (client *client) Lookup(ctx context.Context, nodeID storj.NodeID) (*pb.Node, error) {
|
|
|
|
resp, err := client.conn.Lookup(ctx, &pb.LookupRequest{NodeId: nodeID})
|
2018-06-19 15:00:15 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return resp.GetNode(), nil
|
|
|
|
}
|
2018-09-11 05:52:14 +01:00
|
|
|
|
2018-11-29 18:39:27 +00:00
|
|
|
// BulkLookup provides a list of Nodes with the given IDs
|
2018-12-20 13:57:54 +00:00
|
|
|
func (client *client) BulkLookup(ctx context.Context, nodeIDs storj.NodeIDList) ([]*pb.Node, error) {
|
2018-09-18 05:39:06 +01:00
|
|
|
var reqs pb.LookupRequests
|
2018-09-11 05:52:14 +01:00
|
|
|
for _, v := range nodeIDs {
|
2018-11-29 18:39:27 +00:00
|
|
|
reqs.LookupRequest = append(reqs.LookupRequest, &pb.LookupRequest{NodeId: v})
|
2018-09-11 05:52:14 +01:00
|
|
|
}
|
2018-12-20 13:57:54 +00:00
|
|
|
resp, err := client.conn.BulkLookup(ctx, &reqs)
|
2018-09-11 05:52:14 +01:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, ClientError.Wrap(err)
|
|
|
|
}
|
|
|
|
|
2018-09-18 05:39:06 +01:00
|
|
|
var nodes []*pb.Node
|
2018-11-24 02:46:53 +00:00
|
|
|
for _, v := range resp.LookupResponse {
|
2018-09-11 05:52:14 +01:00
|
|
|
nodes = append(nodes, v.Node)
|
|
|
|
}
|
|
|
|
return nodes, nil
|
|
|
|
}
|