2016-12-02 18:33:39 +00:00
|
|
|
package ipfscluster
|
|
|
|
|
|
|
|
import (
|
2016-12-21 18:37:25 +00:00
|
|
|
"encoding/base64"
|
2016-12-02 18:33:39 +00:00
|
|
|
"encoding/json"
|
2017-01-23 17:38:59 +00:00
|
|
|
"fmt"
|
2016-12-02 18:33:39 +00:00
|
|
|
"io/ioutil"
|
2017-01-30 12:12:25 +00:00
|
|
|
"sync"
|
2016-12-21 18:37:25 +00:00
|
|
|
|
2017-06-30 00:40:06 +00:00
|
|
|
crypto "github.com/libp2p/go-libp2p-crypto"
|
|
|
|
peer "github.com/libp2p/go-libp2p-peer"
|
|
|
|
ma "github.com/multiformats/go-multiaddr"
|
2016-12-21 18:37:25 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Default parameters for the configuration
|
|
|
|
const (
|
2017-02-28 15:01:26 +00:00
|
|
|
DefaultConfigCrypto = crypto.RSA
|
|
|
|
DefaultConfigKeyLength = 2048
|
|
|
|
DefaultAPIAddr = "/ip4/127.0.0.1/tcp/9094"
|
|
|
|
DefaultIPFSProxyAddr = "/ip4/127.0.0.1/tcp/9095"
|
|
|
|
DefaultIPFSNodeAddr = "/ip4/127.0.0.1/tcp/5001"
|
|
|
|
DefaultClusterAddr = "/ip4/0.0.0.0/tcp/9096"
|
|
|
|
DefaultStateSyncSeconds = 60
|
2017-04-05 21:29:22 +00:00
|
|
|
DefaultIPFSSyncSeconds = 130
|
2017-02-28 15:01:26 +00:00
|
|
|
DefaultMonitoringIntervalSeconds = 15
|
2016-12-02 18:33:39 +00:00
|
|
|
)
|
|
|
|
|
2017-01-23 19:56:35 +00:00
|
|
|
// Config represents an ipfs-cluster configuration. It is used by
|
|
|
|
// Cluster components. An initialized version of it can be obtained with
|
|
|
|
// NewDefaultConfig().
|
2016-12-15 18:08:46 +00:00
|
|
|
type Config struct {
|
2016-12-16 18:14:45 +00:00
|
|
|
// Libp2p ID and private key for Cluster communication (including)
|
|
|
|
// the Consensus component.
|
2017-01-23 17:38:59 +00:00
|
|
|
ID peer.ID
|
|
|
|
PrivateKey crypto.PrivKey
|
2016-12-16 18:14:45 +00:00
|
|
|
|
2017-06-22 17:21:05 +00:00
|
|
|
// Swarm key for private network
|
2017-06-30 00:40:06 +00:00
|
|
|
SwarmKey string
|
2017-06-22 17:21:05 +00:00
|
|
|
// Fingerprint for private network
|
|
|
|
PNetFingerprint []byte
|
|
|
|
|
2017-02-02 22:52:06 +00:00
|
|
|
// ClusterPeers is the list of peers in the Cluster. They are used
|
|
|
|
// as the initial peers in the consensus. When bootstrapping a peer,
|
|
|
|
// ClusterPeers will be filled in automatically for the next run upon
|
|
|
|
// shutdown.
|
2017-01-23 17:38:59 +00:00
|
|
|
ClusterPeers []ma.Multiaddr
|
2017-02-02 22:52:06 +00:00
|
|
|
|
|
|
|
// Bootstrap peers multiaddresses. This peer will attempt to
|
|
|
|
// join the clusters of the peers in this list after booting.
|
|
|
|
// Leave empty for a single-peer-cluster.
|
|
|
|
Bootstrap []ma.Multiaddr
|
|
|
|
|
|
|
|
// Leave Cluster on shutdown. Politely informs other peers
|
|
|
|
// of the departure and removes itself from the consensus
|
|
|
|
// peer set. The Cluster size will be reduced by one.
|
|
|
|
LeaveOnShutdown bool
|
2016-12-16 18:14:45 +00:00
|
|
|
|
|
|
|
// Listen parameters for the Cluster libp2p Host. Used by
|
2017-01-23 17:38:59 +00:00
|
|
|
// the RPC and Consensus components.
|
|
|
|
ClusterAddr ma.Multiaddr
|
|
|
|
|
|
|
|
// Listen parameters for the the Cluster HTTP API component.
|
|
|
|
APIAddr ma.Multiaddr
|
|
|
|
|
|
|
|
// Listen parameters for the IPFS Proxy. Used by the IPFS
|
|
|
|
// connector component.
|
|
|
|
IPFSProxyAddr ma.Multiaddr
|
|
|
|
|
|
|
|
// Host/Port for the IPFS daemon.
|
|
|
|
IPFSNodeAddr ma.Multiaddr
|
2016-12-16 18:14:45 +00:00
|
|
|
|
|
|
|
// Storage folder for snapshots, log store etc. Used by
|
|
|
|
// the Consensus component.
|
2017-01-23 17:38:59 +00:00
|
|
|
ConsensusDataFolder string
|
|
|
|
|
2017-04-05 21:29:22 +00:00
|
|
|
// Number of seconds between automatic calls to StateSync().
|
2017-02-02 22:52:06 +00:00
|
|
|
StateSyncSeconds int
|
|
|
|
|
2017-04-05 21:29:22 +00:00
|
|
|
// Number of seconds between automatic calls to SyncAllLocal().
|
|
|
|
IPFSSyncSeconds int
|
|
|
|
|
2017-02-13 15:46:53 +00:00
|
|
|
// ReplicationFactor is the number of copies we keep for each pin
|
|
|
|
ReplicationFactor int
|
|
|
|
|
2017-02-28 15:01:26 +00:00
|
|
|
// MonitoringIntervalSeconds is the number of seconds that can
|
|
|
|
// pass before a peer can be detected as down.
|
|
|
|
MonitoringIntervalSeconds int
|
|
|
|
|
2017-03-27 13:07:12 +00:00
|
|
|
// AllocationStrategy is used to decide on the
|
|
|
|
// Informer/Allocator implementation to use.
|
|
|
|
AllocationStrategy string
|
|
|
|
|
2017-01-30 12:12:25 +00:00
|
|
|
// if a config has been loaded from disk, track the path
|
|
|
|
// so it can be saved to the same place.
|
|
|
|
path string
|
2017-02-02 22:52:06 +00:00
|
|
|
|
|
|
|
saveMux sync.Mutex
|
2017-03-28 16:31:06 +00:00
|
|
|
|
|
|
|
shadow *Config
|
2017-01-23 17:38:59 +00:00
|
|
|
}
|
|
|
|
|
2017-01-23 19:56:35 +00:00
|
|
|
// JSONConfig represents a Cluster configuration as it will look when it is
|
|
|
|
// saved using JSON. Most configuration keys are converted into simple types
|
|
|
|
// like strings, and key names aim to be self-explanatory for the user.
|
2017-01-23 17:38:59 +00:00
|
|
|
type JSONConfig struct {
|
|
|
|
// Libp2p ID and private key for Cluster communication (including)
|
|
|
|
// the Consensus component.
|
|
|
|
ID string `json:"id"`
|
|
|
|
PrivateKey string `json:"private_key"`
|
|
|
|
|
2017-06-22 17:21:05 +00:00
|
|
|
// Swarm key for private network
|
2017-06-30 00:40:06 +00:00
|
|
|
SwarmKey string `json:"swarm_key"`
|
2017-06-22 17:21:05 +00:00
|
|
|
|
2017-02-02 22:52:06 +00:00
|
|
|
// ClusterPeers is the list of peers' multiaddresses in the Cluster.
|
|
|
|
// They are used as the initial peers in the consensus. When
|
|
|
|
// bootstrapping a peer, ClusterPeers will be filled in automatically.
|
2017-01-23 17:38:59 +00:00
|
|
|
ClusterPeers []string `json:"cluster_peers"`
|
|
|
|
|
2017-02-02 22:52:06 +00:00
|
|
|
// Bootstrap peers multiaddresses. This peer will attempt to
|
|
|
|
// join the clusters of the peers in the list. ONLY when ClusterPeers
|
|
|
|
// is empty. Otherwise it is ignored. Leave empty for a single-peer
|
|
|
|
// cluster.
|
|
|
|
Bootstrap []string `json:"bootstrap"`
|
|
|
|
|
|
|
|
// Leave Cluster on shutdown. Politely informs other peers
|
|
|
|
// of the departure and removes itself from the consensus
|
|
|
|
// peer set. The Cluster size will be reduced by one.
|
|
|
|
LeaveOnShutdown bool `json:"leave_on_shutdown"`
|
|
|
|
|
2017-01-23 19:56:35 +00:00
|
|
|
// Listen address for the Cluster libp2p host. This is used for
|
2017-01-26 18:59:31 +00:00
|
|
|
// interal RPC and Consensus communications between cluster peers.
|
2017-01-23 17:38:59 +00:00
|
|
|
ClusterListenMultiaddress string `json:"cluster_multiaddress"`
|
2016-12-16 18:14:45 +00:00
|
|
|
|
2017-01-23 19:56:35 +00:00
|
|
|
// Listen address for the the Cluster HTTP API component.
|
|
|
|
// Tools like ipfs-cluster-ctl will connect to his endpoint to
|
|
|
|
// manage cluster.
|
2017-01-23 18:06:00 +00:00
|
|
|
APIListenMultiaddress string `json:"api_listen_multiaddress"`
|
2016-12-16 18:14:45 +00:00
|
|
|
|
2017-01-23 19:56:35 +00:00
|
|
|
// Listen address for the IPFS Proxy, which forwards requests to
|
|
|
|
// an IPFS daemon.
|
2017-01-23 18:06:00 +00:00
|
|
|
IPFSProxyListenMultiaddress string `json:"ipfs_proxy_listen_multiaddress"`
|
2016-12-16 18:14:45 +00:00
|
|
|
|
2017-01-23 19:56:35 +00:00
|
|
|
// API address for the IPFS daemon.
|
2017-01-23 17:38:59 +00:00
|
|
|
IPFSNodeMultiaddress string `json:"ipfs_node_multiaddress"`
|
|
|
|
|
|
|
|
// Storage folder for snapshots, log store etc. Used by
|
|
|
|
// the Consensus component.
|
|
|
|
ConsensusDataFolder string `json:"consensus_data_folder"`
|
2017-02-02 22:52:06 +00:00
|
|
|
|
|
|
|
// Number of seconds between syncs of the consensus state to the
|
|
|
|
// tracker state. Normally states are synced anyway, but this helps
|
|
|
|
// when new nodes are joining the cluster
|
|
|
|
StateSyncSeconds int `json:"state_sync_seconds"`
|
2017-02-13 15:46:53 +00:00
|
|
|
|
2017-04-05 21:29:22 +00:00
|
|
|
// Number of seconds between syncs of the local state and
|
|
|
|
// the state of the ipfs daemon. This ensures that cluster
|
|
|
|
// provides the right status for tracked items (for example
|
|
|
|
// to detect that a pin has been removed.
|
|
|
|
IPFSSyncSeconds int `json:"ipfs_sync_seconds"`
|
|
|
|
|
2017-02-13 15:46:53 +00:00
|
|
|
// ReplicationFactor indicates the number of nodes that must pin content.
|
|
|
|
// For exampe, a replication_factor of 2 will prompt cluster to choose
|
|
|
|
// two nodes for each pinned hash. A replication_factor -1 will
|
|
|
|
// use every available node for each pin.
|
|
|
|
ReplicationFactor int `json:"replication_factor"`
|
2017-02-28 15:01:26 +00:00
|
|
|
|
|
|
|
// Number of seconds between monitoring checks which detect
|
|
|
|
// if a peer is down and consenquently trigger a rebalance
|
2017-03-03 15:13:09 +00:00
|
|
|
MonitoringIntervalSeconds int `json:"monitoring_interval_seconds"`
|
2017-03-27 13:07:12 +00:00
|
|
|
|
|
|
|
// AllocationStrategy is used to set how pins are allocated to
|
|
|
|
// different Cluster peers. Currently supports "reposize" and "pincount"
|
|
|
|
// values.
|
|
|
|
AllocationStrategy string `json:"allocation_strategy"`
|
2017-01-23 17:38:59 +00:00
|
|
|
}
|
|
|
|
|
2017-01-23 19:56:35 +00:00
|
|
|
// ToJSONConfig converts a Config object to its JSON representation which
|
|
|
|
// is focused on user presentation and easy understanding.
|
2017-01-23 17:38:59 +00:00
|
|
|
func (cfg *Config) ToJSONConfig() (j *JSONConfig, err error) {
|
|
|
|
// Multiaddress String() may panic
|
|
|
|
defer func() {
|
|
|
|
if r := recover(); r != nil {
|
|
|
|
err = fmt.Errorf("%s", r)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
pkeyBytes, err := cfg.PrivateKey.Bytes()
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
pKey := base64.StdEncoding.EncodeToString(pkeyBytes)
|
|
|
|
|
|
|
|
clusterPeers := make([]string, len(cfg.ClusterPeers), len(cfg.ClusterPeers))
|
|
|
|
for i := 0; i < len(cfg.ClusterPeers); i++ {
|
|
|
|
clusterPeers[i] = cfg.ClusterPeers[i].String()
|
|
|
|
}
|
2017-02-02 22:52:06 +00:00
|
|
|
|
|
|
|
bootstrap := make([]string, len(cfg.Bootstrap), len(cfg.Bootstrap))
|
|
|
|
for i := 0; i < len(cfg.Bootstrap); i++ {
|
|
|
|
bootstrap[i] = cfg.Bootstrap[i].String()
|
|
|
|
}
|
2017-01-23 17:38:59 +00:00
|
|
|
|
|
|
|
j = &JSONConfig{
|
|
|
|
ID: cfg.ID.Pretty(),
|
|
|
|
PrivateKey: pKey,
|
2017-06-30 00:40:06 +00:00
|
|
|
SwarmKey: cfg.SwarmKey,
|
2017-01-23 17:38:59 +00:00
|
|
|
ClusterPeers: clusterPeers,
|
2017-02-02 22:52:06 +00:00
|
|
|
Bootstrap: bootstrap,
|
|
|
|
LeaveOnShutdown: cfg.LeaveOnShutdown,
|
2017-01-23 17:38:59 +00:00
|
|
|
ClusterListenMultiaddress: cfg.ClusterAddr.String(),
|
|
|
|
APIListenMultiaddress: cfg.APIAddr.String(),
|
|
|
|
IPFSProxyListenMultiaddress: cfg.IPFSProxyAddr.String(),
|
|
|
|
IPFSNodeMultiaddress: cfg.IPFSNodeAddr.String(),
|
|
|
|
ConsensusDataFolder: cfg.ConsensusDataFolder,
|
2017-02-02 22:52:06 +00:00
|
|
|
StateSyncSeconds: cfg.StateSyncSeconds,
|
2017-04-05 21:29:22 +00:00
|
|
|
IPFSSyncSeconds: cfg.IPFSSyncSeconds,
|
2017-02-13 15:46:53 +00:00
|
|
|
ReplicationFactor: cfg.ReplicationFactor,
|
2017-02-28 15:01:26 +00:00
|
|
|
MonitoringIntervalSeconds: cfg.MonitoringIntervalSeconds,
|
2017-03-27 13:07:12 +00:00
|
|
|
AllocationStrategy: cfg.AllocationStrategy,
|
2017-01-23 17:38:59 +00:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-01-23 19:56:35 +00:00
|
|
|
// ToConfig converts a JSONConfig to its internal Config representation,
|
|
|
|
// where options are parsed into their native types.
|
2017-01-23 17:38:59 +00:00
|
|
|
func (jcfg *JSONConfig) ToConfig() (c *Config, err error) {
|
|
|
|
id, err := peer.IDB58Decode(jcfg.ID)
|
|
|
|
if err != nil {
|
2017-01-23 19:39:09 +00:00
|
|
|
err = fmt.Errorf("error decoding cluster ID: %s", err)
|
2017-01-23 17:38:59 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
pkb, err := base64.StdEncoding.DecodeString(jcfg.PrivateKey)
|
|
|
|
if err != nil {
|
2017-01-23 19:39:09 +00:00
|
|
|
err = fmt.Errorf("error decoding private_key: %s", err)
|
2017-01-23 17:38:59 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
pKey, err := crypto.UnmarshalPrivateKey(pkb)
|
|
|
|
if err != nil {
|
2017-01-23 19:39:09 +00:00
|
|
|
err = fmt.Errorf("error parsing private_key ID: %s", err)
|
2017-01-23 17:38:59 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
clusterPeers := make([]ma.Multiaddr, len(jcfg.ClusterPeers))
|
|
|
|
for i := 0; i < len(jcfg.ClusterPeers); i++ {
|
|
|
|
maddr, err := ma.NewMultiaddr(jcfg.ClusterPeers[i])
|
|
|
|
if err != nil {
|
2017-01-23 19:39:09 +00:00
|
|
|
err = fmt.Errorf("error parsing multiaddress for peer %s: %s",
|
|
|
|
jcfg.ClusterPeers[i], err)
|
2017-01-23 17:38:59 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
clusterPeers[i] = maddr
|
|
|
|
}
|
|
|
|
|
2017-02-02 22:52:06 +00:00
|
|
|
bootstrap := make([]ma.Multiaddr, len(jcfg.Bootstrap))
|
|
|
|
for i := 0; i < len(jcfg.Bootstrap); i++ {
|
|
|
|
maddr, err := ma.NewMultiaddr(jcfg.Bootstrap[i])
|
|
|
|
if err != nil {
|
|
|
|
err = fmt.Errorf("error parsing multiaddress for peer %s: %s",
|
|
|
|
jcfg.Bootstrap[i], err)
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
bootstrap[i] = maddr
|
|
|
|
}
|
|
|
|
|
2017-01-23 17:38:59 +00:00
|
|
|
clusterAddr, err := ma.NewMultiaddr(jcfg.ClusterListenMultiaddress)
|
|
|
|
if err != nil {
|
2017-01-23 19:39:09 +00:00
|
|
|
err = fmt.Errorf("error parsing cluster_listen_multiaddress: %s", err)
|
2017-01-23 17:38:59 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
apiAddr, err := ma.NewMultiaddr(jcfg.APIListenMultiaddress)
|
|
|
|
if err != nil {
|
2017-01-23 19:39:09 +00:00
|
|
|
err = fmt.Errorf("error parsing api_listen_multiaddress: %s", err)
|
2017-01-23 17:38:59 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
ipfsProxyAddr, err := ma.NewMultiaddr(jcfg.IPFSProxyListenMultiaddress)
|
|
|
|
if err != nil {
|
2017-01-23 19:39:09 +00:00
|
|
|
err = fmt.Errorf("error parsing ipfs_proxy_listen_multiaddress: %s", err)
|
2017-01-23 17:38:59 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
ipfsNodeAddr, err := ma.NewMultiaddr(jcfg.IPFSNodeMultiaddress)
|
|
|
|
if err != nil {
|
2017-01-23 19:39:09 +00:00
|
|
|
err = fmt.Errorf("error parsing ipfs_node_multiaddress: %s", err)
|
2017-01-23 17:38:59 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-02-13 15:46:53 +00:00
|
|
|
if jcfg.ReplicationFactor == 0 {
|
|
|
|
logger.Warning("Replication factor set to -1 (pin everywhere)")
|
|
|
|
jcfg.ReplicationFactor = -1
|
|
|
|
}
|
|
|
|
|
2017-02-02 22:52:06 +00:00
|
|
|
if jcfg.StateSyncSeconds <= 0 {
|
|
|
|
jcfg.StateSyncSeconds = DefaultStateSyncSeconds
|
|
|
|
}
|
|
|
|
|
2017-04-05 21:29:22 +00:00
|
|
|
if jcfg.IPFSSyncSeconds <= 0 {
|
|
|
|
jcfg.IPFSSyncSeconds = DefaultIPFSSyncSeconds
|
|
|
|
}
|
|
|
|
|
2017-02-28 15:01:26 +00:00
|
|
|
if jcfg.MonitoringIntervalSeconds <= 0 {
|
|
|
|
jcfg.MonitoringIntervalSeconds = DefaultMonitoringIntervalSeconds
|
|
|
|
}
|
|
|
|
|
2017-03-27 13:07:12 +00:00
|
|
|
if jcfg.AllocationStrategy == "" {
|
|
|
|
jcfg.AllocationStrategy = "reposize"
|
|
|
|
}
|
|
|
|
|
2017-01-23 17:38:59 +00:00
|
|
|
c = &Config{
|
2017-02-28 15:01:26 +00:00
|
|
|
ID: id,
|
|
|
|
PrivateKey: pKey,
|
2017-06-30 00:40:06 +00:00
|
|
|
SwarmKey: jcfg.SwarmKey,
|
2017-02-28 15:01:26 +00:00
|
|
|
ClusterPeers: clusterPeers,
|
|
|
|
Bootstrap: bootstrap,
|
|
|
|
LeaveOnShutdown: jcfg.LeaveOnShutdown,
|
|
|
|
ClusterAddr: clusterAddr,
|
|
|
|
APIAddr: apiAddr,
|
|
|
|
IPFSProxyAddr: ipfsProxyAddr,
|
|
|
|
IPFSNodeAddr: ipfsNodeAddr,
|
|
|
|
ConsensusDataFolder: jcfg.ConsensusDataFolder,
|
|
|
|
StateSyncSeconds: jcfg.StateSyncSeconds,
|
2017-04-05 21:29:22 +00:00
|
|
|
IPFSSyncSeconds: jcfg.IPFSSyncSeconds,
|
2017-02-28 15:01:26 +00:00
|
|
|
ReplicationFactor: jcfg.ReplicationFactor,
|
|
|
|
MonitoringIntervalSeconds: jcfg.MonitoringIntervalSeconds,
|
2017-03-27 13:07:12 +00:00
|
|
|
AllocationStrategy: jcfg.AllocationStrategy,
|
2017-01-23 17:38:59 +00:00
|
|
|
}
|
|
|
|
return
|
2016-12-02 18:33:39 +00:00
|
|
|
}
|
|
|
|
|
2016-12-28 15:25:24 +00:00
|
|
|
// LoadConfig reads a JSON configuration file from the given path,
|
|
|
|
// parses it and returns a new Config object.
|
2016-12-15 18:08:46 +00:00
|
|
|
func LoadConfig(path string) (*Config, error) {
|
2017-01-23 17:38:59 +00:00
|
|
|
jcfg := &JSONConfig{}
|
2016-12-02 18:33:39 +00:00
|
|
|
file, err := ioutil.ReadFile(path)
|
|
|
|
if err != nil {
|
2017-01-23 17:38:59 +00:00
|
|
|
logger.Error("error reading the configuration file: ", err)
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
err = json.Unmarshal(file, jcfg)
|
|
|
|
if err != nil {
|
|
|
|
logger.Error("error parsing JSON: ", err)
|
2016-12-02 18:33:39 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
2017-01-23 17:38:59 +00:00
|
|
|
cfg, err := jcfg.ToConfig()
|
|
|
|
if err != nil {
|
|
|
|
logger.Error("error parsing configuration: ", err)
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-01-30 12:12:25 +00:00
|
|
|
cfg.path = path
|
2017-01-23 17:38:59 +00:00
|
|
|
|
2017-06-30 00:40:06 +00:00
|
|
|
return cfg, nil
|
2017-06-22 17:21:05 +00:00
|
|
|
}
|
|
|
|
|
2017-01-23 17:38:59 +00:00
|
|
|
// Save stores a configuration as a JSON file in the given path.
|
2017-02-02 22:52:06 +00:00
|
|
|
// If no path is provided, it uses the path the configuration was
|
|
|
|
// loaded from.
|
2017-01-23 19:56:35 +00:00
|
|
|
func (cfg *Config) Save(path string) error {
|
2017-02-02 22:52:06 +00:00
|
|
|
cfg.saveMux.Lock()
|
|
|
|
defer cfg.saveMux.Unlock()
|
|
|
|
|
2017-03-28 16:31:06 +00:00
|
|
|
cfg.unshadow()
|
|
|
|
|
2017-02-02 22:52:06 +00:00
|
|
|
if path == "" {
|
|
|
|
path = cfg.path
|
|
|
|
}
|
|
|
|
|
|
|
|
logger.Info("Saving configuration")
|
2017-01-23 19:56:35 +00:00
|
|
|
jcfg, err := cfg.ToJSONConfig()
|
2017-01-23 17:38:59 +00:00
|
|
|
if err != nil {
|
|
|
|
logger.Error("error generating JSON config")
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
json, err := json.MarshalIndent(jcfg, "", " ")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
err = ioutil.WriteFile(path, json, 0600)
|
|
|
|
return err
|
2016-12-02 18:33:39 +00:00
|
|
|
}
|
2016-12-21 18:37:25 +00:00
|
|
|
|
2017-03-28 16:31:06 +00:00
|
|
|
// Shadow copies certain configuration values to a shadow configuration
|
|
|
|
// object. From the moment Shadow is called, configuration keys which are
|
|
|
|
// shadowed may be changed, but Save() will restore them to the original
|
|
|
|
// value stored in the shadow. Currently affects:
|
|
|
|
//
|
|
|
|
// - AllocationStrategy
|
|
|
|
// - LeaveOnShutdown
|
|
|
|
// - Bootstrap
|
|
|
|
//
|
|
|
|
// which are options which can be overriden via ipfs-cluster-service flags.
|
|
|
|
// The shadow dissapears with every call to Save().
|
|
|
|
func (cfg *Config) Shadow() {
|
|
|
|
cfg.shadow = &Config{
|
|
|
|
AllocationStrategy: cfg.AllocationStrategy,
|
|
|
|
LeaveOnShutdown: cfg.LeaveOnShutdown,
|
|
|
|
Bootstrap: cfg.Bootstrap,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cfg *Config) unshadow() {
|
|
|
|
if cfg.shadow != nil {
|
|
|
|
cfg.AllocationStrategy = cfg.shadow.AllocationStrategy
|
|
|
|
cfg.LeaveOnShutdown = cfg.shadow.LeaveOnShutdown
|
|
|
|
cfg.Bootstrap = cfg.shadow.Bootstrap
|
|
|
|
}
|
|
|
|
cfg.shadow = nil
|
|
|
|
}
|
|
|
|
|
2016-12-21 18:37:25 +00:00
|
|
|
// NewDefaultConfig returns a default configuration object with a randomly
|
|
|
|
// generated ID and private key.
|
|
|
|
func NewDefaultConfig() (*Config, error) {
|
|
|
|
priv, pub, err := crypto.GenerateKeyPair(
|
|
|
|
DefaultConfigCrypto,
|
|
|
|
DefaultConfigKeyLength)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
pid, err := peer.IDFromPublicKey(pub)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-01-23 17:38:59 +00:00
|
|
|
|
|
|
|
clusterAddr, _ := ma.NewMultiaddr(DefaultClusterAddr)
|
|
|
|
apiAddr, _ := ma.NewMultiaddr(DefaultAPIAddr)
|
|
|
|
ipfsProxyAddr, _ := ma.NewMultiaddr(DefaultIPFSProxyAddr)
|
|
|
|
ipfsNodeAddr, _ := ma.NewMultiaddr(DefaultIPFSNodeAddr)
|
2016-12-21 18:37:25 +00:00
|
|
|
|
|
|
|
return &Config{
|
2017-02-28 15:01:26 +00:00
|
|
|
ID: pid,
|
|
|
|
PrivateKey: priv,
|
|
|
|
ClusterPeers: []ma.Multiaddr{},
|
|
|
|
Bootstrap: []ma.Multiaddr{},
|
|
|
|
LeaveOnShutdown: false,
|
|
|
|
ClusterAddr: clusterAddr,
|
|
|
|
APIAddr: apiAddr,
|
|
|
|
IPFSProxyAddr: ipfsProxyAddr,
|
|
|
|
IPFSNodeAddr: ipfsNodeAddr,
|
|
|
|
ConsensusDataFolder: "ipfscluster-data",
|
|
|
|
StateSyncSeconds: DefaultStateSyncSeconds,
|
2017-04-05 21:29:22 +00:00
|
|
|
IPFSSyncSeconds: DefaultIPFSSyncSeconds,
|
2017-02-28 15:01:26 +00:00
|
|
|
ReplicationFactor: -1,
|
|
|
|
MonitoringIntervalSeconds: DefaultMonitoringIntervalSeconds,
|
2017-03-31 12:37:41 +00:00
|
|
|
AllocationStrategy: "reposize",
|
2016-12-21 18:37:25 +00:00
|
|
|
}, nil
|
|
|
|
}
|