diff --git a/CHANGELOG.md b/CHANGELOG.md index c20ac9505e..5aee1edb10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,10 +8,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added -- `autoConn` and `isPublic` flag for `skywire-cli` [#1309](https://github.com/skycoin/skywire/pull/1319) -- add error packet to routes to propagate route errors [#1181](https://github.com/skycoin/skywire/issues/1181) -- add `skywire-cli chvpk` to get list of connected hypervisors [#1306](https://github.com/skycoin/skywire/issues/1306) -- add pong packet to send as a response to ping to calculate latency [#1261](https://github.com/skycoin/skywire/issues/1261) +- port of the autopeering system from skybian to the skywire source code. [#1309](https://github.com/skycoin/skywire/pull/1309) +- `-l --hvip` and `-m --autopeer` flags for `skywire-visor` ; connect to a hypervisor by ip address. [#1309](https://github.com/skycoin/skywire/pull/1309) +- `skywire-cli visor pk -w` flag ; http endpoint for visor public key [#1309](https://github.com/skycoin/skywire/pull/1309) +- `-y --autoconn` and `-z --ispublic` flags for `skywire-cli config gen` [#1319](https://github.com/skycoin/skywire/pull/1319) +- error packet to routes to propagate route errors [#1181](https://github.com/skycoin/skywire/issues/1181) +- `skywire-cli chvpk` subcommand to list remote hypervisor(s) a visor is currently connected to [#1306](https://github.com/skycoin/skywire/issues/1306) +- pong packet to send as a response to ping to calculate latency [#1261](https://github.com/skycoin/skywire/issues/1261) ### Changed @@ -27,6 +30,42 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## 1.0.0 +### Added + +- `skywire-cli hv` subcommands for opening the various UIs or printing links to them (HVUI, VPNUI, DMSGPTYUI) [#1270](https://github.com/skycoin/skywire/pull/1270) +- added `add-rhv` and `disable-rhv` flags to `skywire-visor` for adding remote hypervisor PK and disable remote hypervisor PK(s) on config file [#1113](https://github.com/skycoin/skywire/pull/1113) +- shorthand flags for commands [#1151](https://github.com/skycoin/skywire/pull/1151) +- blue & white color scheme with coloredcobra [#1151](https://github.com/skycoin/skywire/pull/1151) +- ascii art text modal of program name to help menus [#1151](https://github.com/skycoin/skywire/pull/1151) +- `--all` flag to skywire-cli & visor to show extra flags [#1151](https://github.com/skycoin/skywire/pull/1151) +- `skywire-cli config gen -n --stdout` write config to stdout [#1151](https://github.com/skycoin/skywire/pull/1151) +- `skywire-cli config gen -w, --hide` dont print the config to the terminal [#1151](https://github.com/skycoin/skywire/pull/1151) +- `skywire-cli config gen --print` parse test ; read config from file & print [#1151](https://github.com/skycoin/skywire/pull/1151) +- `skywire-cli config gen -a, --url` services conf (default "conf.skywire.skycoin.com") [#1151](https://github.com/skycoin/skywire/pull/1151) +- fetch service from endpoint [#1151](https://github.com/skycoin/skywire/pull/1151) +- `skywire-cli visor app` app settings command [#1132](https://github.com/skycoin/skywire/pull/1132) +- `skywire-cli visor route` view and set rules command [#1132](https://github.com/skycoin/skywire/pull/1132) +- `skywire-cli visor tp` view and set transports command [#1132](https://github.com/skycoin/skywire/pull/1132) +- `skywire-cli visor vpn` vpn interface command [#1132](https://github.com/skycoin/skywire/pull/1132) +- root permissions detection +- error on different version config / visor +- display update command on config version error +- support for piping config generated by skywire-cli to skywire-visor via stdin [#1147](https://github.com/skycoin/skywire/pull/1147) +- support for detecting skywire version when `go run` +- `run-vpnsrv` makefile directive [#1147](https://github.com/skycoin/skywire/pull/1147) +- `run-source-test` makefile directive [#1147](https://github.com/skycoin/skywire/pull/1147) +- `run-vpnsrv-test` makefile directive [#1147](https://github.com/skycoin/skywire/pull/1147) +- `run-source-dmsghttp` makefile directive [#1147](https://github.com/skycoin/skywire/pull/1147) +- `run-source-dmsghttp-test` makefile directive [#1147](https://github.com/skycoin/skywire/pull/1147) +- `run-vpnsrv-dmsghttp` makefile directive [#1147](https://github.com/skycoin/skywire/pull/1147) +- `run-vpnsrv -dmsghttp-test` makefile directive [#1147](https://github.com/skycoin/skywire/pull/1147) +- `install-system-linux` and `install-system-linux-systray` makefile directives [#1180](https://github.com/skycoin/skywire/pull/1180) +- `skywire-cli dmsgpty list` to view of connected remote visor to hypervisor [#1250](https://github.com/skycoin/skywire/pull/1250) +- `skywire-cli dmsgpty start ` to connect through dmsgpty to remote visor [#1250](https://github.com/skycoin/skywire/pull/1250) +- `make win-installer-latest` to create installer for latest version of released, not pre-release. +- `trace` log level is added +- `--log-level` flag to generate and update config by `skywire-cli` + ### Changed - remove dsmghttp migration to skywire-visor starting - only support current version of config @@ -40,7 +79,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - remove config path from V1 struct - remove all instance of the visor writing to the config file except via api - remove path to dmsghttp-config.json from config -- revise versioning +- revise versioning - move to skyenv - remove transports cache from visor initialization and check them before make route - `run-source` makefile directive write config to stdout & read config from stdin @@ -48,47 +87,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - `make win-installer` need new argument `CUSTOM_VERSION` to get make installer for this version, use for pre-releases - changed the log levels of most of the logs making info level clutter free -### Added -- added `add-rhv` and `disable-rhv` flags to `skywire-visor` for adding remote hypervisor PK and disable remote hypervisor PK(s) on config file -- shorthand flags for commands -- blue & white color scheme with coloredcobra -- ascii art text modal of program name to help menus -- `--all` flag to skywire-cli & visor to show extra flags -- `skywire-cli config gen -n --stdout` write config to stdout -- `skywire-cli config gen -w, --hide` dont print the config to the terminal -- `skywire-cli config gen --print` parse test ; read config from file & print -- `skywire-cli config gen -a, --url` services conf (default "conf.skywire.skycoin.com") -- fetch service from endpoint -- `skywire-cli visor app` app settings command -- `skywire-cli visor route` view and set rules command -- `skywire-cli visor tp` view and set transports command -- `skywire-cli visor vpn` vpn interface command -- root permissions detection -- error on different version config / visor -- display update command on config version error -- support for piping config generated by skywire-cli to skywire-visor via stdin -- support for detecting skywire version when `go run` -- `run-vpnsrv` makefile directive -- `run-source-test` makefile directive -- `run-vpnsrv-test` makefile directive -- `run-source-dmsghttp` makefile directive -- `run-source-dmsghttp-test` makefile directive -- `run-vpnsrv-dmsghttp` makefile directive -- `run-vpnsrv -dmsghttp-test` makefile directive -- `install-system-linux` and `install-system-linux-systray` makefile directives -- `skywire-cli dmsgpty list` to view of connected remote visor to hypervisor -- `skywire-cli dmsgpty start ` to connect through dmsgpty to remote visor -- `make win-installer-latest` to create installer for latest version of released, not pre-release. -- `trace` log level is added -- `--log-level` flag to generate and update config by `skywire-cli` +### Removed -## 0.6.0 +- inbuilt updater ; instead use packages and the system package manger for installation and updates [#1251](https://github.com/skycoin/skywire/pull/1251) -### Changed +## 0.6.0 -- detecting OS in runtime removed -- skybian flag `-s` removed from `skywire-cli config gen` -- migrate updating logic to debian package model ### Added @@ -110,8 +114,26 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - added `skywire-cli visor vpn-ui` and `skywire-cli visor vpn-url` commands - added dsmghttp migration to skywire-visor starting - added network monitor PKs to skyenv + +### Changed + +- detecting OS in runtime removed +- skybian flag `-s` removed from `skywire-cli config gen` +- migrate updating logic to debian package model + ## 0.5.0 +### Added + +- added persistent_transports field to the config and UI +- added stun_servers field to the config +- added is_public field to root section +- added public_autoconnect field to transport section +- added transport_setup_nodes field to transport section +- added MinHops field to V1Routing section of config +- added `skywire-cli config` subcommand +- added connection_duration field to `/api/visor/{pk}/apps/vpn-client/connections` + ### Changed - config updated to `v1.1.0` @@ -128,18 +150,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - replaced port field to dmsg_port in config - updated visor health status checks, no longer querying multiple external services endpoints. - -### Added - -- added persistent_transports field to the config and UI -- added stun_servers field to the config -- added is_public field to root section -- added public_autoconnect field to transport section -- added transport_setup_nodes field to transport section -- added MinHops field to V1Routing section of config -- added `skywire-cli config` subcommand -- added connection_duration field to `/api/visor/{pk}/apps/vpn-client/connections` - ## 0.2.1 - 2020.04.07 ### Changed diff --git a/Makefile b/Makefile index b230aef6c6..a8a9b32b2a 100644 --- a/Makefile +++ b/Makefile @@ -334,43 +334,43 @@ prepare-systray: prepare ## Run skywire from source, without compiling binaries - requires skywire cloned run-source: prepare - go run ./cmd/skywire-cli/skywire-cli.go config gen -in | go run ./cmd/skywire-visor/skywire-visor.go -nb || true + go run ./cmd/skywire-cli/skywire-cli.go config gen -in | sudo go run ./cmd/skywire-visor/skywire-visor.go -n || true ## Run skywire from source, with vpn server enabled run-systray: prepare-systray - go run -tags systray ./cmd/skywire-cli/skywire-cli.go config gen -ni | go run -tags systray ./cmd/skywire-visor/skywire-visor.go -nb || true + go run -tags systray ./cmd/skywire-cli/skywire-cli.go config gen -ni | sudo go run -tags systray ./cmd/skywire-visor/skywire-visor.go -n || true ## Run skywire from source, without compiling binaries - requires skywire cloned run-vpnsrv: prepare - go run ./cmd/skywire-cli/skywire-cli.go config gen -in --servevpn | go run ./cmd/skywire-visor/skywire-visor.go -nb || true + go run ./cmd/skywire-cli/skywire-cli.go config gen -in --servevpn | sudo go run ./cmd/skywire-visor/skywire-visor.go -n || true ## Run skywire from source with test endpoints run-source-test: prepare - go run ./cmd/skywire-cli/skywire-cli.go config gen -nit | go run ./cmd/skywire-visor/skywire-visor.go -nb || true + go run ./cmd/skywire-cli/skywire-cli.go config gen -nit | sudo go run ./cmd/skywire-visor/skywire-visor.go -n || true ## Run skywire from source, with vpn server enabled run-vpnsrv-test: prepare - go run ./cmd/skywire-cli/skywire-cli.go config gen -nit --servevpn | go run ./cmd/skywire-visor/skywire-visor.go -nb || true + go run ./cmd/skywire-cli/skywire-cli.go config gen -nit --servevpn | sudo go run ./cmd/skywire-visor/skywire-visor.go -n || true ## Run skywire from source, with vpn server enabled run-systray-test: prepare-systray - go run -tags systray ./cmd/skywire-cli/skywire-cli.go config gen -nit | go run -tags systray ./cmd/skywire-visor/skywire-visor.go -nb || true + go run -tags systray ./cmd/skywire-cli/skywire-cli.go config gen -nit | sudo go run -tags systray ./cmd/skywire-visor/skywire-visor.go -nb || true ## Run skywire from source with dmsghttp config run-source-dmsghttp: prepare - go run ./cmd/skywire-cli/skywire-cli.go config gen -din | go run ./cmd/skywire-visor/skywire-visor.go -nb || true + go run ./cmd/skywire-cli/skywire-cli.go config gen -din | sudo go run ./cmd/skywire-visor/skywire-visor.go -nb || true ## Run skywire from source with dmsghttp config and vpn server run-vpnsrv-dmsghttp: prepare - go run ./cmd/skywire-cli/skywire-cli.go config gen -din --servevpn | go run ./cmd/skywire-visor/skywire-visor.go -nb || true + go run ./cmd/skywire-cli/skywire-cli.go config gen -din --servevpn | sudo go run ./cmd/skywire-visor/skywire-visor.go -nb || true ## Run skywire from source with dmsghttp config and test endpoints run-source-dmsghttp-test: prepare - go run ./cmd/skywire-cli/skywire-cli.go config gen -dint | go run ./cmd/skywire-visor/skywire-visor.go -nb || true + go run ./cmd/skywire-cli/skywire-cli.go config gen -dint | sudo go run ./cmd/skywire-visor/skywire-visor.go -nb || true ## Run skywire from source with dmsghttp config, vpn server, and test endpoints run-vpnsrv-dmsghttp-test: prepare - go run ./cmd/skywire-cli/skywire-cli.go config gen -dint --servevpn | go run ./cmd/skywire-visor/skywire-visor.go -nb || true + go run ./cmd/skywire-cli/skywire-cli.go config gen -dint --servevpn | sudo go run ./cmd/skywire-visor/skywire-visor.go -nb || true lint-ui: ## Lint the UI code cd $(MANAGER_UI_DIR) && npm run lint diff --git a/cmd/skywire-cli/commands/hv/hvpk.go b/cmd/skywire-cli/commands/hv/hvpk.go new file mode 100644 index 0000000000..a2bc1477ab --- /dev/null +++ b/cmd/skywire-cli/commands/hv/hvpk.go @@ -0,0 +1,43 @@ +package clihv + +import ( + "fmt" + "net" + "os" + "strings" + + "github.com/spf13/cobra" + + "github.com/skycoin/skywire-utilities/pkg/netutil" + "github.com/skycoin/skywire/pkg/visor" +) + +func init() { + if os.Getenv("SKYBIAN") == "true" { + RootCmd.AddCommand(pkCmd) + } + localIPs, err = netutil.DefaultNetworkInterfaceIPs() + if err != nil { + logger.WithError(err).Fatalln("Could not determine network interface IP address") + } + if len(localIPs) == 0 { + localIPs = append(localIPs, net.ParseIP("192.168.0.1")) + } + var s string + if idx := strings.LastIndex(localIPs[0].String(), "."); idx != -1 { + s = localIPs[0].String()[:idx] + } + pkCmd.Flags().StringVarP(&ipAddr, "ip", "i", s+".2:7998", "ip:port to query") +} + +var pkCmd = &cobra.Command{ + Use: "pk", + Short: "Fetch Hypervisor Public Key", + Run: func(_ *cobra.Command, _ []string) { + s, err := visor.FetchHvPk(ipAddr) + if err != nil { + logger.WithError(err).Fatalln("failed to fetch hypervisor public key") + } + fmt.Printf("%s\n", s) + }, +} diff --git a/cmd/skywire-cli/commands/hv/root.go b/cmd/skywire-cli/commands/hv/root.go index 29c0d19cef..6489688129 100644 --- a/cmd/skywire-cli/commands/hv/root.go +++ b/cmd/skywire-cli/commands/hv/root.go @@ -11,12 +11,15 @@ import ( ) var ( - logger = logging.MustGetLogger("skywire-cli") - rpcAddr string - path string - pk string - url string - pkg bool + logger = logging.MustGetLogger("skywire-cli") + rpcAddr string + path string + pk string + url string + pkg bool + ipAddr string + localIPs []net.IP + err error ) // RootCmd contains commands that interact with the skywire-visor diff --git a/cmd/skywire-cli/commands/visor/info.go b/cmd/skywire-cli/commands/visor/info.go index c4d451dbd1..c2dfc4b3a4 100644 --- a/cmd/skywire-cli/commands/visor/info.go +++ b/cmd/skywire-cli/commands/visor/info.go @@ -3,8 +3,8 @@ package clivisor import ( "fmt" "log" + "net/http" "os" - "unicode/utf8" "github.com/spf13/cobra" @@ -14,16 +14,19 @@ import ( var path string var pkg bool var web bool +var webPort string +var pk string func init() { RootCmd.AddCommand(pkCmd) pkCmd.Flags().StringVarP(&path, "input", "i", "", "path of input config file.") pkCmd.Flags().BoolVarP(&pkg, "pkg", "p", false, "read from /opt/skywire/skywire.json") - pkCmd.Flags().BoolVarP(&web, "http", "w", false, "format as http response") + pkCmd.Flags().BoolVarP(&web, "http", "w", false, "serve public key via http") + pkCmd.Flags().StringVarP(&webPort, "prt", "x", "7998", "serve public key via http") RootCmd.AddCommand(hvpkCmd) hvpkCmd.Flags().StringVarP(&path, "input", "i", "", "path of input config file.") hvpkCmd.Flags().BoolVarP(&pkg, "pkg", "p", false, "read from /opt/skywire/skywire.json") - hvpkCmd.Flags().BoolVarP(&web, "http", "w", false, "format as http response") + hvpkCmd.Flags().BoolVarP(&web, "http", "w", false, "serve public key via http") RootCmd.AddCommand(chvpkCmd) RootCmd.AddCommand(summaryCmd) RootCmd.AddCommand(buildInfoCmd) @@ -48,10 +51,11 @@ var pkCmd = &cobra.Command{ if err != nil { logger.Fatal("Failed to connect:", err) } + pk = overview.PubKey.String() if web { - rc := utf8.RuneCountInString(overview.PubKey.String()) - header := fmt.Sprintf("HTTP/1.0 200 OK\r\nContent-Length: %d\r\n", rc) - fmt.Println(header) + http.HandleFunc("/", srvpk) + logger.Info("\nServing public key " + pk + " on port " + webPort) + http.ListenAndServe(":"+webPort, nil) //nolint } fmt.Println(overview.PubKey) } @@ -124,3 +128,7 @@ var buildInfoCmd = &cobra.Command{ } }, } + +func srvpk(w http.ResponseWriter, _ *http.Request) { + fmt.Fprintf(w, pk) //nolint +} diff --git a/cmd/skywire-visor/commands/root.go b/cmd/skywire-visor/commands/root.go index e1e36bc4c7..f04f46e558 100644 --- a/cmd/skywire-visor/commands/root.go +++ b/cmd/skywire-visor/commands/root.go @@ -8,6 +8,7 @@ import ( "io" "io/fs" "io/ioutil" + "net" "net/http" _ "net/http/pprof" // nolint:gosec // https://golang.org/doc/diagnostics.html#profiling "os" @@ -28,6 +29,7 @@ import ( "github.com/skycoin/skywire-utilities/pkg/cipher" "github.com/skycoin/skywire-utilities/pkg/cmdutil" "github.com/skycoin/skywire-utilities/pkg/logging" + "github.com/skycoin/skywire-utilities/pkg/netutil" "github.com/skycoin/skywire/pkg/restart" "github.com/skycoin/skywire/pkg/skyenv" "github.com/skycoin/skywire/pkg/syslog" @@ -45,6 +47,7 @@ const ( ) var ( + logger = logging.MustGetLogger("skywire-visor") tag string syslogAddr string pprofMode string @@ -55,6 +58,8 @@ var ( hypervisorUI bool remoteHypervisorPKs string disableHypervisorPKs bool + isAutoPeer bool + autoPeerIP string stopVisorFn func() stopVisorWg sync.WaitGroup completion string @@ -62,6 +67,7 @@ var ( all bool pkg bool usr bool + localIPs []net.IP // root indicates process is run with root permissions root bool // nolint:unused // visorBuildInfo holds information about the build @@ -77,6 +83,14 @@ func init() { root = true } + localIPs, err = netutil.DefaultNetworkInterfaceIPs() + if err != nil { + logger.WithError(err).Warn("Could not determine network interface IP address") + if len(localIPs) == 0 { + localIPs = append(localIPs, net.ParseIP("192.168.0.1")) + } + } + rootCmd.Flags().SortFlags = false rootCmd.Flags().StringVarP(&confPath, "config", "c", "", "config file to use (default): "+skyenv.ConfigName) @@ -88,6 +102,12 @@ func init() { hiddenflags = append(hiddenflags, "hv") rootCmd.Flags().BoolVarP(&disableHypervisorPKs, "xhv", "k", false, "disable remote hypervisors set in config file") hiddenflags = append(hiddenflags, "xhv") + if os.Getenv("SKYBIAN") == "true" { + rootCmd.Flags().StringVarP(&autoPeerIP, "hvip", "l", trimStringFromDot(localIPs[0].String())+".2:7998", "set hypervisor by ip") + hiddenflags = append(hiddenflags, "hvip") + rootCmd.Flags().BoolVarP(&isAutoPeer, "autopeer", "m", false, "enable autopeering") + hiddenflags = append(hiddenflags, "autopeer") + } rootCmd.Flags().BoolVarP(&stdin, "stdin", "n", false, "read config from stdin") hiddenflags = append(hiddenflags, "stdin") if root { @@ -118,6 +138,13 @@ func init() { } } +func trimStringFromDot(s string) string { + if idx := strings.LastIndex(s, "."); idx != -1 { + return s[:idx] + } + return s +} + var rootCmd = &cobra.Command{ Use: "skywire-visor", Short: "Skywire Visor", @@ -250,10 +277,10 @@ func runVisor(conf *visorconfig.V1) { conf.Hypervisors = []cipher.PubKey{} } + pubkey := cipher.PubKey{} if remoteHypervisorPKs != "" { hypervisorPKsSlice := strings.Split(remoteHypervisorPKs, ",") for _, pubkeyString := range hypervisorPKsSlice { - pubkey := cipher.PubKey{} if err := pubkey.Set(pubkeyString); err != nil { log.Warnf("Cannot add %s PK as remote hypervisor PK due to: %s", pubkeyString, err) continue @@ -262,9 +289,32 @@ func runVisor(conf *visorconfig.V1) { conf.Hypervisors = append(conf.Hypervisors, pubkey) } } + //autopeering should only happen when there is no local or remote hypervisor set in the config. + if conf.Hypervisors != nil { + if conf.Hypervisor != nil { + isAutoPeer = false + } + } + if isAutoPeer { + hvkey, err := visor.FetchHvPk(autoPeerIP) + if err != nil { + log.WithError(err).Error("Failure autopeering - unable to obtain hypervisor public key") + } else { + hvkey = strings.TrimSpace(hvkey) + hypervisorPKsSlice := strings.Split(hvkey, ",") + for _, pubkeyString := range hypervisorPKsSlice { + if err := pubkey.Set(pubkeyString); err != nil { + log.Warnf("Cannot add %s PK as remote hypervisor PK due to: %s", pubkeyString, err) + continue + } + log.Infof("%s PK added as remote hypervisor PK", pubkeyString) + conf.Hypervisors = append(conf.Hypervisors, pubkey) + } + } + } ctx, cancel := cmdutil.SignalContext(context.Background(), log) - vis, ok := visor.NewVisor(ctx, conf, restartCtx) + vis, ok := visor.NewVisor(ctx, conf, restartCtx, isAutoPeer, autoPeerIP) if !ok { select { case <-ctx.Done(): diff --git a/pkg/visor/init.go b/pkg/visor/init.go index bb88b3d5d2..7f683e56b6 100644 --- a/pkg/visor/init.go +++ b/pkg/visor/init.go @@ -772,9 +772,16 @@ func initHypervisors(ctx context.Context, v *Visor, log *logging.Logger) error { go func(hvErrs chan error) { defer wg.Done() + var autoPeerIP string + if v.autoPeer { + autoPeerIP = v.autoPeerIP + } else { + autoPeerIP = "" + } defer delete(v.connectedHypervisors, hvPK) v.connectedHypervisors[hvPK] = true - ServeRPCClient(ctx, log, v.dmsgC, rpcS, addr, hvErrs) + ServeRPCClient(ctx, log, autoPeerIP, v.dmsgC, rpcS, addr, hvErrs) + }(hvErrs) v.pushCloseStack("hypervisor."+hvPK.String()[:shortHashLen], func() error { diff --git a/pkg/visor/remote_hypervisor.go b/pkg/visor/remote_hypervisor.go new file mode 100644 index 0000000000..8d161b4434 --- /dev/null +++ b/pkg/visor/remote_hypervisor.go @@ -0,0 +1,24 @@ +package visor + +import ( + "io/ioutil" + "net/http" +) + +// FetchHvPk fetches the hypervisor public key from the ip:port passed to it. +func FetchHvPk(ipPort string) (string, error) { + req, err := http.NewRequest(http.MethodGet, "http://"+ipPort, nil) + if err != nil { + return "", err + } + res, err := http.DefaultClient.Do(req) + if err != nil { + return "", err + } + defer res.Body.Close() //nolint:errcheck + resBody, err := ioutil.ReadAll(res.Body) + if err != nil { + return "", err + } + return string(resBody), nil +} diff --git a/pkg/visor/rpc_client_serve.go b/pkg/visor/rpc_client_serve.go index 9c99afd4af..44a56fbcab 100644 --- a/pkg/visor/rpc_client_serve.go +++ b/pkg/visor/rpc_client_serve.go @@ -4,11 +4,13 @@ import ( "context" "net" "net/rpc" + "strings" "time" "github.com/sirupsen/logrus" "github.com/skycoin/dmsg/pkg/dmsg" + "github.com/skycoin/skywire-utilities/pkg/cipher" "github.com/skycoin/skywire-utilities/pkg/netutil" ) @@ -22,15 +24,32 @@ func isDone(ctx context.Context) bool { } // ServeRPCClient repetitively dials to a remote dmsg address and serves a RPC server to that address. -func ServeRPCClient(ctx context.Context, log logrus.FieldLogger, dmsgC *dmsg.Client, rpcS *rpc.Server, rAddr dmsg.Addr, errCh chan<- error) { +func ServeRPCClient(ctx context.Context, log logrus.FieldLogger, autoPeerIP string, dmsgC *dmsg.Client, rpcS *rpc.Server, rAddr dmsg.Addr, errCh chan<- error) { const maxBackoff = time.Second * 5 retry := netutil.NewRetrier(log, netutil.DefaultInitBackoff, maxBackoff, netutil.DefaultTries, netutil.DefaultFactor) - + pubkey := cipher.PubKey{} for { var conn net.Conn err := retry.Do(ctx, func() (rErr error) { log.Info("Dialing...") addr := dmsg.Addr{PK: rAddr.PK, Port: rAddr.Port} + if autoPeerIP != "" { + hvkey, err := FetchHvPk(autoPeerIP) + if err != nil { + log.Error("error autopeering") + } else { + hvkey = strings.TrimSuffix(hvkey, "\n") + hypervisorPKsSlice := strings.Split(hvkey, ",") + for _, pubkeyString := range hypervisorPKsSlice { + //use pubkey.Set as validation or to convert the string to a pubkey + if err := pubkey.Set(pubkeyString); err != nil { + log.Warnf("Cannot add %s PK as remote hypervisor PK due to: %s", pubkeyString, err) + continue + } + addr.PK = pubkey + } + } + } conn, rErr = dmsgC.Dial(ctx, addr) return rErr }) diff --git a/pkg/visor/visor.go b/pkg/visor/visor.go index a9d48b292c..ef77220ef8 100644 --- a/pkg/visor/visor.go +++ b/pkg/visor/visor.go @@ -88,10 +88,11 @@ type Visor struct { // produced by concurrent parts of modules runtimeErrors chan error - isServicesHealthy *internalHealthInfo - - remoteVisors map[cipher.PubKey]Conn // copy of connected remote visors to hypervisor - connectedHypervisors map[cipher.PubKey]bool + isServicesHealthy *internalHealthInfo + autoPeer bool // autoPeer=true tells the visor to query the http endpoint of the hypervisor on the local network for the hypervisor's public key when connectio to the hypervisor is lost + autoPeerIP string // autoPeerCmd is the command string used to return the public key of the hypervisor + remoteVisors map[cipher.PubKey]Conn // remote hypervisors the visor is attempting to connect to + connectedHypervisors map[cipher.PubKey]bool // remote hypervisors the visor is currently connected to } // todo: consider moving module closing to the module system @@ -115,7 +116,7 @@ func (v *Visor) MasterLogger() *logging.MasterLogger { } // NewVisor constructs new Visor. -func NewVisor(ctx context.Context, conf *visorconfig.V1, restartCtx *restart.Context) (*Visor, bool) { +func NewVisor(ctx context.Context, conf *visorconfig.V1, restartCtx *restart.Context, autoPeer bool, autoPeerIP string) (*Visor, bool) { v := &Visor{ log: conf.MasterLogger().PackageLogger("visor"), @@ -179,6 +180,10 @@ func NewVisor(ctx context.Context, conf *visorconfig.V1, restartCtx *restart.Con if !v.processRuntimeErrs() { return nil, false } + if autoPeer { + v.autoPeer = true + v.autoPeerIP = autoPeerIP + } log.Info("Startup complete.") return v, true }