diff --git a/router/connection_maker.go b/router/connection_maker.go index 2208e841..62df026a 100644 --- a/router/connection_maker.go +++ b/router/connection_maker.go @@ -14,12 +14,14 @@ const ( MaxInterval = 10 * time.Minute ) +type peerAddrs map[string]*net.TCPAddr + type ConnectionMaker struct { ourself *LocalPeer peers *Peers port int targets map[string]*Target - directPeers map[string]*net.TCPAddr + directPeers peerAddrs actionChan chan<- ConnectionMakerAction } @@ -38,7 +40,7 @@ func NewConnectionMaker(ourself *LocalPeer, peers *Peers, port int) *ConnectionM ourself: ourself, peers: peers, port: port, - directPeers: make(map[string]*net.TCPAddr), + directPeers: peerAddrs{}, targets: make(map[string]*Target)} } @@ -48,9 +50,9 @@ func (cm *ConnectionMaker) Start() { go cm.queryLoop(actionChan) } -func (cm *ConnectionMaker) InitiateConnections(peers []string) []error { +func (cm *ConnectionMaker) InitiateConnections(peers []string, replace bool) []error { errors := []error{} - addrs := make(map[string]*net.TCPAddr) + addrs := peerAddrs{} for _, peer := range peers { host, port, err := net.SplitHostPort(peer) if err != nil { @@ -64,6 +66,9 @@ func (cm *ConnectionMaker) InitiateConnections(peers []string) []error { } } cm.actionChan <- func() bool { + if replace { + cm.directPeers = peerAddrs{} + } for peer, addr := range addrs { cm.directPeers[peer] = addr // curtail any existing reconnect interval diff --git a/site/features.md b/site/features.md index 9645d19e..f829c545 100644 --- a/site/features.md +++ b/site/features.md @@ -368,6 +368,11 @@ This will prevent the peer from trying to reconnect to that host once connectivity to it is lost, and thus can be used to administratively remove decommissioned peers from the network. +Hosts can also be bulk-replaced. All existing hosts will be forgotten, +and the new hosts will be added, when one runs + + host# weave connect --replace $NEW_HOST1 $NEW_HOST2 + ### Container mobility Containers can be moved between hosts without requiring any diff --git a/test/150_connect_forget_test.sh b/test/150_connect_forget_test.sh index 384488c4..5f34b597 100755 --- a/test/150_connect_forget_test.sh +++ b/test/150_connect_forget_test.sh @@ -6,17 +6,11 @@ C1=10.2.1.4 C2=10.2.1.7 direct_peers() { - weave_on $1 status | awk "/^Direct Peers:$/{f=1;next} /Reconnects:/{f=0} f" + weave_on $1 status | awk "/^Direct Peers:$/{f=1;next} /Reconnects:/{f=0} f" | sort } -assert_connected() { - assert_raises "direct_peers $HOST2 | grep '^$HOST1$'" - assert_raises "exec_on $HOST1 c1 $PING $C2" -} - -assert_disconnected() { - assert "direct_peers $HOST2" "" - assert_raises "exec_on $HOST1 c1 sh -c '! $PING $C2'" +assert_peers() { + assert "direct_peers $1" "$(echo "$2" | sort)" } start_suite "Connecting and forgetting routers after launch" @@ -27,14 +21,21 @@ weave_on $HOST2 launch start_container $HOST1 $C1/24 --name=c1 start_container $HOST2 $C2/24 --name=c2 -assert_disconnected -assert_raises "weave_on $HOST2 connect $HOST1 $HOST2" -assert_connected +# Connect to some bogus hosts +assert_raises "weave_on $HOST2 connect 10.2.2.1 10.2.2.2" +assert_peers $HOST2 "10.2.2.1\n10.2.2.2" +# Replace bogus hosts with real hosts +assert_raises "exec_on $HOST1 c1 sh -c '! $PING $C2'" +assert_raises "weave_on $HOST2 connect --replace $HOST1 $HOST2" +assert_peers $HOST2 "$HOST1\n$HOST2" +assert_raises "exec_on $HOST1 c1 $PING $C2" + +# Forget everyone and disonnect assert_raises "weave_on $HOST2 forget $HOST1 $HOST2" assert_raises "weave_on $HOST1 stop" assert_raises "weave_on $HOST1 launch" - -assert_disconnected +assert_peers $HOST2 "" +assert_raises "exec_on $HOST1 c1 sh -c '! $PING $C2'" end_suite diff --git a/weave b/weave index 181ab48e..220a20db 100755 --- a/weave +++ b/weave @@ -28,7 +28,7 @@ usage() { echo "weave launch [-password ] [-nickname ] [-iprange ] ..." echo "weave launch-dns " echo "weave launch-proxy [-H ] [--with-dns] [--with-ipam]" - echo "weave connect ..." + echo "weave connect [--replace] [ ...]" echo "weave forget ..." echo "weave run [--with-dns] [ ...] ..." echo "weave start [ ...] " @@ -871,7 +871,11 @@ case "$COMMAND" in ;; connect) [ $# -gt 0 ] || usage - http_call $CONTAINER_NAME $HTTP_PORT POST /connect -d $(peer_args "$@") + if [ "$1" == "--replace" ]; then + replace="-d replace=true" + shift + fi + http_call $CONTAINER_NAME $HTTP_PORT POST /connect $replace -d $(peer_args "$@") ;; forget) [ $# -gt 0 ] || usage diff --git a/weaver/main.go b/weaver/main.go index 0dee4960..8b7f20a2 100644 --- a/weaver/main.go +++ b/weaver/main.go @@ -144,7 +144,7 @@ func main() { } router.Start() - if errors := router.ConnectionMaker.InitiateConnections(peers); len(errors) > 0 { + if errors := router.ConnectionMaker.InitiateConnections(peers, false); len(errors) > 0 { log.Fatal(errorMessages(errors)) } @@ -256,7 +256,7 @@ func handleHTTP(router *weave.Router, httpAddr string, allocator *ipam.Allocator 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"]); len(errors) > 0 { + if errors := router.ConnectionMaker.InitiateConnections(r.Form["peer"], r.FormValue("replace") == "true"); len(errors) > 0 { http.Error(w, errorMessages(errors), http.StatusBadRequest) } })