2016-12-28 15:25:24 +00:00
|
|
|
// Package ipfscluster implements a wrapper for the IPFS deamon which
|
|
|
|
// allows to orchestrate pinning operations among several IPFS nodes.
|
2016-12-02 18:33:39 +00:00
|
|
|
//
|
2016-12-28 15:25:24 +00:00
|
|
|
// IPFS Cluster uses a go-libp2p-raft to keep a shared state between
|
|
|
|
// the different members of the cluster. It also uses LibP2P to enable
|
|
|
|
// communication between its different components, which perform different
|
|
|
|
// tasks like managing the underlying IPFS daemons, or providing APIs for
|
|
|
|
// external control.
|
2016-12-02 18:33:39 +00:00
|
|
|
package ipfscluster
|
|
|
|
|
|
|
|
import (
|
|
|
|
"time"
|
|
|
|
|
2016-12-23 18:35:37 +00:00
|
|
|
rpc "github.com/hsanjuan/go-libp2p-rpc"
|
2016-12-16 11:40:28 +00:00
|
|
|
cid "github.com/ipfs/go-cid"
|
|
|
|
logging "github.com/ipfs/go-log"
|
|
|
|
peer "github.com/libp2p/go-libp2p-peer"
|
2016-12-23 18:35:37 +00:00
|
|
|
protocol "github.com/libp2p/go-libp2p-protocol"
|
2016-12-02 18:33:39 +00:00
|
|
|
)
|
|
|
|
|
2016-12-22 16:14:15 +00:00
|
|
|
var logger = logging.Logger("cluster")
|
2016-12-02 18:33:39 +00:00
|
|
|
|
2016-12-28 15:25:24 +00:00
|
|
|
// Version is the current cluster version. Version alignment between
|
|
|
|
// components, apis and tools ensures compatibility among them.
|
2016-12-02 18:33:39 +00:00
|
|
|
const Version = "0.0.1"
|
|
|
|
|
2016-12-23 18:35:37 +00:00
|
|
|
// RPCProtocol is used to send libp2p messages between cluster members
|
|
|
|
var RPCProtocol protocol.ID = "/ipfscluster/" + Version + "/rpc"
|
|
|
|
|
2016-12-16 11:40:28 +00:00
|
|
|
// SilentRaft controls whether all Raft log messages are discarded.
|
|
|
|
var SilentRaft = true
|
|
|
|
|
|
|
|
// SetLogLevel sets the level in the logs
|
2016-12-16 21:00:08 +00:00
|
|
|
func SetLogLevel(l string) {
|
2016-12-16 11:40:28 +00:00
|
|
|
/*
|
|
|
|
CRITICAL Level = iota
|
|
|
|
ERROR
|
|
|
|
WARNING
|
|
|
|
NOTICE
|
|
|
|
INFO
|
|
|
|
DEBUG
|
|
|
|
*/
|
2016-12-22 16:14:15 +00:00
|
|
|
logging.SetLogLevel("cluster", l)
|
2016-12-16 11:40:28 +00:00
|
|
|
}
|
|
|
|
|
2016-12-28 15:25:24 +00:00
|
|
|
// IPFSStatus values
|
|
|
|
const (
|
|
|
|
// IPFSStatus should never take this value
|
|
|
|
Bug = iota
|
|
|
|
// An error occurred pinning
|
|
|
|
PinError
|
|
|
|
// An error occurred unpinning
|
|
|
|
UnpinError
|
|
|
|
// The IPFS daemon has pinned the item
|
|
|
|
Pinned
|
|
|
|
// The IPFS daemon is currently pinning the item
|
|
|
|
Pinning
|
|
|
|
// The IPFS daemon is currently unpinning the item
|
|
|
|
Unpinning
|
|
|
|
// The IPFS daemon is not pinning the item
|
|
|
|
Unpinned
|
|
|
|
// The IPFS deamon is not pinning the item but it is being tracked
|
|
|
|
RemotePin
|
|
|
|
)
|
|
|
|
|
|
|
|
// IPFSStatus represents the status of a tracked Cid in the IPFS daemon
|
|
|
|
type IPFSStatus int
|
|
|
|
|
|
|
|
// GlobalPinInfo contains cluster-wide status information about a tracked Cid,
|
|
|
|
// indexed by cluster member.
|
|
|
|
type GlobalPinInfo struct {
|
|
|
|
Cid *cid.Cid
|
|
|
|
Status map[peer.ID]PinInfo
|
|
|
|
}
|
|
|
|
|
|
|
|
// PinInfo holds information about local pins. PinInfo is
|
|
|
|
// serialized when requesting the Global status, therefore
|
|
|
|
// we cannot use *cid.Cid.
|
|
|
|
type PinInfo struct {
|
|
|
|
CidStr string
|
|
|
|
Peer peer.ID
|
|
|
|
IPFS IPFSStatus
|
|
|
|
TS time.Time
|
|
|
|
}
|
|
|
|
|
|
|
|
// String converts an IPFSStatus into a readable string.
|
|
|
|
func (st IPFSStatus) String() string {
|
|
|
|
switch st {
|
|
|
|
case Bug:
|
|
|
|
return "bug"
|
|
|
|
case PinError:
|
|
|
|
return "pin_error"
|
|
|
|
case UnpinError:
|
|
|
|
return "unpin_error"
|
|
|
|
case Pinned:
|
|
|
|
return "pinned"
|
|
|
|
case Pinning:
|
|
|
|
return "pinning"
|
|
|
|
case Unpinning:
|
|
|
|
return "unpinning"
|
|
|
|
case Unpinned:
|
|
|
|
return "unpinned"
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
2016-12-29 17:38:09 +00:00
|
|
|
// Component represents a piece of ipfscluster. Cluster components
|
2016-12-08 16:24:38 +00:00
|
|
|
// usually run their own goroutines (a http server for example). They
|
2016-12-23 18:35:37 +00:00
|
|
|
// communicate with the main Cluster component and other components
|
|
|
|
// (both local and remote), using an instance of rpc.Client.
|
2016-12-29 17:38:09 +00:00
|
|
|
type Component interface {
|
2016-12-23 18:35:37 +00:00
|
|
|
SetClient(*rpc.Client)
|
2016-12-02 18:33:39 +00:00
|
|
|
Shutdown() error
|
|
|
|
}
|
|
|
|
|
2016-12-15 18:08:46 +00:00
|
|
|
// API is a component which offers an API for Cluster. This is
|
2016-12-02 18:33:39 +00:00
|
|
|
// a base component.
|
2016-12-15 18:08:46 +00:00
|
|
|
type API interface {
|
2016-12-29 17:38:09 +00:00
|
|
|
Component
|
2016-12-02 18:33:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// IPFSConnector is a component which allows cluster to interact with
|
2016-12-08 16:24:38 +00:00
|
|
|
// an IPFS daemon. This is a base component.
|
2016-12-02 18:33:39 +00:00
|
|
|
type IPFSConnector interface {
|
2016-12-29 17:38:09 +00:00
|
|
|
Component
|
2016-12-02 18:33:39 +00:00
|
|
|
Pin(*cid.Cid) error
|
|
|
|
Unpin(*cid.Cid) error
|
2016-12-07 16:21:29 +00:00
|
|
|
IsPinned(*cid.Cid) (bool, error)
|
2016-12-02 18:33:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Peered represents a component which needs to be aware of the peers
|
2016-12-08 16:24:38 +00:00
|
|
|
// in the Cluster and of any changes to the peer set.
|
2016-12-02 18:33:39 +00:00
|
|
|
type Peered interface {
|
|
|
|
AddPeer(p peer.ID)
|
|
|
|
RmPeer(p peer.ID)
|
|
|
|
SetPeers(peers []peer.ID)
|
|
|
|
}
|
|
|
|
|
2016-12-15 18:08:46 +00:00
|
|
|
// State represents the shared state of the cluster and it
|
|
|
|
// is used by the Consensus component to keep track of
|
2016-12-06 21:29:59 +00:00
|
|
|
// objects which objects are pinned. This component should be thread safe.
|
2016-12-15 18:08:46 +00:00
|
|
|
type State interface {
|
|
|
|
// AddPin adds a pin to the State
|
2016-12-06 21:29:59 +00:00
|
|
|
AddPin(*cid.Cid) error
|
2016-12-15 18:08:46 +00:00
|
|
|
// RmPin removes a pin from the State
|
2016-12-06 21:29:59 +00:00
|
|
|
RmPin(*cid.Cid) error
|
2016-12-09 19:54:46 +00:00
|
|
|
// ListPins lists all the pins in the state
|
|
|
|
ListPins() []*cid.Cid
|
2016-12-20 18:51:13 +00:00
|
|
|
// HasPin returns true if the state is holding a Cid
|
|
|
|
HasPin(*cid.Cid) bool
|
2016-12-06 21:29:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// PinTracker represents a component which tracks the status of
|
|
|
|
// the pins in this cluster and ensures they are in sync with the
|
|
|
|
// IPFS daemon. This component should be thread safe.
|
|
|
|
type PinTracker interface {
|
2016-12-29 17:38:09 +00:00
|
|
|
Component
|
2016-12-19 17:35:24 +00:00
|
|
|
// Track tells the tracker that a Cid is now under its supervision
|
|
|
|
// The tracker may decide to perform an IPFS pin.
|
|
|
|
Track(*cid.Cid) error
|
|
|
|
// Untrack tells the tracker that a Cid is to be forgotten. The tracker
|
|
|
|
// may perform an IPFS unpin operation.
|
|
|
|
Untrack(*cid.Cid) error
|
2016-12-20 18:51:13 +00:00
|
|
|
// Status returns the list of pins with their local status.
|
|
|
|
Status() []PinInfo
|
|
|
|
// StatusCid returns the local status of a given Cid.
|
|
|
|
StatusCid(*cid.Cid) PinInfo
|
|
|
|
// Sync makes sure that the Cid status reflect the real IPFS status.
|
|
|
|
// The return value indicates if the Cid status deserved attention,
|
|
|
|
// either because its state was updated or because it is in error state.
|
2016-12-07 16:21:29 +00:00
|
|
|
Sync(*cid.Cid) bool
|
2016-12-20 18:51:13 +00:00
|
|
|
// Recover retriggers a Pin/Unpin operation in Cids with error status.
|
2016-12-07 16:21:29 +00:00
|
|
|
Recover(*cid.Cid) error
|
2016-12-02 18:33:39 +00:00
|
|
|
}
|