Peer Discovery via a web service

This commit is contained in:
Bryan Boreham committed 2017-04-10 14:09:06 +00:00
1 parent 09977a2e04
commit e2d644b86b
3 files changed
+110 -2

No files matched your search

+22
View File
@@ -82,3 +82,25 @@ func findInterface(ifaceName string) (iface *net.Interface, err error) {
}
return
}
func LocalAddresses() ([]*net.IPNet, error) {
links, err := netlink.LinkList()
if err != nil {
return nil, err
}
retval := []*net.IPNet{}
for _, link := range links {
if _, isBridge := link.(*netlink.Bridge); isBridge || (link.Attrs().Flags&net.FlagLoopback) != 0 {
continue
}
addrs, err := netlink.AddrList(link, netlink.FAMILY_V4)
if err != nil {
return nil, err
}
for _, addr := range addrs {
retval = append(retval, addr.IPNet)
}
}
return retval, nil
}
+66
View File
@@ -0,0 +1,66 @@
package main
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"time"
)
// TODO: move these definitions somewhere more shareable
type PeerUpdateRequest struct {
Name string `json:"peername"`
Nickname string `json:"nickname"` // optional
Addresses []string `json:"addresses"` // can be empty
}
type PeerUpdateResponse struct {
Addresses []string `json:"addresses"`
}
var httpClient = &http.Client{Timeout: 30 * time.Second}
func do(verb string, discoveryEndpoint, token string, request interface{}, response interface{}) error {
body := new(bytes.Buffer)
err := json.NewEncoder(body).Encode(request)
if err != nil {
return err
}
req, err := http.NewRequest(verb, discoveryEndpoint+"/peer", body)
if err != nil {
return err
}
req.Header.Set("Authorization", fmt.Sprintf("Scope-Probe token=%s", token))
req.Header.Set("X-Weave-Net-Version", version)
req.Header.Set("Content-Type", "application/json")
Log.Printf("Calling peer discovery %s with %s", req.URL, request)
resp, err := httpClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
rbody, _ := ioutil.ReadAll(resp.Body)
return errors.New(resp.Status + ": " + string(rbody))
}
if response == nil {
return nil
}
err = json.NewDecoder(resp.Body).Decode(response)
Log.Printf("peer discovery result: (%s) %v", err, response)
return err
}
func peerDiscoveryUpdate(discoveryEndpoint, token, peername, nickname string, addresses []string) ([]string, error) {
request := PeerUpdateRequest{
Name: peername,
Nickname: nickname,
Addresses: addresses,
}
var updateResponse PeerUpdateResponse
err := do("POST", discoveryEndpoint, token, request, &updateResponse)
return updateResponse.Addresses, err
}
+22 -2
View File
@@ -143,6 +143,9 @@ func main() {
trustedSubnetStr string
dbPrefix string
isAWSVPC bool
discoveryEndpoint string
token string
advertiseAddress string
defaultDockerHost = "unix:///var/run/docker.sock"
)
@@ -184,6 +187,9 @@ func main() {
mflag.StringVar(&trustedSubnetStr, []string{"-trusted-subnets"}, "", "comma-separated list of trusted subnets in CIDR notation")
mflag.StringVar(&dbPrefix, []string{"-db-prefix"}, "/weavedb/weave", "pathname/prefix of filename to store data")
mflag.BoolVar(&isAWSVPC, []string{"-awsvpc"}, false, "use AWS VPC for routing")
mflag.StringVar(&discoveryEndpoint, []string{"-peer-discovery-url"}, "https://cloud.weave.works/api/weavenet", "url for peer discovery")
mflag.StringVar(&token, []string{"-token"}, "", "token for peer discovery")
mflag.StringVar(&advertiseAddress, []string{"-advertise-address"}, "", "address to advertise for peer discovery")
// crude way of detecting that we probably have been started in a
// container, with `weave launch` --> suppress misleading paths in
@@ -257,7 +263,21 @@ func main() {
router := weave.NewNetworkRouter(config, networkConfig, name, nickName, overlay, db)
Log.Println("Our name is", router.Ourself)
if peers, err = router.InitialPeers(resume, peers); err != nil {
if token != "" {
var addresses []string
if advertiseAddress == "" {
localAddrs, err := weavenet.LocalAddresses()
checkFatal(err)
for _, addr := range localAddrs {
addresses = append(addresses, addr.IP.String())
}
} else {
addresses = strings.Split(advertiseAddress, ",")
}
discoveredPeers, err := peerDiscoveryUpdate(discoveryEndpoint, token, name.String(), nickName, addresses)
checkFatal(err) // TODO: what if it is a transient error, and we are restarting?
peers = append(peers, discoveredPeers...)
} else if peers, err = router.InitialPeers(resume, peers); err != nil {
Log.Fatal("Unable to get initial peer set: ", err)
}
@@ -376,7 +396,7 @@ func options() map[string]string {
mflag.Visit(func(f *mflag.Flag) {
value := f.Value.String()
name := canonicalName(f)
if name == "password" {
if name == "password" || name == "token" {
value = "<redacted>"
}
options[name] = value