5452b59a2e
* Update go-libp2p to v0.22.0 * Testing with go1.19 * build(deps): bump github.com/multiformats/go-multicodec Bumps [github.com/multiformats/go-multicodec](https://github.com/multiformats/go-multicodec) from 0.5.0 to 0.6.0. - [Release notes](https://github.com/multiformats/go-multicodec/releases) - [Commits](https://github.com/multiformats/go-multicodec/compare/v0.5.0...v0.6.0) --- updated-dependencies: - dependency-name: github.com/multiformats/go-multicodec dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump github.com/ipld/go-car from 0.4.0 to 0.5.0 Bumps [github.com/ipld/go-car](https://github.com/ipld/go-car) from 0.4.0 to 0.5.0. - [Release notes](https://github.com/ipld/go-car/releases) - [Commits](https://github.com/ipld/go-car/compare/v0.4.0...v0.5.0) --- updated-dependencies: - dependency-name: github.com/ipld/go-car dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump github.com/prometheus/client_golang Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.12.2 to 1.13.0. - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.12.2...v1.13.0) --- updated-dependencies: - dependency-name: github.com/prometheus/client_golang dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump github.com/hashicorp/go-hclog from 1.2.1 to 1.3.0 Bumps [github.com/hashicorp/go-hclog](https://github.com/hashicorp/go-hclog) from 1.2.1 to 1.3.0. - [Release notes](https://github.com/hashicorp/go-hclog/releases) - [Commits](https://github.com/hashicorp/go-hclog/compare/v1.2.1...v1.3.0) --- updated-dependencies: - dependency-name: github.com/hashicorp/go-hclog dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump github.com/ipfs/go-ds-crdt from 0.3.6 to 0.3.7 Bumps [github.com/ipfs/go-ds-crdt](https://github.com/ipfs/go-ds-crdt) from 0.3.6 to 0.3.7. - [Release notes](https://github.com/ipfs/go-ds-crdt/releases) - [Commits](https://github.com/ipfs/go-ds-crdt/compare/v0.3.6...v0.3.7) --- updated-dependencies: - dependency-name: github.com/ipfs/go-ds-crdt dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump github.com/urfave/cli/v2 from 2.10.2 to 2.14.1 Bumps [github.com/urfave/cli/v2](https://github.com/urfave/cli) from 2.10.2 to 2.14.1. - [Release notes](https://github.com/urfave/cli/releases) - [Changelog](https://github.com/urfave/cli/blob/main/docs/CHANGELOG.md) - [Commits](https://github.com/urfave/cli/compare/v2.10.2...v2.14.1) --- updated-dependencies: - dependency-name: github.com/urfave/cli/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump github.com/libp2p/go-libp2p-http from 0.3.0 to 0.4.0 Bumps [github.com/libp2p/go-libp2p-http](https://github.com/libp2p/go-libp2p-http) from 0.3.0 to 0.4.0. - [Release notes](https://github.com/libp2p/go-libp2p-http/releases) - [Commits](https://github.com/libp2p/go-libp2p-http/compare/v0.3.0...v0.4.0) --- updated-dependencies: - dependency-name: github.com/libp2p/go-libp2p-http dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump github.com/libp2p/go-libp2p-gorpc from 0.4.0 to 0.5.0 Bumps [github.com/libp2p/go-libp2p-gorpc](https://github.com/libp2p/go-libp2p-gorpc) from 0.4.0 to 0.5.0. - [Release notes](https://github.com/libp2p/go-libp2p-gorpc/releases) - [Commits](https://github.com/libp2p/go-libp2p-gorpc/compare/v0.4.0...v0.5.0) --- updated-dependencies: - dependency-name: github.com/libp2p/go-libp2p-gorpc dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump contrib.go.opencensus.io/exporter/prometheus Bumps [contrib.go.opencensus.io/exporter/prometheus](https://github.com/census-ecosystem/opencensus-go-exporter-prometheus) from 0.4.1 to 0.4.2. - [Release notes](https://github.com/census-ecosystem/opencensus-go-exporter-prometheus/releases) - [Commits](https://github.com/census-ecosystem/opencensus-go-exporter-prometheus/compare/v0.4.1...v0.4.2) --- updated-dependencies: - dependency-name: contrib.go.opencensus.io/exporter/prometheus dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump github.com/libp2p/go-libp2p-raft from 0.1.8 to 0.2.0 Bumps [github.com/libp2p/go-libp2p-raft](https://github.com/libp2p/go-libp2p-raft) from 0.1.8 to 0.2.0. - [Release notes](https://github.com/libp2p/go-libp2p-raft/releases) - [Commits](https://github.com/libp2p/go-libp2p-raft/compare/v0.1.8...v0.2.0) --- updated-dependencies: - dependency-name: github.com/libp2p/go-libp2p-raft dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): bump github.com/urfave/cli from 1.22.9 to 1.22.10 Bumps [github.com/urfave/cli](https://github.com/urfave/cli) from 1.22.9 to 1.22.10. - [Release notes](https://github.com/urfave/cli/releases) - [Changelog](https://github.com/urfave/cli/blob/main/docs/CHANGELOG.md) - [Commits](https://github.com/urfave/cli/compare/v1.22.9...v1.22.10) --- updated-dependencies: - dependency-name: github.com/urfave/cli dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * Fix checker/linter/staticcheck warnings Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
310 lines
8.8 KiB
Go
310 lines
8.8 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"time"
|
|
|
|
ipfscluster "github.com/ipfs-cluster/ipfs-cluster"
|
|
"github.com/ipfs-cluster/ipfs-cluster/allocator/balanced"
|
|
"github.com/ipfs-cluster/ipfs-cluster/api/ipfsproxy"
|
|
"github.com/ipfs-cluster/ipfs-cluster/api/pinsvcapi"
|
|
"github.com/ipfs-cluster/ipfs-cluster/api/rest"
|
|
"github.com/ipfs-cluster/ipfs-cluster/cmdutils"
|
|
"github.com/ipfs-cluster/ipfs-cluster/config"
|
|
"github.com/ipfs-cluster/ipfs-cluster/consensus/crdt"
|
|
"github.com/ipfs-cluster/ipfs-cluster/consensus/raft"
|
|
"github.com/ipfs-cluster/ipfs-cluster/informer/disk"
|
|
"github.com/ipfs-cluster/ipfs-cluster/informer/pinqueue"
|
|
"github.com/ipfs-cluster/ipfs-cluster/informer/tags"
|
|
"github.com/ipfs-cluster/ipfs-cluster/ipfsconn/ipfshttp"
|
|
"github.com/ipfs-cluster/ipfs-cluster/monitor/pubsubmon"
|
|
"github.com/ipfs-cluster/ipfs-cluster/observations"
|
|
"github.com/ipfs-cluster/ipfs-cluster/pintracker/stateless"
|
|
"go.opencensus.io/tag"
|
|
|
|
ds "github.com/ipfs/go-datastore"
|
|
host "github.com/libp2p/go-libp2p/core/host"
|
|
peer "github.com/libp2p/go-libp2p/core/peer"
|
|
dual "github.com/libp2p/go-libp2p-kad-dht/dual"
|
|
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
|
|
|
ma "github.com/multiformats/go-multiaddr"
|
|
|
|
errors "github.com/pkg/errors"
|
|
cli "github.com/urfave/cli"
|
|
)
|
|
|
|
func parseBootstraps(flagVal []string) (bootstraps []ma.Multiaddr) {
|
|
for _, a := range flagVal {
|
|
bAddr, err := ma.NewMultiaddr(strings.TrimSpace(a))
|
|
checkErr("error parsing bootstrap multiaddress (%s)", err, a)
|
|
bootstraps = append(bootstraps, bAddr)
|
|
}
|
|
return
|
|
}
|
|
|
|
// Runs the cluster peer
|
|
func daemon(c *cli.Context) error {
|
|
logger.Info("Initializing. For verbose output run with \"-l debug\". Please wait...")
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
var bootstraps []ma.Multiaddr
|
|
if bootStr := c.String("bootstrap"); bootStr != "" {
|
|
bootstraps = parseBootstraps(strings.Split(bootStr, ","))
|
|
}
|
|
|
|
// Execution lock
|
|
locker.lock()
|
|
defer locker.tryUnlock()
|
|
|
|
// Load all the configurations and identity
|
|
cfgHelper, err := cmdutils.NewLoadedConfigHelper(configPath, identityPath)
|
|
checkErr("loading configurations", err)
|
|
defer cfgHelper.Manager().Shutdown()
|
|
|
|
cfgs := cfgHelper.Configs()
|
|
|
|
if c.Bool("stats") {
|
|
cfgs.Metrics.EnableStats = true
|
|
}
|
|
cfgHelper.SetupTracing(c.Bool("tracing"))
|
|
|
|
// Setup bootstrapping
|
|
raftStaging := false
|
|
switch cfgHelper.GetConsensus() {
|
|
case cfgs.Raft.ConfigKey():
|
|
if len(bootstraps) > 0 {
|
|
// Cleanup state if bootstrapping
|
|
raft.CleanupRaft(cfgs.Raft)
|
|
raftStaging = true
|
|
}
|
|
case cfgs.Crdt.ConfigKey():
|
|
if !c.Bool("no-trust") {
|
|
crdtCfg := cfgs.Crdt
|
|
crdtCfg.TrustedPeers = append(crdtCfg.TrustedPeers, ipfscluster.PeersFromMultiaddrs(bootstraps)...)
|
|
}
|
|
}
|
|
|
|
if c.Bool("leave") {
|
|
cfgs.Cluster.LeaveOnShutdown = true
|
|
}
|
|
|
|
store := setupDatastore(cfgHelper)
|
|
|
|
host, pubsub, dht, err := ipfscluster.NewClusterHost(ctx, cfgHelper.Identity(), cfgs.Cluster, store)
|
|
checkErr("creating libp2p host", err)
|
|
|
|
cluster, err := createCluster(ctx, c, cfgHelper, host, pubsub, dht, store, raftStaging)
|
|
checkErr("starting cluster", err)
|
|
|
|
// noop if no bootstraps
|
|
// if bootstrapping fails, consensus will never be ready
|
|
// and timeout. So this can happen in background and we
|
|
// avoid worrying about error handling here (since Cluster
|
|
// will realize).
|
|
go bootstrap(ctx, cluster, bootstraps)
|
|
|
|
return cmdutils.HandleSignals(ctx, cancel, cluster, host, dht, store)
|
|
}
|
|
|
|
// createCluster creates all the necessary things to produce the cluster
|
|
// object and returns it along the datastore so the lifecycle can be handled
|
|
// (the datastore needs to be Closed after shutting down the Cluster).
|
|
func createCluster(
|
|
ctx context.Context,
|
|
c *cli.Context,
|
|
cfgHelper *cmdutils.ConfigHelper,
|
|
host host.Host,
|
|
pubsub *pubsub.PubSub,
|
|
dht *dual.DHT,
|
|
store ds.Datastore,
|
|
raftStaging bool,
|
|
) (*ipfscluster.Cluster, error) {
|
|
|
|
cfgs := cfgHelper.Configs()
|
|
cfgMgr := cfgHelper.Manager()
|
|
cfgBytes, err := cfgMgr.ToDisplayJSON()
|
|
checkErr("getting configuration string", err)
|
|
logger.Debugf("Configuration:\n%s\n", cfgBytes)
|
|
|
|
ctx, err = tag.New(ctx, tag.Upsert(observations.HostKey, host.ID().Pretty()))
|
|
checkErr("tag context with host id", err)
|
|
|
|
err = observations.SetupMetrics(cfgs.Metrics)
|
|
checkErr("setting up Metrics", err)
|
|
|
|
tracer, err := observations.SetupTracing(cfgs.Tracing)
|
|
checkErr("setting up Tracing", err)
|
|
|
|
var apis []ipfscluster.API
|
|
if cfgMgr.IsLoadedFromJSON(config.API, cfgs.Restapi.ConfigKey()) {
|
|
var api *rest.API
|
|
// Do NOT enable default Libp2p API endpoint on CRDT
|
|
// clusters. Collaborative clusters are likely to share the
|
|
// secret with untrusted peers, thus the API would be open for
|
|
// anyone.
|
|
if cfgHelper.GetConsensus() == cfgs.Raft.ConfigKey() {
|
|
api, err = rest.NewAPIWithHost(ctx, cfgs.Restapi, host)
|
|
} else {
|
|
api, err = rest.NewAPI(ctx, cfgs.Restapi)
|
|
}
|
|
checkErr("creating REST API component", err)
|
|
apis = append(apis, api)
|
|
|
|
}
|
|
|
|
if cfgMgr.IsLoadedFromJSON(config.API, cfgs.Pinsvcapi.ConfigKey()) {
|
|
pinsvcapi, err := pinsvcapi.NewAPI(ctx, cfgs.Pinsvcapi)
|
|
checkErr("creating Pinning Service API component", err)
|
|
|
|
apis = append(apis, pinsvcapi)
|
|
}
|
|
|
|
if cfgMgr.IsLoadedFromJSON(config.API, cfgs.Ipfsproxy.ConfigKey()) {
|
|
proxy, err := ipfsproxy.New(cfgs.Ipfsproxy)
|
|
checkErr("creating IPFS Proxy component", err)
|
|
|
|
apis = append(apis, proxy)
|
|
}
|
|
|
|
connector, err := ipfshttp.NewConnector(cfgs.Ipfshttp)
|
|
checkErr("creating IPFS Connector component", err)
|
|
|
|
var informers []ipfscluster.Informer
|
|
if cfgMgr.IsLoadedFromJSON(config.Informer, cfgs.DiskInf.ConfigKey()) {
|
|
diskInf, err := disk.NewInformer(cfgs.DiskInf)
|
|
checkErr("creating disk informer", err)
|
|
informers = append(informers, diskInf)
|
|
}
|
|
if cfgMgr.IsLoadedFromJSON(config.Informer, cfgs.TagsInf.ConfigKey()) {
|
|
tagsInf, err := tags.New(cfgs.TagsInf)
|
|
checkErr("creating numpin informer", err)
|
|
informers = append(informers, tagsInf)
|
|
}
|
|
|
|
if cfgMgr.IsLoadedFromJSON(config.Informer, cfgs.PinQueueInf.ConfigKey()) {
|
|
pinQueueInf, err := pinqueue.New(cfgs.PinQueueInf)
|
|
checkErr("creating pinqueue informer", err)
|
|
informers = append(informers, pinQueueInf)
|
|
}
|
|
|
|
// For legacy compatibility we need to make the allocator
|
|
// automatically compatible with informers that have been loaded. For
|
|
// simplicity we assume that anyone that does not specify an allocator
|
|
// configuration (legacy configs), will be using "freespace"
|
|
if !cfgMgr.IsLoadedFromJSON(config.Allocator, cfgs.BalancedAlloc.ConfigKey()) {
|
|
cfgs.BalancedAlloc.AllocateBy = []string{"freespace"}
|
|
}
|
|
alloc, err := balanced.New(cfgs.BalancedAlloc)
|
|
checkErr("creating allocator", err)
|
|
|
|
ipfscluster.ReadyTimeout = cfgs.Raft.WaitForLeaderTimeout + 5*time.Second
|
|
|
|
cons, err := setupConsensus(
|
|
cfgHelper,
|
|
host,
|
|
dht,
|
|
pubsub,
|
|
store,
|
|
raftStaging,
|
|
)
|
|
if err != nil {
|
|
store.Close()
|
|
checkErr("setting up Consensus", err)
|
|
}
|
|
|
|
var peersF func(context.Context) ([]peer.ID, error)
|
|
if cfgHelper.GetConsensus() == cfgs.Raft.ConfigKey() {
|
|
peersF = cons.Peers
|
|
}
|
|
|
|
tracker := stateless.New(cfgs.Statelesstracker, host.ID(), cfgs.Cluster.Peername, cons.State)
|
|
logger.Debug("stateless pintracker loaded")
|
|
|
|
mon, err := pubsubmon.New(ctx, cfgs.Pubsubmon, pubsub, peersF)
|
|
if err != nil {
|
|
store.Close()
|
|
checkErr("setting up PeerMonitor", err)
|
|
}
|
|
|
|
return ipfscluster.NewCluster(
|
|
ctx,
|
|
host,
|
|
dht,
|
|
cfgs.Cluster,
|
|
store,
|
|
cons,
|
|
apis,
|
|
connector,
|
|
tracker,
|
|
mon,
|
|
alloc,
|
|
informers,
|
|
tracer,
|
|
)
|
|
}
|
|
|
|
// bootstrap will bootstrap this peer to one of the bootstrap addresses
|
|
// if there are any.
|
|
func bootstrap(ctx context.Context, cluster *ipfscluster.Cluster, bootstraps []ma.Multiaddr) {
|
|
for _, bstrap := range bootstraps {
|
|
logger.Infof("Bootstrapping to %s", bstrap)
|
|
err := cluster.Join(ctx, bstrap)
|
|
if err != nil {
|
|
logger.Errorf("bootstrap to %s failed: %s", bstrap, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func setupDatastore(cfgHelper *cmdutils.ConfigHelper) ds.Datastore {
|
|
dsName := cfgHelper.GetDatastore()
|
|
stmgr, err := cmdutils.NewStateManager(cfgHelper.GetConsensus(), dsName, cfgHelper.Identity(), cfgHelper.Configs())
|
|
checkErr("creating state manager", err)
|
|
store, err := stmgr.GetStore()
|
|
checkErr("creating datastore", err)
|
|
if dsName != "" {
|
|
logger.Infof("Datastore backend: %s", dsName)
|
|
}
|
|
return store
|
|
}
|
|
|
|
func setupConsensus(
|
|
cfgHelper *cmdutils.ConfigHelper,
|
|
h host.Host,
|
|
dht *dual.DHT,
|
|
pubsub *pubsub.PubSub,
|
|
store ds.Datastore,
|
|
raftStaging bool,
|
|
) (ipfscluster.Consensus, error) {
|
|
|
|
cfgs := cfgHelper.Configs()
|
|
switch cfgHelper.GetConsensus() {
|
|
case cfgs.Raft.ConfigKey():
|
|
rft, err := raft.NewConsensus(
|
|
h,
|
|
cfgHelper.Configs().Raft,
|
|
store,
|
|
raftStaging,
|
|
)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "creating Raft component")
|
|
}
|
|
return rft, nil
|
|
case cfgs.Crdt.ConfigKey():
|
|
convrdt, err := crdt.New(
|
|
h,
|
|
dht,
|
|
pubsub,
|
|
cfgHelper.Configs().Crdt,
|
|
store,
|
|
)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "creating CRDT component")
|
|
}
|
|
return convrdt, nil
|
|
default:
|
|
return nil, errors.New("unknown consensus component")
|
|
}
|
|
}
|