func mustPeerName() mesh.PeerName { peerName, err := mesh.PeerNameFromString(mustHardwareAddr()) if err != nil { panic(err) } return peerName }
func ExpectMessage(alloc *Allocator, dst string, msgType byte, buf []byte) { m := alloc.gossip.(*mockGossipComms) dstPeerName, _ := mesh.PeerNameFromString(dst) m.Lock() m.messages = append(m.messages, mockMessage{dstPeerName, msgType, buf}) m.Unlock() }
func initMesh(addr, hwaddr, nickname, pw string) *mesh.Router { host, portStr, err := net.SplitHostPort(addr) if err != nil { log.Fatalf("mesh address: %s: %v", addr, err) } port, err := strconv.Atoi(portStr) if err != nil { log.Fatalf("mesh address: %s: %v", addr, err) } name, err := mesh.PeerNameFromString(hwaddr) if err != nil { log.Fatalf("invalid hardware address %q: %v", hwaddr, err) } password := []byte(pw) if len(password) == 0 { // Emtpy password is used to disable secure communication. Using a nil // password disables encryption in mesh. password = nil } return mesh.NewRouter(mesh.Config{ Host: host, Port: port, ProtocolMinVersion: mesh.ProtocolMinVersion, Password: password, ConnLimit: 64, PeerDiscovery: true, TrustedSubnets: []*net.IPNet{}, }, name, nickname, mesh.NullOverlay{}, stdlog.New(ioutil.Discard, "", 0)) }
func TestTombstoneDeletion(t *testing.T) { oldNow := now defer func() { now = oldNow }() now = func() int64 { return 1234 } peername, err := mesh.PeerNameFromString("00:00:00:02:00:00") require.Nil(t, err) nameserver := makeNameserver(peername) nameserver.AddEntry("hostname", "containerid", peername, address.Address(0)) require.Equal(t, []address.Address{0}, nameserver.Lookup("hostname")) nameserver.deleteTombstones() require.Equal(t, []address.Address{0}, nameserver.Lookup("hostname")) nameserver.Delete("hostname", "containerid", "", address.Address(0)) require.Equal(t, []address.Address{}, nameserver.Lookup("hostname")) require.Equal(t, l(Entries{Entry{ ContainerID: "containerid", Origin: peername, Addr: address.Address(0), Hostname: "hostname", Version: 1, Tombstone: 1234, }}), nameserver.entries) now = func() int64 { return 1234 + int64(tombstoneTimeout/time.Second) + 1 } nameserver.deleteTombstones() require.Equal(t, Entries{}, nameserver.entries) }
func initMesh(addr, hwaddr, nickname string) *mesh.Router { host, portStr, err := net.SplitHostPort(addr) if err != nil { log.Fatalf("mesh address: %s: %v", addr, err) } port, err := strconv.Atoi(portStr) if err != nil { log.Fatalf("mesh address: %s: %v", addr, err) } name, err := mesh.PeerNameFromString(hwaddr) if err != nil { log.Fatalf("invalid hardware address %q: %v", hwaddr, err) } return mesh.NewRouter(mesh.Config{ Host: host, Port: port, ProtocolMinVersion: mesh.ProtocolMinVersion, Password: []byte(""), ConnLimit: 64, PeerDiscovery: true, TrustedSubnets: []*net.IPNet{}, }, name, nickname, mesh.NullOverlay{}, stdlog.New(ioutil.Discard, "", 0)) }
func makePeerName(i int) mesh.PeerName { if i >= 10000 { panic("makePeerName: invalid value") } peer, _ := mesh.PeerNameFromString(fmt.Sprintf("%02d:%02d:00:00:00:ff", i/100, i%100)) return peer }
// Lookup a PeerName by nickname or stringified PeerName. We can't // call into the router for this because we are interested in peers // that have gone away but are still in the ring, which is why we // maintain our own nicknames map. func (alloc *Allocator) lookupPeername(name string) (mesh.PeerName, error) { for peername, nickname := range alloc.nicknames { if nickname == name { return peername, nil } } return mesh.PeerNameFromString(name) }
func startServer(t *testing.T, upstream *dns.ClientConfig) (*DNSServer, *Nameserver, int, int) { peername, err := mesh.PeerNameFromString("00:00:00:02:00:00") require.Nil(t, err) nameserver := New(peername, "", func(mesh.PeerName) bool { return true }) dnsserver, err := NewDNSServer(nameserver, "weave.local.", "0.0.0.0:0", &mockUpstream{upstream}, 30, 5*time.Second) require.Nil(t, err) udpPort := dnsserver.servers[0].PacketConn.LocalAddr().(*net.UDPAddr).Port tcpPort := dnsserver.servers[1].Listener.Addr().(*net.TCPAddr).Port go dnsserver.ActivateAndServe() return dnsserver, nameserver, udpPort, tcpPort }
func makeNetwork(size int) ([]*Nameserver, *gossip.TestRouter) { gossipRouter := gossip.NewTestRouter(0.0) nameservers := make([]*Nameserver, size) for i := 0; i < size; i++ { name, _ := mesh.PeerNameFromString(fmt.Sprintf("%02d:00:00:02:00:00", i)) nameserver := makeNameserver(name) nameserver.SetGossip(gossipRouter.Connect(nameserver.ourName, nameserver)) nameserver.Start() nameservers[i] = nameserver } return nameservers, gossipRouter }
func makeAllocator(name string, cidrStr string, quorum uint) (*Allocator, address.Range) { peername, err := mesh.PeerNameFromString(name) if err != nil { panic(err) } _, cidr, err := address.ParseCIDR(cidrStr) if err != nil { panic(err) } alloc := NewAllocator(peername, mesh.PeerUID(rand.Int63()), "nick-"+name, cidr.Range(), quorum, func(mesh.PeerName) bool { return true }) return alloc, cidr.HostRange() }
func TestContainerAndPeerDeath(t *testing.T) { peername, err := mesh.PeerNameFromString("00:00:00:02:00:00") require.Nil(t, err) nameserver := makeNameserver(peername) nameserver.AddEntry("hostname", "containerid", peername, address.Address(0)) require.Equal(t, []address.Address{0}, nameserver.Lookup("hostname")) nameserver.ContainerDied("containerid") require.Equal(t, []address.Address{}, nameserver.Lookup("hostname")) nameserver.AddEntry("hostname", "containerid", peername, address.Address(0)) require.Equal(t, []address.Address{0}, nameserver.Lookup("hostname")) nameserver.PeerGone(peername) require.Equal(t, []address.Address{}, nameserver.Lookup("hostname")) }
func TestCtrlTerminates(t *testing.T) { var ( peerName, _ = mesh.PeerNameFromString("01:23:45:67:89:01") self = meshconn.MeshAddr{PeerName: peerName, PeerUID: 123} others = []net.Addr{} minPeerCount = 5 incomingc = make(chan raftpb.Message) outgoingc = make(chan raftpb.Message, 10000) unreachablec = make(chan uint64) confchangec = make(chan raftpb.ConfChange) snapshotc = make(chan raftpb.Snapshot, 10000) entryc = make(chan raftpb.Entry) proposalc = make(chan []byte) removedc = make(chan struct{}) logger = log.New(os.Stderr, "", log.LstdFlags) ) c := newCtrl( self, others, minPeerCount, incomingc, outgoingc, unreachablec, confchangec, snapshotc, entryc, proposalc, removedc, logger, ) stopped := make(chan struct{}) go func() { c.stop() close(stopped) }() select { case <-stopped: t.Log("ctrl terminated") case <-time.After(5 * time.Second): t.Fatal("ctrl didn't terminate") } }
func checkSuccess(t *testing.T, nameStr string, expected uint64) { actual, err := mesh.PeerNameFromString(nameStr) require.NoError(t, err) require.Equal(t, mesh.PeerName(expected), actual) }
func main() { peers := &stringset{} var ( httpListen = flag.String("http", ":8080", "HTTP listen address") meshListen = flag.String("mesh", net.JoinHostPort("0.0.0.0", strconv.Itoa(mesh.Port)), "mesh listen address") hwaddr = flag.String("hwaddr", mustHardwareAddr(), "MAC address, i.e. mesh peer ID") nickname = flag.String("nickname", mustHostname(), "peer nickname") password = flag.String("password", "", "password (optional)") channel = flag.String("channel", "default", "gossip channel name") ) flag.Var(peers, "peer", "initial peer (may be repeated)") flag.Parse() logger := log.New(os.Stderr, *nickname+"> ", log.LstdFlags) host, portStr, err := net.SplitHostPort(*meshListen) if err != nil { logger.Fatalf("mesh address: %s: %v", *meshListen, err) } port, err := strconv.Atoi(portStr) if err != nil { logger.Fatalf("mesh address: %s: %v", *meshListen, err) } name, err := mesh.PeerNameFromString(*hwaddr) if err != nil { logger.Fatalf("%s: %v", *hwaddr, err) } router := mesh.NewRouter(mesh.Config{ Host: host, Port: port, ProtocolMinVersion: mesh.ProtocolMinVersion, Password: []byte(*password), ConnLimit: 64, PeerDiscovery: true, TrustedSubnets: []*net.IPNet{}, }, name, *nickname, mesh.NullOverlay{}, log.New(ioutil.Discard, "", 0)) peer := newPeer(name, logger) gossip := router.NewGossip(*channel, peer) peer.register(gossip) func() { logger.Printf("mesh router starting (%s)", *meshListen) router.Start() }() defer func() { logger.Printf("mesh router stopping") router.Stop() }() router.ConnectionMaker.InitiateConnections(peers.slice(), true) errs := make(chan error) go func() { c := make(chan os.Signal) signal.Notify(c, syscall.SIGINT) errs <- fmt.Errorf("%s", <-c) }() go func() { logger.Printf("HTTP server starting (%s)", *httpListen) http.HandleFunc("/", handle(peer)) errs <- http.ListenAndServe(*httpListen, nil) }() logger.Print(<-errs) }
func main() { peers := &stringset{} var ( apiListen = flag.String("api", ":8080", "API listen address") meshListen = flag.String("mesh", net.JoinHostPort("0.0.0.0", strconv.Itoa(mesh.Port)), "mesh listen address") hwaddr = flag.String("hwaddr", mustHardwareAddr(), "MAC address, i.e. mesh peer name") nickname = flag.String("nickname", mustHostname(), "peer nickname") password = flag.String("password", "", "password (optional)") channel = flag.String("channel", "default", "gossip channel name") quicktest = flag.Int("quicktest", 0, "set to integer 1-9 to enable quick test setup of node") n = flag.Int("n", 3, "number of peers expected (lower bound)") ) flag.Var(peers, "peer", "initial peer (may be repeated)") flag.Parse() if *quicktest >= 1 && *quicktest <= 9 { *hwaddr = fmt.Sprintf("00:00:00:00:00:0%d", *quicktest) *meshListen = fmt.Sprintf("0.0.0.0:600%d", *quicktest) *apiListen = fmt.Sprintf("0.0.0.0:800%d", *quicktest) *nickname = fmt.Sprintf("%d", *quicktest) for i := 1; i <= 9; i++ { peers.Set(fmt.Sprintf("127.0.0.1:600%d", i)) } } logger := log.New(os.Stderr, *nickname+"> ", log.LstdFlags) host, portStr, err := net.SplitHostPort(*meshListen) if err != nil { logger.Fatalf("mesh address: %s: %v", *meshListen, err) } port, err := strconv.Atoi(portStr) if err != nil { logger.Fatalf("mesh address: %s: %v", *meshListen, err) } name, err := mesh.PeerNameFromString(*hwaddr) if err != nil { logger.Fatalf("%s: %v", *hwaddr, err) } ln, err := net.Listen("tcp", *apiListen) if err != nil { logger.Fatal(err) } logger.Printf("hello!") defer logger.Printf("goodbye!") // Create, but do not start, a router. meshLogger := log.New(ioutil.Discard, "", 0) // no log from mesh please router := mesh.NewRouter(mesh.Config{ Host: host, Port: port, ProtocolMinVersion: mesh.ProtocolMinVersion, Password: []byte(*password), ConnLimit: 64, PeerDiscovery: true, TrustedSubnets: []*net.IPNet{}, }, name, *nickname, mesh.NullOverlay{}, meshLogger) // Create a meshconn.Peer. peer := meshconn.NewPeer(name, router.Ourself.UID, logger) gossip := router.NewGossip(*channel, peer) peer.Register(gossip) // Start the router and join the mesh. func() { logger.Printf("mesh router starting (%s)", *meshListen) router.Start() }() defer func() { logger.Printf("mesh router stopping") router.Stop() }() router.ConnectionMaker.InitiateConnections(peers.slice(), true) terminatec := make(chan struct{}) terminatedc := make(chan error) go func() { c := make(chan os.Signal) signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) sig := <-c // receive interrupt close(terminatec) // terminate metcd.Server <-terminatedc // wait for shutdown terminatedc <- fmt.Errorf("%s", sig) // forward signal }() go func() { metcdServer := metcd.NewServer(router, peer, *n, terminatec, terminatedc, logger) grpcServer := metcd.GRPCServer(metcdServer) defer grpcServer.Stop() logger.Printf("gRPC listening at %s", *apiListen) terminatedc <- grpcServer.Serve(ln) }() logger.Print(<-terminatedc) time.Sleep(time.Second) // TODO(pb): there must be a better way }
func TestFuzzRing(t *testing.T) { var ( numPeers = 25 iterations = 1000 ) peers := make([]mesh.PeerName, numPeers) for i := 0; i < numPeers; i++ { peer, _ := mesh.PeerNameFromString(fmt.Sprintf("%02d:00:00:00:02:00", i)) peers[i] = peer } // Make a valid, random ring makeGoodRandomRing := func() *Ring { addressSpace := end - start numTokens := rand.Intn(int(addressSpace)) tokenMap := make(map[address.Address]bool) for i := 0; i < numTokens; i++ { tokenMap[address.Address(rand.Intn(int(addressSpace)))] = true } var tokens []address.Address for token := range tokenMap { tokens = append(tokens, token) } sort.Sort(addressSlice(tokens)) peer := peers[rand.Intn(len(peers))] ring := New(start, end, peer) for _, token := range tokens { peer = peers[rand.Intn(len(peers))] ring.Entries = append(ring.Entries, &entry{Token: start + token, Peer: peer}) } ring.assertInvariants() return ring } for i := 0; i < iterations; i++ { // make 2 random rings ring1 := makeGoodRandomRing() ring2 := makeGoodRandomRing() // Merge them - this might fail, we don't care // We just want to make sure it doesn't panic ring1.Merge(*ring2) // Check whats left still passes assertions ring1.assertInvariants() ring2.assertInvariants() } // Make an invalid, random ring makeBadRandomRing := func() *Ring { addressSpace := end - start numTokens := rand.Intn(int(addressSpace)) tokens := make([]address.Address, numTokens) for i := 0; i < numTokens; i++ { tokens[i] = address.Address(rand.Intn(int(addressSpace))) } peer := peers[rand.Intn(len(peers))] ring := New(start, end, peer) for _, token := range tokens { peer = peers[rand.Intn(len(peers))] ring.Entries = append(ring.Entries, &entry{Token: start + token, Peer: peer}) } return ring } for i := 0; i < iterations; i++ { // make 2 random rings ring1 := makeGoodRandomRing() ring2 := makeBadRandomRing() // Merge them - this might fail, we don't care // We just want to make sure it doesn't panic ring1.Merge(*ring2) // Check whats left still passes assertions ring1.assertInvariants() } }
func checkFailure(t *testing.T, nameStr string) { _, err := mesh.PeerNameFromString(nameStr) require.Error(t, err) }
import ( "bytes" "fmt" "math/rand" "sort" "testing" "github.com/stretchr/testify/require" "github.com/weaveworks/mesh" "github.com/weaveworks/weave/common" "github.com/weaveworks/weave/net/address" ) var ( peer1name, _ = mesh.PeerNameFromString("01:00:00:00:02:00") peer2name, _ = mesh.PeerNameFromString("02:00:00:00:02:00") peer3name, _ = mesh.PeerNameFromString("03:00:00:00:02:00") start, end = ParseIP("10.0.0.0"), ParseIP("10.0.0.255") dot10, dot245 = ParseIP("10.0.0.10"), ParseIP("10.0.0.245") dot250 = ParseIP("10.0.0.250") middle = ParseIP("10.0.0.128") ) func ParseIP(s string) address.Address { addr, _ := address.ParseIP(s) return addr } func TestInvariants(t *testing.T) {
func TestFuzzRingHard(t *testing.T) { //common.SetLogLevel("debug") var ( numPeers = 100 iterations = 3000 peers []mesh.PeerName rings []*Ring nextPeerID = 0 ) addPeer := func() { peer, _ := mesh.PeerNameFromString(fmt.Sprintf("%02d:%02d:00:00:00:00", nextPeerID/10, nextPeerID%10)) common.Log.Debugf("%s: Adding peer", peer) nextPeerID++ peers = append(peers, peer) rings = append(rings, New(start, end, peer)) } for i := 0; i < numPeers; i++ { addPeer() } rings[0].ClaimItAll() randomPeer := func(exclude int) (int, mesh.PeerName, *Ring) { var peerIndex int if exclude >= 0 { peerIndex = rand.Intn(len(peers) - 1) if peerIndex == exclude { peerIndex++ } } else { peerIndex = rand.Intn(len(peers)) } return peerIndex, peers[peerIndex], rings[peerIndex] } // Keep a map of index -> ranges, as these are a little expensive to // calculate for every ring on every iteration. var theRanges = make(map[int][]address.Range) theRanges[0] = rings[0].OwnedRanges() addOrRmPeer := func() { if len(peers) < numPeers { addPeer() return } // Pick one peer to remove, and a different one to transfer to peerIndex, peername, _ := randomPeer(-1) _, otherPeername, otherRing := randomPeer(peerIndex) // We need to be in a ~converged ring to rmpeer for _, ring := range rings { require.NoError(t, otherRing.Merge(*ring)) } common.Log.Debugf("%s: transferring from peer %s", otherPeername, peername) otherRing.Transfer(peername, otherPeername) // Remove peer from our state peers = append(peers[:peerIndex], peers[peerIndex+1:]...) rings = append(rings[:peerIndex], rings[peerIndex+1:]...) theRanges = make(map[int][]address.Range) // And now tell everyone about the transfer - rmpeer is // not partition safe for i, ring := range rings { require.NoError(t, ring.Merge(*otherRing)) theRanges[i] = ring.OwnedRanges() } } doGrantOrGossip := func() { var ringsWithRanges = make([]int, 0, len(rings)) for index, ranges := range theRanges { if len(ranges) > 0 { ringsWithRanges = append(ringsWithRanges, index) } } if len(ringsWithRanges) > 0 { // Produce a random split in a random owned range, given to a random peer indexWithRanges := ringsWithRanges[rand.Intn(len(ringsWithRanges))] ownedRanges := theRanges[indexWithRanges] ring := rings[indexWithRanges] rangeToSplit := ownedRanges[rand.Intn(len(ownedRanges))] size := address.Subtract(rangeToSplit.End, rangeToSplit.Start) ipInRange := address.Add(rangeToSplit.Start, address.Offset(rand.Intn(int(size)))) _, peerToGiveTo, _ := randomPeer(-1) common.Log.Debugf("%s: Granting [%v, %v) to %s", ring.Peer, ipInRange, rangeToSplit.End, peerToGiveTo) ring.GrantRangeToHost(ipInRange, rangeToSplit.End, peerToGiveTo) // Now 'gossip' this to a random host (note, note could be same host as above) otherIndex, _, otherRing := randomPeer(-1) common.Log.Debugf("%s: 'Gossiping' to %s", ring.Peer, otherRing.Peer) require.NoError(t, otherRing.Merge(*ring)) theRanges[indexWithRanges] = ring.OwnedRanges() theRanges[otherIndex] = otherRing.OwnedRanges() return } // No rings think they own anything (as gossip might be behind) // We're going to pick a random host (which has entries) and gossip // it to a random host (which may or may not have entries). var ringsWithEntries = make([]*Ring, 0, len(rings)) for _, ring := range rings { if len(ring.Entries) > 0 { ringsWithEntries = append(ringsWithEntries, ring) } } ring1 := ringsWithEntries[rand.Intn(len(ringsWithEntries))] ring2index, _, ring2 := randomPeer(-1) common.Log.Debugf("%s: 'Gossiping' to %s", ring1.Peer, ring2.Peer) require.NoError(t, ring2.Merge(*ring1)) theRanges[ring2index] = ring2.OwnedRanges() } for i := 0; i < iterations; i++ { // about 1 in 10 times, rmpeer or add host n := rand.Intn(10) switch { case n < 1: addOrRmPeer() default: doGrantOrGossip() } } }