Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab5f4410b6 | ||
|
|
3abb657777 | ||
|
|
4dd63d8f72 | ||
|
|
79dc464b83 | ||
|
|
3dbd5b11d8 | ||
|
|
0ab5c65185 | ||
|
|
e57ccdc858 | ||
|
|
a73a65b48a | ||
|
|
7c4af88911 | ||
|
|
0aca173e96 | ||
|
|
e95e3cc29d | ||
|
|
67e9310cc1 | ||
|
|
861bf953bf | ||
|
|
06eaac8690 | ||
|
|
6b9e8816d1 | ||
|
|
08e043fea7 | ||
|
|
54ba1009d3 | ||
|
|
8742957f75 | ||
|
|
ace372cfc6 | ||
|
|
27c5f5f49f | ||
|
|
ec5a1a3977 | ||
|
|
77c7963bde | ||
|
|
b80c1343c3 | ||
|
|
e5c5fbcea3 | ||
|
|
fc7d04ce73 | ||
|
|
35f57b3ed2 | ||
|
|
ed9ade05ea | ||
|
|
f485b729bc | ||
|
|
64f7953423 | ||
|
|
fc1d837501 | ||
|
|
9800c43bfa | ||
|
|
b3cda39b0b | ||
|
|
ccae8d42fd | ||
|
|
38f78286c7 | ||
|
|
2bbe6a2ad8 | ||
|
|
f64f63f675 | ||
|
|
f0fb44f6d4 | ||
|
|
fa972615e6 | ||
|
|
f7cb2ef25d | ||
|
|
949f8bb2e7 | ||
|
|
5eaff802d4 | ||
|
|
a6336149f8 | ||
|
|
ca6bce3820 | ||
|
|
9b4f2297b0 | ||
|
|
a31b2876d0 | ||
|
|
b697b6e57b | ||
|
|
4792fe6391 | ||
|
|
7408f72de2 | ||
|
|
3a029686e3 | ||
|
|
9fa7b3956d | ||
|
|
b888ace508 | ||
|
|
2e54efe34d |
No files matched your search
@@ -39,6 +39,7 @@ prog/weavehosts/weavehosts
|
||||
prog/weaveproxy/weaveproxy
|
||||
prog/sigproxy/sigproxy
|
||||
prog/weavewait/weavewait
|
||||
prog/weavewait/weavewait_noop
|
||||
prog/netcheck/netcheck
|
||||
prog/docker_tls_args/docker_tls_args
|
||||
testing/cover/cover
|
||||
@@ -52,6 +53,7 @@ prog/weaveexec/weave
|
||||
prog/weaveexec/weavehosts
|
||||
prog/weaveexec/weaveproxy
|
||||
prog/weaveexec/weavewait
|
||||
prog/weaveexec/weavewait_noop
|
||||
prog/weaveexec/sigproxy
|
||||
prog/weaveexec/netcheck
|
||||
prog/weaveexec/docker_tls_args
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
## Release 1.2.1
|
||||
|
||||
This release contains a number of bug fixes and minor
|
||||
enhancements. More details in the
|
||||
[change log](https://github.com/weaveworks/weave/issues?q=milestone%3A1.2.1).
|
||||
|
||||
The release is fully compatible with 1.2.0 versions, so existing
|
||||
clusters can be upgraded incrementally.
|
||||
|
||||
## Release 1.2.0
|
||||
|
||||
**Highlights**
|
||||
|
||||
@@ -13,11 +13,12 @@ WEAVER_EXE=prog/weaver/weaver
|
||||
WEAVEPROXY_EXE=prog/weaveproxy/weaveproxy
|
||||
SIGPROXY_EXE=prog/sigproxy/sigproxy
|
||||
WEAVEWAIT_EXE=prog/weavewait/weavewait
|
||||
WEAVEWAIT_NOOP_EXE=prog/weavewait/weavewait_noop
|
||||
NETCHECK_EXE=prog/netcheck/netcheck
|
||||
DOCKERTLSARGS_EXE=prog/docker_tls_args/docker_tls_args
|
||||
RUNNER_EXE=testing/runner/runner
|
||||
|
||||
EXES=$(WEAVER_EXE) $(SIGPROXY_EXE) $(WEAVEPROXY_EXE) $(WEAVEWAIT_EXE) $(NETCHECK_EXE) $(DOCKERTLSARGS_EXE) $(RUNNER_EXE)
|
||||
EXES=$(WEAVER_EXE) $(SIGPROXY_EXE) $(WEAVEPROXY_EXE) $(WEAVEWAIT_EXE) $(WEAVEWAIT_NOOP_EXE) $(NETCHECK_EXE) $(DOCKERTLSARGS_EXE) $(RUNNER_EXE)
|
||||
|
||||
WEAVER_UPTODATE=.weaver.uptodate
|
||||
WEAVEEXEC_UPTODATE=.weaveexec.uptodate
|
||||
@@ -76,7 +77,7 @@ $(NETCHECK_EXE): prog/netcheck/netcheck.go
|
||||
# Sigproxy and weavewait need separate rules as they fail the netgo check in
|
||||
# the main build stanza due to not importing net package
|
||||
$(SIGPROXY_EXE): prog/sigproxy/main.go
|
||||
$(WEAVEWAIT_EXE): prog/weavewait/main.go net/*.go
|
||||
$(WEAVEWAIT_EXE): prog/weavewait/*.go net/*.go
|
||||
$(RUNNER_EXE): testing/runner/runner.go
|
||||
$(DOCKERTLSARGS_EXE): prog/docker_tls_args/*.go
|
||||
|
||||
@@ -84,15 +85,20 @@ $(WEAVEWAIT_EXE) $(SIGPROXY_EXE) $(RUNNER_EXE) $(DOCKERTLSARGS_EXE):
|
||||
go get -tags netgo ./$(@D)
|
||||
go build $(BUILD_FLAGS) -o $@ ./$(@D)
|
||||
|
||||
$(WEAVEWAIT_NOOP_EXE): prog/weavewait/*.go
|
||||
go get -tags netgo ./$(@D)
|
||||
go build $(BUILD_FLAGS) -tags noop -o $@ ./$(@D)
|
||||
|
||||
$(WEAVER_UPTODATE): prog/weaver/Dockerfile $(WEAVER_EXE)
|
||||
$(SUDO) docker build -t $(WEAVER_IMAGE) prog/weaver
|
||||
touch $@
|
||||
|
||||
$(WEAVEEXEC_UPTODATE): prog/weaveexec/Dockerfile $(DOCKER_DISTRIB) weave $(SIGPROXY_EXE) $(WEAVEPROXY_EXE) $(WEAVEWAIT_EXE) $(NETCHECK_EXE) $(DOCKERTLSARGS_EXE)
|
||||
$(WEAVEEXEC_UPTODATE): prog/weaveexec/Dockerfile $(DOCKER_DISTRIB) weave $(SIGPROXY_EXE) $(WEAVEPROXY_EXE) $(WEAVEWAIT_EXE) $(WEAVEWAIT_NOOP_EXE) $(NETCHECK_EXE) $(DOCKERTLSARGS_EXE)
|
||||
cp weave prog/weaveexec/weave
|
||||
cp $(SIGPROXY_EXE) prog/weaveexec/sigproxy
|
||||
cp $(WEAVEPROXY_EXE) prog/weaveexec/weaveproxy
|
||||
cp $(WEAVEWAIT_EXE) prog/weaveexec/weavewait
|
||||
cp $(WEAVEWAIT_NOOP_EXE) prog/weaveexec/weavewait_noop
|
||||
cp $(NETCHECK_EXE) prog/weaveexec/netcheck
|
||||
cp $(DOCKERTLSARGS_EXE) prog/weaveexec/docker_tls_args
|
||||
cp $(DOCKER_DISTRIB) prog/weaveexec/docker.tgz
|
||||
|
||||
+40
-12
@@ -55,19 +55,21 @@ type Allocator struct {
|
||||
paxos *paxos.Node
|
||||
paxosTicker *time.Ticker
|
||||
shuttingDown bool // to avoid doing any requests while trying to shut down
|
||||
isKnownPeer func(router.PeerName) bool
|
||||
now func() time.Time
|
||||
}
|
||||
|
||||
// NewAllocator creates and initialises a new Allocator
|
||||
func NewAllocator(ourName router.PeerName, ourUID router.PeerUID, ourNickname string, universe address.Range, quorum uint) *Allocator {
|
||||
func NewAllocator(ourName router.PeerName, ourUID router.PeerUID, ourNickname string, universe address.Range, quorum uint, isKnownPeer func(name router.PeerName) bool) *Allocator {
|
||||
return &Allocator{
|
||||
ourName: ourName,
|
||||
universe: universe,
|
||||
ring: ring.New(universe.Start, universe.End, ourName),
|
||||
owned: make(map[string][]address.Address),
|
||||
paxos: paxos.NewNode(ourName, ourUID, quorum),
|
||||
nicknames: map[router.PeerName]string{ourName: ourNickname},
|
||||
now: time.Now,
|
||||
ourName: ourName,
|
||||
universe: universe,
|
||||
ring: ring.New(universe.Start, universe.End, ourName),
|
||||
owned: make(map[string][]address.Address),
|
||||
paxos: paxos.NewNode(ourName, ourUID, quorum),
|
||||
nicknames: map[router.PeerName]string{ourName: ourNickname},
|
||||
isKnownPeer: isKnownPeer,
|
||||
now: time.Now,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,6 +276,33 @@ func (alloc *Allocator) Free(ident string, addrToFree address.Address) error {
|
||||
return <-errChan
|
||||
}
|
||||
|
||||
func (alloc *Allocator) pickPeerFromNicknames(isValid func(router.PeerName) bool) router.PeerName {
|
||||
for name := range alloc.nicknames {
|
||||
if name != alloc.ourName && isValid(name) {
|
||||
return name
|
||||
}
|
||||
}
|
||||
return router.UnknownPeerName
|
||||
}
|
||||
|
||||
func (alloc *Allocator) pickPeerForTransfer() router.PeerName {
|
||||
// first try alive peers that actively participate in IPAM (i.e. have entries)
|
||||
if heir := alloc.ring.PickPeerForTransfer(alloc.isKnownPeer); heir != router.UnknownPeerName {
|
||||
return heir
|
||||
}
|
||||
// next try alive peers that have IPAM enabled but have no entries
|
||||
if heir := alloc.pickPeerFromNicknames(alloc.isKnownPeer); heir != router.UnknownPeerName {
|
||||
return heir
|
||||
}
|
||||
// next try disappeared peers that still have entries
|
||||
t := func(router.PeerName) bool { return true }
|
||||
if heir := alloc.ring.PickPeerForTransfer(t); heir != router.UnknownPeerName {
|
||||
return heir
|
||||
}
|
||||
// finally, disappeared peers that that passively participated in IPAM
|
||||
return alloc.pickPeerFromNicknames(t)
|
||||
}
|
||||
|
||||
// Shutdown (Sync)
|
||||
func (alloc *Allocator) Shutdown() {
|
||||
alloc.infof("Shutdown")
|
||||
@@ -282,7 +311,7 @@ func (alloc *Allocator) Shutdown() {
|
||||
alloc.shuttingDown = true
|
||||
alloc.cancelOps(&alloc.pendingClaims)
|
||||
alloc.cancelOps(&alloc.pendingAllocates)
|
||||
if heir := alloc.ring.PickPeerForTransfer(); heir != router.UnknownPeerName {
|
||||
if heir := alloc.pickPeerForTransfer(); heir != router.UnknownPeerName {
|
||||
alloc.ring.Transfer(alloc.ourName, heir)
|
||||
alloc.space.Clear()
|
||||
alloc.gossip.GossipBroadcast(alloc.Gossip())
|
||||
@@ -310,7 +339,6 @@ func (alloc *Allocator) AdminTakeoverRanges(peerNameOrNickname string) error {
|
||||
return
|
||||
}
|
||||
|
||||
delete(alloc.nicknames, peername)
|
||||
newRanges, err := alloc.ring.Transfer(peername, alloc.ourName)
|
||||
alloc.space.AddRanges(newRanges)
|
||||
resultChan <- err
|
||||
@@ -332,11 +360,11 @@ func (alloc *Allocator) lookupPeername(name string) (router.PeerName, error) {
|
||||
return router.PeerNameFromString(name)
|
||||
}
|
||||
|
||||
// Restrict the peers in "nicknames" to those in the ring and our own
|
||||
// Restrict the peers in "nicknames" to those in the ring plus peers known to the router
|
||||
func (alloc *Allocator) pruneNicknames() {
|
||||
ringPeers := alloc.ring.PeerNames()
|
||||
for name := range alloc.nicknames {
|
||||
if _, ok := ringPeers[name]; !ok && name != alloc.ourName {
|
||||
if _, ok := ringPeers[name]; !ok && !alloc.isKnownPeer(name) {
|
||||
delete(alloc.nicknames, name)
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -470,9 +470,9 @@ func (r *Ring) ChoosePeersToAskForSpace(start, end address.Address) []router.Pee
|
||||
return result
|
||||
}
|
||||
|
||||
func (r *Ring) PickPeerForTransfer() router.PeerName {
|
||||
func (r *Ring) PickPeerForTransfer(isValid func(router.PeerName) bool) router.PeerName {
|
||||
for _, entry := range r.Entries {
|
||||
if entry.Peer != r.Peer {
|
||||
if entry.Peer != r.Peer && isValid(entry.Peer) {
|
||||
return entry.Peer
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ func makeAllocator(name string, cidrStr string, quorum uint) (*Allocator, addres
|
||||
}
|
||||
|
||||
alloc := NewAllocator(peername, router.PeerUID(rand.Int63()),
|
||||
"nick-"+name, cidr.Range(), quorum)
|
||||
"nick-"+name, cidr.Range(), quorum, func(router.PeerName) bool { return true })
|
||||
|
||||
return alloc, cidr.HostRange()
|
||||
}
|
||||
|
||||
+1
-1
@@ -216,7 +216,7 @@ func (h *handler) handleRecursive(w dns.ResponseWriter, req *dns.Msg) {
|
||||
reqCopy := req.Copy()
|
||||
reqCopy.Id = dns.Id()
|
||||
response, _, err := h.client.Exchange(reqCopy, fmt.Sprintf("%s:%s", server, h.upstream.Port))
|
||||
if err != nil || response == nil {
|
||||
if (err != nil && err != dns.ErrTruncated) || response == nil {
|
||||
h.ns.debugf("error trying %s: %v", server, err)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -42,17 +42,17 @@ func TestTruncation(t *testing.T) {
|
||||
nameserver.AddEntry("foo.weave.local.", "", router.UnknownPeerName, i)
|
||||
}
|
||||
|
||||
doRequest := func(client *dns.Client, request *dns.Msg, port int) *dns.Msg {
|
||||
doRequest := func(client *dns.Client, request *dns.Msg, port int, expectedErr error) *dns.Msg {
|
||||
request.SetQuestion("foo.weave.local.", dns.TypeA)
|
||||
response, _, err := client.Exchange(request, fmt.Sprintf("127.0.0.1:%d", port))
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, expectedErr, err)
|
||||
return response
|
||||
}
|
||||
|
||||
// do a udp query, ensure we get a truncated response
|
||||
{
|
||||
udpClient := dns.Client{Net: "udp", UDPSize: minUDPSize}
|
||||
response := doRequest(&udpClient, &dns.Msg{}, udpPort)
|
||||
response := doRequest(&udpClient, &dns.Msg{}, udpPort, dns.ErrTruncated)
|
||||
require.True(t, response.MsgHdr.Truncated)
|
||||
require.True(t, len(response.Answer) < 100)
|
||||
}
|
||||
@@ -62,7 +62,7 @@ func TestTruncation(t *testing.T) {
|
||||
udpClient := dns.Client{Net: "udp", UDPSize: 65535}
|
||||
request := &dns.Msg{}
|
||||
request.SetEdns0(65535, false)
|
||||
response := doRequest(&udpClient, request, udpPort)
|
||||
response := doRequest(&udpClient, request, udpPort, nil)
|
||||
require.False(t, response.MsgHdr.Truncated)
|
||||
require.Equal(t, len(response.Answer), 100)
|
||||
}
|
||||
@@ -70,7 +70,7 @@ func TestTruncation(t *testing.T) {
|
||||
// do a tcp query, ensure we don't get a truncated response
|
||||
{
|
||||
tcpClient := dns.Client{Net: "tcp"}
|
||||
response := doRequest(&tcpClient, &dns.Msg{}, tcpPort)
|
||||
response := doRequest(&tcpClient, &dns.Msg{}, tcpPort, nil)
|
||||
require.False(t, response.MsgHdr.Truncated)
|
||||
require.Equal(t, len(response.Answer), 100)
|
||||
}
|
||||
|
||||
+36
-12
@@ -18,7 +18,8 @@ type Entry struct {
|
||||
ContainerID string
|
||||
Origin router.PeerName
|
||||
Addr address.Address
|
||||
Hostname string
|
||||
Hostname string // as supplied
|
||||
lHostname string // lowercased (not exported, so not encoded by gob)
|
||||
Version int
|
||||
Tombstone int64 // timestamp of when it was deleted
|
||||
}
|
||||
@@ -69,7 +70,7 @@ func (e1 *Entry) less(e2 *Entry) bool {
|
||||
|
||||
func (e1 *Entry) insensitiveLess(e2 *Entry) bool {
|
||||
// Entries are kept sorted by Hostname, Origin, ContainerID then address
|
||||
e1Hostname, e2Hostname := strings.ToLower(e1.Hostname), strings.ToLower(e2.Hostname)
|
||||
e1Hostname, e2Hostname := e1.lHostname, e2.lHostname
|
||||
switch {
|
||||
case e1Hostname != e2Hostname:
|
||||
return e1Hostname < e2Hostname
|
||||
@@ -100,6 +101,10 @@ func (e1 *Entry) String() string {
|
||||
return fmt.Sprintf("%s -> %s", e1.Hostname, e1.Addr.String())
|
||||
}
|
||||
|
||||
func (e1 *Entry) addLowercase() {
|
||||
e1.lHostname = strings.ToLower(e1.Hostname)
|
||||
}
|
||||
|
||||
func check(es SortableEntries) error {
|
||||
if !sort.IsSorted(es) {
|
||||
return fmt.Errorf("Not sorted!")
|
||||
@@ -126,7 +131,8 @@ func (es *Entries) checkAndPanic() *Entries {
|
||||
func (es *Entries) add(hostname, containerid string, origin router.PeerName, addr address.Address) Entry {
|
||||
defer es.checkAndPanic().checkAndPanic()
|
||||
|
||||
entry := Entry{Hostname: hostname, Origin: origin, ContainerID: containerid, Addr: addr}
|
||||
entry := Entry{Hostname: hostname, lHostname: strings.ToLower(hostname),
|
||||
Origin: origin, ContainerID: containerid, Addr: addr}
|
||||
i := sort.Search(len(*es), func(i int) bool {
|
||||
return !(*es)[i].insensitiveLess(&entry)
|
||||
})
|
||||
@@ -145,6 +151,7 @@ func (es *Entries) add(hostname, containerid string, origin router.PeerName, add
|
||||
|
||||
func (es *Entries) merge(incoming Entries) Entries {
|
||||
defer es.checkAndPanic().checkAndPanic()
|
||||
incoming.checkAndPanic()
|
||||
|
||||
newEntries := Entries{}
|
||||
i := 0
|
||||
@@ -203,23 +210,23 @@ func (es Entries) lookup(hostname string) Entries {
|
||||
|
||||
lowerHostname := strings.ToLower(hostname)
|
||||
i := sort.Search(len(es), func(i int) bool {
|
||||
return strings.ToLower(es[i].Hostname) >= lowerHostname
|
||||
return es[i].lHostname >= lowerHostname
|
||||
})
|
||||
if i >= len(es) || strings.ToLower(es[i].Hostname) != lowerHostname {
|
||||
if i >= len(es) || es[i].lHostname != lowerHostname {
|
||||
return Entries{}
|
||||
}
|
||||
|
||||
j := sort.Search(len(es)-i, func(j int) bool {
|
||||
return strings.ToLower(es[i+j].Hostname) > lowerHostname
|
||||
return es[i+j].lHostname > lowerHostname
|
||||
})
|
||||
|
||||
return es[i : i+j]
|
||||
}
|
||||
|
||||
func (es *Entries) first(f func(*Entry) bool) (*Entry, error) {
|
||||
func (es Entries) first(f func(*Entry) bool) (*Entry, error) {
|
||||
es.checkAndPanic()
|
||||
|
||||
for _, e := range *es {
|
||||
for _, e := range es {
|
||||
if f(&e) {
|
||||
return &e, nil
|
||||
}
|
||||
@@ -227,14 +234,18 @@ func (es *Entries) first(f func(*Entry) bool) (*Entry, error) {
|
||||
return nil, fmt.Errorf("Not found")
|
||||
}
|
||||
|
||||
func (es Entries) addLowercase() {
|
||||
for i := range es {
|
||||
es[i].addLowercase()
|
||||
}
|
||||
}
|
||||
|
||||
type GossipData struct {
|
||||
Timestamp int64
|
||||
Entries
|
||||
}
|
||||
|
||||
func (g *GossipData) Merge(o router.GossipData) {
|
||||
checkAndPanic(CaseSensitive(g.Entries))
|
||||
defer func() { checkAndPanic(CaseSensitive(g.Entries)) }()
|
||||
other := o.(*GossipData)
|
||||
g.Entries.merge(other.Entries)
|
||||
if g.Timestamp < other.Timestamp {
|
||||
@@ -242,10 +253,23 @@ func (g *GossipData) Merge(o router.GossipData) {
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GossipData) Decode(msg []byte) error {
|
||||
if err := gob.NewDecoder(bytes.NewReader(msg)).Decode(g); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
g.Entries.addLowercase() // lowercase strings not sent on the wire
|
||||
sort.Sort(CaseInsensitive(g.Entries))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *GossipData) Encode() [][]byte {
|
||||
checkAndPanic(CaseSensitive(g.Entries))
|
||||
// Make a copy so we can sort: all outgoing data is sent in case-sensitive order
|
||||
g2 := GossipData{Timestamp: g.Timestamp, Entries: make(Entries, len(g.Entries))}
|
||||
copy(g2.Entries, g.Entries)
|
||||
sort.Sort(CaseSensitive(g2.Entries))
|
||||
buf := &bytes.Buffer{}
|
||||
if err := gob.NewEncoder(buf).Encode(g); err != nil {
|
||||
if err := gob.NewEncoder(buf).Encode(g2); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return [][]byte{buf.Bytes()}
|
||||
|
||||
+47
-56
@@ -9,6 +9,19 @@ import (
|
||||
"github.com/weaveworks/weave/router"
|
||||
)
|
||||
|
||||
func l(es Entries) Entries {
|
||||
es.addLowercase()
|
||||
return es
|
||||
}
|
||||
|
||||
func makeEntries(values string) Entries {
|
||||
entries := make(Entries, len(values))
|
||||
for i, c := range values {
|
||||
entries[i] = Entry{Hostname: string(c)}
|
||||
}
|
||||
return l(entries)
|
||||
}
|
||||
|
||||
func TestAdd(t *testing.T) {
|
||||
oldNow := now
|
||||
defer func() { now = oldNow }()
|
||||
@@ -16,68 +29,46 @@ func TestAdd(t *testing.T) {
|
||||
|
||||
entries := Entries{}
|
||||
entries.add("A", "", router.UnknownPeerName, address.Address(0))
|
||||
expected := Entries{
|
||||
expected := l(Entries{
|
||||
Entry{Hostname: "A", Origin: router.UnknownPeerName, Addr: address.Address(0)},
|
||||
}
|
||||
})
|
||||
require.Equal(t, entries, expected)
|
||||
|
||||
entries.tombstone(router.UnknownPeerName, func(e *Entry) bool { return e.Hostname == "A" })
|
||||
expected = Entries{
|
||||
expected = l(Entries{
|
||||
Entry{Hostname: "A", Origin: router.UnknownPeerName, Addr: address.Address(0), Version: 1, Tombstone: 1234},
|
||||
}
|
||||
})
|
||||
require.Equal(t, entries, expected)
|
||||
|
||||
entries.add("A", "", router.UnknownPeerName, address.Address(0))
|
||||
expected = Entries{
|
||||
expected = l(Entries{
|
||||
Entry{Hostname: "A", Origin: router.UnknownPeerName, Addr: address.Address(0), Version: 2},
|
||||
}
|
||||
})
|
||||
require.Equal(t, entries, expected)
|
||||
}
|
||||
|
||||
func TestMerge(t *testing.T) {
|
||||
e1 := Entries{
|
||||
Entry{Hostname: "A"},
|
||||
Entry{Hostname: "C"},
|
||||
Entry{Hostname: "D"},
|
||||
Entry{Hostname: "F"},
|
||||
}
|
||||
|
||||
e2 := Entries{
|
||||
Entry{Hostname: "B"},
|
||||
Entry{Hostname: "E"},
|
||||
Entry{Hostname: "F"},
|
||||
}
|
||||
e1 := makeEntries("ACDF")
|
||||
e2 := makeEntries("BEF")
|
||||
|
||||
diff := e1.merge(e2)
|
||||
expectedDiff := Entries{
|
||||
Entry{Hostname: "B"},
|
||||
Entry{Hostname: "E"},
|
||||
}
|
||||
require.Equal(t, expectedDiff, diff)
|
||||
|
||||
expected := Entries{
|
||||
Entry{Hostname: "A"},
|
||||
Entry{Hostname: "B"},
|
||||
Entry{Hostname: "C"},
|
||||
Entry{Hostname: "D"},
|
||||
Entry{Hostname: "E"},
|
||||
Entry{Hostname: "F"},
|
||||
}
|
||||
require.Equal(t, expected, e1)
|
||||
require.Equal(t, makeEntries("BE"), diff)
|
||||
require.Equal(t, makeEntries("ABCDEF"), e1)
|
||||
|
||||
diff = e1.merge(e1)
|
||||
require.Equal(t, Entries{}, diff)
|
||||
}
|
||||
|
||||
func TestOldMerge(t *testing.T) {
|
||||
e1 := Entries{Entry{Hostname: "A", Version: 0}}
|
||||
diff := e1.merge(Entries{Entry{Hostname: "A", Version: 1}})
|
||||
require.Equal(t, Entries{Entry{Hostname: "A", Version: 1}}, diff)
|
||||
require.Equal(t, Entries{Entry{Hostname: "A", Version: 1}}, e1)
|
||||
e1 := l(Entries{Entry{Hostname: "A", Version: 0}})
|
||||
diff := e1.merge(l(Entries{Entry{Hostname: "A", Version: 1}}))
|
||||
require.Equal(t, l(Entries{Entry{Hostname: "A", Version: 1}}), diff)
|
||||
require.Equal(t, l(Entries{Entry{Hostname: "A", Version: 1}}), e1)
|
||||
|
||||
diff = e1.merge(Entries{Entry{Hostname: "A", Version: 0}})
|
||||
diff = e1.merge(l(Entries{Entry{Hostname: "A", Version: 0}}))
|
||||
require.Equal(t, Entries{}, diff)
|
||||
require.Equal(t, Entries{Entry{Hostname: "A", Version: 1}}, e1)
|
||||
require.Equal(t, l(Entries{Entry{Hostname: "A", Version: 1}}), e1)
|
||||
}
|
||||
|
||||
func TestTombstone(t *testing.T) {
|
||||
@@ -85,48 +76,48 @@ func TestTombstone(t *testing.T) {
|
||||
defer func() { now = oldNow }()
|
||||
now = func() int64 { return 1234 }
|
||||
|
||||
es := Entries{
|
||||
Entry{Hostname: "A"},
|
||||
Entry{Hostname: "B"},
|
||||
}
|
||||
es := makeEntries("AB")
|
||||
|
||||
es.tombstone(router.UnknownPeerName, func(e *Entry) bool {
|
||||
return e.Hostname == "B"
|
||||
})
|
||||
expected := Entries{
|
||||
expected := l(Entries{
|
||||
Entry{Hostname: "A"},
|
||||
Entry{Hostname: "B", Version: 1, Tombstone: 1234},
|
||||
}
|
||||
})
|
||||
require.Equal(t, expected, es)
|
||||
}
|
||||
|
||||
func TestDelete(t *testing.T) {
|
||||
es := Entries{
|
||||
Entry{Hostname: "A"},
|
||||
Entry{Hostname: "B"},
|
||||
}
|
||||
es := makeEntries("AB")
|
||||
|
||||
es.filter(func(e *Entry) bool {
|
||||
return e.Hostname != "A"
|
||||
})
|
||||
expected := Entries{
|
||||
Entry{Hostname: "B"},
|
||||
}
|
||||
require.Equal(t, expected, es)
|
||||
require.Equal(t, makeEntries("B"), es)
|
||||
}
|
||||
|
||||
func TestLookup(t *testing.T) {
|
||||
es := Entries{
|
||||
es := l(Entries{
|
||||
Entry{Hostname: "A"},
|
||||
Entry{Hostname: "B", ContainerID: "bar"},
|
||||
Entry{Hostname: "B", ContainerID: "foo"},
|
||||
Entry{Hostname: "C"},
|
||||
}
|
||||
})
|
||||
|
||||
have := es.lookup("B")
|
||||
want := Entries{
|
||||
want := l(Entries{
|
||||
Entry{Hostname: "B", ContainerID: "bar"},
|
||||
Entry{Hostname: "B", ContainerID: "foo"},
|
||||
}
|
||||
})
|
||||
require.Equal(t, have, want)
|
||||
}
|
||||
|
||||
func TestGossipDataMerge(t *testing.T) {
|
||||
g1 := GossipData{Entries: makeEntries("AcDf")}
|
||||
g2 := GossipData{Entries: makeEntries("BEf")}
|
||||
|
||||
g1.Merge(&g2)
|
||||
|
||||
require.Equal(t, GossipData{Entries: makeEntries("ABcDEf")}, g1)
|
||||
}
|
||||
@@ -35,6 +35,11 @@ func (n *Nameserver) HandleHTTP(router *mux.Router, dockerCli *docker.Client) {
|
||||
return
|
||||
}
|
||||
|
||||
if !dns.IsSubDomain(n.domain, hostname) {
|
||||
n.infof("Ignoring registration %s %s %s (not a subdomain of %s)", hostname, ipStr, container, n.domain)
|
||||
return
|
||||
}
|
||||
|
||||
if err := n.AddEntry(hostname, container, n.ourName, ip); err != nil {
|
||||
n.badRequest(w, fmt.Errorf("Unable to add entry: %v", err))
|
||||
return
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
package nameserver
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
"fmt"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -196,7 +193,6 @@ func (n *Nameserver) Gossip() router.GossipData {
|
||||
Timestamp: now(),
|
||||
}
|
||||
copy(gossip.Entries, n.entries)
|
||||
sort.Sort(CaseSensitive(gossip.Entries))
|
||||
return gossip
|
||||
}
|
||||
|
||||
@@ -206,16 +202,13 @@ func (n *Nameserver) OnGossipUnicast(sender router.PeerName, msg []byte) error {
|
||||
|
||||
func (n *Nameserver) receiveGossip(msg []byte) (router.GossipData, router.GossipData, error) {
|
||||
var gossip GossipData
|
||||
if err := gob.NewDecoder(bytes.NewReader(msg)).Decode(&gossip); err != nil {
|
||||
if err := gossip.Decode(msg); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if delta := gossip.Timestamp - now(); delta > gossipWindow || delta < -gossipWindow {
|
||||
return nil, nil, fmt.Errorf("clock skew of %d detected", delta)
|
||||
}
|
||||
|
||||
sort.Sort(CaseInsensitive(gossip.Entries))
|
||||
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ func (m mapping) Addrs() []address.Address {
|
||||
}
|
||||
|
||||
func TestNameservers(t *testing.T) {
|
||||
wt.RunWithTimeout(t, time.Minute, func() {
|
||||
wt.RunWithTimeout(t, 2*time.Minute, func() {
|
||||
testNameservers(t)
|
||||
})
|
||||
}
|
||||
@@ -81,8 +81,12 @@ func testNameservers(t *testing.T) {
|
||||
//common.SetLogLevel("debug")
|
||||
|
||||
lookupTimeout := 10 // ms
|
||||
nameservers, grouter := makeNetwork(50)
|
||||
nameservers, grouter := makeNetwork(30)
|
||||
defer stopNetwork(nameservers, grouter)
|
||||
// This subset will sometimes lose touch with some of the others
|
||||
badNameservers := nameservers[25:]
|
||||
// This subset will remain well-connected, and we will deal mainly with them
|
||||
nameservers = nameservers[:25]
|
||||
nameserversByName := map[router.PeerName]*Nameserver{}
|
||||
for _, n := range nameservers {
|
||||
nameserversByName[n.ourName] = n
|
||||
@@ -106,7 +110,13 @@ func testNameservers(t *testing.T) {
|
||||
addMapping := func() {
|
||||
nameserver := nameservers[rand.Intn(len(nameservers))]
|
||||
addr := address.Address(rand.Int31())
|
||||
hostname := fmt.Sprintf("hostname%d", rand.Int63())
|
||||
// Create a hostname which has some upper and lowercase letters,
|
||||
// and a unique number so we don't have to check if we allocated it already
|
||||
randomBits := rand.Int63()
|
||||
firstLetter := 'H' + (randomBits&1)*32
|
||||
secondLetter := 'O' + (randomBits&2)*16
|
||||
randomBits = randomBits >> 2
|
||||
hostname := fmt.Sprintf("%c%cstname%d", firstLetter, secondLetter, randomBits)
|
||||
mapping := mapping{hostname, []pair{{nameserver.ourName, addr}}}
|
||||
mappings = append(mappings, mapping)
|
||||
|
||||
@@ -129,6 +139,12 @@ func testNameservers(t *testing.T) {
|
||||
check(nameserver, mapping)
|
||||
}
|
||||
|
||||
loseConnection := func() {
|
||||
nameserver1 := badNameservers[rand.Intn(len(badNameservers))]
|
||||
nameserver2 := nameservers[rand.Intn(len(nameservers))]
|
||||
nameserver1.PeerGone(&router.Peer{Name: nameserver2.ourName})
|
||||
}
|
||||
|
||||
deleteMapping := func() {
|
||||
if len(mappings) <= 0 {
|
||||
return
|
||||
@@ -179,7 +195,7 @@ func testNameservers(t *testing.T) {
|
||||
require.Equal(t, mapping.hostname, hostname)
|
||||
}
|
||||
|
||||
for i := 0; i < 1000; i++ {
|
||||
for i := 0; i < 800; i++ {
|
||||
r := rand.Float32()
|
||||
switch {
|
||||
case r < 0.1:
|
||||
@@ -191,7 +207,10 @@ func testNameservers(t *testing.T) {
|
||||
case 0.2 <= r && r < 0.3:
|
||||
deleteMapping()
|
||||
|
||||
case 0.3 <= r && r < 0.9:
|
||||
case 0.3 <= r && r < 0.35:
|
||||
loseConnection()
|
||||
|
||||
case 0.35 <= r && r < 0.9:
|
||||
doLookup()
|
||||
|
||||
case 0.9 <= r:
|
||||
@@ -241,14 +260,14 @@ func TestTombstoneDeletion(t *testing.T) {
|
||||
err = nameserver.Delete("hostname", "containerid", "", address.Address(0))
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, []address.Address{}, nameserver.Lookup("hostname"))
|
||||
require.Equal(t, Entries{{
|
||||
require.Equal(t, l(Entries{Entry{
|
||||
ContainerID: "containerid",
|
||||
Origin: peername,
|
||||
Addr: address.Address(0),
|
||||
Hostname: "hostname",
|
||||
Version: 1,
|
||||
Tombstone: 1234,
|
||||
}}, nameserver.entries)
|
||||
}}), nameserver.entries)
|
||||
|
||||
now = func() int64 { return 1234 + int64(tombstoneTimeout/time.Second) + 1 }
|
||||
nameserver.deleteTombstones()
|
||||
|
||||
@@ -5,6 +5,7 @@ LABEL works.weave.role=system
|
||||
|
||||
WORKDIR /home/weave
|
||||
VOLUME /w
|
||||
VOLUME /w-noop
|
||||
ENTRYPOINT ["/home/weave/sigproxy", "/home/weave/weave"]
|
||||
|
||||
RUN apk add --update \
|
||||
@@ -20,4 +21,5 @@ RUN apk add --update \
|
||||
ADD ./weave ./sigproxy ./weaveproxy /home/weave/
|
||||
ADD ./netcheck ./docker_tls_args /usr/bin/
|
||||
ADD ./weavewait /w/w
|
||||
ADD ./weavewait_noop /w-noop/w
|
||||
ADD ./docker.tgz /
|
||||
+8
-4
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/davecheney/profile"
|
||||
"github.com/docker/docker/pkg/mflag"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/weaveworks/go-odp/odp"
|
||||
|
||||
. "github.com/weaveworks/weave/common"
|
||||
"github.com/weaveworks/weave/common/docker"
|
||||
@@ -119,8 +118,12 @@ func main() {
|
||||
os.Exit(0)
|
||||
|
||||
case createDatapath:
|
||||
err := weave.CreateDatapath(datapathName)
|
||||
if odp.IsKernelLacksODPError(err) {
|
||||
err, odp_supported := weave.CreateDatapath(datapathName)
|
||||
if !odp_supported {
|
||||
if err != nil {
|
||||
Log.Error(err)
|
||||
}
|
||||
|
||||
// When the kernel lacks ODP support, exit
|
||||
// with a special status to distinguish it for
|
||||
// the weave script.
|
||||
@@ -368,7 +371,8 @@ func createAllocator(router *weave.Router, ipRangeStr string, defaultSubnetStr s
|
||||
Log.Fatalf("IP address allocation default subnet %s does not overlap with allocation range %s", defaultSubnet, ipRange)
|
||||
}
|
||||
}
|
||||
allocator := ipam.NewAllocator(router.Ourself.Peer.Name, router.Ourself.Peer.UID, router.Ourself.Peer.NickName, ipRange.Range(), quorum)
|
||||
isKnownPeer := func(name weave.PeerName) bool { return router.Peers.Fetch(name) != nil }
|
||||
allocator := ipam.NewAllocator(router.Ourself.Peer.Name, router.Ourself.Peer.UID, router.Ourself.Peer.NickName, ipRange.Range(), quorum, isKnownPeer)
|
||||
|
||||
allocator.SetInterfaces(router.NewGossip("IPallocation", allocator))
|
||||
allocator.Start()
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// +build !noop
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
weavenet "github.com/weaveworks/weave/net"
|
||||
)
|
||||
|
||||
func checkNetwork() error {
|
||||
_, err := weavenet.EnsureInterfaceAndMcastRoute("ethwe")
|
||||
return err
|
||||
}
|
||||
@@ -6,8 +6,6 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"syscall"
|
||||
|
||||
weavenet "github.com/weaveworks/weave/net"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -19,8 +17,7 @@ func main() {
|
||||
args = os.Args[1:]
|
||||
)
|
||||
|
||||
_, err := weavenet.EnsureInterfaceAndMcastRoute("ethwe")
|
||||
checkErr(err)
|
||||
checkErr(checkNetwork())
|
||||
|
||||
if len(args) == 0 {
|
||||
checkErr(ErrNoCommandSpecified)
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
// +build noop
|
||||
|
||||
package main
|
||||
|
||||
func checkNetwork() error {
|
||||
return nil
|
||||
}
|
||||
@@ -21,6 +21,7 @@ var (
|
||||
containerIDRegexp = regexp.MustCompile("^(/v[0-9\\.]*)?/containers/([^/]*)/.*")
|
||||
weaveWaitEntrypoint = []string{"/w/w"}
|
||||
weaveEntrypoint = "/home/weave/weaver"
|
||||
weaveContainerName = "/weave"
|
||||
)
|
||||
|
||||
func callWeave(args ...string) ([]byte, []byte, error) {
|
||||
@@ -154,3 +155,25 @@ func weaveContainerIPs(containerID string) (mac string, ips []net.IP, nets []*ne
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func addVolume(hostConfig jsonObject, source, target, mode string) error {
|
||||
configBinds, err := hostConfig.StringArray("Binds")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var binds []string
|
||||
for _, bind := range configBinds {
|
||||
s := strings.Split(bind, ":")
|
||||
if len(s) >= 2 && s[1] == target {
|
||||
continue
|
||||
}
|
||||
binds = append(binds, bind)
|
||||
}
|
||||
bind := source + ":" + target
|
||||
if mode != "" {
|
||||
bind += ":" + mode
|
||||
}
|
||||
hostConfig["Binds"] = append(binds, bind)
|
||||
return nil
|
||||
}
|
||||
@@ -53,7 +53,7 @@ func (i *createContainerInterceptor) InterceptRequest(r *http.Request) error {
|
||||
Log.Infof("Leaving container alone because %s", err)
|
||||
} else {
|
||||
Log.Infof("Creating container with WEAVE_CIDR \"%s\"", strings.Join(cidrs, " "))
|
||||
if err := i.proxy.addWeaveWaitVolume(hostConfig); err != nil {
|
||||
if err := addVolume(hostConfig, i.proxy.weaveWaitVolume, "/w", "ro"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := i.setWeaveWaitEntrypoint(container); err != nil {
|
||||
|
||||
@@ -22,30 +22,9 @@ func (i *inspectContainerInterceptor) InterceptResponse(r *http.Response) error
|
||||
return err
|
||||
}
|
||||
|
||||
if err := updateContainerNetworkSettings(container); err != nil {
|
||||
if err := i.proxy.updateContainerNetworkSettings(container); err != nil {
|
||||
Log.Warningf("Inspecting container %s failed: %s", container["Id"], err)
|
||||
}
|
||||
|
||||
return marshalResponseBody(r, container)
|
||||
}
|
||||
|
||||
func updateContainerNetworkSettings(container jsonObject) error {
|
||||
containerID, err := container.String("Id")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mac, ips, nets, err := weaveContainerIPs(containerID)
|
||||
if err != nil || len(ips) == 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
networkSettings, err := container.Object("NetworkSettings")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
networkSettings["MacAddress"] = mac
|
||||
networkSettings["IPAddress"] = ips[0].String()
|
||||
networkSettings["IPPrefixLen"], _ = nets[0].Mask.Size()
|
||||
return nil
|
||||
}
|
||||
@@ -27,7 +27,7 @@ func (i *inspectExecInterceptor) InterceptResponse(r *http.Response) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := updateContainerNetworkSettings(container); err != nil {
|
||||
if err := i.proxy.updateContainerNetworkSettings(container); err != nil {
|
||||
Log.Warningf("Inspecting exec %s failed: %s", exec["Id"], err)
|
||||
}
|
||||
|
||||
|
||||
+62
-28
@@ -70,6 +70,7 @@ type Proxy struct {
|
||||
dockerBridgeIP string
|
||||
hostnameMatchRegexp *regexp.Regexp
|
||||
weaveWaitVolume string
|
||||
weaveWaitNoopVolume string
|
||||
normalisedAddrs []string
|
||||
waiters map[*http.Request]*wait
|
||||
}
|
||||
@@ -106,7 +107,7 @@ func NewProxy(c Config) (*Proxy, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = p.findWeaveWaitVolume(); err != nil {
|
||||
if err = p.findWeaveWaitVolumes(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -135,23 +136,31 @@ func (proxy *Proxy) Dial() (net.Conn, error) {
|
||||
return net.Dial("unix", dockerSock)
|
||||
}
|
||||
|
||||
func (proxy *Proxy) findWeaveWaitVolume() error {
|
||||
func (proxy *Proxy) findWeaveWaitVolumes() error {
|
||||
var err error
|
||||
if proxy.weaveWaitVolume, err = proxy.findVolume("/w"); err != nil {
|
||||
return err
|
||||
}
|
||||
proxy.weaveWaitNoopVolume, err = proxy.findVolume("/w-noop")
|
||||
return err
|
||||
}
|
||||
|
||||
func (proxy *Proxy) findVolume(v string) (string, error) {
|
||||
container, err := proxy.client.InspectContainer("weaveproxy")
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not find the weavewait volume: %s", err)
|
||||
return "", fmt.Errorf("Could not find the weavewait volume: %s", err)
|
||||
}
|
||||
|
||||
if container.Volumes == nil {
|
||||
return fmt.Errorf("Could not find the weavewait volume")
|
||||
return "", fmt.Errorf("Could not find the weavewait volume")
|
||||
}
|
||||
|
||||
volume, ok := container.Volumes["/w"]
|
||||
volume, ok := container.Volumes[v]
|
||||
if !ok {
|
||||
return fmt.Errorf("Could not find the weavewait volume")
|
||||
return "", fmt.Errorf("Could not find the weavewait volume")
|
||||
}
|
||||
|
||||
proxy.weaveWaitVolume = volume
|
||||
return nil
|
||||
return volume, nil
|
||||
}
|
||||
|
||||
func (proxy *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -315,7 +324,8 @@ func containerShouldAttach(container *docker.Container) bool {
|
||||
}
|
||||
|
||||
func containerIsWeaveRouter(container *docker.Container) bool {
|
||||
return len(container.Config.Entrypoint) > 0 && container.Config.Entrypoint[0] == weaveEntrypoint
|
||||
return container.Name == weaveContainerName &&
|
||||
len(container.Config.Entrypoint) > 0 && container.Config.Entrypoint[0] == weaveEntrypoint
|
||||
}
|
||||
|
||||
func (proxy *Proxy) createWait(r *http.Request, ident string) {
|
||||
@@ -357,6 +367,24 @@ func (proxy *Proxy) waitForStart(r *http.Request) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// If some other operation is waiting for a container to start, join in the wait
|
||||
func (proxy *Proxy) waitForStartByIdent(ident string) error {
|
||||
var ch chan error
|
||||
proxy.Lock()
|
||||
for _, wait := range proxy.waiters {
|
||||
if ident == wait.ident && !wait.done {
|
||||
ch = wait.ch
|
||||
break
|
||||
}
|
||||
}
|
||||
proxy.Unlock()
|
||||
if ch != nil {
|
||||
Log.Debugf("Wait for start of container %s", ident)
|
||||
return <-ch
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (proxy *Proxy) ContainerDied(ident string) {
|
||||
}
|
||||
|
||||
@@ -406,7 +434,7 @@ func (proxy *Proxy) attachRouter(container *docker.Container) error {
|
||||
|
||||
func (proxy *Proxy) weaveCIDRs(networkMode string, env []string) ([]string, error) {
|
||||
if networkMode == "host" || strings.HasPrefix(networkMode, "container:") {
|
||||
return nil, fmt.Errorf("the container was created with the '--net=%s'", networkMode)
|
||||
return nil, fmt.Errorf("the container has '--net=%s'", networkMode)
|
||||
}
|
||||
for _, e := range env {
|
||||
if strings.HasPrefix(e, "WEAVE_CIDR=") {
|
||||
@@ -422,24 +450,6 @@ func (proxy *Proxy) weaveCIDRs(networkMode string, env []string) ([]string, erro
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (proxy *Proxy) addWeaveWaitVolume(hostConfig jsonObject) error {
|
||||
configBinds, err := hostConfig.StringArray("Binds")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var binds []string
|
||||
for _, bind := range configBinds {
|
||||
s := strings.Split(bind, ":")
|
||||
if len(s) >= 2 && s[1] == "/w" {
|
||||
continue
|
||||
}
|
||||
binds = append(binds, bind)
|
||||
}
|
||||
hostConfig["Binds"] = append(binds, fmt.Sprintf("%s:/w:ro", proxy.weaveWaitVolume))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (proxy *Proxy) setWeaveDNS(hostConfig jsonObject, hostname, dnsDomain string) error {
|
||||
dns, err := hostConfig.StringArray("Dns")
|
||||
if err != nil {
|
||||
@@ -494,3 +504,27 @@ func (proxy *Proxy) getDNSDomain() (domain string) {
|
||||
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func (proxy *Proxy) updateContainerNetworkSettings(container jsonObject) error {
|
||||
containerID, err := container.String("Id")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := proxy.waitForStartByIdent(containerID); err != nil {
|
||||
return err
|
||||
}
|
||||
mac, ips, nets, err := weaveContainerIPs(containerID)
|
||||
if err != nil || len(ips) == 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
networkSettings, err := container.Object("NetworkSettings")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
networkSettings["MacAddress"] = mac
|
||||
networkSettings["IPAddress"] = ips[0].String()
|
||||
networkSettings["IPPrefixLen"], _ = nets[0].Mask.Size()
|
||||
return nil
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package proxy
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type startContainerInterceptor struct{ proxy *Proxy }
|
||||
@@ -31,11 +32,23 @@ func (i *startContainerInterceptor) InterceptRequest(r *http.Request) error {
|
||||
hostConfig = params
|
||||
}
|
||||
if hostConfig != nil {
|
||||
i.proxy.addWeaveWaitVolume(hostConfig)
|
||||
if dnsDomain := i.proxy.getDNSDomain(); dnsDomain != "" {
|
||||
if err := i.proxy.setWeaveDNS(hostConfig, container.Config.Hostname, dnsDomain); err != nil {
|
||||
networkMode, err := jsonObject(hostConfig).String("NetworkMode")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if strings.HasPrefix(networkMode, "container:") || networkMode == "host" {
|
||||
if err := addVolume(hostConfig, i.proxy.weaveWaitNoopVolume, "/w", "ro"); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := addVolume(hostConfig, i.proxy.weaveWaitVolume, "/w", "ro"); err != nil {
|
||||
return err
|
||||
}
|
||||
if dnsDomain := i.proxy.getDNSDomain(); dnsDomain != "" {
|
||||
if err := i.proxy.setWeaveDNS(hostConfig, container.Config.Hostname, dnsDomain); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Note we marshal the original top-level dictionary to avoid disturbing anything else
|
||||
|
||||
+38
-5
@@ -1,25 +1,58 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"syscall"
|
||||
|
||||
"github.com/weaveworks/go-odp/odp"
|
||||
)
|
||||
|
||||
// ODP admin functionality
|
||||
|
||||
func CreateDatapath(dpname string) error {
|
||||
func CreateDatapath(dpname string) (err error, supported bool) {
|
||||
dpif, err := odp.NewDpif()
|
||||
if err != nil {
|
||||
return err
|
||||
if odp.IsKernelLacksODPError(err) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return err, true
|
||||
}
|
||||
|
||||
defer dpif.Close()
|
||||
|
||||
_, err = dpif.CreateDatapath(dpname)
|
||||
dp, err := dpif.CreateDatapath(dpname)
|
||||
if err != nil && !odp.IsDatapathNameAlreadyExistsError(err) {
|
||||
return err
|
||||
return err, true
|
||||
}
|
||||
|
||||
return nil
|
||||
// Pick an ephemeral port number to use in probing for vxlan
|
||||
// support.
|
||||
udpconn, err := net.ListenUDP("udp4", nil)
|
||||
if err != nil {
|
||||
return err, true
|
||||
}
|
||||
|
||||
// we leave the UDP socket open, so creating a vxlan vport on
|
||||
// the same port number should fail. But that's fine: It's
|
||||
// still sufficient to probe for support.
|
||||
portno := uint16(udpconn.LocalAddr().(*net.UDPAddr).Port)
|
||||
vpid, err := dp.CreateVport(odp.NewVxlanVportSpec(
|
||||
fmt.Sprintf("vxlan-%d", portno), portno))
|
||||
if nlerr, ok := err.(odp.NetlinkError); ok {
|
||||
if syscall.Errno(nlerr) == syscall.EAFNOSUPPORT {
|
||||
dp.Delete()
|
||||
return fmt.Errorf("kernel does not have Open vSwitch VXLAN support"), false
|
||||
}
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
dp.DeleteVport(vpid)
|
||||
}
|
||||
|
||||
udpconn.Close()
|
||||
return nil, true
|
||||
}
|
||||
|
||||
func DeleteDatapath(dpname string) error {
|
||||
|
||||
@@ -327,8 +327,6 @@ func (peers *Peers) ApplyUpdate(update []byte) (PeerNameSet, PeerNameSet, error)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
ourVersion := peers.ourself.Version
|
||||
|
||||
// By this point, we know the update doesn't refer to any peers we
|
||||
// have no knowledge of. We can now apply the update. Start by
|
||||
// adding in any new peers.
|
||||
@@ -349,13 +347,6 @@ func (peers *Peers) ApplyUpdate(update []byte) (PeerNameSet, PeerNameSet, error)
|
||||
updateNames[peer.Name] = void
|
||||
}
|
||||
|
||||
if peers.ourself.Version != ourVersion {
|
||||
// Our short id changed, i.e. due to a short ID
|
||||
// change. So we need to include ourself in the
|
||||
// update
|
||||
newUpdate[peers.ourself.Name] = void
|
||||
}
|
||||
|
||||
return updateNames, newUpdate, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -69,3 +69,17 @@
|
||||
s.parentNode.insertBefore(wf, s);
|
||||
})();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
piAId = '124932';
|
||||
piCId = '85570';
|
||||
|
||||
(function() {
|
||||
function async_load(){
|
||||
var s = document.createElement('script'); s.type = 'text/javascript';
|
||||
s.src = ('https:' == document.location.protocol ? 'https://pi' : 'http://cdn') + '.pardot.com/pd.js';
|
||||
var c = document.getElementsByTagName('script')[0]; c.parentNode.insertBefore(s, c);
|
||||
}
|
||||
if(window.attachEvent) { window.attachEvent('onload', async_load); }
|
||||
else { window.addEventListener('load', async_load, false); }
|
||||
})();
|
||||
</script>
|
||||
+9
-1
@@ -219,7 +219,7 @@ NB: By default docker permits communication between containers on the
|
||||
same host, via their docker-assigned IP addresses. For complete
|
||||
isolation between application containers, that feature needs to be
|
||||
disabled by
|
||||
[setting `--icc=false`](https://docs.docker.com/articles/networking/#between-containers)
|
||||
[setting `--icc=false`](https://docs.docker.com/engine/userguide/networking/default_network/container-communication/#communication-between-containers)
|
||||
in the docker daemon configuration. Furthermore, containers should be
|
||||
prevented from capturing and injecting raw network packets - this can
|
||||
be accomplished by starting them with the `--cap-drop net_raw` option.
|
||||
@@ -307,6 +307,14 @@ supplying a password will [cause weave to fall back to a slower
|
||||
method](#fast-data-path) for transporting data between
|
||||
peers.
|
||||
|
||||
Be aware that:
|
||||
|
||||
* Containers will be able to access the router REST API if you have
|
||||
disabled fast datapath. You can prevent this by setting
|
||||
[`--icc=false`](https://docs.docker.com/engine/userguide/networking/default_network/container-communication/#communication-between-containers)
|
||||
* Containers are able to access the router control and data plane
|
||||
ports, but you can mitigate this by enabling encryption
|
||||
|
||||
### <a name="host-network-integration"></a>Host network integration
|
||||
|
||||
Weave application networks can be integrated with a host's network,
|
||||
|
||||
+18
-16
@@ -105,21 +105,11 @@ range. This can be overridden with the `--ipalloc-range` option, e.g.
|
||||
|
||||
and must be the same on every host.
|
||||
|
||||
> The specified range is for *exclusive* use by the IP allocator. In
|
||||
> particular, when starting containers with manually assigned IP
|
||||
> addresses, these must be outside the IP allocator's range. If, in
|
||||
> our example, you subsequently executed `docker run -e
|
||||
> WEAVE_CIDR=10.2.3.1/24 -ti ubuntu`, the IP allocator might assign
|
||||
> the same address to another container, which will break IP routing
|
||||
> for the containers sharing an address.
|
||||
|
||||
The range parameter is written in
|
||||
[CIDR notation](http://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing) -
|
||||
in this example "/16" means the first 16 bits of the address form the
|
||||
network address and the allocator is to allocate container addresses
|
||||
that all start 10.2. The ".0" and ".-1" addresses in a subnet are not
|
||||
used, as required by
|
||||
[RFC 1122](https://tools.ietf.org/html/rfc1122#page-29).
|
||||
that all start 10.2.
|
||||
|
||||
Weave shares the IP address range across all peers, dynamically
|
||||
according to their needs. If a group of peers becomes isolated from
|
||||
@@ -129,11 +119,16 @@ to the rest of the network without any conflicts arising.
|
||||
|
||||
## <a name="subnets"></a>Automatic allocation across multiple subnets
|
||||
|
||||
When
|
||||
[running containers on different subnets](features.html#application-isolation),
|
||||
you may wish to request the allocation of an address from a particular
|
||||
subnet. This is done by specifying the subnet with `net:<subnet>`, in
|
||||
CIDR notation, e.g.
|
||||
IP subnets are used to define or restrict routing. By default, weave
|
||||
puts all containers in a subnet that spans the entire allocation
|
||||
range, so every weave-attached container can talk to every other
|
||||
weave-attached container.
|
||||
|
||||
If you want some [isolation](features.html#application-isolation), you
|
||||
can choose to run containers on different subnets. To request the
|
||||
allocation of an address from a particular subnet, set the
|
||||
`WEAVE_CIDR` environment variable to `net:<subnet>` when creating the
|
||||
container, e.g.
|
||||
|
||||
host1$ docker run -e WEAVE_CIDR=net:10.2.7.0/24 -ti ubuntu
|
||||
|
||||
@@ -143,6 +138,9 @@ for instance:
|
||||
|
||||
host1$ docker run -e WEAVE_CIDR="net:10.2.7.0/24 net:10.2.8.0/24 ip:10.3.9.1/24" -ti ubuntu
|
||||
|
||||
(Note the ".0" and ".-1" addresses in a subnet are not used, as required by
|
||||
[RFC 1122](https://tools.ietf.org/html/rfc1122#page-29)).
|
||||
|
||||
When working with multiple subnets in this way, it is usually
|
||||
desirable to constrain the default subnet - i.e. the one chosen by the
|
||||
allocator when no subnet is supplied - so that it does not overlap
|
||||
@@ -227,3 +225,7 @@ guide](troubleshooting.html#weave-status) for full details.
|
||||
|
||||
The 'Service: ipam' section displays the consensus state as well as
|
||||
the total allocation range and default subnet.
|
||||
|
||||
Note that the 'Range' is written using interval notation - '[' means
|
||||
the start of the range is included and ')' means the end of the range
|
||||
is not included.
|
||||
+4
-4
@@ -57,13 +57,13 @@ All docker commands can be run via the proxy, so it is safe to adjust
|
||||
your `DOCKER_HOST` to point at the proxy. Weave provides a convenient
|
||||
command for this:
|
||||
|
||||
host1$ eval "$(weave env)"
|
||||
host1$ eval $(weave env)
|
||||
host1$ docker ps
|
||||
...
|
||||
|
||||
The prior settings can be restored with
|
||||
|
||||
host1$ eval "$(weave env --restore)"
|
||||
host1$ eval $(weave env --restore)
|
||||
|
||||
Alternatively, the proxy host can be set on a per-command basis with
|
||||
|
||||
@@ -194,7 +194,7 @@ ultimately be handed over to weaveDNS for registration.
|
||||
For instance, we can launch the proxy using all three flags
|
||||
|
||||
host1$ weave launch-router && weave launch-proxy --hostname-from-label hostname-label --hostname-match '^aws-[0-9]+-(.*)$' --hostname-replacement 'my-app-$1'
|
||||
host1$ eval "$(weave env)"
|
||||
host1$ eval $(weave env)
|
||||
|
||||
Note how regexp substitution groups should be prepended with a dollar sign
|
||||
(e.g. `$1`). For further details on the regular expression syntax please see
|
||||
@@ -264,7 +264,7 @@ with
|
||||
|
||||
$ mkdir -pv ~/.docker
|
||||
$ cp -v {ca,cert,key}.pem ~/.docker
|
||||
$ eval "$(weave env)"
|
||||
$ eval $(weave env)
|
||||
$ export DOCKER_TLS_VERIFY=1
|
||||
$ docker version
|
||||
...
|
||||
|
||||
Executable
+22
@@ -0,0 +1,22 @@
|
||||
#! /bin/bash
|
||||
|
||||
. ./config.sh
|
||||
|
||||
start_suite "Rolling restart with reset"
|
||||
|
||||
weave_on $HOST1 launch-router
|
||||
weave_on $HOST2 launch-router $HOST1
|
||||
|
||||
start_container $HOST1 --name=c1
|
||||
start_container $HOST2 --name=c2
|
||||
|
||||
# Now reset the routers so they should give their space away, and restart
|
||||
weave_on $HOST1 reset
|
||||
weave_on $HOST1 launch-router $HOST2
|
||||
weave_on $HOST2 reset
|
||||
weave_on $HOST2 launch-router $HOST1
|
||||
|
||||
# And try to start a container
|
||||
assert_raises "timeout 10 cat <( start_container $HOST1 )"
|
||||
|
||||
end_suite
|
||||
@@ -21,6 +21,13 @@ start_container_with_dns $HOST1 $C1/24 --name=c1 $STATICS_ARGS
|
||||
|
||||
assert_dns_record $HOST1 c1 $NAME $C2
|
||||
|
||||
# Check that 'weave expose -h' names are added to DNS
|
||||
weave_on $HOST1 expose
|
||||
EXPOSE=$(weave_on $HOST1 expose -h testexpose1.weave.local)
|
||||
weave_on $HOST1 expose -h testexpose2.weave.local
|
||||
assert_dns_record $HOST1 c1 testexpose1.weave.local $EXPOSE
|
||||
assert_dns_record $HOST1 c1 testexpose2.weave.local
|
||||
|
||||
# check we respect the --add-host arguments
|
||||
for C in c1 c2 ; do
|
||||
assert_dns_a_record $HOST1 $C $STATIC1_NAME $STATIC1
|
||||
|
||||
@@ -7,10 +7,22 @@ C2=10.2.0.34
|
||||
NAME=seetwo.weave.local
|
||||
|
||||
check_attached() {
|
||||
assert_raises "proxy exec_on $HOST1 c2 $CHECK_ETHWE_UP"
|
||||
assert_raises "exec_on $HOST1 c2 $CHECK_ETHWE_UP"
|
||||
assert_dns_record $HOST1 c1 $NAME $C2
|
||||
}
|
||||
|
||||
wait_for_proxy() {
|
||||
for i in $(seq 1 120); do
|
||||
echo "Waiting for proxy to start"
|
||||
if proxy docker_on $1 info > /dev/null 2>&1 ; then
|
||||
return
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
echo "Timed out waiting for proxy to start" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
start_suite "Proxy restart reattaches networking to containers"
|
||||
|
||||
WEAVE_DOCKER_ARGS=--restart=always WEAVEPROXY_DOCKER_ARGS=--restart=always weave_on $HOST1 launch
|
||||
@@ -32,13 +44,13 @@ check_attached
|
||||
|
||||
# Restart docker itself, using different commands for systemd- and upstart-managed.
|
||||
run_on $HOST1 sh -c "command -v systemctl >/dev/null && sudo systemctl restart docker || sudo service docker restart"
|
||||
sleep 10
|
||||
wait_for_proxy $HOST1
|
||||
check_attached
|
||||
|
||||
# Restarting proxy shouldn't kill unattachable containers
|
||||
proxy_start_container $HOST1 -di --name=c3 --restart=always # Use ipam, so it won't be attachable w/o weave
|
||||
weave_on $HOST1 stop
|
||||
weave_on $HOST1 launch-proxy
|
||||
assert_raises "proxy exec_on $HOST1 c3 $CHECK_ETHWE_UP"
|
||||
assert_raises "exec_on $HOST1 c3 $CHECK_ETHWE_UP"
|
||||
|
||||
end_suite
|
||||
@@ -9,8 +9,8 @@ docker_bridge_ip=$(weave_on $HOST1 docker-bridge-ip)
|
||||
proxy_start_container $HOST1 --name=c1
|
||||
|
||||
check_hostconfig() {
|
||||
docker_on $HOST1 attach c2 >/dev/null 2>&1 || true # Wait for container to exit
|
||||
assert "docker_on $HOST1 inspect -f '{{.HostConfig.Dns}} {{.HostConfig.NetworkMode}} {{.State.Running}} {{.State.ExitCode}}' $1" "[$docker_bridge_ip] $2 false 0"
|
||||
docker_on $HOST1 attach $1 >/dev/null 2>&1 || true # Wait for container to exit
|
||||
assert "docker_on $HOST1 inspect -f '{{.HostConfig.Dns}} {{.HostConfig.NetworkMode}} {{.State.Running}} {{.State.ExitCode}}' $1" "[$3] $2 false 0"
|
||||
}
|
||||
|
||||
# Start c2 with a sneaky HostConfig
|
||||
@@ -26,7 +26,7 @@ check_hostconfig c5 container:c1
|
||||
# Start c3 with HostConfig having empty binds and null dns/networking settings
|
||||
proxy docker_on $HOST1 create --name=c3 -v /tmp:/hosttmp $SMALL_IMAGE $CHECK_ETHWE_UP
|
||||
proxy docker_api_on $HOST1 POST /containers/c3/start '{"Binds":[],"Dns":null,"DnsSearch":null,"ExtraHosts":null,"VolumesFrom":null,"Devices":null,"NetworkMode":""}'
|
||||
check_hostconfig c3 default
|
||||
check_hostconfig c3 default $docker_bridge_ip
|
||||
|
||||
# Start c4 with an 'null' HostConfig and check this doesn't remove previous parameters
|
||||
proxy docker_on $HOST1 create --name=c4 --memory-swap -1 $SMALL_IMAGE echo foo
|
||||
@@ -42,6 +42,17 @@ check_hostconfig c6 container:c1
|
||||
proxy docker_on $HOST1 create --name=c7 --memory-swap -1 $SMALL_IMAGE $CHECK_ETHWE_UP
|
||||
proxy docker_api_on $HOST1 POST /containers/c7/start '{"HostConfig":{}}'
|
||||
assert "docker_on $HOST1 inspect -f '{{.HostConfig.MemorySwap}}' c7" "0"
|
||||
check_hostconfig c7 default
|
||||
check_hostconfig c7 default $docker_bridge_ip
|
||||
|
||||
# Start c8 in host network mode
|
||||
proxy docker_on $HOST1 create --name=c8 $SMALL_IMAGE $CHECK_ETHWE_MISSING
|
||||
proxy docker_api_on $HOST1 POST /containers/c8/start '{"HostConfig": {"NetworkMode": "host"}}'
|
||||
check_hostconfig c8 host
|
||||
|
||||
# Start c10 in network of host container
|
||||
proxy_start_container $HOST1 --name=c9 --net=host
|
||||
proxy docker_on $HOST1 create --name=c10 $SMALL_IMAGE $CHECK_ETHWE_MISSING
|
||||
proxy docker_api_on $HOST1 POST /containers/c10/start '{"HostConfig": {"NetworkMode": "container:c9"}}'
|
||||
check_hostconfig c10 container:c9
|
||||
|
||||
end_suite
|
||||
@@ -40,6 +40,7 @@ TEST_IMAGES="$SMALL_IMAGE $DNS_IMAGE"
|
||||
|
||||
PING="ping -nq -W 1 -c 1"
|
||||
CHECK_ETHWE_UP="grep ^1$ /sys/class/net/ethwe/carrier"
|
||||
CHECK_ETHWE_MISSING="test ! -d /sys/class/net/ethwe"
|
||||
|
||||
DOCKER_PORT=2375
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ type TestRouterClient struct {
|
||||
}
|
||||
|
||||
func (grouter *TestRouter) run(sender router.PeerName, gossiper router.Gossiper, gossipChan chan interface{}) {
|
||||
gossipTimer := time.Tick(10 * time.Second)
|
||||
gossipTimer := time.Tick(2 * time.Second)
|
||||
for {
|
||||
select {
|
||||
case gossip := <-gossipChan:
|
||||
|
||||
+1
-1
@@ -60,6 +60,6 @@ export DEBIAN_FRONTEND=noninteractive
|
||||
/etc/init.d/puppet stop
|
||||
apt-get -qq remove puppet chef
|
||||
apt-get -qq autoremove
|
||||
killall -9 chef-client
|
||||
killall -9 chef-client 2>/dev/null || true
|
||||
SCRIPT
|
||||
end
|
||||
@@ -420,6 +420,10 @@ create_bridge() {
|
||||
run_iptables -t filter -I FORWARD -i $DOCKER_BRIDGE -o $BRIDGE -j DROP
|
||||
fi
|
||||
|
||||
# let DNS traffic to weaveDNS, since otherwise it might get blocked by the likes of UFW
|
||||
add_iptables_rule filter INPUT -i $DOCKER_BRIDGE -p udp --dport 53 -j ACCEPT
|
||||
add_iptables_rule filter INPUT -i $DOCKER_BRIDGE -p tcp --dport 53 -j ACCEPT
|
||||
|
||||
# Work around the situation where there are no rules allowing traffic
|
||||
# across our bridge. E.g. ufw
|
||||
add_iptables_rule filter FORWARD -i $BRIDGE -o $BRIDGE -j ACCEPT
|
||||
@@ -525,6 +529,8 @@ destroy_bridge() {
|
||||
run_iptables -t filter -D FORWARD -i $DOCKER_BRIDGE -o $BRIDGE -j DROP 2>/dev/null || true
|
||||
fi
|
||||
|
||||
run_iptables -t filter -D INPUT -i $DOCKER_BRIDGE -p udp --dport 53 -j ACCEPT >/dev/null 2>&1 || true
|
||||
run_iptables -t filter -D INPUT -i $DOCKER_BRIDGE -p tcp --dport 53 -j ACCEPT >/dev/null 2>&1 || true
|
||||
run_iptables -t filter -D FORWARD -i $BRIDGE -o $BRIDGE -j ACCEPT 2>/dev/null || true
|
||||
run_iptables -t nat -F WEAVE >/dev/null 2>&1 || true
|
||||
run_iptables -t nat -D POSTROUTING -j WEAVE >/dev/null 2>&1 || true
|
||||
@@ -1475,7 +1481,7 @@ launch_router() {
|
||||
$(router_opts_$BRIDGE_TYPE) \
|
||||
--ipalloc-range "$IPRANGE" \
|
||||
--dns-effective-listen-address $DOCKER_BRIDGE_IP \
|
||||
${NETHOST_OPT:+$DNS_ROUTER_OPTS} $NO_DNS_OPT \
|
||||
${NETHOST_OPT:+$DNS_ROUTER_OPTS --http-addr 127.0.0.1:$HTTP_PORT} $NO_DNS_OPT \
|
||||
--docker-api "unix:///var/run/docker.sock" "$@")
|
||||
with_container_netns_or_die $CONTAINER_NAME setup_router_iface_$BRIDGE_TYPE
|
||||
attach_router
|
||||
@@ -1896,9 +1902,9 @@ EOF
|
||||
arp_update $BRIDGE $CIDR
|
||||
add_iptables_rule nat WEAVE -d $CIDR ! -s $CIDR -j MASQUERADE
|
||||
add_iptables_rule nat WEAVE -s $CIDR ! -d $CIDR -j MASQUERADE
|
||||
if [ -n "$FQDN" ] ; then
|
||||
when_weave_running put_dns_fqdn_no_check_alive weave:expose $FQDN $CIDR
|
||||
fi
|
||||
fi
|
||||
if [ -n "$FQDN" ] ; then
|
||||
when_weave_running put_dns_fqdn_no_check_alive weave:expose $FQDN $CIDR
|
||||
fi
|
||||
done
|
||||
show_addrs $ALL_CIDRS
|
||||
@@ -1927,8 +1933,8 @@ EOF
|
||||
;;
|
||||
stop)
|
||||
[ $# -eq 0 ] || usage
|
||||
stop_proxy
|
||||
stop_router
|
||||
stop_proxy
|
||||
;;
|
||||
stop-router)
|
||||
[ $# -eq 0 ] || usage
|
||||
|
||||
Reference in new issue
Block a user