2018-11-03 12:17:14 +00:00
|
|
|
// Copyright (C) 2018 Storj Labs, Inc.
|
|
|
|
// See LICENSE for copying information
|
|
|
|
|
|
|
|
package testplanet
|
|
|
|
|
|
|
|
import (
|
2018-11-19 20:39:25 +00:00
|
|
|
"context"
|
2018-11-27 17:46:12 +00:00
|
|
|
"fmt"
|
2018-11-03 12:17:14 +00:00
|
|
|
"io"
|
2018-11-27 17:46:12 +00:00
|
|
|
"math/rand"
|
2018-11-03 12:17:14 +00:00
|
|
|
"net"
|
|
|
|
|
2018-11-15 08:57:47 +00:00
|
|
|
"go.uber.org/zap"
|
2018-11-19 20:39:25 +00:00
|
|
|
"google.golang.org/grpc"
|
2018-11-15 08:57:47 +00:00
|
|
|
|
2018-11-19 14:40:01 +00:00
|
|
|
"storj.io/storj/pkg/auth/grpcauth"
|
2018-11-03 12:17:14 +00:00
|
|
|
"storj.io/storj/pkg/kademlia"
|
|
|
|
"storj.io/storj/pkg/overlay"
|
|
|
|
"storj.io/storj/pkg/pb"
|
|
|
|
"storj.io/storj/pkg/pointerdb/pdbclient"
|
|
|
|
"storj.io/storj/pkg/provider"
|
2018-11-27 17:46:12 +00:00
|
|
|
"storj.io/storj/pkg/statdb"
|
2018-11-03 12:17:14 +00:00
|
|
|
"storj.io/storj/pkg/transport"
|
|
|
|
"storj.io/storj/pkg/utils"
|
|
|
|
"storj.io/storj/storage/teststore"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Node is a general purpose
|
|
|
|
type Node struct {
|
2018-11-15 08:57:47 +00:00
|
|
|
Log *zap.Logger
|
2018-11-03 12:17:14 +00:00
|
|
|
Info pb.Node
|
|
|
|
Identity *provider.FullIdentity
|
2018-11-06 17:49:17 +00:00
|
|
|
Transport transport.Client
|
2018-11-03 12:17:14 +00:00
|
|
|
Listener net.Listener
|
|
|
|
Provider *provider.Provider
|
|
|
|
Kademlia *kademlia.Kademlia
|
2018-11-27 17:46:12 +00:00
|
|
|
StatDB *statdb.Server
|
2018-11-03 12:17:14 +00:00
|
|
|
Overlay *overlay.Cache
|
|
|
|
|
|
|
|
Dependencies []io.Closer
|
|
|
|
}
|
|
|
|
|
2018-11-19 14:40:01 +00:00
|
|
|
// newNode creates a new node.
|
|
|
|
func (planet *Planet) newNode(name string) (*Node, error) {
|
|
|
|
identity, err := planet.newIdentity()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
listener, err := planet.newListener()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
node := &Node{
|
|
|
|
Log: planet.log.Named(name),
|
|
|
|
Identity: identity,
|
|
|
|
Listener: listener,
|
|
|
|
}
|
|
|
|
|
|
|
|
node.Transport = transport.NewClient(identity)
|
|
|
|
|
|
|
|
node.Provider, err = provider.NewProvider(node.Identity, node.Listener, grpcauth.NewAPIKeyInterceptor())
|
|
|
|
if err != nil {
|
|
|
|
return nil, utils.CombineErrors(err, listener.Close())
|
|
|
|
}
|
|
|
|
|
|
|
|
node.Info = pb.Node{
|
|
|
|
Id: node.Identity.ID.String(),
|
|
|
|
Address: &pb.NodeAddress{
|
|
|
|
Transport: pb.NodeTransport_TCP_TLS_GRPC,
|
|
|
|
Address: node.Listener.Addr().String(),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
planet.nodes = append(planet.nodes, node)
|
|
|
|
planet.nodeInfos = append(planet.nodeInfos, node.Info)
|
|
|
|
planet.nodeLinks = append(planet.nodeLinks, node.Info.Id+":"+node.Listener.Addr().String())
|
|
|
|
|
|
|
|
return node, nil
|
|
|
|
}
|
|
|
|
|
2018-11-03 12:17:14 +00:00
|
|
|
// ID returns node id
|
|
|
|
// TODO: switch to storj.NodeID
|
|
|
|
func (node *Node) ID() string { return node.Info.Id }
|
|
|
|
|
|
|
|
// Addr retursn node address
|
|
|
|
func (node *Node) Addr() string { return node.Info.Address.Address }
|
|
|
|
|
|
|
|
// Shutdown shuts down all node dependencies
|
|
|
|
func (node *Node) Shutdown() error {
|
|
|
|
var errs []error
|
|
|
|
if node.Provider != nil {
|
|
|
|
errs = append(errs, node.Provider.Close())
|
|
|
|
}
|
|
|
|
// Provider automatically closes listener
|
|
|
|
// if node.Listener != nil {
|
|
|
|
// errs = append(errs, node.Listener.Close())
|
|
|
|
// }
|
|
|
|
if node.Kademlia != nil {
|
|
|
|
errs = append(errs, node.Kademlia.Disconnect())
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, dep := range node.Dependencies {
|
|
|
|
err := dep.Close()
|
|
|
|
if err != nil {
|
|
|
|
errs = append(errs, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return utils.CombineErrors(errs...)
|
|
|
|
}
|
|
|
|
|
|
|
|
// DialPointerDB dials destination with apikey and returns pointerdb Client
|
|
|
|
func (node *Node) DialPointerDB(destination *Node, apikey string) (pdbclient.Client, error) {
|
|
|
|
// TODO: use node.Transport instead of pdbclient.NewClient
|
|
|
|
/*
|
|
|
|
conn, err := node.Transport.DialNode(context.Background(), &destination.Info)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return piececlient.NewPSClient
|
|
|
|
*/
|
2018-11-19 20:39:25 +00:00
|
|
|
|
|
|
|
// TODO: handle disconnect
|
2018-11-03 12:17:14 +00:00
|
|
|
return pdbclient.NewClient(node.Identity, destination.Addr(), apikey)
|
|
|
|
}
|
|
|
|
|
2018-11-19 20:39:25 +00:00
|
|
|
// DialOverlay dials destination and returns an overlay.Client
|
|
|
|
func (node *Node) DialOverlay(destination *Node) (overlay.Client, error) {
|
|
|
|
conn, err := node.Transport.DialNode(context.Background(), &destination.Info, grpc.WithBlock())
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: handle disconnect
|
|
|
|
return overlay.NewClientFrom(pb.NewOverlayClient(conn)), nil
|
|
|
|
}
|
|
|
|
|
2018-11-03 12:17:14 +00:00
|
|
|
// initOverlay creates overlay for a given planet
|
|
|
|
func (node *Node) initOverlay(planet *Planet) error {
|
|
|
|
routing, err := kademlia.NewRoutingTable(node.Info, teststore.New(), teststore.New())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
kad, err := kademlia.NewKademliaWithRoutingTable(node.Info, planet.nodeInfos, node.Identity, 5, routing)
|
|
|
|
if err != nil {
|
|
|
|
return utils.CombineErrors(err, routing.Close())
|
|
|
|
}
|
|
|
|
|
|
|
|
node.Kademlia = kad
|
|
|
|
|
2018-11-27 17:46:12 +00:00
|
|
|
node.Overlay = overlay.NewOverlayCache(teststore.New(), node.Kademlia, node.StatDB)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// initStatDB creates statdb for a given planet
|
|
|
|
func (node *Node) initStatDB() error {
|
|
|
|
dbPath := fmt.Sprintf("file:memdb%d?mode=memory&cache=shared", rand.Int63())
|
|
|
|
sdb, err := statdb.NewServer("sqlite3", dbPath, "", zap.NewNop())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
node.StatDB = sdb
|
2018-11-03 12:17:14 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type closerFunc func() error
|
|
|
|
|
|
|
|
func (fn closerFunc) Close() error { return fn() }
|