From ba8926a6ea6fec862b3bd74a1a713aec74f090d0 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Fri, 12 Feb 2016 10:53:23 +0000 Subject: [PATCH 1/2] Persist set of peers to connect to --- prog/weaver/main.go | 4 ++-- router/http.go | 2 ++ router/network_router.go | 25 +++++++++++++++++++++++-- vendor/github.com/weaveworks/mesh | 2 +- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/prog/weaver/main.go b/prog/weaver/main.go index 627696db..5c77b4eb 100644 --- a/prog/weaver/main.go +++ b/prog/weaver/main.go @@ -166,7 +166,7 @@ func main() { checkFatal(err) defer db.Close() - router := weave.NewNetworkRouter(config, networkConfig, name, nickName, overlay) + router := weave.NewNetworkRouter(config, networkConfig, name, nickName, overlay, db) Log.Println("Our name is", router.Ourself) var dockerCli *docker.Client @@ -215,7 +215,7 @@ func main() { } router.Start() - if errors := router.ConnectionMaker.InitiateConnections(peers, false); len(errors) > 0 { + if errors := router.SetInitialPeers(peers); len(errors) > 0 { Log.Fatal(ErrorMessages(errors)) } diff --git a/router/http.go b/router/http.go index c4057e87..c4f03bfb 100644 --- a/router/http.go +++ b/router/http.go @@ -17,6 +17,7 @@ func (router *NetworkRouter) HandleHTTP(muxRouter *mux.Router) { if errors := router.ConnectionMaker.InitiateConnections(r.Form["peer"], r.FormValue("replace") == "true"); len(errors) > 0 { http.Error(w, common.ErrorMessages(errors), http.StatusBadRequest) } + router.persistPeers() }) muxRouter.Methods("POST").Path("/forget").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -24,6 +25,7 @@ func (router *NetworkRouter) HandleHTTP(muxRouter *mux.Router) { http.Error(w, fmt.Sprint("unable to parse form: ", err), http.StatusBadRequest) } router.ConnectionMaker.ForgetConnections(r.Form["peer"]) + router.persistPeers() }) } diff --git a/router/network_router.go b/router/network_router.go index f936cc04..a95b7968 100644 --- a/router/network_router.go +++ b/router/network_router.go @@ -8,6 +8,7 @@ import ( "github.com/weaveworks/mesh" "github.com/weaveworks/weave/common" + "github.com/weaveworks/weave/db" ) const ( @@ -45,9 +46,10 @@ type NetworkRouter struct { *mesh.Router NetworkConfig Macs *MacCache + db db.DB } -func NewNetworkRouter(config mesh.Config, networkConfig NetworkConfig, name mesh.PeerName, nickName string, overlay NetworkOverlay) *NetworkRouter { +func NewNetworkRouter(config mesh.Config, networkConfig NetworkConfig, name mesh.PeerName, nickName string, overlay NetworkOverlay, db db.DB) *NetworkRouter { if overlay == nil { overlay = NullNetworkOverlay{} } @@ -55,7 +57,7 @@ func NewNetworkRouter(config mesh.Config, networkConfig NetworkConfig, name mesh networkConfig.Bridge = NullBridge{} } - router := &NetworkRouter{Router: mesh.NewRouter(config, name, nickName, overlay), NetworkConfig: networkConfig} + router := &NetworkRouter{Router: mesh.NewRouter(config, name, nickName, overlay), NetworkConfig: networkConfig, db: db} router.Peers.OnInvalidateShortIDs(overlay.InvalidateShortIDs) router.Routes.OnChange(overlay.InvalidateRoutes) router.Macs = NewMacCache(macMaxAge, @@ -204,3 +206,22 @@ func (router *NetworkRouter) relayBroadcast(srcPeer *mesh.Peer, key PacketKey) F return op } + +// Persisting the set of peers we are supposed to connect to +const peersIdent = "directPeers" + +func (router *NetworkRouter) persistPeers() { + if err := router.db.Save(peersIdent, router.ConnectionMaker.Targets()); err != nil { + log.Errorf("Error persisting peers: %s", err) + return + } +} + +func (router *NetworkRouter) SetInitialPeers(peers []string) []error { + // Load is a no-op if persistence entry has never been saved + if err := router.db.Load(peersIdent, &peers); err != nil { + return []error{err} + } + log.Println("Initiating connections to peers:", peers) + return router.ConnectionMaker.InitiateConnections(peers, false) +} diff --git a/vendor/github.com/weaveworks/mesh b/vendor/github.com/weaveworks/mesh index 9af1d5f8..240359e7 160000 --- a/vendor/github.com/weaveworks/mesh +++ b/vendor/github.com/weaveworks/mesh @@ -1 +1 @@ -Subproject commit 9af1d5f8b1dd29cc2c70fb7cbdd7d32b6465c34d +Subproject commit 240359e72610b8bafc7c44a9a01ade0222be4358 From b064bcce498268b63e92261110be48919397e608 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Fri, 19 Feb 2016 11:38:57 +0000 Subject: [PATCH 2/2] Log when command-line peer list overridden by persisted list Reworked interface to router so we split setting up the initial list from beginning to make connections - we shouldn't do that until after router.Start(). --- prog/weaver/main.go | 7 ++++-- router/http.go | 6 ++--- router/network_router.go | 41 ++++++++++++++++++++++++++++----- test/162_persist_ipam_2_test.sh | 13 ++++------- 4 files changed, 46 insertions(+), 21 deletions(-) diff --git a/prog/weaver/main.go b/prog/weaver/main.go index 5c77b4eb..e6a58b19 100644 --- a/prog/weaver/main.go +++ b/prog/weaver/main.go @@ -127,7 +127,6 @@ func main() { } Log.Println("Command line options:", options()) - Log.Println("Command line peers:", peers) if prof != "" { p := *profile.CPUProfile @@ -169,6 +168,10 @@ func main() { router := weave.NewNetworkRouter(config, networkConfig, name, nickName, overlay, db) Log.Println("Our name is", router.Ourself) + if peers, err = router.InitialPeers(peers); err != nil { + Log.Fatal("Unable to get initial peer set: ", err) + } + var dockerCli *docker.Client if dockerAPI != "" { dc, err := docker.NewClient(dockerAPI) @@ -215,7 +218,7 @@ func main() { } router.Start() - if errors := router.SetInitialPeers(peers); len(errors) > 0 { + if errors := router.InitiateConnections(peers, false); len(errors) > 0 { Log.Fatal(ErrorMessages(errors)) } diff --git a/router/http.go b/router/http.go index c4f03bfb..90079ba7 100644 --- a/router/http.go +++ b/router/http.go @@ -14,18 +14,16 @@ func (router *NetworkRouter) HandleHTTP(muxRouter *mux.Router) { if err := r.ParseForm(); err != nil { http.Error(w, fmt.Sprint("unable to parse form: ", err), http.StatusBadRequest) } - if errors := router.ConnectionMaker.InitiateConnections(r.Form["peer"], r.FormValue("replace") == "true"); len(errors) > 0 { + if errors := router.InitiateConnections(r.Form["peer"], r.FormValue("replace") == "true"); len(errors) > 0 { http.Error(w, common.ErrorMessages(errors), http.StatusBadRequest) } - router.persistPeers() }) muxRouter.Methods("POST").Path("/forget").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if err := r.ParseForm(); err != nil { http.Error(w, fmt.Sprint("unable to parse form: ", err), http.StatusBadRequest) } - router.ConnectionMaker.ForgetConnections(r.Form["peer"]) - router.persistPeers() + router.ForgetConnections(r.Form["peer"]) }) } diff --git a/router/network_router.go b/router/network_router.go index a95b7968..029d9029 100644 --- a/router/network_router.go +++ b/router/network_router.go @@ -217,11 +217,40 @@ func (router *NetworkRouter) persistPeers() { } } -func (router *NetworkRouter) SetInitialPeers(peers []string) []error { - // Load is a no-op if persistence entry has never been saved - if err := router.db.Load(peersIdent, &peers); err != nil { - return []error{err} +func (router *NetworkRouter) InitiateConnections(peers []string, replace bool) []error { + errors := router.ConnectionMaker.InitiateConnections(peers, replace) + router.persistPeers() + return errors +} + +func (router *NetworkRouter) ForgetConnections(peers []string) { + router.ConnectionMaker.ForgetConnections(peers) + router.persistPeers() +} + +func (router *NetworkRouter) InitialPeers(peers []string) ([]string, error) { + var storedPeers []string + if err := router.db.Load(peersIdent, &storedPeers); err != nil { + return nil, err } - log.Println("Initiating connections to peers:", peers) - return router.ConnectionMaker.InitiateConnections(peers, false) + + if storedPeers != nil && !equal(peers, storedPeers) { + log.Println("Overriding initial peer list with stored list:", storedPeers) + peers = storedPeers + } else { + log.Println("Initial set of peers:", peers) + } + return peers, nil +} + +func equal(a, b []string) bool { + if len(a) != len(b) { + return false + } + for i, v := range a { + if v != b[i] { + return false + } + } + return true } diff --git a/test/162_persist_ipam_2_test.sh b/test/162_persist_ipam_2_test.sh index e5efac96..c4cf5151 100755 --- a/test/162_persist_ipam_2_test.sh +++ b/test/162_persist_ipam_2_test.sh @@ -14,7 +14,7 @@ launch_router_with_db() { run_on $HOST1 "sudo rm -f /tmp/test162-*" run_on $HOST2 "sudo rm -f /tmp/test162-*" -launch_router_with_db $HOST1 +launch_router_with_db $HOST1 $HOST2 launch_router_with_db $HOST2 $HOST1 start_container $HOST1 --name=c1 @@ -31,13 +31,8 @@ start_container $HOST2 --name=c3 C3=$(container_ip $HOST2 c3) assert_raises "[ $C3 != $C1 ]" -stop_router_on $HOST2 - -# Now start HOST1 with HOST2 down and see if it hangs when we launch a container -launch_router_with_db $HOST1 $HOST2 -start_container $HOST1 --name=c4 -C4=$(container_ip $HOST1 c4) -assert_raises "[ $C4 != $C1 ]" -assert_raises "[ $C4 != $C3 ]" +# Restart HOST1 and see if it remembers to connect to HOST2 +launch_router_with_db $HOST1 +assert_raises "exec_on $HOST2 c2 $PING $C1" end_suite