Merge branch 'ind-bootstrap' into protocol

# Conflicts:
#	version.go
This commit is contained in:
David Vennik
2023-01-14 21:18:51 +00:00
19 changed files with 647 additions and 254 deletions

1
.gitignore vendored
View File

@@ -4,6 +4,7 @@
*.dll
*.so
*.dylib
indra
# Test binary, built with `go test -c`
*.test

View File

@@ -26,9 +26,93 @@ func init() {
}
var (
timeout = 120 * time.Second
defaultBuildingTimeout = 800 * time.Second
defaultRepositoryName = "indralabs"
defaultBuildContainer = "golang:1.19.4"
)
func strPtr(str string) *string { return &str }
var buildConfigurations = []docker.BuildConfiguration{
//docker.BuildConfiguration{
// Name: defaultRepositoryName + "/" + "scratch",
// ContextFilePath: "/tmp/scratch.tar",
// BuildOpts: types.ImageBuildOptions{
// Dockerfile: "docker/scratch/Dockerfile",
// Tags: []string{
// indra.SemVer,
// "latest",
// },
// BuildArgs: map[string]*string{
// "base_image": strPtr("busybox"),
// },
// SuppressOutput: false,
// Remove: true,
// ForceRemove: true,
// PullParent: true,
// },
//},
docker.BuildConfiguration{
Name: defaultRepositoryName + "/" + "btcd",
ContextFilePath: "/tmp/btcd.tar",
BuildOpts: types.ImageBuildOptions{
Dockerfile: "docker/btcd/Dockerfile",
Tags: []string{
"v0.23.4",
"latest",
},
BuildArgs: map[string]*string{
"base_image": strPtr(defaultBuildContainer),
"target_image": strPtr("indralabs/scratch:latest"),
// This argument is the tag fetched by git
// It MUST be updated alongside the tag above
"git_repository": strPtr("github.com/btcsuite/btcd"),
"git_tag": strPtr("v0.23.4"),
},
SuppressOutput: false,
Remove: true,
ForceRemove: true,
PullParent: true,
},
},
//docker.BuildConfiguration{
// Name: defaultRepositoryName + "/" + "lnd",
// ContextFilePath: "/tmp/lnd.tar",
// BuildOpts: types.ImageBuildOptions{
// Dockerfile: "docker/lnd/Dockerfile",
// Tags: []string{
// "v0.15.5-beta",
// "latest",
// },
// BuildArgs: map[string]*string{
// // This argument is the tag fetched by git
// // It MUST be updated alongside the tag above
// "git_tag": strPtr("v0.15.5-beta"),
// },
// SuppressOutput: false,
// Remove: true,
// ForceRemove: true,
// PullParent: true,
// },
//},
//docker.BuildConfiguration{
// Name: defaultRepositoryName + "/" + "indra",
// ContextFilePath: "/tmp/indra-" + indra.SemVer + ".tar",
// BuildOpts: types.ImageBuildOptions{
// Dockerfile: "docker/indra/Dockerfile",
// Tags: []string{
// indra.SemVer,
// "latest",
// },
// BuildArgs: map[string]*string{},
// SuppressOutput: false,
// Remove: true,
// ForceRemove: true,
// PullParent: true,
// },
//},
}
var commands = &cmds.Command{
Name: "release",
Description: "Builds the indra docker image and pushes it to a list of docker repositories.",
@@ -61,7 +145,7 @@ var commands = &cmds.Command{
}
// Set a Timeout for 120 seconds
ctx, cancel := context.WithTimeout(context.Background(), timeout)
ctx, cancel := context.WithTimeout(context.Background(), defaultBuildingTimeout)
defer cancel()
// Setup a new instance of the docker client
@@ -75,15 +159,14 @@ var commands = &cmds.Command{
defer cli.Close()
// Get ready to submit a build
var builder = docker.NewBuilder(ctx, cli)
// Get ready to submit the builds
var builder = docker.NewBuilder(ctx, cli, buildConfigurations)
if err = builder.Build(); check(err) {
return err
}
if err = builder.Push(types.ImagePushOptions{}); check(err) {
if err = builder.Push(); check(err) {
return err
}

View File

@@ -118,9 +118,7 @@ var commands = &cmds.Command{
return err
}
log.I.Ln("starting the server.")
if srv.Serve(); check(err) {
if err = srv.Serve(); check(err) {
return err
}

58
docker/btcd/Dockerfile Normal file
View File

@@ -0,0 +1,58 @@
ARG base_image="golang"
ARG target_image="indralabs/scratch"
# ---
# Build Process
# ---
FROM ${base_image} AS builder
# Get the repo and build
ARG git_repository="github.com/indra-labs/btcd"
ARG git_tag="master"
# Install dependencies and build the binaries.
RUN git clone "https://"${git_repository} /go/src/${git_repository}
WORKDIR $GOPATH/src/${git_repository}
RUN git checkout ${git_tag}
# Source/Target release defaults
ARG ARCH=amd64
ARG GOARCH=amd64
ENV GO111MODULE=on GOOS=linux
WORKDIR $GOPATH/src/${git_repository}
RUN cp sample-btcd.conf /tmp/btcd.conf
RUN set -ex \
&& CGO_ENABLED=0 go build --ldflags '-w -s' -o /tmp/bin/btcd . \
&& CGO_ENABLED=0 go build --ldflags '-w -s' -o /tmp/bin/ ./cmd/...
# ---
# Target Configuration
# ---
FROM indralabs/scratch:latest
## Migrate the binaries and storage folder
COPY --from=builder /tmp/btcd.conf /etc/btcd/btcd.conf
COPY --from=builder /tmp/bin /bin
# Enable the btcd user
USER btcd:btcd
# Set the data volumes
#VOLUME ["/etc/btcd"]
#VOLUME ["/var/btcd"]
# :8333 btcd peer-to-peer port
# :8334 btcd RPC port
EXPOSE 8333 8334
ENTRYPOINT ["/bin/btcd", "--configfile=/etc/btcd/btcd.conf", "--datadir=/var/btcd", "--logdir=/var/btcd", "--rpckey=/etc/btcd/keys/rpc.key", "--rpccert=/etc/btcd/keys/rpc.cert", "--listen=0.0.0.0:8333", "--rpclisten=0.0.0.0:8334"]

72
docker/lnd/Dockerfile Normal file
View File

@@ -0,0 +1,72 @@
FROM golang:1.19.4 AS builder
# User/Group definition
ENV USER=lnd GROUP=lnd UID=9735 GID=9735
## Create a user/group for indra, to be migrated to the target container
RUN addgroup ${GROUP} --gid ${GID} \
&& adduser \
--disabled-password \
--gecos "" \
--home "/var/lnd" \
--shell "/sbin/nologin" \
#--no-create-home \
--uid "${UID}" \
--gid "${GID}" \
"${USER}" \
&& mkdir -pv /var/lnd/.lnd && chown -R lnd:lnd /var/lnd
# Pass a tag, branch or a commit using build-arg. This allows a docker
# image to be built from a specified Git state. The default image
# will use the Git tip of master by default.
ARG git_tag="master"
# Install dependencies and build the binaries.
RUN git clone "https://github.com/lightningnetwork/lnd" /go/src/github.com/lightningnetwork/lnd \
&& cd /go/src/github.com/lightningnetwork/lnd \
&& git checkout ${git_tag}
# Source/Target release defaults
ARG ARCH=amd64
ARG GOARCH=amd64
ENV GO111MODULE=on GOOS=linux
WORKDIR $GOPATH/src/github.com/lightningnetwork/lnd
RUN set -ex \
&& cp /go/src/github.com/lightningnetwork/lnd/sample-lnd.conf /var/lnd/.lnd/lnd.conf \
&& chown -R lnd:lnd /var/lnd \
&& CGO_ENABLED=0 go build --ldflags '-w -s' -o /bin/lnd ./cmd/lnd/. \
&& CGO_ENABLED=0 go build --ldflags '-w -s' -o /bin/lncli ./cmd/lncli/.
# ---
# Configure and Build the target container
# ---
FROM scratch
# Migrate User/Group to target
COPY --from=builder /etc/passwd /etc/passwd
COPY --from=builder /etc/group /etc/group
# Migrate the binaries and storage folder
COPY --from=builder /bin /bin
COPY --from=builder --chown=lnd:lnd /var/lnd /var/lnd
# Enable the indra user
USER lnd:lnd
# ENV defaults
# ENV IND_LOGFILEPATH=""
# Set the data volume
#VOLUME ["/var/lnd"]
# :9735 lnd peer-to-peer port
# :10009 lnd RPC port
EXPOSE 9735 10009
ENTRYPOINT ["/bin/lnd"]
# docker run -it --rm --entrypoint="/bin/lncli" -v ~/rpc.cert:/var/lnd/.lnd/rpc.cert indralabs/lnd --skipverify -s <host>:<port> -u <username> -P <password> <function>

134
docker/scratch/Dockerfile Normal file
View File

@@ -0,0 +1,134 @@
ARG base_image=busybox
FROM ${base_image} as base
RUN set -ex && echo "creating root filesystem" \
&& mkdir -pv /tmp/root-fs \
&& mkdir -pv /tmp/root-fs/etc \
&& mkdir -pv /tmp/root-fs/var \
&& mkdir -pv /tmp/root-fs/bin
RUN set -ex && echo "checking root filesystem" \
&& ls -hal /tmp/root-fs \
&& ls -hal /tmp/root-fs/etc \
&& ls -hal /tmp/root-fs/var \
&& ls -hal /tmp/root-fs/bin
##
## Users and Groups
##
RUN set -ex && echo "adding users and groups" \
&& echo "btcd:*:::::::" >> /etc/shadow \
&& echo "btcd:x:8333:" >> /etc/group \
&& echo "btcd:x:8333:8333:btcd:/var/btcd:/sbin/false" >> /etc/passwd \
&& echo "lnd:*:::::::" >> /etc/shadow \
&& echo "lnd:x:9735:" >> /etc/group \
&& echo "lnd:x:9735:9735:lnd:/var/lnd:/sbin/false" >> /etc/passwd \
&& echo "indra:*:::::::" >> /etc/shadow \
&& echo "indra:x:8337:" >> /etc/group \
&& echo "indra:x:8337:8337:indra:/var/indra:/sbin/false" >> /etc/passwd
RUN set -ex && echo "checking users and groups" \
&& cat /etc/shadow \
&& cat /etc/group \
&& cat /etc/passwd
RUN set -ex && echo "copying users and groups to root filesystem" \
&& cp -p /etc/shadow /tmp/root-fs/etc/shadow \
&& cp -p /etc/group /tmp/root-fs/etc/group \
&& cp -p /etc/passwd /tmp/root-fs/etc/passwd
# DEBUG
RUN set -ex && echo "checking users and groups to root filesystem" \
&& ls -hal /tmp/root-fs/etc \
&& cat /tmp/root-fs/etc/shadow \
&& cat /tmp/root-fs/etc/passwd \
&& cat /tmp/root-fs/etc/group
##
## Configuration and Data directories
##
RUN set -ex && echo "adding and permissioning /etc directories" \
&& mkdir -pv /etc/btcd && chmod 755 /etc/btcd \
&& mkdir -pv /etc/btcd/keys && chmod 750 /etc/btcd/keys && chown btcd:btcd /etc/btcd/keys \
&& mkdir -pv /etc/lnd && chmod 755 /etc/lnd \
&& mkdir -pv /etc/lnd/keys && chmod 750 /etc/lnd/keys && chown lnd:lnd /etc/lnd/keys \
&& mkdir -pv /etc/indra && chmod 755 /etc/indra
RUN set -ex && echo "copying /etc directories to root filesystem" \
&& cp -rp /etc/btcd /tmp/root-fs/etc/btcd \
&& cp -rp /etc/lnd /tmp/root-fs/etc/lnd \
&& cp -rp /etc/indra /tmp/root-fs/etc/indra
# DEBUG
RUN set -ex && echo "checking /etc directories on root filesystem" \
&& ls -hal /tmp/root-fs/etc \
&& ls -hal /tmp/root-fs/etc/btcd \
&& ls -hal /tmp/root-fs/etc/btcd/keys \
&& ls -hal /tmp/root-fs/etc/lnd \
&& ls -hal /tmp/root-fs/etc/lnd/keys \
&& ls -hal /tmp/root-fs/etc/indra
RUN set -ex && echo "adding and permissioning /var directories" \
&& mkdir -pv /var/btcd && chmod 750 /var/btcd && chown btcd:btcd /var/btcd \
&& mkdir -pv /var/btcd/.btcd && chmod 750 /var/btcd/.btcd && chown btcd:btcd /var/btcd/.btcd \
&& mkdir -pv /var/lnd && chmod 750 /var/lnd && chown lnd:lnd /var/lnd \
&& mkdir -pv /var/lnd/.lnd && chmod 750 /var/lnd/.lnd && chown lnd:lnd /var/lnd/.lnd \
&& mkdir -pv /var/indra && chmod 750 /var/indra && chown indra:indra /var/indra
RUN set -ex && echo "copying /var directories to root filesystem" \
&& cp -rp /var/btcd /tmp/root-fs/var/btcd \
&& cp -rp /var/lnd /tmp/root-fs/var/lnd \
&& cp -rp /var/indra /tmp/root-fs/var/indra
# DEBUG
RUN set -ex && echo "checking /var directories on root filesystem" \
&& ls -hal /tmp/root-fs/var \
&& ls -hal /tmp/root-fs/var/btcd \
&& ls -hal /tmp/root-fs/var/btcd/.btcd \
&& ls -hal /tmp/root-fs/var/lnd \
&& ls -hal /tmp/root-fs/var/lnd/.lnd \
&& ls -hal /tmp/root-fs/var/indra
WORKDIR /tmp/root-fs
RUN set -ex && echo "building root-fs tarball" \
&& tar -cvzf /tmp/root-fs.tgz . \
&& rm -rf /tmp/root-fs \
&& ls -hal /tmp
#RUN set -ex && tar -xzvf /tmp/root-fs.tgz \
# && ls -hal /tmp \
# && ls -hal /tmp/root-fs \
# && ls -hal /tmp/root-fs/etc \
# && ls -hal /tmp/root-fs/etc/btcd \
##
## Base Image
##
#
# Note: We CANNOT use the scratch container to build the our scratch image.
#
# When using the COPY command between container, docker does not preserve permissions.
# Instead, we will opt for generating a root-fs on the build image and extracting it as a tarball.
#
#FROM scratch
#
## Migrate over users and groups
#COPY --from=base /etc/passwd /etc/passwd
#COPY --from=base /etc/group /etc/group
#
## Configuration
#COPY --from=base /etc/btcd /etc/btcd
#COPY --from=base /etc/lnd /etc/lnd
#COPY --from=base /etc/indra /etc/indra
#
### Data
#COPY --from=base --chown=btcd:btcd /var/btcd /var/btcd
#COPY --from=base --chown=lnd:lnd /var/lnd /var/lnd
#COPY --from=base --chown=indra:indra /var/indra /var/indra

9
docker/scratch/build.sh Executable file
View File

@@ -0,0 +1,9 @@
#!/bin/bash
docker build -t indralabs/scratch-builder .
docker run --rm -it --volume=${PWD}/tmp:/output indralabs/scratch-builder cp /tmp/root-fs.tgz /output
docker image import tmp/root-fs.tgz indralabs/scratch
docker push indralabs/scratch:latest

1
docker/scratch/tmp/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
root-fs.tgz

View File

View File

@@ -1,5 +1,25 @@
version: '3'
services:
btcd:
sysctls:
- "net.ipv6.conf.all.disable_ipv6=0"
image: indralabs/btcd:latest
container_name: indra-btcd
volumes:
- btcd_config:/etc/btcd:ro
- btcd_data:/var/btcd
networks:
indranet:
ipv4_address: 172.16.238.254
expose:
- 8333
- 8334
command:
- "--listen=0.0.0.0:8333"
- "--rpclisten=0.0.0.0:8334"
- "--rpcuser=simnet"
- "--rpcpass=simnet"
- "--simnet"
seed0:
sysctls:
- "net.ipv6.conf.all.disable_ipv6=0"
@@ -17,6 +37,8 @@ services:
environment:
INDRA_SERVE_KEY: "66T7j5JnhsjDTqVvV8zEM2rTUobu66tocizfqArVEnP1"
INDRA_SERVE_LISTEN: "/ip4/0.0.0.0/tcp/62134,/ip6/::/tcp/62134"
command:
- "serve"
seed1:
sysctls:
- "net.ipv6.conf.all.disable_ipv6=0"
@@ -36,6 +58,8 @@ services:
environment:
INDRA_SERVE_KEY: "66T7j5JnhsjDTqVvV8zEM2rTUobu66tocizfqArVEnP2"
INDRA_SERVE_LISTEN: "/ip4/0.0.0.0/tcp/62134,/ip6/::/tcp/62134"
command:
- "serve"
seed2:
sysctls:
- "net.ipv6.conf.all.disable_ipv6=0"
@@ -56,6 +80,8 @@ services:
environment:
INDRA_SERVE_KEY: "66T7j5JnhsjDTqVvV8zEM2rTUobu66tocizfqArVEnP3"
INDRA_SERVE_LISTEN: "/ip4/0.0.0.0/tcp/62134,/ip6/::/tcp/62134"
command:
- "serve"
peer0:
sysctls:
- "net.ipv6.conf.all.disable_ipv6=0"
@@ -76,6 +102,8 @@ services:
environment:
#INDRA_SERVE_SEED: "/dns4/seed0/tcp/62134/p2p/16Uiu2HAm2LgowPNBM47dR6gSJmEeQaqCZ6u4WPhTCSWkxyNrfAxo"
INDRA_SERVE_LISTEN: "/ip4/0.0.0.0/tcp/62134,/ip6/::/tcp/62134"
command:
- "serve"
peer1:
sysctls:
- "net.ipv6.conf.all.disable_ipv6=0"
@@ -96,6 +124,8 @@ services:
environment:
#INDRA_SERVE_SEED: "/dns4/seed0/tcp/62134/p2p/16Uiu2HAm2LgowPNBM47dR6gSJmEeQaqCZ6u4WPhTCSWkxyNrfAxo"
INDRA_SERVE_LISTEN: "/ip4/0.0.0.0/tcp/62134,/ip6/::/tcp/62134"
command:
- "serve"
peer2:
sysctls:
- "net.ipv6.conf.all.disable_ipv6=0"
@@ -116,7 +146,11 @@ services:
environment:
#INDRA_SERVE_SEED: "/dns4/seed0/tcp/62134/p2p/16Uiu2HAm2LgowPNBM47dR6gSJmEeQaqCZ6u4WPhTCSWkxyNrfAxo"
INDRA_SERVE_LISTEN: "/ip4/127.0.0.1/tcp/62134,/ip6/::1/tcp/62134"
command:
- "serve"
volumes:
btcd_config:
btcd_data:
seed0_gopath:
seed1_gopath:
seed2_gopath:

View File

@@ -2,4 +2,4 @@
go mod tidy
IPFS_LOGGING=info go run ./cmd/indra/. -lcl serve
IPFS_LOGGING=info go run ./cmd/indra/. $@

View File

@@ -26,19 +26,6 @@ var (
)
var (
buildRepositoryName = "indralabs/indra"
buildContextFilePath = "/tmp/indra-" + indra.SemVer + ".tar"
buildOpts = types.ImageBuildOptions{
Dockerfile: "docker/indra/Dockerfile",
Tags: []string{
buildRepositoryName + ":" + indra.SemVer,
buildRepositoryName + ":" + "latest",
},
SuppressOutput: false,
Remove: true,
ForceRemove: true,
PullParent: true,
}
isRelease = false
isPushable = false
)
@@ -53,17 +40,21 @@ func SetPush() {
type Builder struct {
*client.Client
ctx context.Context
ctx context.Context
configs []BuildConfiguration
}
func (cli *Builder) Build() (err error) {
func (self *Builder) build(buildConfig BuildConfiguration) (err error) {
log.I.Ln("building", buildOpts.Tags[0], "from", buildOpts.Dockerfile)
// We need the absolute path for build tags to be valid
buildConfig.BuildOpts.Tags = buildConfig.FixTagPrefix()
log.I.Ln("building", buildConfig.BuildOpts.Tags[0], "from", buildConfig.BuildOpts.Dockerfile)
// If we're building a release, we should also tag stable.
if isRelease {
buildOpts.Tags = append(buildOpts.Tags, buildRepositoryName+":"+"stable")
buildConfig.BuildOpts.Tags = append(buildConfig.BuildOpts.Tags, "stable")
}
// Generate a tar file for docker's release context. It will contain the root of the repository's path.
@@ -83,7 +74,7 @@ func (cli *Builder) Build() (err error) {
var response types.ImageBuildResponse
if response, err = cli.ImageBuild(cli.ctx, tar, buildOpts); check(err) {
if response, err = self.ImageBuild(self.ctx, tar, buildConfig.BuildOpts); check(err) {
return
}
@@ -101,7 +92,7 @@ func (cli *Builder) Build() (err error) {
log.I.Ln("pruning release container(s)...")
if _, err = cli.ImagesPrune(cli.ctx, filters.NewArgs()); check(err) {
if _, err = self.ImagesPrune(self.ctx, filters.NewArgs()); check(err) {
return
}
@@ -111,7 +102,19 @@ func (cli *Builder) Build() (err error) {
return
}
func (cli *Builder) Push(opts types.ImagePushOptions) (err error) {
func (self *Builder) Build() (err error) {
for _, buildConfig := range self.configs {
if err = self.build(buildConfig); check(err) {
return
}
}
return nil
}
func (self *Builder) push(buildConfig BuildConfiguration) (err error) {
if !isPushable {
return nil
@@ -148,15 +151,15 @@ func (cli *Builder) Push(opts types.ImagePushOptions) (err error) {
authConfigBytes, _ := json.Marshal(auth)
opts.RegistryAuth = base64.URLEncoding.EncodeToString(authConfigBytes)
buildConfig.PushOpts.RegistryAuth = base64.URLEncoding.EncodeToString(authConfigBytes)
// Pushes each tag to the docker repository.
for _, tag := range buildOpts.Tags {
for _, tag := range buildConfig.FixTagPrefix() {
log.I.Ln("pushing", tag)
if pushResponse, err = cli.ImagePush(cli.ctx, tag, opts); check(err) {
if pushResponse, err = self.ImagePush(self.ctx, tag, buildConfig.PushOpts); check(err) {
return
}
@@ -175,10 +178,23 @@ func (cli *Builder) Push(opts types.ImagePushOptions) (err error) {
return nil
}
func NewBuilder(ctx context.Context, cli *client.Client) (builder *Builder) {
func (self *Builder) Push() (err error) {
for _, buildConfig := range self.configs {
if err = self.push(buildConfig); check(err) {
return
}
}
return nil
}
func NewBuilder(ctx context.Context, cli *client.Client, buildConfigs []BuildConfiguration) (builder *Builder) {
return &Builder{
cli,
ctx,
buildConfigs,
}
}

24
pkg/docker/config.go Normal file
View File

@@ -0,0 +1,24 @@
package docker
import (
"github.com/docker/docker/api/types"
)
type BuildConfiguration struct {
Name string
ContextFilePath string
BuildOpts types.ImageBuildOptions
PushOpts types.ImagePushOptions
}
func (self *BuildConfiguration) FixTagPrefix() []string {
var fullTags = []string{}
for _, tag := range self.BuildOpts.Tags {
fullTags = append(fullTags, self.Name+":"+tag)
}
return fullTags
}

View File

@@ -6,6 +6,7 @@ import (
"os/exec"
"os/signal"
"runtime"
"strings"
"syscall"
"github.com/indra-labs/indra"
@@ -49,14 +50,20 @@ var interruptCallbackSources []string
// responds to custom shutdown signals as required
func Listener() {
invokeCallbacks := func() {
log.D.Ln(
"running interrupt callbacks",
len(interruptCallbacks),
strings.Repeat(" ", 48),
interruptCallbackSources,
)
// run handlers in LIFO order.
for i := range interruptCallbacks {
idx := len(interruptCallbacks) - 1 - i
log.I.Ln("running callback", idx,
log.D.Ln("running callback", idx,
interruptCallbackSources[idx])
interruptCallbacks[idx]()
}
log.I.Ln("interrupt handlers finished")
log.D.Ln("interrupt handlers finished")
close(HandlersDone)
if Restart {
var file string
@@ -103,8 +110,7 @@ out:
case sig := <-ch:
// if !requested {
// L.Printf("\r>>> received signal (%s)\n", sig)
fmt.Print("\r")
log.I.Ln("received interrupt signal", sig)
log.I.Ln("received signal", sig)
requested.Store(true)
invokeCallbacks()
// pprof.Lookup("goroutine").WriteTo(os.Stderr, 2)
@@ -137,7 +143,7 @@ func AddHandler(handler func()) {
// all other callbacks and exits if not already done.
_, loc, line, _ := runtime.Caller(1)
msg := fmt.Sprintf("%s:%d", loc, line)
log.I.Ln("handler added by:", msg)
log.D.Ln("handler added by:", msg)
if ch == nil {
ch = make(chan os.Signal)
signal.Notify(ch, signals...)

View File

@@ -0,0 +1,96 @@
package introducer
import (
"context"
"errors"
"github.com/indra-labs/indra"
log2 "github.com/indra-labs/indra/pkg/log"
dht "github.com/libp2p/go-libp2p-kad-dht"
"github.com/libp2p/go-libp2p/core/host"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/protocol"
"github.com/multiformats/go-multiaddr"
"sync"
)
var (
log = log2.GetLogger(indra.PathBase)
check = log.E.Chk
)
var (
name = "[introducer.bootstrap]"
protocolPrefix protocol.ID = "/indra"
)
var (
wg sync.WaitGroup
m sync.Mutex
c context.Context
h host.Host = nil
kadht *dht.IpfsDHT
bootstrapPeers []peer.AddrInfo
)
func Bootstrap(ctx context.Context, host host.Host, seeds []multiaddr.Multiaddr) (err error) {
log.I.Ln("starting [introducer.bootstrap]")
// Guarding against multiple instantiations
if !m.TryLock() {
return errors.New("[introducer.bootstrap] service is in use.")
}
c = ctx
h = host
log.I.Ln("using seeds:")
var bootstrapPeer *peer.AddrInfo
for _, seed := range seeds {
log.I.Ln("-", seed.String())
if bootstrapPeer, err = peer.AddrInfoFromP2pAddr(seed); check(err) {
return
}
// We can skip ourselves
if bootstrapPeer.ID == host.ID() {
continue
}
bootstrapPeers = append(bootstrapPeers, *bootstrapPeer)
}
var options = []dht.Option{
dht.Mode(dht.ModeServer),
dht.ProtocolPrefix(protocolPrefix),
dht.BootstrapPeers(bootstrapPeers...),
dht.DisableValues(),
dht.DisableProviders(),
//dht.Validator(),
}
if kadht, err = dht.New(ctx, h, options...); check(err) {
return
}
if err = kadht.Bootstrap(ctx); check(err) {
return
}
log.I.Ln("[introducer.bootstrap] is ready")
select {
case <-c.Done():
log.I.Ln("shutting down [introducer.bootstrap]")
return
}
return
}

View File

@@ -1,48 +0,0 @@
package metrics
import (
"context"
"time"
"github.com/indra-labs/indra"
log2 "github.com/indra-labs/indra/pkg/log"
"github.com/libp2p/go-libp2p/core/host"
)
var (
log = log2.GetLogger(indra.PathBase)
check = log.E.Chk
)
var (
hostStatusTimeout = 30 * time.Second
)
func SetTimeout(key string, timeout time.Duration) {
hostStatusTimeout = timeout
}
func HostStatus(ctx context.Context, host host.Host) {
for {
time.Sleep(hostStatusTimeout)
select {
case <-ctx.Done():
log.I.Ln("shutting down metrics.hoststatus")
return
default:
}
log.I.Ln("---- host status ----")
log.I.Ln("-- peers:", len(host.Network().Peers()))
log.I.Ln("-- connections:", len(host.Network().Conns()))
log.I.Ln("---- ---- ------ ----")
}
}

View File

@@ -1,107 +0,0 @@
package seed
import (
"context"
"errors"
"sync"
"time"
"github.com/indra-labs/indra"
log2 "github.com/indra-labs/indra/pkg/log"
"github.com/libp2p/go-libp2p/core/host"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/multiformats/go-multiaddr"
)
var (
log = log2.GetLogger(indra.PathBase)
check = log.E.Chk
)
var (
defaultConnectionAttempts uint = 3
defaultConnectionAttemptInterval = 10 * time.Second
defaultConnectionsMax uint = 32
defaultConnectionsToSatisfy uint = 5
)
var (
wg sync.WaitGroup
m sync.Mutex
c context.Context
h host.Host = nil
failedChan = make(chan error)
)
func connection_attempt(peer *peer.AddrInfo, attempts_left uint) {
if attempts_left == 0 {
wg.Done()
return
}
if err := h.Connect(c, *peer); err != nil {
log.I.Ln("connection attempt failed:", peer.ID)
select {
case <-time.After(defaultConnectionAttemptInterval):
connection_attempt(peer, attempts_left-1)
case <-c.Done():
wg.Done()
}
return
}
log.I.Ln("seed connection established:", peer.String())
wg.Done()
}
func Bootstrap(ctx context.Context, host host.Host, seeds []multiaddr.Multiaddr) (err error) {
log.I.Ln("[seed.bootstrap] starting")
// Guarding against multiple instantiations
if !m.TryLock() {
return errors.New("bootstrapping service is in use.")
}
c = ctx
h = host
log.I.Ln("attempting peering with seeds...")
var peerInfo *peer.AddrInfo
for _, peerAddr := range seeds {
log.I.Ln("-", peerAddr.String())
if peerInfo, err = peer.AddrInfoFromP2pAddr(peerAddr); check(err) {
return
}
// We can skip ourselves
if peerInfo.ID == host.ID() {
continue
}
wg.Add(1)
log.I.Ln("attempting connection", peerInfo.ID)
go connection_attempt(peerInfo, defaultConnectionAttempts)
}
wg.Wait()
log.I.Ln("finished seed bootstrapping")
return
}

View File

@@ -0,0 +1,60 @@
package metrics
import (
"context"
"sync"
"time"
"github.com/indra-labs/indra"
log2 "github.com/indra-labs/indra/pkg/log"
"github.com/libp2p/go-libp2p/core/host"
)
var (
log = log2.GetLogger(indra.PathBase)
check = log.E.Chk
)
var (
hostStatusInterval = 10 * time.Second
)
var (
mutex sync.Mutex
)
func SetInterval(timeout time.Duration) {
hostStatusInterval = timeout
}
func HostStatus(ctx context.Context, host host.Host) {
log.I.Ln("starting [metrics.hoststatus]")
// Guarding against multiple instantiations
if !mutex.TryLock() {
return
}
log.I.Ln("[metrics.hoststatus] is ready")
for {
select {
case <-time.After(hostStatusInterval):
log.I.Ln()
log.I.Ln("---- host status ----")
log.I.Ln("-- peers:", len(host.Network().Peers()))
log.I.Ln("-- connections:", len(host.Network().Conns()))
log.I.Ln("---- ---- ------ ----")
case <-ctx.Done():
log.I.Ln("shutting down [metrics.hoststatus]")
return
}
}
}

View File

@@ -6,12 +6,12 @@ import (
"github.com/indra-labs/indra/pkg/cfg"
"github.com/indra-labs/indra/pkg/interrupt"
log2 "github.com/indra-labs/indra/pkg/log"
"github.com/indra-labs/indra/pkg/p2p/metrics"
"github.com/indra-labs/indra/pkg/p2p/seed"
"github.com/indra-labs/indra/pkg/p2p/introducer"
"github.com/indra-labs/indra/pkg/server/metrics"
"github.com/libp2p/go-libp2p"
dht "github.com/libp2p/go-libp2p-kad-dht"
"github.com/libp2p/go-libp2p/core/host"
"github.com/multiformats/go-multiaddr"
"time"
)
var (
@@ -31,7 +31,6 @@ type Server struct {
params *cfg.Params
host host.Host
dht *dht.IpfsDHT
}
func (srv *Server) Restart() (err error) {
@@ -43,25 +42,21 @@ func (srv *Server) Restart() (err error) {
func (srv *Server) Shutdown() (err error) {
//log.I.Ln("shutting down the dht...")
//
//if srv.dht.Close(); check(err) {
// return
//}
log.I.Ln("shutting down the p2p host...")
log.I.Ln("shutting down [p2p.host]")
if srv.host.Close(); check(err) {
return
}
log.I.Ln("shutdown complete.")
log.I.Ln("shutdown complete")
return nil
}
func (srv *Server) Serve() (err error) {
log.I.Ln("starting the server")
// Here we create a context with cancel and add it to the interrupt handler
var ctx context.Context
var cancel context.CancelFunc
@@ -70,54 +65,23 @@ func (srv *Server) Serve() (err error) {
interrupt.AddHandler(cancel)
// Introduce your node to the network
go introducer.Bootstrap(ctx, srv.host, srv.config.SeedAddresses)
// Get some basic metrics for the host
//metrics.Init()
//metrics.Set('indra.host.status.reporting.interval', 30 * time.Second)
//metrics.Enable('indra.host.status')
metrics.SetInterval(30 * time.Second)
go metrics.HostStatus(ctx, srv.host)
// Run the bootstrapping service on the peer.
if err = seed.Bootstrap(ctx, srv.host, srv.config.SeedAddresses); check(err) {
return
}
//log.I.Ln("bootstrapping the DHT")
// Bootstrap the DHT. In the default configuration, this spawns a Background
// thread that will refresh the peer table every five minutes.
//if err = srv.dht.Bootstrap(srv.Context); check(err) {
// return err
//}
log.I.Ln("successfully connected")
//var pingService *ping.PingService
//
//if pingService = ping.NewPingService(srv.host); check(err) {
// return
//}
//
//go func() {
//
// log.I.Ln("attempting ping")
//
// for {
//
// for _, peer := range srv.host.Peerstore().Peers() {
//
// select {
// case result := <- pingService.Ping(context.Background(), peer):
// log.I.Ln("ping", peer.String(), "-", result.RTT)
// }
// }
//
// time.Sleep(10 * time.Second)
// }
//
//}()
select {
case <-ctx.Done():
log.I.Ln("shutting down server")
srv.Shutdown()
}
@@ -151,13 +115,5 @@ func New(params *cfg.Params, config *Config) (srv *Server, err error) {
config.SeedAddresses = append(config.SeedAddresses, seedAddresses...)
// Start a DHT, for use in peer discovery. We can't just make a new DHT
// client because we want each peer to maintain its own local copy of the
// DHT, so that the bootstrapping node of the DHT can go down without
// inhibiting future peer discovery.
//if s.dht, err = dht.New(s.Context, s.host); check(err) {
// return nil, err
//}
return &s, err
}