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-03 12:17:14 +00:00
|
|
|
"io"
|
|
|
|
"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-12-14 19:23:54 +00:00
|
|
|
"storj.io/storj/pkg/discovery"
|
2018-11-03 12:17:14 +00:00
|
|
|
"storj.io/storj/pkg/kademlia"
|
2018-12-12 15:40:33 +00:00
|
|
|
"storj.io/storj/pkg/node"
|
2018-11-03 12:17:14 +00:00
|
|
|
"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-30 13:40:13 +00:00
|
|
|
"storj.io/storj/pkg/storj"
|
2018-11-03 12:17:14 +00:00
|
|
|
"storj.io/storj/pkg/transport"
|
|
|
|
"storj.io/storj/pkg/utils"
|
2018-12-27 09:56:25 +00:00
|
|
|
"storj.io/storj/satellite"
|
2018-12-14 20:17:30 +00:00
|
|
|
"storj.io/storj/satellite/satellitedb"
|
2018-11-03 12:17:14 +00:00
|
|
|
"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-12-14 19:23:54 +00:00
|
|
|
Discovery *discovery.Discovery
|
2018-12-14 20:17:30 +00:00
|
|
|
StatDB statdb.DB
|
2018-11-03 12:17:14 +00:00
|
|
|
Overlay *overlay.Cache
|
2018-12-27 09:56:25 +00:00
|
|
|
Database satellite.DB
|
2018-11-03 12:17:14 +00:00
|
|
|
|
|
|
|
Dependencies []io.Closer
|
|
|
|
}
|
|
|
|
|
2018-11-19 14:40:01 +00:00
|
|
|
// newNode creates a new node.
|
2018-11-29 14:57:00 +00:00
|
|
|
func (planet *Planet) newNode(name string, nodeType pb.NodeType) (*Node, error) {
|
2018-11-19 14:40:01 +00:00
|
|
|
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,
|
|
|
|
}
|
|
|
|
|
2018-12-12 15:40:33 +00:00
|
|
|
node.Log.Debug("id=" + identity.ID.String())
|
|
|
|
|
2018-11-19 14:40:01 +00:00
|
|
|
node.Transport = transport.NewClient(identity)
|
|
|
|
|
2018-12-07 13:44:25 +00:00
|
|
|
serverConfig := provider.ServerConfig{Address: node.Listener.Addr().String()}
|
|
|
|
opts, err := provider.NewServerOptions(node.Identity, serverConfig)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
node.Provider, err = provider.NewProvider(opts, node.Listener, grpcauth.NewAPIKeyInterceptor())
|
2018-11-19 14:40:01 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, utils.CombineErrors(err, listener.Close())
|
|
|
|
}
|
|
|
|
|
|
|
|
node.Info = pb.Node{
|
2018-11-29 18:39:27 +00:00
|
|
|
Id: node.Identity.ID,
|
2018-11-29 14:57:00 +00:00
|
|
|
Type: nodeType,
|
2018-11-19 14:40:01 +00:00
|
|
|
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)
|
2018-11-29 18:39:27 +00:00
|
|
|
planet.nodeLinks = append(planet.nodeLinks, node.Info.Id.String()+":"+node.Listener.Addr().String())
|
2018-11-19 14:40:01 +00:00
|
|
|
|
|
|
|
return node, nil
|
|
|
|
}
|
|
|
|
|
2018-11-03 12:17:14 +00:00
|
|
|
// ID returns node id
|
2018-11-29 18:39:27 +00:00
|
|
|
func (node *Node) ID() storj.NodeID { return node.Info.Id }
|
2018-11-03 12:17:14 +00:00
|
|
|
|
|
|
|
// 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
|
2018-12-07 18:31:59 +00:00
|
|
|
if node.Kademlia != nil {
|
|
|
|
errs = append(errs, node.Kademlia.Disconnect())
|
|
|
|
}
|
2018-11-03 12:17:14 +00:00
|
|
|
if node.Provider != nil {
|
|
|
|
errs = append(errs, node.Provider.Close())
|
|
|
|
}
|
|
|
|
// Provider automatically closes listener
|
|
|
|
// if node.Listener != nil {
|
|
|
|
// errs = append(errs, node.Listener.Close())
|
|
|
|
// }
|
|
|
|
|
|
|
|
for _, dep := range node.Dependencies {
|
|
|
|
err := dep.Close()
|
|
|
|
if err != nil {
|
|
|
|
errs = append(errs, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return utils.CombineErrors(errs...)
|
|
|
|
}
|
|
|
|
|
2018-12-12 15:40:33 +00:00
|
|
|
// NewNodeClient creates a node client for this node
|
|
|
|
func (n *Node) NewNodeClient() (node.Client, error) { //nolint renaming to node would conflict with package name; rename Node to Peer to resolve
|
|
|
|
// TODO: handle disconnect verification
|
|
|
|
return node.NewNodeClient(n.Identity, n.Info, n.Kademlia)
|
|
|
|
}
|
|
|
|
|
2018-11-03 12:17:14 +00:00
|
|
|
// 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 {
|
2018-12-14 20:17:30 +00:00
|
|
|
var err error
|
|
|
|
node.Database, err = satellitedb.NewInMemory()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
err = node.Database.CreateTables()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2018-12-22 00:48:53 +00:00
|
|
|
routing, err := kademlia.NewRoutingTable(node.Log.Named("routing"), node.Info, teststore.New(), teststore.New())
|
2018-11-03 12:17:14 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2018-12-18 15:13:32 +00:00
|
|
|
kad, err := kademlia.NewKademliaWithRoutingTable(node.Log.Named("kademlia"), node.Info, planet.nodeInfos, node.Identity, 5, routing)
|
2018-11-03 12:17:14 +00:00
|
|
|
if err != nil {
|
|
|
|
return utils.CombineErrors(err, routing.Close())
|
|
|
|
}
|
|
|
|
|
2018-12-22 04:51:42 +00:00
|
|
|
node.Kademlia = kad
|
2018-12-14 20:17:30 +00:00
|
|
|
node.StatDB = node.Database.StatDB()
|
2018-12-20 13:57:54 +00:00
|
|
|
node.Overlay = overlay.NewCache(teststore.New(), node.StatDB)
|
2018-12-22 00:48:53 +00:00
|
|
|
node.Discovery = discovery.NewDiscovery(node.Log.Named("discovery"), node.Overlay, node.Kademlia, node.StatDB)
|
2018-12-04 20:18:26 +00:00
|
|
|
|
2018-11-03 12:17:14 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type closerFunc func() error
|
|
|
|
|
|
|
|
func (fn closerFunc) Close() error { return fn() }
|