Compare commits

..
96 Commits
Author SHA1 Message Date
Adam Harrison 6c0075ab82 Add release v1.4.6 2016-03-23 17:37:21 +00:00
Matthias Radestock ae0a4fef50 Merge pull request #2092 from weaveworks/issues/2083-error-not-panic
Change invariant fail on Merge() from panic to error

Fixes #2083.
2016-03-23 16:38:52 +00:00
Matthias Radestock 8360024e06 Merge pull request #2088 from weaveworks/issues/2087-leave-direct-targets
Don't delete targets that seem invalid if they are 'direct' targets

Fixes #2087.
2016-03-23 16:22:08 +00:00
Bryan Boreham 2e4d56efd6 Suspend connecting to targets that seem invalid, if they are 'direct' targets.
Introduce TargetSuspended state to reflect this.
2016-03-23 15:36:55 +00:00
Bryan Boreham 6bc199a8bc Change invariant fail on Merge() from panic to error 2016-03-23 15:26:26 +00:00
Matthias Radestock 537868008f make linter happy 2016-03-22 16:28:25 +00:00
Matthias Radestock 1664fce9d1 Merge pull request #2081 from weaveworks/issues/2023-override-stale-dns
Override stale dns entries received via gossip

Fixes #1867 and #2023.
2016-03-22 13:47:17 +00:00
Bryan Boreham c2cf825cdf Smoke test for stale DNS entries 2016-03-22 12:57:07 +00:00
Bryan Boreham 38a79b7f59 Pick entry with newer tombstone to merge 2016-03-22 12:57:07 +00:00
Bryan Boreham 010766fe9e Check entries claiming to originate from us against our current data, and override if necessary 2016-03-22 12:57:07 +00:00
Matthias Radestock 6b33f4215b Merge branch 'latest_release_doc_updates' into 1.4 2016-03-21 15:53:18 +00:00
Matthias Radestock cc43782d87 Merge pull request #2080 from weaveworks/issues/2061-correct-weave-status
Correct IPAM state docs

Fixes #2061.
2016-03-21 15:49:03 +00:00
Adam Harrison c2eb900dd3 Correct IPAM state docs 2016-03-21 15:33:37 +00:00
Bryan Boreham 001322751f Don't hold Nameserver lock over call out via isKnownPeer 2016-03-21 11:52:13 +00:00
Bryan Boreham b1ec2b788a Bump template name so it will fetch latest Docker 2016-03-19 14:12:17 +00:00
Matthias Radestock f42e275884 broadcast ipam ring update after rmpeer
So that other peers notice the change more promptly.

Fixes #2068.
2016-03-19 13:57:20 +00:00
Matthias Radestock 5dfd104728 reduce docker event subscription retry max interval 2016-03-18 19:29:21 +00:00
Bryan Boreham 9c096526b8 Merge pull request #2049 from weaveworks/issues/2016-retry-docker-event-subscription
Retry docker event subscription
2016-03-16 14:38:27 +00:00
Adam Harrison 922f465ecb Reset retry interval if we spent long enough processing events 2016-03-16 13:41:18 +00:00
Adam Harrison 08e9db900a Retry docker event subscription 2016-03-16 09:23:32 +00:00
Adam Harrison 30b9d33276 Adjust tests to accomodate docker/docker#14012 2016-03-02 11:59:10 +00:00
Bryan Boreham be3f88656b Add release v1.4.5 2016-02-29 22:28:58 +00:00
David Wragg 27367ab292 Process DiscardingFlowOp correctly in FastDatapath send()
The nil FlowOp check in collectFlowOps was not addressed with the
introduction of DiscardingFlowOp.  This meant that DiscardingFlowOps
produced in the router core would get handled by fastdp as if they were
foreign FlowOps, preventing flow creation and so leading to unwarranted
ODP misses.

To fix this, collectFlowOps cannot simply eliminate FlowOps for which
Discards() is true, because it's true for odpFlowKeyFlowOp.  So the
Discards() case has to be handled in FastDatapath send().
2016-02-29 13:27:15 -08:00
Matthias Radestock 20620f0002 Merge branch 'latest_release_doc_updates' into 1.4 2016-02-29 19:13:00 +00:00
Matthias Radestock 8d79e33ba1 remove stale ToC entry
This was missed in 8b061fd55
2016-02-29 19:12:00 +00:00
Bryan Boreham ce4857f5dc Merge pull request #2001 from weaveworks/issues/1996-try-all-pending-allocations
Try all pending allocations - LGTM.  Fixes #1996
2016-02-29 08:20:49 -08:00
Adam Harrison bceabe32a2 Try all pending allocations
We can have outstanding allocations for different ranges owned by
different peers, so we should not short circuit after the first space
request.
2016-02-25 14:56:33 +00:00
Matthias Radestock 6a9f9f66dc don't check for 'Restarting' when attaching on startup
It is overkill.
2016-02-23 13:20:22 +00:00
Adam Harrison 639e0e82c9 Merge pull request #1989 from weaveworks/1977-restarting-not-running
treat 'restarting' as 'not running'
2016-02-23 10:49:31 +00:00
Adam Harrison 4b0a6e1433 Merge pull request #1983 from weaveworks/1929-auto-detect-odp-on-relaunch
don't complain on relaunch when ODP is not supported
2016-02-23 10:46:36 +00:00
Matthias Radestock cb6db91b09 Merge branch 'latest_release_doc_updates' into 1.4 2016-02-23 10:16:08 +00:00
Matthias Radestock 6a02e2dc17 explain TCP/UDP connections, heartbeats, back-off
Fixes #1969
2016-02-23 09:54:15 +00:00
Ilya Dmitrichenko b377207faf Merge branch 'latest_release_doc_updates' into 1.4 2016-02-22 14:16:02 +00:00
Ilya Dmitrichenko 24ebb7cc7c Add missing dependency for latest gsutil 2016-02-22 14:11:36 +00:00
Ilya Dmitrichenko b5518db03c Add missing argument to tar 2016-02-22 14:02:39 +00:00
Ilya Dmitrichenko 2aa4e6a83a Use "official" gsutil installation instructions 2016-02-22 13:58:42 +00:00
Ilya Dmitrichenko 7c655cc3ba Fix false-positive docs uploads 2016-02-22 13:56:49 +00:00
Matthias Radestock 75cda01167 Merge branch 'latest_release_doc_updates' into 1.4 2016-02-22 13:55:18 +00:00
Matthias Radestock 4f0f3cf98d warn against using the plugin in combination with --net=weave
and expand the basic proxy usage docs slightly.
2016-02-22 13:53:39 +00:00
Matthias Radestock e014140134 Merge branch 'latest_release_doc_updates' into 1.4 2016-02-22 13:36:33 +00:00
Matthias Radestock c8ae128e59 for Travis, this no longer is a go project
Travis insists that one picks a project language. There is no go left
in the steps executed by travis. Instead we have Python, Ruby and
shell. Let's pick the first...

Picking Python makes travis unhappy with "Can not perform a '--user'
install. User site-packages are not visible in this
virtualenv". Dropping the '--user' flag fixes that.

(cherry picked from commit 1d8d098450)
2016-02-22 13:29:33 +00:00
Matthias Radestock 12d848162d shrink Travis usage
There is no point running builds, tests, lints on Travis, since we
already do that on Circle.

The only thing we aren't doing (and can't do) on Circle is doc
publishing, so now Travis does just that.

(cherry picked from commit 1038cbd1a3)
2016-02-22 13:29:33 +00:00
Matthias Radestock b12096bd6c tweak 2016-02-22 13:23:29 +00:00
Matthias Radestock 1430982166 Merge branch 'latest_release_doc_updates' into 1.4 2016-02-22 13:13:13 +00:00
Matthias Radestock 2a83aad1d6 warn against using plugin and proxy simultaneously
and give a complete example.

Partially addresses #1988.
2016-02-22 13:11:02 +00:00
Matthias Radestock 4a7157959a don't attempt to attach 'restarting' containers
this is an optimisation... there is no point attempting to attach a
'restarting' container - it will fail.

When the container *actually* restarts we'll get a 'Start' event, and
attach at that point.

Also, there is no point checking for 'Paused' since 'Paused' ->
'Running'.
2016-02-20 11:00:04 +00:00
Matthias Radestock e52abafc48 treat restarting containers as "not running"
thus preventing stale DNS & IPAM entries.

Fixes #1977
2016-02-20 10:59:47 +00:00
Matthias Radestock ee531b8023 don't complain on relaunch when ODP is not supported
...and WEAVE_NO_FASTDP isn't set.

Fixes #1929.
2016-02-18 22:00:08 +00:00
Matthias Radestock 5e761a62b0 Merge pull request #1985 from weaveworks/issues/1984-discovery
Add two functions required by ipamapi "contract"

Fixes #1984
2016-02-18 21:55:53 +00:00
Bryan Boreham b442567406 Add two functions required by ipamapi "contract" but not actually used 2016-02-18 15:29:10 +00:00
Matthias Radestock 17d53af2a2 improve logging of dns entry creation
- log inside the lock, so we get proper serialisation
- include the container name, so we can identify the specific entry
2016-02-16 14:04:34 +00:00
Adam Harrison 1228dbddb9 Add release v1.4.4 2016-02-09 11:20:51 +00:00
Adam Harrison c00b00d623 Merge pull request #1963 from weaveworks/issues/1959-dont-remove-network
Don't remove weave network on plugin shutdown because it bricks Docker 1.10
2016-02-09 10:53:13 +00:00
Bryan Boreham 7bbc9f1b82 Don't remove the weave network on shutdown because it bricks Docker 1.10 2016-02-09 10:02:06 +00:00
Matthias Radestock 15a92f9c92 Merge pull request #1961 from weaveworks/issues/1956-any-iface
Wait for multicast route on any interface

Fixes #1956.
2016-02-09 09:29:05 +00:00
Bryan Boreham 9386c01845 Wait for multicast route on any interface, to match weave script
which only adds a route if there isn't one already
2016-02-08 14:04:25 +00:00
Adam Harrison 5232a9af6b Add release v1.4.3 2016-02-02 16:35:32 +00:00
Adam Harrison c393b23b31 Merge pull request #1918 from weaveworks/issues/1906-plugin-no-weave
Return an error when weave isn't running, on RequestPool
2016-02-02 15:54:39 +00:00
Adam Harrison 955fbca44a Merge pull request #1943 from weaveworks/1942-mcast-iface-up
don't set the interface 'up' before it is fully configured
2016-02-01 15:29:46 +00:00
Matthias Radestock 18c26e9fbb don't set the interface 'up' before it is fully configured
This was causing container entrypoints to execute too early,
e.g. before the interface had been given an IP address. But only when
running with --no-multicast-route, since otherwise weavewait is
waiting for the multicast route to appear.

Fixes #1942.
2016-02-01 12:04:15 +00:00
Matthias Radestock b54efbde69 fix typo in comment 2016-01-30 11:15:57 +00:00
Matthias Radestock be9d64b2cc Merge pull request #1936 from weaveworks/issues/1934-rm-socket
Remove Unix domain sockets on shutdown

Fixes #1934.
2016-01-29 15:46:24 +00:00
Matthias Radestock c6f356a167 Merge pull request #1935 from weaveworks/issues/1757-volumes-container
Reduce docker volumes for weavewait to just one set per release

Fixes #1757.
2016-01-29 15:24:42 +00:00
Matthias Radestock eae45ebc94 Merge pull request #1921 from weaveworks/issues/1745-plugin-ps
Make weave script scan veths with prefix 'ethwe'

Fixes #1745
2016-01-29 12:45:10 +00:00
Bryan Boreham ea50b3d5cc Create a different weavevolumes container for each Weave version.
They will be named 'weavevolumes-v1.4.3', 'weavevolumes-latest', etc.
Use a label to identify these containers so they can all be removed on `weave reset`.
2016-01-29 12:22:22 +00:00
Bryan Boreham 3297b93edb Smoke-test 'weave ps' and restarting when using plugin 2016-01-29 12:13:00 +00:00
Bryan Boreham 6d0e867ad0 Capture addresses from veths with prefix 'ethwe'
This is to address the plugin case, where the veth will have a name like 'ethwe0'.
Previously we only looked at the device named exactly 'ethwe'.
Covers `weave ps` and reclaim of addresses for IPAM and WeaveDNS.
2016-01-29 12:13:00 +00:00
Bryan Boreham 1cea9c1c87 Extract function to detect container running in host namespace 2016-01-29 12:13:00 +00:00
Bryan Boreham 3320a9e7d4 Re-organise code so we can clean up using defer and return error codes to top level 2016-01-29 11:41:24 +00:00
Bryan Boreham 9b90a938f5 Remove Unix domain sockets on shutdown 2016-01-28 18:26:34 +00:00
Matthias Radestock c6d0149ba6 add missing dependency
The plugin image derives from the weaveexec image.
2016-01-28 17:50:26 +00:00
Bryan Boreham 598efe5d1a Reduce docker volumes for weavewait to just one set.
- Create an auxilliary container 'weavevolumes' to hold the '/w/w'
  files, and map into that instead of creating new volumes every time.
- Show "/bin/false" as its command in `docker ps` instead of
"/home/weave/sigproxy".
- Remove volumes when cleaning up smoketest containers.
2016-01-28 15:57:22 +00:00
Matthias Radestock 3679065258 cope with nil route.Dst
Fixes #1932.
2016-01-27 22:02:07 +00:00
Matthias Radestock 4649f1158a Merge pull request #1926 from weaveworks/issues/1905-fix-negative-fragment
Negative fragment fix

Fixes #1905.
2016-01-26 16:56:03 +00:00
Adam Harrison de17a44f35 Fix fragmentation test
The assumptions on which this test was based were violated by the
introduction of fast datapath. A new rule is required to block fast
datapath traffic, to ensure that sleeve is selected for forwarding; the
rules must also be moved from the FORWARD chain to INPUT as the router
now runs in the host netns (NB we use INPUT instead of OUTPUT as the
latter results in sleeve receiving an 'operation not permitted' udpv4
write error when it tries to send a packet that is too big, rather than
the packet just being silently dropped as required)
2016-01-25 10:58:31 +00:00
Adam Harrison 52ce4df18e Increase the lowest possible good PMTU
The current minimum PMTU we can detect is eight bytes, which, being
lower than the minimum IPv4 MTU of 68 bytes, can cause an exception in
the sleeve packet fragmentation implementation. We increase that minimum
to 552, the lowest PMTU value that Linux will cache.
2016-01-25 10:53:10 +00:00
Matthias Radestock f1ed5bf838 Merge branch 'latest_release_doc_updates' into 1.4 2016-01-22 13:35:27 +00:00
Matthias Radestock 256a801d16 typo 2016-01-22 13:34:59 +00:00
Matthias Radestock c416cf8da5 tidying of plugin docs 2016-01-22 13:27:22 +00:00
Matthias Radestock 75e812a061 Merge branch 'latest_release_doc_updates' into 1.4 2016-01-21 12:30:14 +00:00
Matthias Radestock 4cc7b01940 Merge pull request #1907 from weaveworks/systemd-timeout
Suggest disabling systemd timeout if using Weave Net plugin
2016-01-21 12:29:42 +00:00
Matthias Radestock a2ff7e5981 Merge pull request #1919 from weaveworks/issues/1900-dont-stop-stoppin
Warn, don't error, if unable to remove network in 'weave stop'

Fixes #1900.
2016-01-21 11:22:21 +00:00
Bryan Boreham cda98a6375 Merge pull request #1917 from weaveworks/issues/1911-fix-unexpected-eof
Fix unexpected EOF with Docker 1.10-rc1 and proxy --rewrite-inspect
2016-01-21 10:15:20 +00:00
Matthias Radestock 3b7a754b0a Merge branch 'latest_release_doc_updates' into 1.4 2016-01-20 18:56:26 +00:00
Anita Buehrle c01c6bcb91 fixed logo image in header 2016-01-20 12:48:31 -06:00
Bryan Boreham e47360f8dc Warn, don't error, if unable to remove network in 'weave stop' 2016-01-20 16:18:09 +00:00
Bryan Boreham 6035b54277 Send back an http error code in case of error, so Docker is clear something went wrong 2016-01-20 15:36:42 +00:00
Bryan Boreham a238130613 Give more explanation if we can't find weave to talk to 2016-01-20 15:36:34 +00:00
Bryan Boreham 998be42a52 Don't crash if no default subnet available 2016-01-20 15:36:25 +00:00
Adam Harrison 14944da396 Ignore stderr in proxy_addrs 2016-01-20 14:24:59 +00:00
Adam Harrison a3974c2aeb Abort inspect exec rewrite unless Containers node is present 2016-01-20 14:24:28 +00:00
Bryan Boreham 13ec517f94 Merge pull request #1910 from weaveworks/1909-forEachRoute-panic
cope with errors during route traversal
2016-01-20 14:05:10 +00:00
Matthias Radestock 43419815f4 bypass netlink.LinkByIndex
since we are seeing some cases where it returns "Link not found" when
the link is in fact there.
2016-01-19 16:36:16 +00:00
Matthias Radestock b5256f7b71 refactor: inline
This eliminates the unnecessary indirection via interface names,
instead identifying the interface by its index.
2016-01-19 16:36:16 +00:00
Matthias Radestock 0caa9dd652 cope with errors during route traversal
Fixes #1909.
2016-01-19 15:28:31 +00:00
Bryan Boreham 5e1e8ec543 Suggest user disables systemd timeout if using plugin 2016-01-18 11:45:17 +00:00
37 changed files with 512 additions and 195 deletions

No files matched your search

+5 -20
View File
@@ -1,28 +1,13 @@
language: go
language: python
sudo: false
go:
- 1.4
env:
- PATH="${PATH}:${HOME}/.local/bin"
addons:
apt:
packages:
- libpcap-dev
- PATH="${PATH}:${HOME}/gsutil"
install:
- go clean -i net
- go install -tags netgo std
- go get github.com/golang/lint/golint
- pip install --user --upgrade gsutil
- pip install pyopenssl
- curl --silent --location https://storage.googleapis.com/pub/gsutil.tar.gz | tar xz -C $HOME
- bin/setup-ci-secrets $encrypted_5ba036e89377_key $encrypted_5ba036e89377_iv
- make travis
- go get ./...
script:
- make tests
after_success:
- go get github.com/mattn/goveralls
- test "${TRAVIS_PULL_REQUEST}" = "false" && site/build-and-publish.sh
- 'test "${TRAVIS_PULL_REQUEST}" = "true" || site/build-and-publish.sh'
+74
View File
@@ -1,3 +1,77 @@
## Release 1.4.6
Fixes some issues encountered by our users.
* Restarting a peer could leave stale entries in WeaveDNS
#1867/#2023/#2081
* Weave proxy occasionally failing to attach any new containers
#2016/#2049
Other fixes:
* Resolved a crash when a restarting peer re-connected to a peer that
had not received the latest IPAM data #2083/#2092
* Make IP address space available immediately after a dead peer is
removed #2068
## Release 1.4.5
Higher performance for multicast and broadcast traffic when using
Weave's Fast Datapath
* The flow rule to deliver broadcast and multicast packets in-kernel
was not created correctly, hence every such packet caused a
context-switch to the software router #2003/#2008
Other fixes:
* Remove DNS entries for containers that are being restarted by Docker
but are not live yet #1977/#1989
* Don't let one failing allocation attempt prevent others from
succeeding; they could be in different subnets which are more
available #1996/#2001
* Don't complain on second router launch on kernels that lack support
for Fast Datapath #1929/#1983
* Fix build broken by change in libnetwork IPAM API #1984/#1985
## Release 1.4.4
Fixing a rather serious issue that slipped through our preparations
for Docker 1.10:
* Restarting Docker or rebooting your machine while the Weave Net
plugin is running causes Docker 1.10.0 to fail to start #1959/#1963
Also one other small fix:
* Avoid a hang when trying to use plugin and proxy at the same time
#1956/#1961
## Release 1.4.3
Preparing for Docker 1.10, plus some bug-fixes.
* Avoid hang in Docker v1.10 on `docker volume ls` after `weave stop`,
`weave stop-plugin` or `weave reset` #1934/#1936
* Fix "unexpected EOF" from Docker 1.10 on `docker exec` with Weave
proxy `--rewrite-inspect` enabled #1911/#1917
* Avoid losing DNS entries and potentially double-allocating IP
Addresses allocated via plugin, on router restart; also extend
`weave ps` to show IP addresses allocated via plugin #1745/#1921
* Stop creating lots of copies of `weavewait` program in Docker
volumes #1757/#1935
* Prevent container starting prematurely when proxy in
`--no-multicast-route` mode #1942/#1943
* Log error message from plugin rather than crashing when weave not
running #1906/#1918
* Warn, don't error, if unable to remove plugin network in 'weave
stop', to avoid breaking the usual upgrade or config change process
#1900/#1919
* Don't crash if network conditions suggest only very small packets
will get through #1905/#1926
* Cope with unexpected errors during route traversal when starting
container via proxy #1909/#1910/#1932
## Release 1.4.2
Bug-fixes and minor improvements.
+1 -1
View File
@@ -119,7 +119,7 @@ $(WEAVEEXEC_UPTODATE): prog/weaveexec/Dockerfile prog/weaveexec/symlink $(DOCKER
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker build -t $(WEAVEEXEC_IMAGE) prog/weaveexec
touch $@
$(DOCKERPLUGIN_UPTODATE): prog/plugin/Dockerfile $(DOCKERPLUGIN_EXE)
$(DOCKERPLUGIN_UPTODATE): prog/plugin/Dockerfile $(DOCKERPLUGIN_EXE) $(WEAVEEXEC_UPTODATE)
$(SUDO) docker build -t $(DOCKERPLUGIN_IMAGE) prog/plugin
touch $@
+33 -15
View File
@@ -4,12 +4,18 @@ import (
"errors"
"fmt"
"strings"
"time"
docker "github.com/fsouza/go-dockerclient"
. "github.com/weaveworks/weave/common"
)
const (
InitialInterval = 1 * time.Second
MaxInterval = 20 * time.Second
)
// An observer for container events
type ContainerObserver interface {
ContainerStarted(ident string)
@@ -72,21 +78,33 @@ func (c *Client) Info() string {
// AddObserver adds an observer for docker events
func (c *Client) AddObserver(ob ContainerObserver) error {
events := make(chan *docker.APIEvents)
if err := c.AddEventListener(events); err != nil {
Log.Errorf("[docker] Unable to add listener to Docker API: %s", err)
return err
}
go func() {
for event := range events {
switch event.Status {
case "start":
id := event.ID
ob.ContainerStarted(id)
case "die":
id := event.ID
ob.ContainerDied(id)
retryInterval := InitialInterval
for {
events := make(chan *docker.APIEvents)
if err := c.AddEventListener(events); err != nil {
Log.Errorf("[docker] Unable to add listener to Docker API: %s - retrying in %ds", err, retryInterval/time.Second)
} else {
start := time.Now()
for event := range events {
switch event.Status {
case "start":
id := event.ID
ob.ContainerStarted(id)
case "die":
id := event.ID
ob.ContainerDied(id)
}
}
if time.Since(start) > retryInterval {
retryInterval = InitialInterval
}
Log.Errorf("[docker] Event listener channel closed - retrying subscription in %ds", retryInterval/time.Second)
}
time.Sleep(retryInterval)
retryInterval = retryInterval * 3 / 2
if retryInterval > MaxInterval {
retryInterval = MaxInterval
}
}
}()
@@ -97,7 +115,7 @@ func (c *Client) AddObserver(ob ContainerObserver) error {
func (c *Client) IsContainerNotRunning(idStr string) bool {
container, err := c.InspectContainer(idStr)
if err == nil {
return !container.State.Running
return !container.State.Running || container.State.Restarting
}
if _, notThere := err.(*docker.NoSuchContainer); notThere {
return true
+15 -18
View File
@@ -140,29 +140,23 @@ func (alloc *Allocator) cancelOpsFor(ops *[]operation, ident string) bool {
return found
}
// Try all pending operations
func (alloc *Allocator) tryPendingOps() {
// The slightly different semantics requires us to operate on 'claims' and
// 'allocates' separately:
// Claims must be tried before Allocates
for i := 0; i < len(alloc.pendingClaims); {
op := alloc.pendingClaims[i]
// Try all operations in a queue
func (alloc *Allocator) tryOps(ops *[]operation) {
for i := 0; i < len(*ops); {
op := (*ops)[i]
if !op.Try(alloc) {
i++
continue
}
alloc.pendingClaims = append(alloc.pendingClaims[:i], alloc.pendingClaims[i+1:]...)
*ops = append((*ops)[:i], (*ops)[i+1:]...)
}
}
// When the first Allocate fails, bail - no need to
// send too many begs for space.
for i := 0; i < len(alloc.pendingAllocates); {
op := alloc.pendingAllocates[i]
if !op.Try(alloc) {
break
}
alloc.pendingAllocates = append(alloc.pendingAllocates[:i], alloc.pendingAllocates[i+1:]...)
}
// Try all pending operations
func (alloc *Allocator) tryPendingOps() {
// Process existing claims before servicing new allocations
alloc.tryOps(&alloc.pendingClaims)
alloc.tryOps(&alloc.pendingAllocates)
}
func (alloc *Allocator) spaceRequestDenied(sender mesh.PeerName, r address.Range) {
@@ -340,7 +334,10 @@ func (alloc *Allocator) AdminTakeoverRanges(peerNameOrNickname string) error {
}
newRanges, err := alloc.ring.Transfer(peername, alloc.ourName)
alloc.space.AddRanges(newRanges)
if err == nil && len(newRanges) > 0 {
alloc.space.AddRanges(newRanges)
alloc.gossip.GossipBroadcast(alloc.Gossip())
}
resultChan <- err
}
return <-resultChan
+16 -9
View File
@@ -46,33 +46,37 @@ var (
)
func (r *Ring) checkInvariants() error {
if !sort.IsSorted(r.Entries) {
return r.checkEntries(r.Entries)
}
func (r *Ring) checkEntries(entries entries) error {
if !sort.IsSorted(entries) {
return ErrNotSorted
}
// Check no token appears twice
// We know it's sorted...
for i := 1; i < len(r.Entries); i++ {
if r.Entries[i-1].Token == r.Entries[i].Token {
for i := 1; i < len(entries); i++ {
if entries[i-1].Token == entries[i].Token {
return ErrTokenRepeated
}
}
if len(r.Entries) == 0 {
if len(entries) == 0 {
return nil
}
// Check tokens are in range
if r.Entries.entry(0).Token < r.Start {
if entries.entry(0).Token < r.Start {
return ErrTokenOutOfRange
}
if r.Entries.entry(-1).Token >= r.End {
if entries.entry(-1).Token >= r.End {
return ErrTokenOutOfRange
}
// Check all the freespaces are in range
for i, entry := range r.Entries {
next := r.Entries.entry(i + 1)
for i, entry := range entries {
next := entries.entry(i + 1)
distance := r.distance(entry.Token, next.Token)
if entry.Free > distance {
@@ -181,7 +185,6 @@ func (r *Ring) GrantRangeToHost(start, end address.Address, peer mesh.PeerName)
// Merge the given ring into this ring and return any new ranges added
func (r *Ring) Merge(gossip Ring) error {
r.assertInvariants()
defer r.assertInvariants()
defer r.updateExportedVariables()
// Don't panic when checking the gossiped in ring.
@@ -267,6 +270,10 @@ func (r *Ring) Merge(gossip Ring) error {
previousOwner = nil
}
if err := r.checkEntries(result); err != nil {
return fmt.Errorf("Merge of incoming data causes: %s", err)
}
if len(r.Seeds) == 0 {
r.Seeds = gossip.Seeds
}
+10 -2
View File
@@ -32,6 +32,7 @@ const (
TargetWaiting TargetState = iota // we are waiting to connect there
TargetAttempting // we are attempting to connect there
TargetConnected // we are connected to there
TargetSuspended // not currently attempting to connect here
)
// Information about an address where we may find a peer
@@ -266,16 +267,23 @@ func (cm *ConnectionMaker) connectToTargets(validTarget map[string]struct{}, dir
now := time.Now() // make sure we catch items just added
after := MaxDuration
for address, target := range cm.targets {
if target.state != TargetWaiting {
if target.state != TargetWaiting && target.state != TargetSuspended {
continue
}
if _, valid := validTarget[address]; !valid {
delete(cm.targets, address)
// Not valid: suspend reconnects if direct peer,
// otherwise forget this target entirely
if _, direct := directTarget[address]; direct {
target.state = TargetSuspended
} else {
delete(cm.targets, address)
}
continue
}
if target.tryAfter.IsZero() {
continue
}
target.state = TargetWaiting
switch duration := target.tryAfter.Sub(now); {
case duration <= 0:
target.state = TargetAttempting
+1
View File
@@ -181,6 +181,7 @@ func NewLocalConnectionStatusSlice(cm *ConnectionMaker) []LocalConnectionStatus
add("retrying", target.lastError.Error())
}
case TargetConnected:
case TargetSuspended:
}
}
resultChan <- slice
+20 -2
View File
@@ -93,6 +93,9 @@ func (e1 *Entry) merge(e2 *Entry) bool {
e1.Version = e2.Version
e1.Tombstone = e2.Tombstone
return true
} else if e2.Version == e1.Version && e2.Tombstone > e1.Tombstone {
e1.Tombstone = e2.Tombstone
return true
}
return false
}
@@ -105,6 +108,11 @@ func (e1 *Entry) addLowercase() {
e1.lHostname = strings.ToLower(e1.Hostname)
}
func (e1 *Entry) tombstone() {
e1.Version++
e1.Tombstone = now()
}
func check(es SortableEntries) error {
if !sort.IsSorted(es) {
return fmt.Errorf("Not sorted!")
@@ -182,8 +190,7 @@ func (es *Entries) tombstone(ourname mesh.PeerName, f func(*Entry) bool) Entries
tombstoned := Entries{}
for i, e := range *es {
if f(&e) && e.Origin == ourname {
e.Version++
e.Tombstone = now()
e.tombstone()
(*es)[i] = e
tombstoned = append(tombstoned, e)
}
@@ -191,6 +198,7 @@ func (es *Entries) tombstone(ourname mesh.PeerName, f func(*Entry) bool) Entries
return tombstoned
}
// note f() may only modify entries such that they remain in order defined by less()
func (es *Entries) filter(f func(*Entry) bool) {
defer es.checkAndPanic().checkAndPanic()
@@ -205,6 +213,16 @@ func (es *Entries) filter(f func(*Entry) bool) {
*es = (*es)[:i]
}
func (es Entries) findEqual(e *Entry) (*Entry, bool) {
i := sort.Search(len(es), func(i int) bool {
return !es[i].insensitiveLess(e)
})
if i < len(es) && es[i].equal(*e) {
return &es[i], true
}
return nil, false
}
func (es Entries) lookup(hostname string) Entries {
es.checkAndPanic()
+15
View File
@@ -86,6 +86,21 @@ func TestTombstone(t *testing.T) {
Entry{Hostname: "B", Version: 1, Tombstone: 1234},
})
require.Equal(t, expected, es)
// Now try a merge including two entries which differ only in tombstone
e2 := make(Entries, len(es))
copy(e2, es)
e2[1].Tombstone = 5555
diff := es.merge(e2)
expected2 := l(Entries{
Entry{Hostname: "A"},
Entry{Hostname: "B", Version: 1, Tombstone: 5555},
})
require.Equal(t, expected2, es)
expectedDiff := l(Entries{Entry{Hostname: "B", Version: 1, Tombstone: 5555}})
require.Equal(t, expectedDiff, diff)
}
func TestDelete(t *testing.T) {
+22 -2
View File
@@ -84,8 +84,8 @@ func (n *Nameserver) broadcastEntries(es ...Entry) error {
}
func (n *Nameserver) AddEntry(hostname, containerid string, origin mesh.PeerName, addr address.Address) error {
n.infof("adding entry %s -> %s", hostname, addr.String())
n.Lock()
n.infof("adding entry for %s: %s -> %s", containerid, hostname, addr.String())
entry := n.entries.add(hostname, containerid, origin, addr)
n.Unlock()
return n.broadcastEntries(entry)
@@ -203,11 +203,31 @@ func (n *Nameserver) receiveGossip(msg []byte) (mesh.GossipData, mesh.GossipData
return nil, nil, fmt.Errorf("clock skew of %d detected", delta)
}
// Filter to remove entries from unknown peers, done before we take
// the nameserver lock, so we don't have to worry what isKnownPeer locks.
gossip.Entries.filter(func(e *Entry) bool {
return n.isKnownPeer(e.Origin)
})
n.Lock()
defer n.Unlock()
// Check entries claiming to originate from us against our current data
gossip.Entries.filter(func(e *Entry) bool {
return n.isKnownPeer(e.Origin)
if e.Origin == n.ourName {
if ourEntry, ok := n.entries.findEqual(e); ok {
if ourEntry.Version < e.Version ||
(ourEntry.Version == e.Version && ourEntry.Tombstone != e.Tombstone) {
// Take our version of the data, but make the version higher than the incoming
nextVersion := e.Version + 1
*e = *ourEntry
e.Version = nextVersion
}
} else { // We have no entry matching the one that came in with us as Origin
e.tombstone()
}
}
return true
})
newEntries := n.entries.merge(gossip.Entries)
+16 -7
View File
@@ -52,16 +52,25 @@ func EnsureInterfaceAndMcastRoute(ifaceName string) (*net.Interface, error) {
return nil, err
}
dest := net.IPv4(224, 0, 0, 0)
// check for currently-existing route after subscribing, to avoid race
if CheckRouteExists(ifaceName, dest) {
return iface, err
check := func(route netlink.Route) bool {
return route.Dst != nil && route.Dst.IP.Equal(dest)
}
for update := range ch {
link, _ := netlink.LinkByIndex(update.Route.LinkIndex)
if link.Attrs().Name == ifaceName && update.Route.Dst.IP.Equal(dest) {
break
// check for currently-existing route after subscribing, to avoid race
routes, err := netlink.RouteList(nil, netlink.FAMILY_V4)
if err != nil {
return nil, err
}
for _, route := range routes {
if check(route) {
return iface, nil
}
}
for update := range ch {
if check(update.Route) {
return iface, nil
}
}
// should never get here
return iface, nil
}
+12 -20
View File
@@ -10,7 +10,7 @@ import (
// A network is considered free if it does not overlap any existing
// routes on this host. This is the same approach taken by Docker.
func CheckNetworkFree(subnet *net.IPNet, ignoreIfaceNames map[string]struct{}) error {
return forEachRoute(ignoreIfaceNames, func(name string, route netlink.Route) error {
return forEachRoute(ignoreIfaceNames, func(route netlink.Route) error {
if route.Dst != nil && overlaps(route.Dst, subnet) {
return fmt.Errorf("Network %s overlaps with existing route %s on host.", subnet, route.Dst)
}
@@ -26,7 +26,7 @@ func overlaps(n1, n2 *net.IPNet) bool {
// For a specific address, we only care if it is actually *inside* an
// existing route, because weave-local traffic never hits IP routing.
func CheckAddressOverlap(addr net.IP, ignoreIfaceNames map[string]struct{}) error {
return forEachRoute(ignoreIfaceNames, func(name string, route netlink.Route) error {
return forEachRoute(ignoreIfaceNames, func(route netlink.Route) error {
if route.Dst != nil && route.Dst.Contains(addr) {
return fmt.Errorf("Address %s overlaps with existing route %s on host.", addr, route.Dst)
}
@@ -34,32 +34,24 @@ func CheckAddressOverlap(addr net.IP, ignoreIfaceNames map[string]struct{}) erro
})
}
func forEachRoute(ignoreIfaceNames map[string]struct{}, check func(name string, r netlink.Route) error) error {
func forEachRoute(ignoreIfaceNames map[string]struct{}, check func(r netlink.Route) error) error {
ignoreIfaceIndices := make(map[int]struct{})
for ifaceName := range ignoreIfaceNames {
if iface, err := net.InterfaceByName(ifaceName); err == nil {
ignoreIfaceIndices[iface.Index] = struct{}{}
}
}
routes, err := netlink.RouteList(nil, netlink.FAMILY_V4)
if err != nil {
return err
}
for _, route := range routes {
link, err := netlink.LinkByIndex(route.LinkIndex)
if err == nil {
if _, found := ignoreIfaceNames[link.Attrs().Name]; found {
continue
}
if _, found := ignoreIfaceIndices[route.LinkIndex]; found {
continue
}
if err := check(link.Attrs().Name, route); err != nil {
if err := check(route); err != nil {
return err
}
}
return nil
}
func CheckRouteExists(ifaceName string, dest net.IP) bool {
found := false
forEachRoute(map[string]struct{}{}, func(name string, route netlink.Route) error {
if name == ifaceName && route.Dst.IP.Equal(dest) {
found = true
}
return nil
})
return found
}
+23 -1
View File
@@ -1,10 +1,13 @@
package ipamplugin
import (
"fmt"
"net"
"github.com/docker/libnetwork/discoverapi"
"github.com/docker/libnetwork/ipamapi"
"github.com/docker/libnetwork/netlabel"
godocker "github.com/fsouza/go-dockerclient"
"github.com/weaveworks/weave/api"
. "github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/common/docker"
@@ -20,7 +23,13 @@ type ipam struct {
}
func NewIpam(client *docker.Client, version string) (ipamapi.Ipam, error) {
resolver := func() (string, error) { return client.GetContainerIP(WeaveContainer) }
resolver := func() (string, error) {
addr, err := client.GetContainerIP(WeaveContainer)
if _, ok := err.(*godocker.NoSuchContainer); ok {
return "", fmt.Errorf("%s container is not present. Have you launched it?", WeaveContainer)
}
return addr, err
}
return &ipam{client: client, weave: api.NewClientWithResolver(resolver)}, nil
}
@@ -33,6 +42,9 @@ func (i *ipam) RequestPool(addressSpace, pool, subPool string, options map[strin
Log.Debugln("RequestPool", addressSpace, pool, subPool, options)
cidr, err := i.weave.DefaultSubnet()
Log.Debugln("RequestPool returning ", cidr, err)
if err != nil {
return "", nil, nil, err
}
// Pass back a fake "gateway address"; we don't actually use it,
// so just give the network address.
data := map[string]string{netlabel.Gateway: cidr.String()}
@@ -56,3 +68,13 @@ func (i *ipam) ReleaseAddress(poolID string, address net.IP) error {
Log.Debugln("ReleaseAddress", poolID, address)
return i.weave.ReleaseIP(address.String())
}
// Functions required by ipamapi "contract" but not actually used.
func (i *ipam) DiscoverNew(discoverapi.DiscoveryType, interface{}) error {
return nil
}
func (i *ipam) DiscoverDelete(discoverapi.DiscoveryType, interface{}) error {
return nil
}
+1
View File
@@ -265,6 +265,7 @@ func sendError(w http.ResponseWriter, msg string, code int) {
}
func errorResponse(w http.ResponseWriter, fmtString string, item ...interface{}) {
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(map[string]string{
"Err": fmt.Sprintf(fmtString, item...),
})
+19 -15
View File
@@ -69,25 +69,35 @@ func main() {
Log.Println("Weave plugin", version, "Command line options:", os.Args[1:])
Log.Info(dockerClient.Info())
var globalListener, meshListener net.Listener
err = run(dockerClient, address, meshAddress, meshNetworkName, nameserver, noMulticastRoute)
if err != nil {
Log.Fatal(err)
}
}
func run(dockerClient *docker.Client, address, meshAddress, meshNetworkName, nameserver string, noMulticastRoute bool) error {
endChan := make(chan error, 1)
if address != "" {
globalListener, err := listenAndServe(dockerClient, address, nameserver, noMulticastRoute, endChan, "global", false)
if err != nil {
Log.Fatalf("unable to create driver: %s", err)
return err
}
defer os.Remove(address)
defer globalListener.Close()
}
if meshAddress != "" {
meshListener, err := listenAndServe(dockerClient, meshAddress, nameserver, noMulticastRoute, endChan, "local", true)
if err != nil {
Log.Fatalf("unable to create driver: %s", err)
return err
}
defer os.Remove(meshAddress)
defer meshListener.Close()
}
if meshNetworkName != "" {
createNetwork(dockerClient, meshNetworkName, meshAddress)
if err := createNetwork(dockerClient, meshNetworkName, meshAddress); err != nil {
return err
}
}
sigChan := make(chan os.Signal, 1)
@@ -96,16 +106,9 @@ func main() {
select {
case sig := <-sigChan:
Log.Debugf("Caught signal %s; shutting down", sig)
if err := dockerClient.Client.RemoveNetwork(meshNetworkName); err != nil {
Log.Fatal(err)
}
return nil
case err := <-endChan:
if err != nil {
Log.Errorf("Error from listener: %s", err)
globalListener.Close()
meshListener.Close()
os.Exit(1)
}
return err
}
}
@@ -141,7 +144,7 @@ func listenAndServe(dockerClient *docker.Client, address, nameserver string, noM
return listener, nil
}
func createNetwork(dockerClient *docker.Client, networkName, address string) {
func createNetwork(dockerClient *docker.Client, networkName, address string) error {
if _, err := dockerClient.Client.NetworkInfo(networkName); err == nil {
Log.Printf("Docker network '%s' already exists", networkName)
} else if _, ok := err.(*go_docker.NoSuchNetwork); ok {
@@ -157,7 +160,8 @@ func createNetwork(dockerClient *docker.Client, networkName, address string) {
}
_, err := dockerClient.Client.CreateNetwork(options)
if err != nil {
Log.Fatalf("Error creating network: %s", err)
return fmt.Errorf("Error creating network: %s", err)
}
}
return nil
}
-3
View File
@@ -4,9 +4,6 @@ MAINTAINER Weaveworks Inc <help@weave.works>
LABEL works.weave.role=system
WORKDIR /home/weave
VOLUME /w
VOLUME /w-noop
VOLUME /w-nomcast
ENTRYPOINT ["/home/weave/sigproxy", "/home/weave/weave"]
RUN apk add --update \
+4
View File
@@ -22,6 +22,10 @@ func (i *inspectExecInterceptor) InterceptResponse(r *http.Response) error {
return err
}
if _, ok := exec["Container"]; !ok {
return nil
}
container, err := exec.Object("Container")
if err != nil {
return err
+2 -1
View File
@@ -132,7 +132,8 @@ func (proxy *Proxy) AttachExistingContainers() {
}
continue
}
if containerShouldAttach(container) && (container.State.Running || container.State.Paused) {
// The 'Running' check is purely an optimisation.
if containerShouldAttach(container) && container.State.Running {
proxy.attach(container, false)
}
}
+8 -4
View File
@@ -775,10 +775,10 @@ func (fwd *fastDatapathForwarder) Forward(key ForwardPacketKey) FlowOp {
defer fwd.lock.RUnlock()
if fwd.remoteAddr == nil {
// Returning nil would discard the packet, but also
// result in a flow rule, which we would have to
// invalidate when we learn the remote IP. So for
// now, just prevent flows.
// Returning a DiscardingFlowOp would discard the
// packet, but also result in a flow rule, which we
// would have to invalidate when we learn the remote
// IP. So for now, just prevent flows.
return vetoFlowCreationFlowOp{}
}
@@ -1086,6 +1086,10 @@ func (fastdp *FastDatapath) send(fops FlowOp, frame []byte, lock *fastDatapathLo
case vetoFlowCreationFlowOp:
createFlow = false
default:
if xfop.Discards() {
continue
}
// A foreign FlowOp (e.g. a sleeve forwarding
// FlowOp), so send the packet through the
// FlowOp interface, decoding the packet
+1 -4
View File
@@ -84,15 +84,12 @@ func (mfop *MultiFlowOp) Discards() bool {
return true
}
// Flatten out a FlowOp to eliminate any MultiFlowOps
func FlattenFlowOp(fop FlowOp) []FlowOp {
return collectFlowOps(nil, fop)
}
func collectFlowOps(into []FlowOp, fop FlowOp) []FlowOp {
if fop == nil {
return into
}
if mfop, ok := fop.(*MultiFlowOp); ok {
for _, op := range mfop.ops {
into = collectFlowOps(into, op)
+1 -1
View File
@@ -917,7 +917,7 @@ func (fwd *sleeveForwarder) processSendError(err error) error {
return nil
}
fwd.mtuHighestGood = 8
fwd.mtuHighestGood = 552
fwd.mtuLowestBad = mtu + 1
fwd.mtuCandidate = mtu
fwd.mtuTestsSent = 0
+1 -1
View File
@@ -2,7 +2,7 @@
<div class="navbar navbar-inverse">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="http://weave.works/"><img src="http://weave.works/img/weave-logo.png"></a>
<a class="navbar-brand" href="http://weave.works/"><img src="http://www.weave.works/wp-content/uploads/2015/11/weave-logo-nav.png" class=" img-responsive" align="left"></a>
</div>
<div class="nav-wrapper">
<ul class="nav navbar-nav navbar-right">
+9 -1
View File
@@ -87,7 +87,12 @@ launched via the Docker
[command-line interface](https://docs.docker.com/reference/commandline/cli/)
or
[remote API](https://docs.docker.com/reference/api/docker_remote_api/)
are attached to the weave network before they begin execution.
are attached to the weave network before they begin execution. To use
the proxy, run
$ eval $(weave env)
and then start containers as usual.
Containers started in this way that subsequently restart, either by an
explicit `docker restart` command or by Docker restart policy, are
@@ -100,6 +105,9 @@ named `weave` is created by `weave launch`, which you can use like this:
$ docker run --net=weave -ti ubuntu
> NB: The plugin is an *alternative* to the proxy, hence one should
> *not* run `eval $(weave env)` beforehand.
For more details see the [plugin documentation](plugin.html).
### <a name="addressing"></a>Address allocation
+19 -13
View File
@@ -48,17 +48,6 @@ time, you can give the number of peers like this:
host3$ weave launch --init-peer-count 3 $HOST2
The consensus mechanism used to determine a majority transitions
through three states: 'deferred', 'waiting' and 'achieved':
* 'deferred' - no allocation requests or claims have been made yet;
consensus is deferred until then
* 'waiting' - an attempt to achieve consensus is ongoing, triggered by
an allocation or claim request; allocations will block. This state
persists until a quorum of peers are able to communicate amongst
themselves successfully
* 'achieved' - consensus achieved; allocations proceed normally
### More on `--init-peer-count`
TL;DR: it isn't a problem to over-estimate by a bit, but if you supply
@@ -214,7 +203,7 @@ reports on the current status of the weave router and IP allocator:
...
Service: ipam
Consensus: waiting(quorum: 2, known: 0)
Status: awaiting consensus (quorum: 2, known: 0)
Range: 10.32.0.0-10.47.255.255
DefaultSubnet: 10.32.0.0/12
@@ -225,4 +214,21 @@ The first section covers the router; see the [troubleshooting
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.
the total allocation range and default subnet. Columns are as follows:
* 'Status' - allocator state
* 'idle' - no allocation requests or claims have been made yet;
consensus is deferred until then
* 'awaiting consensus' - an attempt to achieve consensus is
ongoing, triggered by an allocation or claim request;
allocations will block. This state persists until a quorum of
peers are able to communicate amongst themselves successfully
* 'ready' - consensus achieved; allocations proceed normally
* 'waiting for IP range grant from peers' - peer has exhausted its
agreed portion of the range and is waiting to be granted some
more
* 'all IP ranges owned by unreachable peers' - peer has exhausted
its agreed portion of the range but cannot reach anyone to ask
for more
* 'Range' - total allocation range set by `--ipalloc-range`
* 'DefaultSubnet' - default subnet set by `--ipalloc-default-subnet`
+48 -25
View File
@@ -5,36 +5,53 @@ layout: default
# Weave Plugin
New in Docker version 1.9 is a plugin mechanism to add different
network providers.
Docker versions 1.9 and later have a plugin mechanism for adding
different network providers. Weave installs itself as a network plugin
when you start it with `weave launch`. To create a network that spans
multiple docker hosts, the weave peers must be connected in the usual
way, i.e. by specifying other hosts in `weave launch` or
[`weave connect`](features.html#dynamic-topologies).
To install, download the `weave` script as per the [readme][].
The Weave Net plugin runs automatically when you `weave launch`. You
must still tell the weave peers to connect to one another, either via
`weave launch` or `weave connect`.
## Starting a container
Subsequently you can start containers with, e.g.
$ docker run --net=weave -ti ubuntu
## Using WeaveDNS for Service Discovery
on any of the hosts, and they can all communicate with each other.
You need to pass the additional arguments `--dns` and `-dns-search`,
for which we provide a helper in the weave script:
> WARNING: It is inadvisable to attach containers to the weave network
> using both the Weave Docker Networking Plugin and
> [Weave Docker API Proxy](proxy.html) simultaneously. Such containers
> will end up with two weave network interfaces and two IP addresses,
> which is rarely desirable. To ensure the proxy is not being used,
> *do not run `eval $(weave env)`, or `docker $(weave config) ...`*.
In order to use Weave's [Service Discovery](weavedns.html), you
need to pass the additional arguments `--dns` and `-dns-search`, for
which we provide a helper in the weave script:
$ docker run --net=weave -h foo.weave.local $(weave dns-args) -tdi ubuntu
$ docker run --net=weave -h bar.weave.local $(weave dns-args) -ti ubuntu
# ping foo
For more details see the [Weave Service Discovery documentation][service-discovery].
Here is a complete example of using the plugin for connectivity
between two containers running on different hosts:
host1$ weave launch
host1$ docker run --net=weave -h foo.weave.local $(weave dns-args) -tdi ubuntu
host2$ weave launch $HOST1
host2$ docker run --net=weave $(weave dns-args) -ti ubuntu
root@cb73d1a8aece:/# ping -c1 -q foo
PING foo (10.32.0.1) 56(84) bytes of data.
--- foo ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.341/1.341/1.341/0.000 ms
## Under the hood
The Weave Net plugin actually provides *two* network drivers to Docker
- one named `weavemesh` that can operate without a [cluster
store](#cluster-store) (like Docker's overlay driver) and one named
`weave` that can only work with one.
The Weave plugin actually provides *two* network drivers to Docker
- one named `weavemesh` that can operate without a cluster store and
one named `weave` that can only work with one (like Docker's overlay
driver).
### `weavemesh` driver
@@ -54,7 +71,8 @@ networks.
* Used with Docker's cluster store based IPAM
There's no specific documentation from Docker on using a cluster
store, but the first part of [Getting Started with Docker Multi-host Networking][docker-net]
store, but the first part of
[Getting Started with Docker Multi-host Networking](https://github.com/docker/docker/blob/master/docs/userguide/networking/get-started-overlay.md)
should point the way.
Note that in the case of multiple networks using the `weave` driver, all containers are
@@ -87,9 +105,14 @@ route, add the `--no-multicast-route` flag to `weave launch-plugin`.
We start the plugin with a policy of `--restart=always`, so that it is
there after a restart or reboot. If you remove this container
(e.g. using `weave reset`) before removing all endpoints created using
`--net=weave`, Docker can
[hang](https://github.com/docker/libnetwork/issues/813).
`--net=weave`, Docker may hang for a long time when it subsequently
tries to talk to the plugin.
[readme]: https://github.com/weaveworks/weave/blob/master/README.md#installation
[service-discovery]: weavedns.html
[docker-net]: https://github.com/docker/docker/blob/master/docs/userguide/networking/get-started-overlay.md
Unfortunately, [Docker 1.9 may also try to talk to the plugin before it has even started it](https://github.com/docker/libnetwork/issues/813).
If using `systemd`, we advise that you modify the Docker unit to
remove the timeout on startup, to give Docker enough time to abandon
its attempts.
E.g. in the file `/lib/systemd/system/docker.service`, add under `[Service]`:
TimeoutStartSec=0
+8 -1
View File
@@ -62,7 +62,7 @@ $ weave status
TrustedSubnets: none
Service: ipam
Consensus: achieved
Status: ready
Range: 10.32.0.0-10.47.255.255
DefaultSubnet: 10.32.0.0/12
@@ -124,6 +124,13 @@ Proxy](proxy.html#troubleshooting).
### <a name="weave-status-connections"></a>List connections
Connections between weave peers carry control traffic over TCP and
data traffic over UDP. For a connection to be fully established, the
TCP connection and UDP data path must be able to transmit information
in both directions. Weave routers check this regularly with
heartbeats. Failed connections are automatically retried, with an
exponential back-off.
Detailed information on the local weave router's connections can be
obtained with `weave status connections`:
-1
View File
@@ -18,7 +18,6 @@ hosts.
* [Adding and removing extra DNS entries](#add-remove)
* [Resolve weaveDNS entries from host](#resolve-weavedns-entries-from-host)
* [Hot-swapping service containers](#hot-swapping)
* [Retaining DNS entries when containers stop](#retain-stopped)
* [Configuring a custom TTL](#ttl)
* [Configuring the domain search path](#domain-search-path)
* [Using a different local domain](#local-domain)
+6 -3
View File
@@ -8,7 +8,8 @@ C2=10.2.1.71
# 700 = Linux's minimum PMTU (552) + weave framing overheads
# (currently about 60, but we leave some margin). That way the PMTUs
# seen by containers is still >= 552.
drop_large_udp_packets="FORWARD -p udp --destination-port 6783 -m length '!' --length 0:700 -j DROP"
drop_large_sleeve_packets="INPUT -p udp --destination-port 6783 -m length '!' --length 0:700 -j DROP"
drop_large_fastdp_packets="INPUT -p udp --destination-port 6784 -m length '!' --length 0:700 -j DROP"
start_suite "PMTU discovery and packet fragmentation"
@@ -18,7 +19,8 @@ weave_on $HOST2 launch
start_container $HOST1 $C1/24 --name=c1
start_container $HOST2 $C2/24 --name=c2
run_on $HOST2 "sudo iptables -I $drop_large_udp_packets"
run_on $HOST1 "sudo iptables -I $drop_large_sleeve_packets"
run_on $HOST1 "sudo iptables -I $drop_large_fastdp_packets"
assert_raises "weave_on $HOST2 connect $HOST1"
sleep 35 # give weave time to discover the PMTU
@@ -28,6 +30,7 @@ sleep 35 # give weave time to discover the PMTU
exec_on $HOST2 c2 $PING -s 10000 $C1 1>/dev/null 2>&1 || true
assert_raises "exec_on $HOST2 c2 $PING -s 10000 $C1"
run_on $HOST2 "sudo iptables -D $drop_large_udp_packets"
run_on $HOST1 "sudo iptables -D $drop_large_fastdp_packets"
run_on $HOST1 "sudo iptables -D $drop_large_sleeve_packets"
end_suite
+31
View File
@@ -0,0 +1,31 @@
#! /bin/bash
. ./config.sh
start_suite "Check propagation of DNS entries when gossip is delayed"
weave_on $HOST1 launch-router --no-discovery
weave_on $HOST2 launch-router --no-discovery $HOST1
weave_on $HOST3 launch-router --no-discovery $HOST2
start_container $HOST1 --name=c1
C1=$(container_ip $HOST1 c1)
start_container_with_dns $HOST3 --name=c3
assert_dns_record $HOST3 c3 c1.weave.local $C1
# Stall the propagation of gossip, stop weave and kill the container
run_on $HOST3 "sudo iptables -A INPUT -s $HOST2 -j DROP"
weave_on $HOST1 stop-router
docker_on $HOST1 rm -f c1
weave_on $HOST1 launch-router --no-discovery $HOST3
# Now re-enable gossip
run_on $HOST3 "sudo iptables -D INPUT -s $HOST2 -j DROP"
# Currently failing due to Mesh #28
# assert_no_dns_record $HOST3 c3 c1.weave.local
end_suite
+13 -2
View File
@@ -6,15 +6,26 @@ entrypoint() {
docker_on $HOST1 inspect --format="{{.Config.Entrypoint}}" "$@"
}
check_iface_ready() {
assert_raises "proxy docker_on $HOST1 run -e 'WEAVE_CIDR=$1' $BASE_IMAGE $CHECK_ETHWE_UP"
assert_raises "proxy docker_on $HOST1 run -e 'WEAVE_CIDR=$1' $BASE_IMAGE ip -4 -o addr show ethwe | grep -q '$1'"
}
start_suite "Proxy waits for weave to be ready before running container commands"
weave_on $HOST1 launch-proxy
BASE_IMAGE=busybox
# Ensure the base image does not exist, so that it will be pulled
! docker_on $HOST1 inspect --format=" " $BASE_IMAGE >/dev/null 2>&1 || docker_on $HOST1 rmi $BASE_IMAGE
assert_raises "proxy docker_on $HOST1 run --name c1 -e 'WEAVE_CIDR=10.2.1.1/24' $BASE_IMAGE $CHECK_ETHWE_UP"
# check that interface is ready, with and without --no-multicast-route
weave_on $HOST1 launch-proxy --no-multicast-route
check_iface_ready 10.2.1.1/24
weave_on $HOST1 stop-proxy
weave_on $HOST1 launch-proxy
check_iface_ready 10.2.1.1/24
# Check committed containers only have one weavewait prepended
proxy_start_container $HOST1 --name c1 -e 'WEAVE_CIDR=10.2.1.1/24'
COMMITTED_IMAGE=$(proxy docker_on $HOST1 commit c1)
assert_raises "proxy docker_on $HOST1 run --name c2 $COMMITTED_IMAGE"
assert "entrypoint c2" "$(entrypoint $COMMITTED_IMAGE)"
+2 -2
View File
@@ -34,8 +34,8 @@ assert_raises "proxy docker_on $HOST1 ps"
weave_on $HOST1 stop-proxy
# Booting it over tls errors
assert_raises "DOCKER_CLIENT_ARGS='--tls' weave_on $HOST1 launch-proxy" 1
assert_raises "DOCKER_CERT_PATH='./tls' DOCKER_TLS_VERIFY=1 weave_on $HOST1 launch-proxy" 1
assert_raises "! DOCKER_CLIENT_ARGS='--tls' weave_on $HOST1 launch-proxy"
assert_raises "! DOCKER_CERT_PATH='./tls' DOCKER_TLS_VERIFY=1 weave_on $HOST1 launch-proxy"
# Booting it with a specific -H overrides defaults
weave_on $HOST1 launch-proxy -H tcp://0.0.0.0:12345
+1 -1
View File
@@ -6,7 +6,7 @@ start_suite "Proxy failure modes"
# docker run should fail when weave router is not running
weave_on $HOST1 launch-proxy
assert_raises "proxy docker_on $HOST1 run --rm $SMALL_IMAGE true" 1
assert_raises "! proxy docker_on $HOST1 run --rm $SMALL_IMAGE true"
assert_raises "proxy docker_on $HOST1 run --rm $SMALL_IMAGE true 2>&1 1>/dev/null | grep 'Error response from daemon: weave container is not present. Have you launched it?'"
end_suite
+24
View File
@@ -0,0 +1,24 @@
#! /bin/bash
. ./config.sh
C1_NAME=c1.weave.local
start_suite "Recovery of container details on router restart (via 'local' plugin)"
weave_on $HOST1 launch
start_container_local_plugin $HOST1 --name=c1 --hostname=$C1_NAME
c1ip=$(container_ip $HOST1 c1)
weave_on $HOST1 stop-router
weave_on $HOST1 launch-router
assert "container_ip $HOST1 c1" "$c1ip"
assert "weave_on $HOST1 dns-lookup $C1_NAME" "$c1ip"
# check that c1 IP has been reclaimed and doesn't get assigned to a
# fresh container
start_container $HOST1 --name=c2
assert_raises "container_ip $HOST1 c2 | grep -v $c1ip"
end_suite
+1 -1
View File
@@ -176,7 +176,7 @@ proxy_start_container_with_dns() {
rm_containers() {
host=$1
shift
[ $# -eq 0 ] || docker_on $host rm -f "$@" >/dev/null
[ $# -eq 0 ] || docker_on $host rm -f -v "$@" >/dev/null
}
container_ip() {
+1 -1
View File
@@ -11,7 +11,7 @@ set -e
: ${SSH_KEY_FILE:=$HOME/.ssh/gce_ssh_key}
: ${PROJECT:=positive-cocoa-90213}
: ${IMAGE:=ubuntu-14-04}
: ${TEMPLATE_NAME:=test-template-9}
: ${TEMPLATE_NAME:=test-template-10}
: ${ZONE:=us-central1-a}
: ${NUM_HOSTS:=5}
SUFFIX=""
+49 -18
View File
@@ -344,6 +344,7 @@ IMAGE=$BASE_IMAGE:$IMAGE_VERSION
BASE_PLUGIN_IMAGE=$DOCKERHUB_USER/plugin
PLUGIN_IMAGE=$BASE_PLUGIN_IMAGE:$IMAGE_VERSION
PLUGIN_CONTAINER_NAME=weaveplugin
VOLUMES_CONTAINER_NAME=weavevolumes-$IMAGE_VERSION
PROCFS=${PROCFS:-/proc}
DOCKER_BRIDGE=${DOCKER_BRIDGE:-docker0}
@@ -535,7 +536,9 @@ create_bridge() {
add_iptables_rule nat POSTROUTING -j WEAVE
else
if [ -n "$LAUNCHING_ROUTER" ] ; then
if [ "$BRIDGE_TYPE" = bridge -a -z "$WEAVE_NO_FASTDP" ] ; then
if [ "$BRIDGE_TYPE" = bridge -a -z "$WEAVE_NO_FASTDP" ] &&
util_op create-datapath $DATAPATH 2>/dev/null &&
util_op delete-datapath $DATAPATH 2>/dev/null ; then
cat <<EOF >&1
WEAVE_NO_FASTDP is not set, but there is already a bridge present of
the wrong type for fast datapath. Please do 'weave reset' to remove
@@ -762,11 +765,11 @@ connect_container_to_bridge() {
# veth pair in the 'up' or 'down' state. Furthermore, moving one
# end into a netns normally sets them to 'down'. But, moving an
# end into the default netns is a null operation, so they stay up,
# which leads to errors later on. So to get a consistent result,
# we have to be explicit in setting them 'up' or 'down' as
# necessary.
# which leads to errors in 'set name' since that requires the
# interface to be down. So to get a consistent result, we set the
# interface 'down' to begin with.
if ! netnsenter ip link set $GUEST_IFNAME down ||
! netnsenter ip link set $GUEST_IFNAME name $1 up ||
! netnsenter ip link set $GUEST_IFNAME name $1 ||
! ip link set $LOCAL_IFNAME up ||
! add_iface_$BRIDGE_TYPE $LOCAL_IFNAME ||
! configure_arp_cache $1 "netnsenter" ; then
@@ -833,8 +836,12 @@ setup_router_iface_bridged_fastdp() {
setup_router_iface_fastdp "$@"
}
container_in_host_ns() {
[ -h "$PROCFS/$CONTAINER_PID/ns/net" -a -h "/proc/self/ns/net" -a "$(readlink $PROCFS/$CONTAINER_PID/ns/net)" = "$(readlink /proc/self/ns/net)" ]
}
attach() {
if [ -h "$PROCFS/$CONTAINER_PID/ns/net" -a -h "/proc/self/ns/net" -a "$(readlink $PROCFS/$CONTAINER_PID/ns/net)" = "$(readlink /proc/self/ns/net)" ] ; then
if container_in_host_ns ; then
echo "Container is running in the host network namespace, and therefore cannot be" >&2
echo "connected to weave. Perhaps the container was started with --net=host." >&2
return 1
@@ -895,8 +902,8 @@ detach() {
netnsenter ip link del $CONTAINER_IFNAME type veth
}
container_weave_addrs() {
netnsenter ip addr show dev $CONTAINER_IFNAME
container_ip_addr_show() {
! container_in_host_ns && netnsenter ip addr show
}
######################################################################
@@ -1027,6 +1034,17 @@ wait_for_status() {
done
}
# Parse the output of `ip addr show`, outputing weave addresses of kind $1
addrs_from_ip_addr_show() {
while read first second rest ; do
if [ "$first" != "${first%:}" ] ; then
iname="${second%:}"
elif [ "$first" = "$1" -a \( "$iname" = "weave" -o "$iname" != "${iname#ethwe}" \) ] ; then
echo $second
fi
done
}
# Call $1 for all containers, passing container ID, all MACs and all IPs
with_container_addresses() {
COMMAND=$1
@@ -1035,12 +1053,14 @@ with_container_addresses() {
if [ "$CONTAINER_ID" = "weave:expose" ] ; then
ADDRS_CMD="ip addr show dev $BRIDGE"
else
ADDRS_CMD="with_container_netns $CONTAINER_ID container_weave_addrs"
ADDRS_CMD="with_container_netns $CONTAINER_ID container_ip_addr_show"
fi
if CONTAINER_ADDRS=$($ADDRS_CMD 2>/dev/null) ; then
CONTAINER_MAC=$(echo "$CONTAINER_ADDRS" | grep -o 'link/ether .*' | cut -d ' ' -f 2)
CONTAINER_IPS=$(echo "$CONTAINER_ADDRS" | grep -o 'inet .*' | cut -d ' ' -f 2)
$COMMAND "$CONTAINER_ID" "$CONTAINER_MAC" "$CONTAINER_IPS"
CONTAINER_MAC=$(echo "$CONTAINER_ADDRS" | addrs_from_ip_addr_show 'link/ether')
CONTAINER_IPS=$(echo "$CONTAINER_ADDRS" | addrs_from_ip_addr_show 'inet')
if [ -n "$CONTAINER_MAC$CONTAINER_IPS" ] ; then
$COMMAND "$CONTAINER_ID" "$CONTAINER_MAC" "$CONTAINER_IPS"
fi
fi
done
}
@@ -1278,7 +1298,7 @@ collect_dns_add_remove_args() {
# with_container_addresses.
ipam_reclaim() {
for CIDR in $3 ; do
# NB: CONTAINER_IP is the IP of the weave container; it is set by wait_for_status.
# NB: CONTAINER_IP is the IP of the weave container.
http_call $CONTAINER_IP:$HTTP_PORT PUT /ip/$1/${CIDR%/*}?noErrorOnUnknown=true
done
}
@@ -1476,7 +1496,7 @@ proxy_args() {
}
proxy_addrs() {
if addr="$(http_call_unix $PROXY_CONTAINER_NAME status.sock GET /status 2>&1)" ; then
if addr="$(http_call_unix $PROXY_CONTAINER_NAME status.sock GET /status 2>/dev/null)" ; then
echo "$addr" | sed "s/0.0.0.0/$PROXY_HOST/g"
else
@@ -1650,7 +1670,7 @@ attach_router() {
if [ -z "$NO_DNS_OPT" ] ; then
# Tell the newly-started weaveDNS about existing weave IPs
for CONTAINER in $(docker ps -q --no-trunc) ; do
if CONTAINER_IPS=$(with_container_netns $CONTAINER container_weave_addrs 2>&1 | sed -n -e 's/inet \([^/]*\)\/\(.*\)/\1/p') ; then
if CONTAINER_IPS=$(with_container_netns $CONTAINER container_ip_addr_show 2>/dev/null | addrs_from_ip_addr_show 'inet') && [ -n "$CONTAINER_IPS" ] ; then
with_container_fqdn $CONTAINER put_dns_fqdn $CONTAINER_IPS
fi
done
@@ -1669,8 +1689,14 @@ launch_proxy() {
docker_client_args $DOCKER_CLIENT_ARGS
proxy_args "$@"
mkdir -p /var/run/weave
# Create a data-only container to mount the weavewait files from
if ! docker inspect -f ' ' $VOLUMES_CONTAINER_NAME > /dev/null 2>&1 ; then
docker create -v /w -v /w-noop -v /w-nomcast --name=$VOLUMES_CONTAINER_NAME \
--label=weavevolumes --entrypoint=/bin/false $EXEC_IMAGE >/dev/null
fi
PROXY_CONTAINER=$(docker run --privileged -d --name=$PROXY_CONTAINER_NAME --net=host \
$PROXY_VOLUMES \
--volumes-from $VOLUMES_CONTAINER_NAME \
$(docker_sock_options) \
-v /var/run/weave:/var/run/weave \
-v /proc:/hostproc \
@@ -1715,8 +1741,12 @@ remove_plugin_network() {
$PLUGIN_IMAGE --remove-network
}
warn_plugin_active() {
echo "WARNING: docker may hang in this state; re-launch weave and remove attached containers before shutting down" >&2
}
stop_plugin() {
remove_plugin_network
remove_plugin_network || warn_plugin_active
stop $PLUGIN_CONTAINER_NAME "Plugin"
}
@@ -2152,14 +2182,15 @@ EOF
;;
reset)
[ $# -eq 0 ] || usage
plugin_disabled || remove_plugin_network || \
echo "WARNING: docker may hang in this state; re-launch weave and remove attached containers before shutting down" >&2
plugin_disabled || remove_plugin_network || warn_plugin_active
warn_if_stopping_proxy_in_env
call_weave DELETE /peer >/dev/null 2>&1 || true
for NAME in $PLUGIN_CONTAINER_NAME $CONTAINER_NAME $PROXY_CONTAINER_NAME ; do
docker stop $NAME >/dev/null 2>&1 || true
docker rm -f $NAME >/dev/null 2>&1 || true
done
VOLUME_CONTAINERS=$(docker ps -qa --filter label=weavevolumes)
[ -n "$VOLUME_CONTAINERS" ] && docker rm -v $VOLUME_CONTAINERS >/dev/null 2>&1 || true
conntrack -D -p udp --dport $PORT >/dev/null 2>&1 || true
destroy_bridge
for LOCAL_IFNAME in $(ip link show | grep v${CONTAINER_IFNAME}pl | cut -d ' ' -f 2 | tr -d ':') ; do