Compare commits

...
536 Commits
Author SHA1 Message Date
Bryan Boreham 851b58cca8 Add release v1.9.0 2017-02-02 11:01:34 +00:00
Bryan Boreham cb48ebc399 Bump alpine version to 3.5 for arm64
Since 3.4 doesn't exist, and the package repo seems ok for ulogd now
2017-02-02 10:43:29 +00:00
Martynas Pumputis 5278eb7ebc Merge pull request #2747 from weaveworks/issues/2689-npc-mcast-simple
Add rule to allow multicast at top level
2017-02-01 18:20:38 +00:00
Bryan Boreham 418c256689 Allow traffic to forward off the weave bridge 2017-02-01 15:01:18 +00:00
Bryan Boreham 4eeb846507 Add tests for connectivity to the world 2017-02-01 15:01:18 +00:00
Bryan Boreham 7529f5f9af Raise ping timeout to reduce false negatives 2017-02-01 15:01:18 +00:00
Michal Rostecki 8506e57482 Pin alpine container version
Alpine 3.5 doesn't provide PCAP plugin with ulogd, so until
we investigate the problem upstream, we need to pin to 3.4
version.

Fixes #2732
2017-02-01 12:05:31 +00:00
Adam Harrison b1d09305e4 Merge pull request #2687 from weaveworks/issues/1644-fastdp-crypto
Fastdp crypto
2017-02-01 10:28:24 +00:00
Martynas Pumputis 07892bff7d Reduce the default MTU 2017-01-31 17:21:01 +00:00
Martynas Pumputis 50985dee90 Enable ESN in fastdp-crypto 2017-01-31 17:21:01 +00:00
Martynas Pumputis 60323d0960 Add fastdp crypto 2017-01-31 17:21:01 +00:00
Bryan Boreham a9cef6327f Update information about Weaveworks products 2017-01-31 12:43:53 +00:00
Bryan Boreham fdeb9010ba Merge pull request #2757 from weaveworks/upgrade-build-tools
Upgrade to latest 'common' and 'build-tools'.
2017-01-31 12:17:31 +00:00
Marc CARRE ee659d4033 Replace weave/common/mflagext with common/mflagext.
Removes duplication between weave and common and reduces the amount of sources to compile.
2017-01-31 10:49:29 +00:00
Marc CARRE 8f9b2a36c0 Remove dep. on docker and use mflag from common.
This reduces the number of dependencies, and avoids having docker as a vendored dependency, which should speed the build up.
2017-01-31 10:30:12 +00:00
Bryan Boreham 6a83130685 Document multicast behaviour of weave-npc 2017-01-30 18:14:57 +00:00
Marc CARRE 77e6c6f886 Upgrade to latest 'common' and 'build-tools'.
If building against the latest 'build-tools', you would typically get:
tools/runner/runner.go:18:2: cannot find package github.com/weaveworks/common/mflag
This change fixes the issue by upgrading both dependencies.
2017-01-30 18:05:58 +00:00
Adam Harrison 8a5a15d5e9 Merge pull request #2753 from weaveworks/mv-signal-to-common
Move signal handling loop to common.
2017-01-30 12:38:23 +00:00
Bryan Boreham bcc8c73f59 Fix build of manifest_tool in 'make publish' 2017-01-30 11:02:11 +00:00
Bryan Boreham e22c6375c9 Fix build of manifest_tool 2017-01-27 18:09:22 +00:00
Marc Carré 22ae0d200c Merge pull request #2752 from weaveworks/makefile-cleanup
Makefile cleanup after multiarch merge
2017-01-27 16:51:44 +00:00
Bryan Boreham 7231bd00f8 Remove .weavedb.uptodate file when we remove the weavedb image in 'make clean-bin' 2017-01-27 16:26:05 +00:00
Tom Wilkie 590a151bde Move signal handling loop to common. 2017-01-26 17:55:19 +00:00
Martynas Pumputis f5dfefef75 Merge pull request #2749 from weaveworks/shfmt-ignore
Upgrade Weave Net to latest version of build-tools, skipping bash scripts when lint-ing.
2017-01-26 10:55:36 +00:00
Marc CARRE 8e6cb5e24d Print files we currently do not lint.
Makes what the build does explicitly and helps for potential debugging.
Also reminds us that we are skipping these files, so that we ultimately shfmt them and stop lint-ignoring them.
2017-01-25 17:14:48 +00:00
Marc CARRE ed629d420d Pass additional options to ./tools/test to revert to previous behaviour.
Previous commit upgrades Weave Net to the latest version of `build-tools`.
However, `./tools/test`'s default behaviour has changed, so we need to explicitly pass new options/arguments, in order to keep it behaving like before fd568682c3.
2017-01-25 17:14:05 +00:00
Marc CARRE fd568682c3 Upgrade Weave Net to latest version of build-tools, skipping bash scripts when lint-ing.
Lint-ing all of Weave Net is currently not desirable because:

* it would create conflicts on many branches,
* it would pollute the git history,
* etc.

and because `lint` currently lints all files except `./vendor`, this breaks Weave Net's build.
As a result, Weave Net is not using the latest commit in `build-tools`'s `master` branch, which is also source of problems:

* it limits standardisation of projects across Weaveworks,
* it limits the ability to use the latest features of `build-tools`,
* it complexifies merging changes in `build-tools` (e.g. #53 and weaveworks/weave#2694 for weaveworks/weave#2647),
* etc.

This change:

* brings Weave Net to the latest version of `build-tools` (which now supports `.lintignore` files),
* adds such a `.lintignore` file to skip all bash scripts (in order to avoid breaking the build).

`GLOB`s in `.lintignore` can then, over time and as scripts are `shfmt`-ed, be relaxed and maybe even removed.
2017-01-25 16:50:32 +00:00
Bryan Boreham dbb9849b8c Remove whitespace from blank lines and comment lines
Principally because emacs complains about it, but also to remove the
overhead of firing up a shell process to ignore a comment in a recipe
2017-01-25 14:20:54 +00:00
Bryan Boreham 776af44782 Make manifest-tool using weave build container 2017-01-25 14:18:55 +00:00
Bryan Boreham 69dacd0594 Restrict CircleCI publishing to AMD64 2017-01-25 10:52:53 +00:00
Bryan Boreham f17a2a00b1 Merge pull request #2713 from luxaslabs/multiarch
Make Weave Net multi-architecture
2017-01-24 18:07:32 +00:00
Lucas Käldström 1a64420e01 Fix duplicate publish target 2017-01-24 17:38:44 +02:00
Bryan Boreham 49b9a2c8df Bump Docker to 1.10 2017-01-24 17:28:08 +02:00
Bryan Boreham 6c251417d5 Update 'docker inspect weavedb' format for Docker 1.10 2017-01-24 17:27:53 +02:00
Lucas Käldström 8c0c38c8b3 Add manifest-tool as a submodule 2017-01-24 17:27:30 +02:00
Lucas Käldström 29eee4e858 Fixing review feedback, adding checksums, etc 2017-01-24 17:24:04 +02:00
Lucas Käldström 454c6f713d Make Weave Net multi-architecture and add support for ARM and ARM 64-bit 2017-01-24 17:23:00 +02:00
Marc Carré dd715e18ec Merge pull request #2743 from weaveworks/fix-uuid
Don't fail if only half the system IDs are blank
2017-01-23 15:00:06 +00:00
Bryan Boreham f067c7d44e Add rule to allow multicast at top level 2017-01-23 12:11:44 +00:00
Bryan Boreham c1023eaf18 Hard-code repository name for weavebuild container
so we don't create a new one when testing publish to different DOCKERHUB_USER
2017-01-20 14:55:10 +00:00
Bryan Boreham b091f59311 Merge pull request #2734 from Compositional/master
Add partial support for non-FHS host systems
2017-01-20 14:45:33 +00:00
Marc Carré f98ad822e3 Merge pull request #2740 from weaveworks/issues/2738-dedupe-surrogate
Update mesh lib to break cycle of old gossip
2017-01-20 12:36:08 +00:00
Bryan Boreham 917c1ddbad Update mesh lib to break cycle of old gossip 2017-01-20 12:05:55 +00:00
Marc Carré d81d2f691d Merge pull request #2742 from weaveworks/build-improvements
Build improvements
2017-01-20 11:26:18 +00:00
Bryan Boreham 1ad118a38f Merge branch '1.8' 2017-01-20 09:45:13 +00:00
Bryan Boreham 9d1648cee7 Merge pull request #2741 from weaveworks/document-mtu-with-weave-kube
Document WEAVE_MTU in weave-kube config options
2017-01-20 09:40:57 +00:00
Bryan Boreham 929167366a Don't fail if only half the system IDs are blank 2017-01-19 15:57:21 +00:00
Bryan Boreham 353ccf5e6c Move build to 'dependencies' section
This means we don't spend time trying to run other tests if the build failed.
2017-01-19 10:59:16 +00:00
Bryan Boreham cfc1fa4fae Build test runner inside build container for consistency 2017-01-19 10:59:04 +00:00
Robert Hensing d881f47088 Add partial support for non-FHS host systems
Fixes weaveworks/weave#2733 partially, where <host>/etc/resolv.conf is not a
symlink
2017-01-18 23:28:49 +01:00
Bryan Boreham 84013c4452 Merge pull request #2735 from weaveworks/issues/2732-pin-alpine-version
Pin alpine container version
2017-01-18 16:49:04 +00:00
Adam Harrison d9dc1a988c Document WEAVE_MTU in weave-kube config options 2017-01-18 15:11:41 +00:00
Marc CARRE 5fd14348aa Fix broken link to 'Building Weave Net' documentation. 2017-01-17 17:49:17 +00:00
Adam Harrison 57a250a20b Pin alpine container version 2017-01-16 12:27:53 +00:00
Adam Harrison 81add75258 Merge pull request #2711 from weaveworks/issues/2427-unique-ids
Better machine unique IDs
2017-01-13 09:40:18 +00:00
Bryan Boreham 0145282a10 Merge pull request #2728 from weaveworks/issues/2653-ulogd-pdeathsig
SIGKILL ulogd on weave-npc exit
2017-01-11 17:31:18 +00:00
Adam Harrison ae0cb5d483 SIGKILL ulogd on weave-npc exit 2017-01-11 14:12:01 +00:00
Bryan Boreham e7eeecd762 Smoke test for peer names 2017-01-11 13:14:35 +00:00
Bryan Boreham 7d308a4ac5 Wire weaveutil unique-id into weave script
Also ensure the right host directories are mounted when create-bridge
is called from either the weave script or weave-kube.
2017-01-11 13:14:35 +00:00
Bryan Boreham ebcb7f6108 Use persisted peer name if it matches old-style ID 2017-01-11 13:14:35 +00:00
Bryan Boreham e03c7b1b7c Allow opening persistence file read-only 2017-01-11 13:13:19 +00:00
Bryan Boreham 70a20b4d26 Generate peer name / mac address in Go 2017-01-11 13:12:30 +00:00
Bryan Boreham d143470d77 Refactor: extract db filename to a constant 2017-01-11 13:05:25 +00:00
Bryan Boreham 30d6639a98 Refactor: move peer name identifier to DB package 2017-01-11 13:05:25 +00:00
Adam Harrison 92cfd3b4f9 Merge pull request #2725 from weaveworks/update-tools
Update tools submodule to avoid breaking on missing Docker mflag
2017-01-09 17:09:53 +00:00
Adam Harrison 7659ea21c7 Merge branch '1.8'
Fixes #2693.
2017-01-09 16:24:08 +00:00
Adam Harrison 4e740736e7 Merge pull request #2697 from weaveworks/issues/2693-npc-log-instructions
Fix instructions to view npc logs when >1 pod exists
2017-01-09 16:23:42 +00:00
Adam Harrison 4f44d9e25a Merge branch '1.8'
Fixes #2719.
2017-01-09 15:49:29 +00:00
Adam Harrison 2ae2d52289 Merge pull request #2722 from weaveworks/issues/2719-delete-pods
Warn not to delete all Weave Net pods
2017-01-09 15:48:48 +00:00
Adam Harrison 635191970f Merge pull request #2688 from weaveworks/issues/2684-exec-weaver
Exec weaver from weave-kube launch rather than running in background
2017-01-09 15:24:19 +00:00
Bryan Boreham e370443a3f Merge pull request #2699 from weaveworks/2647-parallelise-sanity-checks
Parallelise sanity checks in order to speed them up.
2017-01-09 12:57:44 +00:00
Bryan Boreham 738ff2b65f Update tools submodule to avoid breaking on missing Docker mflag 2017-01-09 12:50:18 +00:00
Bryan Boreham cef8c908d0 Merge pull request #2704 from weaveworks/2647-parallelise-setup
Parallelise setup.sh's individual tasks.
2017-01-09 12:30:53 +00:00
Marc CARRE edc0cdbc10 Sanity checks' output is now redirected to $CIRCLE_ARTIFACTS directly when running smoke tests in CircleCI.
Previously sanity checks' output was redirected to /tmp and then copied to $CIRCLE_ARTIFACTS, which is more "moving pieces".
2017-01-09 12:25:29 +00:00
Marc CARRE 89e116961c Now measure time spent in setup. 2017-01-09 12:03:13 +00:00
Marc CARRE 71180f97e7 Parallelise setup.sh. 2017-01-09 12:03:09 +00:00
Adam Harrison be8d9d88d8 Merge pull request #2724 from weaveworks/2647-remove-dependency-on-jq
Removed dependency on jq in test #175.
2017-01-09 10:59:52 +00:00
Bryan Boreham 35de3720e9 Merge pull request #2698 from weaveworks/2647-find-relative-dir
Finding and running tests no longer depends on current directory.
2017-01-09 10:34:07 +00:00
Marc CARRE 4a7e2054db Removed dependency on jq in test #175.
If the machine coordinating the test runs does not have jq, then test #175 fails with:
> test #1 "weave_on test-0.lon1.weave-net report | jq -r '.Router.Targets[] | tostring' | sort" failed:
>     expected "test-1.lon1.weave-net
> test-2.lon1.weave-net"
>     got nothing
This change completely removes the dependency on jq to make the test more robust and avoid potential confusion.
2017-01-09 10:16:05 +00:00
Marc CARRE fe75047988 weave-daemonset.yaml is now referred to using relative paths. 2017-01-09 10:08:38 +00:00
Marc CARRE f73fb5307f Redirect sanity checks' output to temporary files (and archive them as artifact files under CircleCLI).
This should make it easier to find and access relevant debugging information without polluting STDOUT and without any risk of log interleaving. See also:
- https://weaveworks.slack.com/archives/net/p1482154505001192
- https://weaveworks.slack.com/archives/net/p1482254780001493
2017-01-09 09:17:45 +00:00
Marc CARRE 172597a68d Now measure time spent in sanity checks. 2017-01-09 09:17:45 +00:00
Marc CARRE f05169e457 Initialise pids before using it, to avoid potential issues with previously set values. 2017-01-09 09:17:45 +00:00
Marc CARRE b171497466 Ensure sanity checks exit early in case of a ping failure. 2017-01-09 09:17:45 +00:00
Marc CARRE 61375fb785 Format ping output as one line. 2017-01-09 09:17:45 +00:00
Marc CARRE 04cc4edf26 Parallelise sanity checks in order to speed them up. 2017-01-09 09:17:45 +00:00
Marc CARRE 0101a12fba Undo 0dff07dc8b since current directory is already changed on previous line. 2017-01-09 09:16:53 +00:00
Marc CARRE e094fb1547 DOCKER_CERT_PATH is now set using a relative path. 2017-01-09 09:16:53 +00:00
Marc CARRE e0a44a901a Tests now source dependencies using relative paths (previously breaking make depending on current directory). 2017-01-09 09:16:53 +00:00
Marc CARRE d4f9abeefd Finding tests no longer depends on current directory. 2017-01-09 09:16:53 +00:00
Bryan Boreham 0338d4595b Fix instructions to view npc logs when >1 pod exists 2017-01-06 11:24:20 +00:00
Bryan Boreham 7328c3fe86 Comment about full build on first push 2017-01-06 10:54:13 +00:00
Bryan Boreham bf288ff6f5 Warn not to delete all Weave Net pods 2017-01-06 10:30:46 +00:00
Marc Carré ef4c4024bc Merge pull request #2720 from weaveworks/2647-fix-test-150
Fix ordering bug in test #150.
2017-01-05 15:29:58 +00:00
Marc CARRE 6f24cca4b1 Fix ordering bug in test #150.
Test hard-codes a string containing '\n' and then expects echo
to interpret it as a newline, which it does not without the -e option.

This fixes flaky test runs like the below:
>>> Running /root/src/github.com/weaveworks/weave/test/150_connect_forget_2_test.sh on [138.68.153.213 138.68.149.186]
>>> Test /root/src/github.com/weaveworks/weave/test/150_connect_forget_2_test.sh finished after 12.4 secs with error: exit status 1
test #5 "direct_peers 138.68.149.186 | sort" failed:
  expected "138.68.153.213\n138.68.149.186"
  got "138.68.149.186\n138.68.153.213"
2017-01-05 15:02:16 +00:00
Bryan Boreham bf59a003bb Exec weaver from weave-kube launch rather than running in background
So we only have one process running inside the container after all
set-up is finished
2017-01-04 15:00:52 +00:00
Bryan Boreham 2298a40327 Fix bug which was killing all smoke-tests
- only fail if there is no secret password
2017-01-04 14:53:43 +00:00
Adam Harrison 61d22bb8b4 Merge pull request #2686 from weaveworks/issues/2580-allow-ips
Allow docker bridge to have more than one IP address
2017-01-04 14:35:48 +00:00
Adam Harrison eb3bbff883 Merge pull request #2708 from weaveworks/weave-kube-mounts
Mount /etc under a different path for weave-kube
2017-01-04 10:15:54 +00:00
Adam Harrison 03c1379d1b Merge pull request #2716 from liubog2008/fix
fix a bug of updating network policy
2017-01-03 17:44:58 +00:00
liubog2008 1635093341 fix a bug of updating network policy 2016-12-28 14:12:06 +08:00
Bryan Boreham 93dcc4550a Merge pull request #2712 from luxaslabs/deprecate_maintainer_dockerfile
Remove the deprecated MAINTAINER field in Dockerfiles and change to "LABEL maintainer" instead
2016-12-23 16:06:41 +00:00
Bryan Boreham ab55da47b6 Check if we have secrets before decrypting or running smoke tests
And enable running CircleCI on forked pull requests
2016-12-23 16:06:20 +00:00
Lucas Käldström 17971a5a3a Remove the deprecated MAINTAINER field in Dockerfiles for LABEL maintainer instead
Also add https://microbadger.com/labels labels and remove LABEL fields where they already are inherited
2016-12-23 14:57:02 +02:00
Bryan Boreham e0b90e8f02 Inline single-line function docker_bridge_ip 2016-12-23 12:15:04 +00:00
Bryan Boreham ea014d1362 Reimplement docker_bridge_ip shell pipeline in Go 2016-12-23 12:10:26 +00:00
Bryan Boreham 6ef302b8a1 Extract FindBridgeIP to net package 2016-12-23 11:57:04 +00:00
Bryan Boreham 1e7afe3bec Merge branch '1.8' 2016-12-23 11:35:53 +00:00
Bryan Boreham 48508044d6 Merge pull request #2703 from weaveworks/issues/2700-ip-link
Docs: improve IP route links
2016-12-23 11:26:52 +00:00
Bryan Boreham a4ad66f1c8 Mount /etc under a different path for weave-kube
So we don't accidentally read or write the hosts's /etc.
Also move the other volumes under /host to be more consistent with
what the weave script expects.
2016-12-22 10:35:47 +00:00
Bryan Boreham 0f85a959bb Merge branch '1.8' 2016-12-21 11:15:04 +00:00
Bryan Boreham d9a8adda1d Merge pull request #2706 from weaveworks/issues/2638-segfault-dp
Do not segfault if the datapath exists
2016-12-21 11:12:19 +00:00
Marc Carré ef4a8648a9 Merge pull request #2707 from weaveworks/2647-fix-typo-in-sanity-checks
Fixed typo in sanity check of weave's version
2016-12-21 10:28:09 +00:00
Marc CARRE 8bb72aa175 Fixed typo in sanity check of weave's version (previously checking locally, now checking test host). 2016-12-21 10:03:05 +00:00
Martynas Pumputis fa05dcf6ee Do not segfault if the datapath exists
If the datapath exists when creating it, dpif.CreateDatapath
will return an empty handle which access will cause the segfault.
2016-12-20 18:16:16 +02:00
Martynas Pumputis 8affa26858 Merge pull request #2695 from weaveworks/issues/2692-consistent-npc-log
Change rest of npc to weave common logging

Fixes #2692
2016-12-19 16:41:27 +02:00
Martynas Pumputis 856cb48170 Merge pull request #2685 from weaveworks/issues/2480-correct-mac
Take peerName from weave bridge if not specified

Fixes #2480
2016-12-19 16:35:15 +02:00
Bryan Boreham 1239fca567 Docs: improve IP route links 2016-12-19 12:34:05 +00:00
Bryan Boreham 6592a9afc7 Merge branch '1.8' 2016-12-14 11:57:11 +00:00
Mathias Methner 7ffd96f425 Document how to publish prometheus metric endpoint on all interfaces
This is a combination of 4 commits.
 The first commit's message is:
2677 docu, how to publish prometheus metric endpoint on all interfaces

 This is the 2nd commit message:
2677 change docu on how to publish metrics, be more careful with publishing on all interfaces

 This is the 3rd commit message:
2677 fix spelling

 This is the 4th commit message:
2677 fix wrong port title and grammar
2016-12-14 11:54:56 +00:00
Bryan Boreham 906d9a47b1 Merge pull request #2696 from weaveworks/2647-import-using-absolute-paths
Scripts now source dependencies using relative paths
2016-12-13 17:00:58 +00:00
Marc CARRE 0dff07dc8b Scripts now source dependencies using relative paths (previously breaking make depending on current directory). 2016-12-13 16:00:37 +00:00
Bryan Boreham 9261d17dbe Fix option name 2016-12-13 14:59:45 +00:00
Bryan Boreham 7d8a18bd20 Change rest of npc to weave common logging 2016-12-13 13:52:48 +00:00
Bryan Boreham 29cb13cba6 Merge branch '1.8' 2016-12-13 13:34:03 +00:00
Martynas Pumputis 52f375ac1e Merge pull request #2663 from weaveworks/issues/2389-report-mtu
Add MTU to connection status

Fixes #2389
2016-12-13 11:53:39 +00:00
Bryan Boreham 73f184df7e Fix quotes in anchors 2016-12-13 11:42:20 +00:00
Bryan Boreham bbd631f08f weave-kube no longer needs to supply the peer address 2016-12-09 15:34:31 +00:00
Bryan Boreham cf315fb6ba Take peerName from weave bridge if not specified 2016-12-09 15:34:31 +00:00
Bryan Boreham c03a2caac2 Allow docker0 to have >1 IP address
and log the one we end up using
2016-12-09 15:22:49 +00:00
Bryan Boreham 9c2bc0b825 Add MTU to connection status 2016-12-09 13:59:49 +00:00
Martynas Pumputis fcda8985fb Remove bin/setup-ci-secrets
It was used by Travis CI which we do not use anymore.
2016-12-08 16:22:12 +00:00
Martynas Pumputis 14082f9332 Merge branch '1.8' 2016-12-08 15:44:40 +00:00
Martynas Pumputis 83401eb245 Update release-process.md
git.io/weave-kube does not point to the weave-kube repo anymore.
2016-12-08 15:35:54 +00:00
Martynas Pumputis 022a98d4a4 Add release v1.8.2 2016-12-08 15:11:21 +00:00
Bryan Boreham bb1cca713d Merge branch '1.8' 2016-12-08 12:27:40 +00:00
Bryan Boreham 1d80a8d676 Merge pull request #2674 from weaveworks/issues/2650-fix-looping-flows
Detect looping flows
2016-12-08 12:27:15 +00:00
Martynas Pumputis aa9c032176 Add sanity check to detect when receiving own packets 2016-12-08 11:38:37 +00:00
Martynas Pumputis baa8f229f7 Detect enabling of hairpin mode on vethwe-bridge
Enabled hairpin mode on vethwe-bridge was one of the root causes
for installing looping flows in the fastdp mode.

Also, it confused the weave custom L2 bridge, as the bridge treats
a bounced back packet, e.g. ARP brodcast request, as a local one
(the case for "Captured a packet associated with remote host").
2016-12-08 11:37:52 +00:00
Martynas Pumputis ab1b99a4d9 Update vishvananda/netlink vendored dependency
The updated version includes parsing of IFLA_PROTINFO
which is needed to get info about hairpin mode when
subscribing to link updates.
2016-12-08 10:33:22 +00:00
Adam Harrison 11ff1880e5 Merge pull request #2666 from weaveworks/issues/2633-json-events
Log objects via JSON for better debugging
2016-12-07 17:25:55 +00:00
Bryan Boreham 71bf040715 Add --log-level option, default to debug 2016-12-07 11:53:40 +00:00
Bryan Boreham 6a04c6c7bd Change to weave common logging 2016-12-07 11:53:31 +00:00
Bryan Boreham 8530528dd5 Drop pod log messages to Debug level 2016-12-07 11:51:53 +00:00
Adam Harrison e1d8992ec5 Merge branch '1.8'
Fixes #2673.
2016-12-07 11:24:13 +00:00
Adam Harrison b03311e99d Merge pull request #2683 from weaveworks/issues/2673-expose-again
Re-add expose to ensure it gets run on all nodes
2016-12-07 11:23:52 +00:00
Adam Harrison 0c1138ee60 Merge pull request #2662 from weaveworks/issues/2594-setup-cni
Unify weave and launch.sh CNI setup
2016-12-07 11:21:25 +00:00
Bryan Boreham 8a45292e24 Log objects via JSON for better debugging 2016-12-06 17:40:17 +00:00
Bryan Boreham d1712e9589 Re-add expose to ensure it gets run on all nodes
Previous change in a07e3301b1 meant that if there are no pods on
this node then the 'expose' never gets run.
2016-12-06 14:58:31 +00:00
Bryan Boreham ec21afb426 Unify weave and launch.sh CNI setup
Test 830 has to run CNI plugin under sudo now
2016-12-06 11:52:09 +00:00
Bryan Boreham 882bff292e Fix test invocation of weave again
Previous fix in b4a43f1b85 did not work
when built with code coverage.

Running a test script with -v causes `weave_on` to output progress
messages, so we don't want to use those commands inside `$()`
2016-12-06 11:48:48 +00:00
Adam Harrison f3843a6b18 Merge branch '1.8' 2016-12-06 11:41:45 +00:00
Adam Harrison 597c6c111d Merge pull request #2657 from weaveworks/remove-bridge-on-error
Remove weave bridge if something goes wrong when creating it
2016-12-06 11:41:29 +00:00
Adam Harrison ac4957e15c Merge branch '1.8' 2016-12-06 11:30:32 +00:00
Adam Harrison f3915592b2 Merge pull request #2679 from weaveworks/expose-loop
Run iptables commands in a loop
2016-12-06 11:30:20 +00:00
Bryan Boreham 8a292fd9f3 Merge pull request #2678 from weaveworks/issues/2593-remove-cni-from-plugin
Remove CNI support from Docker plugin
2016-12-06 02:51:23 -08:00
Bryan Boreham f34936d9be Merge branch '1.8' 2016-12-06 10:39:50 +00:00
Bryan Boreham d4367457a9 Merge pull request #2671 from weaveworks/document-env-vars
Document env-var configuration for weave-kube
2016-12-06 02:39:20 -08:00
Bryan Boreham b4a43f1b85 Fix test running with -v flag
Running a test script with -v causes `weave_on` and `docker_on` to
output progress messages, so we don't want to use those commands
inside `$()`
2016-12-05 16:12:15 +00:00
Bryan Boreham 3674808244 Remove weave bridge and associated devices if something goes wrong when creating it
Otherwise it is left in a half-created state and the user has to run `weave reset` to continue.
2016-12-05 15:11:47 +00:00
Bryan Boreham 44cc978a94 Update CNI information 2016-12-05 14:29:07 +00:00
Bryan Boreham f441ec2644 Document env-var configuration for weave-kube
E.g. how to configure the IP allocation range
2016-12-05 13:55:33 +00:00
Martynas Pumputis 0ae13a2650 Detect hairpin flows
The introduced "isHairpinFlow" detects whether a flow has been
created due to enabled hairpin mode.
2016-12-05 12:42:24 +00:00
Bryan Boreham ee6596e21c Run iptables commands in a loop
in case they get  "temporarily unavailable" exit
2016-12-05 11:11:20 +00:00
Anita Buehrle a63147beda Improve wording of kube-addon page 2016-11-30 16:15:30 +00:00
Adam Harrison cdcf5808db Remove CNI support from Docker plugin 2016-11-30 10:43:50 +00:00
Bryan Boreham d501c78795 Merge pull request #2659 from weaveworks/issues/2581-optional-bridge-nf
Optional bridge-nf detection
2016-11-28 18:09:40 -08:00
Adam Harrison e61ddc59c4 Merge branch '1.8'
Fixes #2669.
2016-11-28 11:54:03 +00:00
Adam Harrison 46e4f047de Merge pull request #2672 from weaveworks/issues/2669-iprange-clash
Check whether Weave's IP range overlaps something on the host already
2016-11-28 11:53:50 +00:00
Adam Harrison 9cff5f2c5e Merge branch '1.8' 2016-11-25 17:23:39 +00:00
Adam Harrison 5f031453d3 Remove backticks which are tripping up the markdown renderer 2016-11-25 16:55:22 +00:00
Marc CARRE 028216021f Fixed formatting of documentation about logging of connection blocked by Weave NPC. 2016-11-25 16:00:05 +00:00
Bryan Boreham d6544302d3 Check whether Weave's IP range overlaps something on the host already 2016-11-25 14:43:23 +00:00
Adam Harrison bc529c5d09 Merge branch '1.8'
Fixes #2667.
2016-11-25 13:10:29 +00:00
Adam Harrison 354d1ddd5c Merge pull request #2670 from weaveworks/issues/2667-firewall-rules
Run GCE test VMs on a locked-down network
2016-11-25 13:09:54 +00:00
Adam Harrison 28bf4e6e95 Optional bridge-nf detection 2016-11-25 12:40:20 +00:00
Marc Carré 33b7faa17d Merge pull request #2668 from weaveworks/fix-doc-formatting
Fix documentation's formatting.
2016-11-25 12:28:26 +00:00
Marc CARRE ac731c0ff7 Fixed formatting of documentation about logging of connection blocked by Weave NPC. 2016-11-25 12:19:53 +00:00
Bryan Boreham fd34dda6c1 Run test instances on a locked-down network
and open up a rule from the specific IP running the tests
2016-11-24 17:17:12 +00:00
Bryan Boreham 16fca913de Merge branch '1.8' 2016-11-24 15:27:36 +00:00
Bryan Boreham f989a82eb0 Merge pull request #2573 from weaveworks/2546-clarify-npc-packet-drop-no-link
Clarified and documented Weave NPC packet drops (w/o short URL).
2016-11-24 15:26:49 +00:00
Marc CARRE d410ecd34c Document logging of connection blocked by Weave NPC. 2016-11-24 14:04:43 +00:00
Marc CARRE 48569265e2 Add logging of connection blocked by Weave NPC. 2016-11-24 14:02:22 +00:00
Bryan Boreham ad43acf843 Merge branch '1.8' 2016-11-24 10:53:59 +00:00
Bryan Boreham 71782a6aa5 Merge pull request #2661 from weaveworks/fix-700-again
Wait up to 30s for version check error in logs
2016-11-24 10:52:47 +00:00
Adam Harrison 6df24d1a40 Merge branch '1.8' 2016-11-23 12:37:14 +00:00
Adam Harrison e283b0a1ce Add release v1.8.1 2016-11-23 12:25:07 +00:00
Adam Harrison fa15193011 Wait up to 30s for version check error in logs 2016-11-23 10:53:42 +00:00
Bryan Boreham dff14c19f8 Don't remove base CNI plugins in test 2016-11-23 10:38:23 +00:00
Adam Harrison 6103595b9c Merge branch '1.8' 2016-11-23 10:36:53 +00:00
Adam Harrison 01c436ae15 Merge pull request #2642 from weaveworks/fix-launch-version
Fix weave-kube launch.sh version usage
2016-11-23 10:36:16 +00:00
Adam Harrison c3a2539445 Merge branch '1.8' 2016-11-22 16:17:30 +00:00
Adam Harrison 664ba8735f Merge pull request #2643 from weaveworks/issues/2632-cni-no-check-alive
Don't release CNI-allocated IP address when container dies
2016-11-22 16:17:11 +00:00
Bryan Boreham 937036aa64 Simplify default version string 2016-11-22 15:43:17 +00:00
Bryan Boreham 47cdf2b755 Simplify version sed 2016-11-22 15:42:53 +00:00
Adam Harrison ef270764f3 Merge branch '1.8'
Fixes #2632.
2016-11-22 15:28:03 +00:00
Adam Harrison a6edd40de3 Merge pull request #2658 from weaveworks/issues/2632-use-pod-status
Make NPC only look at IP addresses on running pods
2016-11-22 15:27:48 +00:00
Bryan Boreham 4219c2c2ab Only look at IP addresses on pods that haven't finished 2016-11-22 13:49:28 +00:00
Bryan Boreham 4785de1a34 Merge branch '1.8' 2016-11-22 09:59:27 +00:00
Bryan Boreham cbec624cd8 Remove CNI files when tearing down Kubernetes 2016-11-21 16:08:50 +00:00
Bryan Boreham e7bde18f71 Merge pull request #2656 from weaveworks/add-jq-to-vagrantfile
Include jq in the build VM
2016-11-21 11:53:03 +00:00
Bryan Boreham e9eeaee520 Warn user on unknown gce util command 2016-11-21 09:49:41 +00:00
Bryan Boreham d5ec9fb38d Fix test 700 to use resolver override
instead of /etc/hosts override that didn't work in netgo mode
2016-11-18 20:42:15 +00:00
Adam Harrison 233a776c41 Include jq in the build VM
Required to run the tests.
2016-11-18 17:59:13 +00:00
Bryan Boreham d5f1c233bf Remove punctuation from the end of error messages
to placate the linter
2016-11-18 10:40:41 +00:00
Bryan Boreham af732d0495 Merge pull request #2529 from weaveworks/use-golang-171
Build container FROM golang:1.7.3
2016-11-17 15:04:12 +00:00
Marc Carré 04a87f951b Merge pull request #2644 from weaveworks/issues/2567-tighter-iprange
Better value for --ipalloc-range in attach-router
2016-11-17 11:38:12 +00:00
Bryan Boreham 9cc98919fa Adjust CNI smoke-test to cope with new plugin behaviour 2016-11-14 19:53:54 +00:00
Bryan Boreham e42600632f Don't release dead container's IP addresses if not asked to check it is alive. 2016-11-14 19:53:54 +00:00
Bryan Boreham 93aa3fed16 Merge branch '1.8' 2016-11-14 19:47:05 +00:00
Bryan Boreham 49e76d1486 Merge pull request #2645 from weaveworks/fix-test-700
Replace iptables block with resolver override
2016-11-14 19:44:26 +00:00
Adam Harrison 965bed7c4f Replace iptables block with resolver override 2016-11-14 17:11:17 +00:00
Bryan Boreham 317c6ba04c Better value for --ipalloc-range in attach-router
The previous regex matched a blank --ipalloc-range and the following
parameter, which defeated the whole point of the check.
2016-11-14 16:11:42 +00:00
Adam Harrison 41d127934b Remove redundant GO15VENDOREXPERIMENT setting 2016-11-14 15:13:19 +00:00
Adam Harrison 915638d17a Address linter failures 2016-11-14 15:13:19 +00:00
Adam Harrison f73355abcc Incorporate Docker's malformed host fix 2016-11-14 15:13:19 +00:00
Adam Harrison 8f9da95e5e Restore golint 2016-11-14 15:13:19 +00:00
Adam Harrison 0935aa9221 Build container FROM golang:1.7.3 2016-11-14 15:13:19 +00:00
Adam Harrison aaa073afed Merge branch '1.8'
Fixes #2617 and fixes #2570.
2016-11-14 15:11:57 +00:00
Adam Harrison 9b606fb823 Merge pull request #2637 from weaveworks/issues/2617-cni-expose
Remove 'weave expose' race in CNI plugin
2016-11-14 15:11:38 +00:00
Bryan Boreham 15d91c558b Quote version string which may contain spaces, etc 2016-11-14 12:49:00 +00:00
Bryan Boreham ffc5a78139 Add code-coverage options to weaver version call 2016-11-14 12:42:17 +00:00
Bryan Boreham f8693074a3 Move CNI config file to the end of launch script
So something waiting for the config (e.g. Kubernetes) doesn't try to
talk to Weave before then (this only helps on first install, but that
tends to be when things are busiest).
2016-11-14 12:37:42 +00:00
Bryan Boreham 1629f4f3f0 Loop round iptables commands on EAGAIN 2016-11-14 12:37:42 +00:00
Bryan Boreham 10baab38d3 Extend smoke-test to include pinging 2016-11-14 12:37:42 +00:00
Bryan Boreham e458c11e66 Weave script calls Go implementation of expose_nat 2016-11-14 12:37:42 +00:00
Bryan Boreham a07e3301b1 Add 'weave expose' NAT iptables rules inside CNI plugin
This avoids a race between the plugin and the script
2016-11-14 12:37:42 +00:00
Bryan Boreham 2b4d13c5b1 Don't error on bridge address already there 2016-11-14 12:37:42 +00:00
Bryan Boreham 755e42836c Merge branch '1.8' 2016-11-14 11:29:34 +00:00
Bryan Boreham ad743b0e96 Merge pull request #2577 from weaveworks/2548-fix-reclaim-after-using-cni
Fix reclaim after using CNI; Fixes #2548.
2016-11-14 11:28:42 +00:00
Marc CARRE 0544901357 Factorise "_" duplicates as a constant. 2016-11-11 17:00:26 +00:00
Marc CARRE bc94633180 Re-claim IP on start-up when an existing ID has been found.
- Rewrote conditions to keep c.ident immutable and hopefully makes
things clearer.
- Added a case to tolerate reclaim after we have used CNI (passed CID
is “_” and existing CID is a real container ID).
2016-11-11 17:00:26 +00:00
Marc CARRE 16415404c7 Added automated test reproducing the issue.
test #4 "[
3e52b548e6df304c61ea5bee0af4b3515e025e7e25152c65ecae3d03c71cf52d ==
Unable to claim: address 10.32.0.3/12 is already owned by
fbe411facc8b657c5850591ab56fc40fb56160d43db0d7363a29ba3edad61134
Unable to claim: address 10.32.0.1/12 is already owned by
cf16a2bcdee8dd1ef7e5f0a611127611e67ea734f45d7526678fc3b1fc0c6f5d
3e52b548e6df304c61ea5bee0af4b3515e025e7e25152c65ecae3d03c71cf52d ]"
failed:
	program terminated with code 2 instead of 0
1 of 6 tests failed in 6.499s.
2016-11-11 17:00:26 +00:00
Adam Harrison 702d12d801 Merge branch '1.8'
Fixes #2537.
2016-11-11 16:14:52 +00:00
Adam Harrison 46eb01604c Merge pull request #2565 from weaveworks/2537-fix-status-on-version-check-failures
Improve 'status' to handle cases when the checkpoint API is not available
2016-11-11 16:14:24 +00:00
Adam Harrison af36682a7e Merge branch '1.8' 2016-11-11 11:27:25 +00:00
Bryan Boreham 03d9e3db69 weaveutil now depends on plugin code 2016-11-10 17:04:10 +00:00
Marc CARRE b03b3fccc7 Fixes 2537: status now prints 'failed to check latest version' when the checkpoint API is not available (+test). 2016-11-09 17:46:52 +00:00
Marc Carré 9414e2979d Merge pull request #2599 from weaveworks/replace-kubectl-create-with-apply
Updated doc: replaced kubectl create with kubectl apply.
2016-11-07 16:31:31 +00:00
Marc CARRE 865664425b Updated doc: replaced kubectl create with kubectl apply. 2016-11-07 16:18:40 +00:00
Adam Harrison b060cf30f4 Add release v1.8.0 2016-11-04 15:49:36 +00:00
Marc Carré 5352ed837a Merge pull request #2598 from weaveworks/cni-setup-remove-symlink
Clean up CNI symlinks from weave-kube
2016-11-04 15:28:44 +00:00
Adam Harrison d4d54a1ff5 Clean up CNI symlinks from weave-kube 2016-11-04 14:41:34 +00:00
Adam Harrison ea82a6715f Merge pull request #2569 from weaveworks/weave-kube-smoke-test
weave-kube smoke test
2016-11-04 12:58:20 +00:00
Martynas Pumputis d356e32bdf Merge pull request #2588 from weaveworks/kube-npc-docs
Document k8s addon & prometheus metrics
2016-11-04 12:50:41 +00:00
Martynas Pumputis 6193d22d2e Merge pull request #2595 from weaveworks/change-npc-metrics-port
Change default NPC metrics port
2016-11-04 12:41:25 +00:00
Adam Harrison 50c9568073 Document Prometheus metrics endpoints 2016-11-04 12:33:06 +00:00
Adam Harrison 9d05ed41b2 Change default NPC metrics port 2016-11-04 12:31:01 +00:00
Adam Harrison e3f7e0a23a Merge pull request #2590 from weaveworks/issues/2586-/opt/cni/bin-never-upgraded
Add support for atomic and versioned upgrades of CNI plugin.
2016-11-04 12:27:48 +00:00
Marc CARRE da2f0803ce Add support for atomic and versioned upgrades of CNI plugin. 2016-11-04 11:54:22 +00:00
Bryan Boreham 6dde5e5ee9 Add code-coverage options to weaver start 2016-11-04 10:52:36 +00:00
Bryan Boreham 494df21bdf Disable imagePullPolicy so we test the image we just built 2016-11-04 10:52:36 +00:00
Bryan Boreham e44bbbec63 Add smoke-test for weave-kube 2016-11-04 10:52:36 +00:00
Bryan Boreham c19f49a284 Install Kubernetes packages and pre-pull images
Bump template version too
Note that we disable kubelet in the image, so you have to start it if
you want to use it.
2016-11-04 10:52:36 +00:00
Adam Harrison d3f2c110e4 Merge pull request #2589 from weaveworks/issues/2587-cni-weaveutil
Fix CNI plugin calling weaveutil
2016-11-04 10:47:38 +00:00
Bryan Boreham 09628178e4 Weave-kube doesn't need to depend on plugin repo any more 2016-11-03 17:42:39 +00:00
Bryan Boreham 5630a01a8c Implement CNI plugin via weaveutil 2016-11-03 17:42:39 +00:00
Adam Harrison 40b3a49c90 Merge pull request #2563 from weaveworks/update-test-template
Update CI VMs to Ubuntu 16.04 and Docker 1.11
2016-11-03 17:35:21 +00:00
Adam Harrison 431b87b94a Merge pull request #2591 from weaveworks/reset-npc
Have 'weave reset' remove NPC rules
2016-11-03 15:22:46 +00:00
Adam Harrison 828c3d21d2 Recommend using the k8s addon from the CNI docs 2016-11-03 15:13:50 +00:00
Adam Harrison f0e75481d5 Add network policy to features 2016-11-03 15:13:50 +00:00
Adam Harrison 8bb7e1cf24 Document Kubernetes Addon 2016-11-03 15:13:50 +00:00
Bryan Boreham e117a6bd04 Have 'weave reset' remove NPC rules 2016-11-03 14:24:26 +00:00
Adam Harrison ac44fa63c8 Fix breakage caused by #2574 2016-11-03 11:52:58 +00:00
Martynas Pumputis bb639dbf32 Merge pull request #2585 from weaveworks/merge-weave-npc
Merge weave npc
2016-11-02 11:58:43 +00:00
Bryan Boreham 64c890005a Merge pull request #2583 from damoon/fixup-74b477ac82e1ae267cf8501519f52e1f71a782dc
weaveworks/weave-kube:latest broken - fixup! allow to not run NPC: do not create iptables rules for NPC
2016-11-02 11:58:02 +00:00
Adam Harrison 19088ba8bc Import from weave-npc repo 2016-11-02 11:28:59 +00:00
Martynas Pumputis ec5f7033a4 Merge pull request #2579 from weaveworks/issues/2557-improve-metric-naming
Improve metric naming
2016-11-02 11:02:23 +00:00
Bryan Boreham eb60f68df2 Report metrics on all connection states 2016-11-02 09:51:13 +00:00
David Sauer d72e671d8b fixup! allow to not run NPC: do not create iptables rules for NPC 2016-11-02 10:10:33 +01:00
Martynas Pumputis 3462357481 Merge pull request #2578 from weaveworks/issues/2576-metrics-on
Serve metrics by default, on port 6782
2016-11-02 09:08:13 +00:00
Bryan Boreham 2b4da35b1c Remove 'total' DNS entries; let the caller add them up 2016-11-01 18:03:35 +00:00
Bryan Boreham 86d68c9875 Move total IPs in range from a state to a separate metric 2016-11-01 18:03:35 +00:00
Bryan Boreham cfff8ee8be Merge pull request #2568 from weaveworks/rename-conn-term-prom-metric
Rename weave_connection_termination_count metric
2016-11-01 18:02:55 +00:00
Bryan Boreham af10cef5f0 Set --status-addr for metrics by default 2016-11-01 17:04:04 +00:00
Bryan Boreham a1a42736ed Fix hard-coded http address 2016-11-01 16:53:37 +00:00
Adam Harrison b533a11bee Update client-go
weave-npc needs some fixes from client-go master (specifically the
unversioned.LabelSelector change)
2016-11-01 16:19:43 +00:00
Bryan Boreham afed9e9646 Merge pull request #2574 from pondohva/fix_weave_static_pod
allow to not run NPC: do not create iptables rules for NPC
2016-11-01 15:35:49 +00:00
Artur Gadelshin 74b477ac82 allow to not run NPC: do not create iptables rules for NPC 2016-11-01 17:32:41 +03:00
Bryan Boreham bf74c8f108 Add dependency of weave-kube on launch.sh 2016-11-01 10:46:25 +00:00
Bryan Boreham 04c7f5283e Reconfigure and restart docker for systemctl 2016-10-31 17:33:33 +00:00
Bryan Boreham d1d53ba45c Pre-install more stuff in the image.
Install bc and jq in the image rather than on every build.
Also pre-pull some Docker images
2016-10-31 17:33:33 +00:00
Bryan Boreham dfadb8f189 Upgrade to Ubuntu 16.04 and Docker 1.11
Using Docker 1.11 since there isn't a Docker-supplied package for 1.10 on Xenial
2016-10-31 17:33:33 +00:00
Bryan Boreham 5335c133a3 Update deprecated gcloud syntax 2016-10-31 17:33:33 +00:00
Adam Harrison 8fcb5daedf Merge pull request #2551 from weaveworks/weave-kube
Merge weave-kube into the Weave Net repo
2016-10-31 17:12:03 +00:00
Martynas Pumputis ede70a78d6 Rename weave_connection_termination_count metric
To make it follow the Prometheus naming conventions:
https://prometheus.io/docs/practices/naming/
2016-10-31 13:23:12 +00:00
Bryan Boreham 23056cbb45 Temporarily release weave-daemonset.yaml to weave-kube repo 2016-10-31 10:59:15 +00:00
Bryan Boreham 29e9e70ac9 Add weave-kube to release script 2016-10-31 10:59:15 +00:00
Bryan Boreham d0b711513e Add weave-daemonset.yaml 2016-10-31 10:59:15 +00:00
Bryan Boreham 7dbee74e85 Add weave-kube image 2016-10-31 10:59:15 +00:00
Bryan Boreham 4e7a3b1805 Add kube-peers program 2016-10-31 10:59:15 +00:00
Bryan Boreham 3c7b244f18 Change image layering - plugin builds on weaver & weaver builds on weaveexec 2016-10-31 10:59:13 +00:00
Bryan Boreham e50f5c52c5 Make templating of Dockerfiles more generic 2016-10-31 10:56:18 +00:00
Bryan Boreham baf91658d6 Fix static linking flags 2016-10-28 14:51:26 +01:00
Adam Harrison fda035d8d6 Merge branch '1.7' 2016-10-28 14:29:26 +01:00
Adam Harrison a4a53e1a11 Fix broken link 2016-10-28 14:08:54 +01:00
Martynas Pumputis aad3e52d72 Merge pull request #2564 from weaveworks/improved-dh-org-override-fix
Improve Dockerfile template substitution
2016-10-28 10:24:28 +01:00
Adam Harrison cb778a9af5 Improve Dockerfile template substitution 2016-10-27 11:43:41 +01:00
Marc CARRE 3af9732c84 Merge branch '1.7' 2016-10-26 16:49:58 +01:00
Marc Carré 00e754ed9f Merge pull request #2562 from weaveworks/build-test-runner-with-vendoring
Use vendoring when building test runner & Vagrantfile improvements
2016-10-26 16:44:15 +01:00
Marc CARRE d893f44833 Vagrantfile now copies SSH key required to run smoke tests from host to guest. 2016-10-26 16:09:09 +01:00
Marc CARRE 4839f41809 Improve resolution of Dockerfile since used in both Vagrantfile and test/Vagrantfile. 2016-10-26 16:09:09 +01:00
Marc CARRE c801409c94 Set VM's memory to 2048 MB by default. 2016-10-26 16:09:09 +01:00
Marc CARRE 1c4a01d52c Read Go version from Dockerfile in order to keep things 'DRY'. 2016-10-26 16:09:09 +01:00
Adam Harrison 880b0a883a Use vendoring when building test runner 2016-10-26 16:09:09 +01:00
Adam Harrison 4b77662e3b Merge pull request #2561 from weaveworks/issues/2560-fix-dns-ipam-metrics
Do not expose IPAM or DNS metrics if weave does not run IPAM or DNS
2016-10-26 14:24:43 +01:00
Adam Harrison a5ff7ab8df Merge pull request #2475 from weaveworks/issues/2419-withnetns
Add a safer version of WithNetNS*
2016-10-26 13:50:34 +01:00
Adam Harrison 04a6e6d13b Merge branch '1.7' 2016-10-26 13:47:05 +01:00
Martynas Pumputis 5c2e878c64 Do not expose IPAM or DNS metrics when weave does not run IPAM or DNS
Otherwise, GET /metrics will crash weaver.
2016-10-25 16:54:35 +01:00
Adam Harrison f9bada5af8 Merge pull request #2558 from weaveworks/fix-broken-url-in-doc
Fixed broken link to plugin.md to weave-docker-api.md.
2016-10-24 16:57:07 +01:00
Marc CARRE 80d66f8f68 Fixed broken link to plugin.md to weave-docker-api.md. 2016-10-24 16:37:55 +01:00
Martynas Pumputis 98b35b87a9 Fix weave_connection_termination_count
Do not count terminations caused by connect-to-ourselves.
2016-10-24 11:37:15 +01:00
Martynas Pumputis b1d6605e8f Remove inaccurate Prometheus metrics
The metrics include:
- weave_packets_total
- weave_bytes_total

The problem with those metrics is that fastdp periodically flushes
flows including their stats thus makes the current implementation
of the metrics unreliable.
2016-10-24 11:23:10 +01:00
Martynas Pumputis 2cd3bde348 Merge pull request #2555 from weaveworks/forget-immediately
Recompute targets immediately after 'weave forget'
2016-10-24 10:52:14 +01:00
Bryan Boreham f2454775b9 Merge pull request #2552 from weaveworks/issues/2550-fix-make-dockerhub-user
Ensure Dockerfiles obey DOCKERHUB_USER
2016-10-24 09:59:38 +01:00
Bryan Boreham a53d1e00ee Recompute targets immediately after 'weave forget' 2016-10-21 18:02:25 +01:00
Martynas Pumputis 523a964ac8 Merge pull request #2547 from weaveworks/prometheus-metrics
Prometheus metrics
2016-10-21 14:57:42 +01:00
Adam Harrison f8cf7a1054 Ensure Dockerfiles obey DOCKERHUB_USER 2016-10-21 14:45:10 +01:00
Bryan Boreham 4d8a40c0b5 Reduce metrics mechanism to just support fastdp 2016-10-21 14:44:12 +01:00
Martynas Pumputis 9754da15d6 Encode "list-netdevs" output in JSON 2016-10-20 18:18:57 +01:00
Bryan Boreham 0458d32089 Serve metrics on a different socket to the main API
Serve metrics+status on status socket and api+status+metrics on api
socket; the reasoning is that metrics or status are read-only hence
may be scraped from an off-machine connection, while we don't want to
open the control port up unprotected.
2016-10-20 16:25:16 +01:00
Bryan Boreham ee4e8eb994 Pull in updated mesh lib 2016-10-20 16:25:16 +01:00
Bryan Boreham b8d619dde7 Add Prometheus http handler for metrics
Metrics are: connection counts, active IP addresses, DNS addresses,
FastDP flow metrics, connection termination count
2016-10-20 16:25:16 +01:00
Bryan Boreham 00c86fed42 Expose overlay metrics from fastdp
and allow them to pass through OverlaySwitch
2016-10-20 16:25:16 +01:00
Bryan Boreham 6d5af85eee Report count of active IP addresses in status 2016-10-20 14:04:41 +01:00
Bryan Boreham 1ae2d33714 Remove old-style 'expvar' metrics 2016-10-20 13:54:42 +01:00
Bryan Boreham 71d550260f Extract countDNSEntries function 2016-10-20 13:54:42 +01:00
Bryan Boreham 1092bae05c Refactor: move 'unreachable' logic out of printing function 2016-10-20 13:54:42 +01:00
Martynas Pumputis e611f04f41 Move NetDev utils from common/ to net/ 2016-10-19 17:03:30 +01:00
Martynas Pumputis 3492cd93d0 Use safe version of WithNetNS 2016-10-19 16:15:59 +01:00
Martynas Pumputis 947ae11fee Refactor NetDev utilities
- Make them safe by using the safe version of WithNetNS.
- Improve naming.
2016-10-19 16:07:53 +01:00
Martynas Pumputis cdd6ed548c Add netdev subcommands to weaveutil
The subcommands are going to be used with WithNetNS wrapper.
2016-10-19 16:07:53 +01:00
Martynas Pumputis fc940d0017 Merge pull request #2549 from weaveworks/log-drops-via-nflog
Log dropped policy controller traffic via NFLOG
2016-10-19 11:02:28 +01:00
Bryan Boreham b38a55ca7c Include more context in error messages from CNI operations 2016-10-18 17:45:09 +01:00
Adam Harrison 8e739d5240 Log dropped policy controller traffic via NFLOG
Send blocked NEW connection attempts to NFLOG group 86 for accounting by
the weave-npc process.
2016-10-14 15:59:15 +01:00
Adam Harrison 71f8bb7e9a Merge branch '1.7' 2016-10-11 17:02:00 +01:00
Adam Harrison ebfaf11f4a Add release v1.7.2 2016-10-11 11:07:18 +01:00
Matthias Radestock 4a6cec3ecc Merge branch '1.7' 2016-10-07 12:47:04 +01:00
Matthias Radestock 1abce148a3 Merge pull request #2543 from weaveworks/issues/2527-remote-addr
Update Weave Mesh to bring in two fixes

Fixes #2481 via weaveworks/mesh#57
Fixes #2527 via weaveworks/mesh#60
2016-10-07 12:45:51 +01:00
Adam Harrison e0cc7f17b2 Merge branch '1.7'
Fixes #2540
2016-10-07 12:24:11 +01:00
Adam Harrison 264e5c9979 Merge pull request #2541 from weaveworks/issues/2540-withnetns
Change namespace via nsenter, for plugin arp-config step
2016-10-07 12:20:47 +01:00
Bryan Boreham a6a1ce5c9e Update Weave Mesh to bring in fix of panic 2016-10-07 12:13:49 +01:00
Bryan Boreham 6ac7ab162f Merge branch '1.7' 2016-10-06 16:42:07 +01:00
Bryan Boreham 5e660311d2 Merge pull request #2538 from weaveworks/2506-uts-release-bytes
inline (u)int8 array to string conversion
2016-10-06 16:41:26 +01:00
Martynas Pumputis 4a49ff3083 Replace usage of WithNetNSUnsafe in plugin/net/watcher.go with safer version
Unsafe version was in ConfigureARPforVeths; replacement is via `weaveutil configure-arp`
2016-10-06 15:25:05 +01:00
Martynas Pumputis 7f92c8c4c6 Add a safer version of WithNetNS*
The introduced functions are executing the work function via
a process which executes "nsenter --net=path weaveutil ...".
2016-10-06 15:25:05 +01:00
Matthias Radestock 85ac8177ad inline (u)int8 array to string conversion
so that the code compiles regardless of the uts.Release array type,
which varies across platforms.

Fixes #2506
2016-10-06 08:57:12 +01:00
Adam Harrison 03bd1fb91d Merge branch '1.7' 2016-10-05 16:49:33 +01:00
Adam Harrison eb5b16614c Add release v1.7.1 2016-10-05 15:23:25 +01:00
Adam Harrison a5873a3970 Merge branch '1.7' 2016-10-05 15:18:26 +01:00
Adam Harrison e48ca80dee Disable golint as it no longer builds with 1.5.x 2016-10-05 15:16:23 +01:00
Bryan Boreham e7c9e22350 Merge pull request #2274 from weaveworks/issues/2273-improve-doc-ci
Improve doc CI
2016-10-03 15:34:39 +01:00
Adam Harrison b8e7d83f19 Rename SKIP_TESTS 2016-10-03 14:07:57 +01:00
Adam Harrison 4c304c0013 Extract install-wordepress 2016-10-03 14:01:15 +01:00
Adam Harrison 7249350757 Merge pull request #2531 from weaveworks/process-addrs
Add weaveutil process-addrs
2016-09-30 10:28:59 +01:00
Bryan Boreham 50a8dc1383 Add weaveutil process-addrs
Fetches addresses for every veth that is in a network namespace and
attached to the specified bridge.  Works by iterating over every process.
2016-09-29 14:16:05 +01:00
Bryan Boreham 71491138aa Extract function to return all current process ids
This implementation should be more efficient because it only uses the
names under /proc, whereas the previous implementation fetched the
full directory entry for each one, and sorted them too.
2016-09-29 14:12:02 +01:00
Bryan Boreham ca87f8ada3 Improve comments 2016-09-29 14:06:43 +01:00
Adam Harrison 835b3f3d67 Improve script names 2016-09-29 13:01:18 +01:00
Adam Harrison 263dffeedc Extract shared function 2016-09-29 11:45:28 +01:00
Adam Harrison e1063944f6 Comment on GitHub PR with site changes 2016-09-29 11:45:28 +01:00
Adam Harrison 2380018457 Skip tests if PR contains only site changes 2016-09-29 11:45:28 +01:00
Adam Harrison a9db631836 Add toggle for skipping tests 2016-09-29 11:35:01 +01:00
Adam Harrison b45f138ff1 Propagate state between scripts 2016-09-29 11:25:34 +01:00
Adam Harrison b239694d34 Move circle commands into shell scripts 2016-09-29 11:25:34 +01:00
Adam Harrison 0c2774f367 Add release v1.7.0 2016-09-27 14:46:35 +01:00
Bryan Boreham ea4647bc74 Merge pull request #2524 from weaveworks/expect-npc
Implement `--expect-npc` flag to `create-bridge`
2016-09-27 13:41:22 +01:00
Adam Harrison 6ec21d3a58 Implement --expect-npc flag to create-bridge
Add a private flag for weave-kube to steer overlay traffic via the
network policy engine chain.
2016-09-27 09:23:19 +01:00
Adam Harrison 44a4a56024 Merge branch '1.6' 2016-09-21 17:14:07 +01:00
Adam Harrison 0aac614c08 Add release v1.6.2 2016-09-21 16:18:03 +01:00
Adam Harrison 2ea027d3a8 Merge branch '1.6' 2016-09-21 11:15:49 +01:00
Adam Harrison cd4cbed5a0 Merge pull request #2501 from weaveworks/issues/2495-filter-empty-peers
Reject empty peers
2016-09-21 11:12:10 +01:00
Adam Harrison 69b688b357 Merge pull request #2509 from weaveworks/issues/2503-persist-peers-fix
Create restart.sentinel after storing the peer list
2016-09-21 10:09:05 +01:00
Adam Harrison 7a81bc2ddc Merge pull request #2510 from weaveworks/issues/2329-fix-830-flakiness
Enable unsolicited ARPs in 830 test suite
2016-09-20 17:17:19 +01:00
Martynas Pumputis cdeae04238 Create restart.sentinel after storing peer list
Otherwise, we risk to lose peer list when any failure happens after
the creation but before storing the list and as a consequence,
the weave container gets restarted.
2016-09-20 17:07:48 +01:00
Martynas Pumputis 6df2782d73 Update weaveworks/mesh submodule 2016-09-20 17:03:38 +01:00
Adam Harrison 3fc7efa536 Merge pull request #2498 from weaveworks/broken-link
fixed broken link to command line args
2016-09-20 16:40:06 +01:00
Adam Harrison a556deec78 Merge branch '1.6' 2016-09-20 16:26:48 +01:00
Adam Harrison 71e43c2023 Merge pull request #2511 from weaveworks/issues/2340-make-640-less-flaky
Filter out netns of non-existing containers
2016-09-20 15:52:54 +01:00
Bryan Boreham 370f258c3a Fix outdated option ipam-seed 2016-09-16 15:53:43 -07:00
Martynas Pumputis 9b32bc2ab3 Close opened netns 2016-09-14 16:47:40 +01:00
Martynas Pumputis fd5e1970e1 Return nil netdev if netns of container cannot be found
The change applies to GetNetDevsWithPredicate. The function calls
FindNetDevs which already does the same filtering.

The change prevents from "container-addrs" (weaveutil) returning
"unable to open X process namespace" error which happens when
a container dies while the cmd is being executed.
2016-09-14 16:47:16 +01:00
Martynas Pumputis a1de7f3eef Enable unsolicited ARPs in 830 test case
Otherwise, ping (c1->c3) after the address reuse might time out.
2016-09-14 11:05:00 +01:00
Matthias Radestock 06a63db4cf Merge branch '1.6' 2016-09-08 12:55:05 +01:00
Matthias Radestock c720ebec02 Merge pull request #2502 from weaveworks/issues/2469-supply-subnet
Pass in default subnet when creating 'weave' plugin network.

Fixes #2469.
2016-09-08 12:49:01 +01:00
Matthias Radestock 6a528409ab Merge pull request #2504 from weaveworks/check-tx-off
Check current tx value before trying to set it
2016-09-08 12:32:15 +01:00
Bryan Boreham c69e140e9e Check current tx value before trying to set it 2016-09-08 10:20:35 +01:00
Anita Buehrle 8ed0c13645 removed broken link 2016-09-06 14:36:25 +01:00
Anita Buehrle b635f9a994 fixed broken link to command line args 2016-09-06 14:36:25 +01:00
Bryan Boreham ac4246e1f5 Pass in default subnet when creating 'weave' plugin network.
New behaviour in Docker 1.12 means it disregards a plugin-supplied
address pool that overlaps an existing route, which causes a hang as
noted in #2469. When we pass in the subnet, Docker believes we really
do want that address range and avoids the hang.
2016-09-06 12:05:51 +01:00
Martynas Pumputis 06a325a05f Use weaveworks/docker/pkg/mflag everywhere 2016-09-05 17:22:28 +03:00
Martynas Pumputis 68e9bbe350 Add github.com/weaveworks/docker submodule 2016-09-05 16:16:06 +03:00
Matthias Radestock 3bd9e369cd Merge branch '1.6' 2016-09-05 12:51:30 +01:00
Matthias Radestock 3d12e8088e Merge pull request #2491 from weaveworks/switch-ci-14.04
Switch CircleCI build VM to 14.04
2016-09-05 12:49:25 +01:00
Martynas Pumputis aee35b34fe Pin joffrey/docker-py image to 1.8.1 vsn
The latest image requires 1.12.x dockerd.
2016-09-05 14:30:49 +03:00
Martynas Pumputis c06ccb3b0d Change owner of /usr/local/go on build VM
Otherwise "go get -tags netgo" fails with the permission denied error.
2016-09-05 14:30:49 +03:00
Martynas Pumputis 268bb656fc Do not fetch Google Cloud SDK
As it is already installed on CircleCI 14.04 build VMs
2016-09-05 14:30:49 +03:00
Martynas Pumputis 57357a728c Merge branch '1.6' 2016-09-05 13:48:30 +03:00
Martynas Pumputis a335c419ec Fix typo 2016-09-05 13:27:49 +03:00
Martynas Pumputis e263295720 Revert "Do not fetch Google Cloud SDK"
This reverts commit f557835ad0.
2016-08-26 14:42:50 +01:00
Martynas Pumputis 0c854f2144 Merge pull request #2489 from weaveworks/fix-mflag-missing
Use mflag package from weaveworks fork until we find a better solution
2016-08-26 12:19:59 +01:00
Alfonso Acosta bdf4debdfd Use mflag package from weaveworks fork until we find a better solution 2016-08-26 11:07:21 +00:00
Martynas Pumputis f557835ad0 Do not fetch Google Cloud SDK
As it is already installed on CircleCI 14.04 build VMs
2016-08-26 11:38:37 +01:00
Martynas Pumputis 17a7391086 Remove unused functions 2016-08-26 10:15:27 +01:00
Martynas Pumputis e65293eb50 Merge branch '1.6' 2016-08-19 14:12:26 +01:00
Martynas Pumputis 48c9547943 Update CHANGELOG.md 2016-08-19 14:11:57 +01:00
Martynas Pumputis caa6c6c931 Merge branch '1.6' 2016-08-19 11:22:07 +01:00
Martynas Pumputis 11f56031f1 Add release v1.6.1 2016-08-18 17:39:46 +01:00
Adam Harrison 2e825242cd Merge branch '1.6' 2016-08-18 11:32:43 +01:00
Adam Harrison ebe4c5b8b7 Merge pull request #2478 from weaveworks/bridge-veth-setup
Refactor: move bridge veth creation into 'init_bridge'
2016-08-18 11:31:16 +01:00
Adam Harrison 027064cbdb Merge branch '1.6' 2016-08-18 10:56:03 +01:00
Adam Harrison 9fddb827f9 Merge pull request #2442 from weaveworks/cni-setup-fixes
CNI setup fixes
2016-08-18 10:55:46 +01:00
Bryan Boreham 3162009325 Refactor: move bridge veth creation into 'init_bridge' 2016-08-17 17:33:34 +01:00
Martynas Pumputis 060f6392c7 Merge branch '1.6' 2016-08-16 18:03:00 +01:00
Martynas Pumputis 8c8c6db7dd Increase sleep time in 830_cni_plugin_test
Fix #2329
2016-08-16 18:00:46 +01:00
Matthias Radestock cd94dd0088 setup CNI on weave launch[-router]
not just `setup[-cni]`

Fixes #2435
2016-08-16 14:18:55 +01:00
Matthias Radestock afc6f49e80 mount CNI_NETNS dir, in case it is some exotic location
Fixes #2394
2016-08-16 14:18:28 +01:00
Martynas Pumputis c509b6e5bb Revert "Derive the bridge MAC from concatenated multiple sources"
This reverts commit c2083cbce0.
2016-08-15 09:48:55 +01:00
Bryan Boreham a466f55d59 Merge pull request #2462 from weaveworks/note-proxy-file
added note about net flag
2016-08-12 16:55:57 +01:00
Bryan Boreham c79b6a8bd7 Merge pull request #2460 from weaveworks/issues/2427-detect-peerid-clashes
Detect and report peer name collisions
2016-08-12 16:52:56 +01:00
Martynas Pumputis c2083cbce0 Derive the bridge MAC from concatenated multiple sources
The sources include:

- /etc/machine-id (generated by "systemd-machine-id-setup") or
  /var/lib/dbus/machine-id (generated by "dbus-uuidgen").
- /sys/class/dmi/id/product_uuid.
- /sys/hypervisor/uuid.

The product of the concatenation should produce an unique identifier
which is stable across reboots.
2016-08-11 12:01:35 +01:00
Martynas Pumputis 4157d9298d Update vendored weaveworks/mesh 2016-08-11 12:01:20 +01:00
Adam Harrison f686408808 Merge branch '1.6' 2016-08-10 14:44:25 +01:00
Adam Harrison 432e10e19f Merge pull request #2474 from weaveworks/issues/2375-check-vxlan-udp-port
Check if a vxlan vport netdev is UP after its creation
2016-08-10 14:44:11 +01:00
Adam Harrison b8c57ef10f Merge branch '1.6' 2016-08-10 13:58:53 +01:00
Adam Harrison 601bda3176 Merge pull request #2457 from weaveworks/issues/2424-weaken-tls-check
Do not fail launching the proxy if unable to detect a running instance of docker daemon
2016-08-10 13:58:42 +01:00
Martynas Pumputis d9bde790c6 Check if a vxlan vport netdev is up after its creation
This bypasses a kernel bug when the creation of vxlan vport
completes successfully regardless whether an vxlan UDP port has been
bind (http://marc.info/?l=linux-netdev&m=147075637009483&w=2).
2016-08-10 13:34:44 +01:00
Adam Harrison 5cc0826ca0 Merge branch '1.6' 2016-08-10 13:16:24 +01:00
Adam Harrison 96f2eb3ecf Merge pull request #2471 from weaveworks/cni-bridge-ip
CNI plugin assigns an IP to the bridge by itself
2016-08-10 11:49:25 +01:00
Adam Harrison e703f2f3f2 Merge branch '1.6' 2016-08-10 11:48:31 +01:00
Adam Harrison 1c0ffbc177 Stop publishing historic versions 2016-08-10 11:12:23 +01:00
Adam Harrison f544da9e19 Merge branch '1.6' 2016-08-10 10:18:01 +01:00
Adam Harrison c0592ba1b3 Merge pull request #2470 from weaveworks/no-force-tag
Remove -f flag from 'docker tag' commands
2016-08-10 10:17:06 +01:00
Bryan Boreham 0cbf5ca130 Allow 'weave create-bridge', if the user insists.
For example this is used when setting up CNI for Kubernetes, in
an environment where we know none of the bad consequences apply.
2016-08-10 10:00:17 +01:00
Adam Harrison 472eab2acd Merge pull request #2466 from weaveworks/issues/2464-enable-create-bridge
Re-enable 'weave create-bridge' in fastdp mode.
2016-08-10 09:57:40 +01:00
Bryan Boreham 7a5d7fca6c Allow 'weave create-bridge', if the user insists.
For example this is used when setting up CNI for Kubernetes, in
an environment where we know none of the bad consequences apply.
2016-08-08 17:20:25 +01:00
Bryan Boreham 081b95dfd0 CNI plugin assigns an IP to the bridge by itself
No need to call `weave expose` before use.
2016-08-08 15:28:26 +01:00
Matthias Radestock faf5b14d8b make CNI setup work on recent Docker-for-Macs
Docker for Mac 1.12.0-rc3 (as of beta18) looks for mounted paths on VM
first, and when it doesn't find them there, it assumes they refer to
paths on the Mac OS host. At which point it will complain that the
paths don't exit.

So instead we mount / since that will always exist on the VM. It's
also what we used to do already when launching the router.

Fixes #2434.
2016-08-04 22:03:39 +01:00
Bryan Boreham 38958049f4 Remove -f flag from 'docker tag' commands
This flag was deprecated in Docker 1.10 and removed in Docker 1.12.
2016-08-04 17:03:35 +01:00
Bryan Boreham 589b45dace Merge branch '1.6' 2016-08-03 14:34:49 +01:00
Bryan Boreham 7ebf3d7a88 Don't crash when dockerCli is nil 2016-08-03 14:28:05 +01:00
Anita Buehrle 3273d13666 gave points numbers for clarity 2016-08-02 16:40:16 -05:00
abuehrle 5fdbbf3722 wording formatting 2016-08-02 16:38:41 -05:00
abuehrle 14350ff463 added anchor to attaching containers 2016-08-02 16:35:52 -05:00
abuehrle 0b49c961a7 reconfigured note to include additional method 2016-08-02 16:30:32 -05:00
abuehrle 39b80f26ed made terminology consistent 2016-08-02 13:15:17 -05:00
abuehrle 74b20265e4 fixed links and some titles 2016-08-02 12:59:27 -05:00
abuehrle 358fddb958 fixed broken link and title 2016-08-02 12:52:36 -05:00
abuehrle 5c8f6175b5 added note about net flag 2016-08-02 12:34:52 -05:00
Martynas Pumputis e8d823d66b Do not fail launching the proxy if unable to detect dockerd 2016-07-28 12:53:44 +01:00
Adam Harrison 83ce5875ee Merge branch '1.6' 2016-07-28 12:52:53 +01:00
Adam Harrison ed83efbceb Merge pull request #2450 from weaveworks/eval-considered-harmless
remove dire warnings about 'eval' when using plugin
2016-07-28 12:49:55 +01:00
Adam Harrison 223116c4bf Merge pull request #2393 from weaveworks/intro-ops-guide
intro to ops guide (#2387)
2016-07-28 12:32:34 +01:00
Matthias Radestock 8056a098a8 remove dire warnings about 'eval' when using plugin
since as of #2330 the proxy ignores containers started with specified
user networks.
2016-07-28 11:49:54 +01:00
abuehrle 15a2cba7f8 added anchors to concepts 2016-07-28 11:49:06 +01:00
Anita Buehrle b37bb02a8b intro to ops guide (#2387) 2016-07-28 11:49:06 +01:00
Adam Harrison 0c14e5135a Delint (spelling error) 2016-07-28 11:48:14 +01:00
Adam Harrison f5a30c790e Merge branch '1.6' 2016-07-28 11:30:47 +01:00
Adam Harrison b06ddeb962 Merge pull request #2445 from weaveworks/fix-weave-ps
Fix "weave ps" output when weave is not running
2016-07-28 11:30:31 +01:00
Martynas Pumputis 34415c3c17 Merge pull request #2422 from weaveworks/log-resolvconf-errors
Log errors arising from reading resolv.conf
2016-07-26 18:01:33 +01:00
Matthias Radestock 6387fa8bc9 Merge branch '1.6' 2016-07-20 07:30:56 +01:00
Matthias Radestock f6e6926171 cosmetic: fix wrapped quote
apparently our wp md renderer does not handle this correctly
2016-07-20 07:09:09 +01:00
Matthias Radestock 25e7868cd5 fix some indentation in docs block quote 2016-07-20 07:03:17 +01:00
Matthias Radestock 385e6ff9b8 Merge pull request #2446 from weaveworks/explicit-sudo-s
Make use of `sudo -s` more explicit
2016-07-20 06:45:50 +01:00
Matthias Radestock 3755906689 blockquote sudo-ing 2016-07-20 06:26:23 +01:00
Matthias Radestock 63cbb34dec Make use of sudo -s more explicit
since people keep tripping over that.

Also

- add new error message spat out by recent dockers correct the socket
- URLs - they had fallen victim to a 'docker'->'Docker' replacement
- shorten the note on using the plugin
2016-07-20 06:26:03 +01:00
Adam Harrison 8ec6b699b1 Merge branch '1.6' 2016-07-18 11:48:08 +01:00
Adam Harrison 369852a3a7 Merge pull request #2430 from weaveworks/remove-duplicate-no-dns
remove duplication of `--no-dns`
2016-07-18 11:47:48 +01:00
Matthias Radestock c82be57639 Merge pull request #2423 from philwinder/docs/cni-mesos
Refactor CNI documentation.
2016-07-18 09:58:00 +01:00
Phil Winder 092c3a17d1 Change title. 2016-07-18 09:22:24 +01:00
Martynas Pumputis fd0a7efa23 Fix "weave ps" output when weave is not running
The #2418 has changed a behaviour of "weave ps" which outputs
"Link not found" in the case of weave not running. The previous
behaviour was to output an empty line.
2016-07-14 15:15:14 +01:00
Matthias Radestock 551f164ec3 Merge branch '1.6' 2016-07-12 20:47:23 +01:00
Matthias Radestock acdd739deb Merge branch 'fix-broken-link' into 1.6 2016-07-12 20:46:52 +01:00
Paul Bellamy 45e3016c6a Fixing a broken link in docs 2016-07-12 20:44:57 +01:00
Bryan Boreham 88bf64722f Merge branch '1.6' 2016-07-12 10:33:38 +00:00
Bryan Boreham c1483dbf1f Merge pull request #2418 from weaveworks/issues/2388-weave-ps
Fix "weave ps"; fixes #2388
2016-07-12 11:04:00 +01:00
Matthias Radestock d9c998b5c4 Merge pull request #2386 from weaveworks/issues/354-multicast-isolation
Provide multicast isolation with in-container-netns iptables rules

Fixes #354.
2016-07-12 09:46:14 +01:00
Adam Harrison 170e19c283 Merge branch '1.6' 2016-07-12 09:39:45 +01:00
Adam Harrison bce07b7491 Merge pull request #2439 from weaveworks/restore-script-function-grouping
refactor: restore grouping of functions in script
2016-07-12 09:39:15 +01:00
Matthias Radestock 8b5741506d refactor: restore grouping of functions in script
Recent(ish) changes placed functions in the wrong sections. Fix that
and label the sections more clearly.
2016-07-11 21:38:07 +01:00
Bryan Boreham 7c47a8ffb7 Log errors arising from reading resolv.conf 2016-07-11 12:08:04 +01:00
Matthias Radestock 791ab55875 Merge branch '1.6' 2016-07-09 05:42:02 +01:00
Matthias Radestock e642f366f5 cosmetic 2016-07-09 05:41:37 +01:00
Bryan Boreham bd1a9d020c Merge branch '1.6' 2016-07-07 11:20:50 +00:00
pidster d794b203f7 Adds ipam option to help.
Fixes https://github.com/weaveworks/weave/issues/2425
2016-07-07 11:20:00 +00:00
Matthias Radestock 7ec68119a6 remove duplication of --no-dns
This was harmless, but annoying.
2016-07-06 23:21:42 +01:00
Martynas Pumputis 71fd3b6b2b Merge remote-tracking branch 'origin/1.6' 2016-07-05 17:37:50 +01:00
Martynas Pumputis 93c60395f6 Merge pull request #2417 from weaveworks/issues/1852-less-logging
Move 'ODP miss' log from every miss to specific places

Fixes #1852
2016-07-05 17:34:57 +01:00
Phil Winder af27aa04f2 Add Mesos instructions. Edit old links. 2016-07-05 16:01:01 +01:00
Martynas Pumputis 0861d05522 Address PR comments
- Do not re-enter the root netns when querying weave bridge.
- Enter the root netns when constructing the predicate.
2016-07-05 15:12:39 +01:00
Martynas Pumputis 89221f117b Denote WithNetNS* functions with unsafe
Please see https://github.com/weaveworks/weave/issues/2388#issuecomment-228365069
for more details.
2016-07-05 15:12:39 +01:00
Martynas Pumputis 7f5c37ef1e Fix "weave ps"
Make sure that any network namespace changes happens at the end of
the cmd invocation. Otherwise, we are risking to end up in a situation
in which OS scheduling threads are in a "wrong" namespace.

See WithNetNS for more details.
2016-07-05 15:12:39 +01:00
Martynas Pumputis 05baa566c6 Refactor common.GetBridgeNetDev
- Optimize. Use LinkByName instead of iterating over list of available
  links. Linux does not support interfaces with the same names.
- Remove unnecessary indirection in utility functions which return
  common.NetDev.
2016-07-05 15:12:39 +01:00
Bryan Boreham f8ac27a6cc Merge branch '1.6' 2016-07-05 13:22:25 +01:00
Bryan Boreham e5c23bf9f5 Don't crash if docker API is disabled by params 2016-07-05 13:02:59 +01:00
Matthias Radestock 954cd0b86a Merge branch '1.6' 2016-07-04 16:27:59 +01:00
Matthias Radestock 0635ed1854 highlight the need for weave expose in CNI/k8s (#2411)
* highlight the need for `weave expose` in CNI/k8s

Fixes #2405

* Extend error message

* rearranged the sentences

weave launch <peer hosts> seems a bit orphaned here maybe include the weave connect command as well, since it's being mentioned.
2016-07-04 16:27:11 +01:00
Matthias Radestock 9dedeadf15 Merge branch '1.6' 2016-07-04 16:22:42 +01:00
Matthias Radestock 4424e877f0 Merge branch '1710-lb-clarification' into 1.6 2016-07-04 16:21:54 +01:00
Matthias Radestock 6561272f8d Merge branch '1.6' 2016-07-04 16:20:37 +01:00
Matthias Radestock aa54d332c2 correct RFC3484 address selection caveat (#2407)
and move it to a more prominent location

Fixes #1710
2016-07-04 16:20:19 +01:00
Matthias Radestock 881e795db5 correct RFC3484 address selection caveat (#2407)
and move it to a more prominent location

Fixes #1710
2016-07-04 16:19:20 +01:00
Matthias Radestock 4216231ec7 Merge branch '1.6' 2016-07-04 14:30:03 +01:00
Matthias Radestock e5aeb4bd05 improve --trusted-subnets docs (#2415)
improve --trusted-subnets docs

Fixes #2211
2016-07-04 14:28:11 +01:00
Matthias Radestock 333d5f7511 Merge pull request #2412 from weaveworks/1803-plugin-create
Refactor plugin to create veths in CreateEndpoint



Fixes #1803.
2016-07-04 12:19:01 +01:00
Matthias Radestock 7be7945b29 Merge branch '1.6' 2016-07-04 10:08:43 +01:00
Matthias Radestock 566ed64607 Merge pull request #2413 from weaveworks/2347-document-host
document --host

Fixes #2347.
2016-07-04 10:07:48 +01:00
Anita Buehrle 83c358c8d2 edited sentence 2016-07-03 09:51:52 -05:00
Bryan Boreham afe882cd94 Use more chars from endpointID to reduce clashes in veth names
Import library to get max name length IFNAMSIZ
2016-07-01 16:05:02 +01:00
Matthias Radestock 5b8a359475 Merge branch '1.6' 2016-07-01 10:31:39 +01:00
Matthias Radestock ae95248499 Merge remote-tracking branch 'upstream/issues/2293-warn-router-down' into 1.6 2016-07-01 10:31:12 +01:00
Matthias Radestock df0af203f8 Merge pull request #2416 from weaveworks/issues/2293-warn-router-down
Check that weave router is running before launching plugin

Fixes #2293.
2016-07-01 10:24:15 +01:00
Bryan Boreham 53b8c804f2 Launch the whole of weave to avoid tripping over plugin-only test 2016-07-01 10:17:05 +01:00
Bryan Boreham 7d0aaea6e8 Move 'ODP miss' log from every miss to specific places
Added log lines for packets that we will broadcast;
Added log lines for flows we don't know how to handle;
Moved the line for when we expect to insert a flow down to the miss-handler;
Packets handled by the bridge already have their own logging via --pktdebug
2016-07-01 10:12:53 +01:00
Bryan Boreham 45a66ac517 Extend 'mac associated with other peer' error info 2016-06-30 18:02:39 +01:00
Bryan Boreham 087d948941 Check that weave router is running before launching plugin 2016-06-30 12:02:52 +01:00
Matthias Radestock 5b2a4ff614 Merge branch '1.6' 2016-06-29 20:12:58 +01:00
Matthias Radestock 72e92db96e document --host
and add some broader points about access control early on, since some
users will wonder about that right from the start.

Fixes #2347
2016-06-29 20:09:02 +01:00
Matthias Radestock 768414534f cosmetic: more logical order of args in usage 2016-06-29 20:00:47 +01:00
Bryan Boreham ceb5f8c714 Move endpoint creation into CreateEndpoint so we can return the MAC address 2016-06-29 17:38:07 +01:00
Bryan Boreham cc3359dfe5 Merge branch '1.6' 2016-06-29 14:42:17 +01:00
Bryan Boreham f1ca4854b8 Merge pull request #2409 from weaveworks/issues/2381-awsvpc-fix-attach-router
Fix re-attaching of weave router in awsvpc mode
2016-06-29 14:41:14 +01:00
Martynas Pumputis 6319860230 Change the order of awsvpc initialization
We want to setup the necessary arp settings as soon as possible
and before we re-insert DNS entries. Otherwise, the announced
containers might not be reachable.

Also, do not try to reclaim for weave:expose inside populate_router,
because we do expose before calling it.
2016-06-29 11:15:56 +01:00
Martynas Pumputis 58caf38f07 Fix re-attaching of weave router in awsvpc mode
In order to re-attach the router and make it work in awsvpc mode,
the following has to be done:

- expose_ip on the router
- adjusting arp settings
- restoring host routes

To detect that we run in awsvpc mode, we inspect cmd parameters
of the weave router instead of GET'ing /ipinfo/tracker. This is so,
because the HTTP server started by the router might not be running
at the time of restoration.
2016-06-29 11:15:49 +01:00
Matthias Radestock cb4b5fd143 correct RFC3484 address selection caveat
and move it to a more prominent location

Fixes #1710
2016-06-29 06:57:17 +01:00
Matthias Radestock cda6785f1d Merge remote-tracking branch 'upstream/master' 2016-06-29 05:58:29 +01:00
Matthias Radestock cb030be4ad Merge branch '1.6' 2016-06-29 05:57:01 +01:00
Matthias Radestock 7165414fc3 improve clock skew error message
Fixes #2174
2016-06-29 05:48:10 +01:00
Bryan Boreham b464ce86f7 Merge branch '1.6' 2016-06-28 13:36:10 +00:00
Bryan Boreham d72d3af36e Remove deprecated -awsvpc option 2016-06-28 13:35:47 +00:00
Adam Harrison 80b3514e24 Merge branch '1.6' 2016-06-20 16:29:29 +01:00
Adam Harrison f07ed7153b Remove link to non-existent blog post 2016-06-20 15:32:00 +01:00
Adam Harrison e33f56f9b0 Merge branch '1.6' 2016-06-20 14:53:03 +01:00
Adam Harrison 6c46af25cc Fix typo 2016-06-20 14:47:52 +01:00
Adam Harrison f386548890 Maintain per-subnet ACCEPT rule for multicast ingress 2016-06-17 17:19:52 +01:00
Adam Harrison c80d87554a Maintain per-interface DROP rule for multicast ingress 2016-06-17 16:10:13 +01:00
232 changed files with 6323 additions and 1216 deletions

No files matched your search

+7 -2
View File
@@ -43,12 +43,16 @@ prog/weavewait/weavewait
prog/weavewait/weavewait_noop
prog/weavewait/weavewait_nomcast
prog/weaveutil/weaveutil
prog/*/Dockerfile.weaveworks
prog/kube-peers/kube-peers
prog/weave-kube/kube-peers
prog/weave-npc/weave-npc
prog/plugin/plugin
testing/cover/cover
testing/runner/runner
releases
.*.uptodate
weave.tar.gz
weave*.tar.gz
prog/weaveexec/weave
prog/weaveexec/weavehosts
prog/weaveexec/weaveproxy
@@ -57,9 +61,10 @@ prog/weaveexec/weavewait_noop
prog/weaveexec/weavewait_nomcast
prog/weaveexec/sigproxy
prog/weaveexec/weaveutil
prog/weaveexec/docker*.tgz
prog/weaveexec/docker*
Vagrantfile.local
test/tls/tls
test/tls/*.pem
test/coverage
test/coverage.*
*qemu-*-static
+49 -1
View File
@@ -3,7 +3,7 @@
url = https://github.com/weaveworks/build-tools
[submodule "vendor/github.com/vishvananda/netlink"]
path = vendor/github.com/vishvananda/netlink
url = https://github.com/vishvananda/netlink.git
url = https://github.com/weaveworks/netlink.git
[submodule "vendor/github.com/gorilla/mux"]
path = vendor/github.com/gorilla/mux
url = https://github.com/gorilla/mux.git
@@ -76,3 +76,51 @@
[submodule "vendor/github.com/aws/aws-sdk-go"]
path = vendor/github.com/aws/aws-sdk-go
url = https://github.com/aws/aws-sdk-go
[submodule "vendor/golang.org/x/sys"]
path = vendor/golang.org/x/sys
url = https://go.googlesource.com/sys
[submodule "vendor/github.com/beorn7/perks"]
path = vendor/github.com/beorn7/perks
url = https://github.com/beorn7/perks
[submodule "vendor/github.com/prometheus/procfs"]
path = vendor/github.com/prometheus/procfs
url = https://github.com/prometheus/procfs
[submodule "vendor/github.com/prometheus/client_golang"]
path = vendor/github.com/prometheus/client_golang
url = https://github.com/prometheus/client_golang
[submodule "vendor/github.com/prometheus/client_model"]
path = vendor/github.com/prometheus/client_model
url = https://github.com/prometheus/client_model
[submodule "vendor/github.com/prometheus/common"]
path = vendor/github.com/prometheus/common
url = https://github.com/prometheus/common
[submodule "vendor/github.com/golang/protobuf"]
path = vendor/github.com/golang/protobuf
url = https://github.com/golang/protobuf
[submodule "vendor/github.com/matttproud/golang_protobuf_extensions"]
path = vendor/github.com/matttproud/golang_protobuf_extensions
url = https://github.com/matttproud/golang_protobuf_extensions
[submodule "vendor/k8s.io/client-go"]
path = vendor/k8s.io/client-go
url = https://github.com/kubernetes/client-go
[submodule "vendor/github.com/pkg/errors"]
path = vendor/github.com/pkg/errors
url = https://github.com/pkg/errors
[submodule "vendor/github.com/spf13/cobra"]
path = vendor/github.com/spf13/cobra
url = https://github.com/spf13/cobra
[submodule "vendor/github.com/spf13/plag"]
path = vendor/github.com/spf13/plag
url = https://github.com/spf13/pflag
[submodule "vendor/github.com/spf13/pflag"]
path = vendor/github.com/spf13/pflag
url = https://github.com/spf13/pflag
[submodule "vendor/github.com/mgutz/ansi"]
path = vendor/github.com/mgutz/ansi
url = https://github.com/mgutz/ansi
[submodule "vendor/github.com/estesp/manifest-tool"]
path = vendor/github.com/estesp/manifest-tool
url = https://github.com/estesp/manifest-tool
[submodule "vendor/github.com/weaveworks/common"]
path = vendor/github.com/weaveworks/common
url = https://github.com/weaveworks/common
+8
View File
@@ -0,0 +1,8 @@
# IMPORTANT: Please only use GLOBs to ignore files and directories.
# Do not lint any bash script in Weave Net, in order to
# avoid breaking the build on make lint:
*.sh
bin/*
prog/weaveexec/symlink
weave
+135 -1
View File
@@ -1,3 +1,137 @@
## Release 1.9.0
Highlights:
* Encryption is now available for Fast Datapath connections, which
greatly improves the performance. #1644,#2687
* We now build images for Intel/AMD 64-bit, ARM and ARM 64-bit. #2713
* Weave Net Docker images are now labelled with description, vendor, etc. #2712
* `weave status connections` now shows the MTU #2389,#2663
* CNI plugin is now a stand-alone binary that does not depend on Docker #2594,#2662
* Embedded docker client updated to version 1.10.3 #2395
**NOTE:** The move to multi-architecture required that we update the
embedded Docker client, and this has the effect that this release of
Weave Net will not work with Docker installations older than
1.10.
[Full list of changes](https://github.com/weaveworks/weave/issues?q=milestone%3A1.9.0).
## Release 1.8.2
Bug fixes and minor improvements
* Fixed a bug where looping flows were installed which caused high CPU
usage #2650, #2674
* Fixed a bug where Kubernetes master could not contact pods #2673, #2683
* Fixed a bug where weave-kube was crashing in a loop due to invalid
Weave bridge state #2657
* Fixed a bug where iptables NAT rules were not appended due to
"temporary unavailable" iptables error #2679
* Added a detection of enabling the hairpin mode on the Weave bridge port
which caused installation of looping flows #2674
* Added a detection of overlaps between Weave and the host IP address
ranges when launching weave-kube #2669, #2672
* Added logging of connections blocked by weave-npc #2546, #2573
More details in the [change log](https://github.com/weaveworks/weave/issues?q=milestone%3A1.8.2).
## Release 1.8.1
Bug fixes and minor improvements
* Fixed weave-npc crash from Succeeded/Failed pods #2632,#2658
* Fixed occasional failure to create Weave bridge on node reboot
#2617,#2637
* Fixed a bug where weave-kube would fail to install when run with
unrelease snapshot builds #2642
* Improved conformance to CNI spec by not releasing IP addresses when
a container dies #2643
* Improved troubleshooting of install failure by creating CNI config
after Weave Net is up #2570
* "up to date" shown even when the version check was blocked by
firewall #2537,#2565,#2645
* "Unable to claim" message on re-launching Weave after using CNI
#2548,#2577
* Eliminated spurious IP reclaim operations when IPAM was disabled
#2567,#2644
* Include `jq` tool in our build VM configuration #2656
## Release 1.8.0
Highlights:
* Exposed network policy controller Prometheus metrics
weaveworks/weave-npc#23, #2595, #2549
* Exposed router Prometheus metrics #2535, #2547, #2523, #2579, #2578,
#2568, #2560, #2561
More details in the [change log](https://github.com/weaveworks/weave/issues?q=milestone%3A1.8.0).
## Release 1.7.2
Bug fixes and minor improvements
* Fixed an error where the Docker plugin could fail to attach a
container with a `bridge "weave" not present` error #2540/#2541
* Fixed `cannot connect to itself` panic on weave launch #2527/#2543
* Fixed inferred initial peer count when target peers includes self
#2481/#2543
* Fixed compilation on Raspberry Pi #2506/#2538
## Release 1.7.1
Bug fixes and minor improvements
* Added utility to recover container addresses without asking Docker #2531
* Improved CI #2274
## Release 1.7.0
Highlights:
* weave-kube - Deploy Weave Net to Kubernetes with a single command
* weave-npc - Kubernetes network policy controller implementation
More details in the [change log](https://github.com/weaveworks/weave/issues?q=milestone%3A1.7.0).
## Release 1.6.2
Bug fixes and minor improvements
* Fixed hang after stopping and restarting on Docker 1.12 #2469/#2502
* Avoid an error on Google container images by checking for tx offload support #2504
* Fixed an issue where the supplied peer list could be ignored when restarting after failure #2503/#2509
* Check for empty peer name on launch #2495/#2501
More details in the [change log](https://github.com/weaveworks/weave/issues?q=milestone%3A1.6.2).
## Release 1.6.1
Bug fixes and minor improvements
* `weave ps` was occasionally failing to list allocated addresses of containers #2388/#2418/#2445
* `weave launch[-router]` on 4.2 kernel would appear to succeed even if the fast datapath VXLAN UDP port was in use by a different process #2375/#2474
* Launching the proxy would fail when the Docker daemon could not be detected #2457/#2424
* The CNI plugin did not work with Apache Mesos #2394/#2442
* Router stopped working after a restart in the AWSVPC mode #2381/#2409
* Router crashed when the Docker API endpoint parameter was explicitly set to empty #2421/#2467
* The CNI plugin did not work on recent versions of Docker for Mac #2434/#2442
* The CNI plugin assigns an IP to the bridge if necessary, which avoids failures if `weave expose` has not run yet #2471
* Distinguish peer name collisions from attempts to connect to self in logs #2460
* Improve host clock skew detection message #2174
* Improve the error message returned when executing `weave launch-plugin` without the router running #2293/#2416
* The `create-bridge` subcommand was not enabled in the fast datapath mode #2464/2466
* Allow users to omit `weave setup[-cni]` by initializing the CNI plugin on the `launch[-router]` subcommand #2435/#2442
* Reduce verbosity of fast datapath miss event logs #1852/#2417
* Include the `ipam` option in the help output of the `status` subcommand #2425/#2426
* Remove a harmless duplication of the `--no-dns` parameter #2430
* Internal refactoring
* Improvements to testing and building
* Improvements to the documentation
More details in the [change log](https://github.com/weaveworks/weave/issues?q=milestone%3A1.6.1).
## Release 1.6.0
## Highlights
@@ -8,7 +142,7 @@
overlays
* Docker 1.12 introduced some internal changes that made it
incompatible with previous version of Weave Net - this version
restores compatability
restores compatibility
* An [operational guide](https://weave.works/docs/net/latest/operational-guide)
detailing best practices for deploying and operating Weave Net
* Changes to the target peer list are remembered across restarts,
+215 -47
View File
@@ -1,7 +1,5 @@
PUBLISH=publish_weave publish_weaveexec publish_plugin
.DEFAULT: all
.PHONY: all exes testrunner update tests lint publish $(PUBLISH) clean clean-bin prerequisites build run-smoketests
.PHONY: all exes testrunner update tests lint publish-one-arch $(PUBLISH) clean clean-bin prerequisites build run-smoketests
# If you can use docker without being root, you can do "make SUDO="
SUDO=$(shell docker info >/dev/null 2>&1 || echo "sudo -E")
@@ -10,43 +8,130 @@ RM=--rm
RUN_FLAGS=-ti
COVERAGE=
DOCKERHUB_USER=weaveworks
WEAVE_VERSION=git-$(shell git rev-parse --short=12 HEAD)
# This specifies the architecture we're building for
ARCH?=amd64
# We're using QEMU to be able to build Docker images for other architectures
# from amd64 machines.
QEMU_VERSION=v2.7.0
# A list of all supported architectures here. Should be named as Go is naming platforms
# All supported architectures must have an "ifeq" block below that customizes the parameters
ALL_ARCHITECTURES=amd64 arm arm64
ML_PLATFORMS=linux/amd64,linux/arm,linux/arm64
ifeq ($(ARCH),amd64)
# The architecture to use when downloading the docker binary
WEAVEEXEC_DOCKER_ARCH?=x86_64
# The name of the alpine baseimage to use as the base for weave images
ALPINE_BASEIMAGE?=alpine:3.4
# The extension for the made images
# Specifying none means for example weaveworks/weave:latest
ARCH_EXT?=
# The name of the gcc we're using for compiling C code
CC=gcc
# Optional parameters that can be passed when linking C code into the Go binary
CGO_LDFLAGS=
endif
ifeq ($(ARCH),arm)
# The architecture to use when downloading the docker binary
WEAVEEXEC_DOCKER_ARCH?=armel
# Using the (semi-)official alpine image
ALPINE_BASEIMAGE?=armhf/alpine:3.4
# arm images have the -arm suffix, for instance weaveworks/weave-arm:latest
ARCH_EXT?=-arm
# The name of the gcc binary
CC=arm-linux-gnueabihf-gcc
# The architecture name to use when downloading a prebuilt QEMU binary
QEMUARCH=arm
# In the weaveworks/build image; libpcap libraries for arm are placed here
# Tell the gcc linker to search for libpcap here
CGO_LDFLAGS="-L/usr/local/lib/$(CC)"
endif
ifeq ($(ARCH),arm64)
# Use the arm 32-bit docker client variant
WEAVEEXEC_DOCKER_ARCH?=armel
# Using the (semi-)official alpine image
ALPINE_BASEIMAGE?=aarch64/alpine:3.5
# arm64 images have the -arm64 suffix, for instance weaveworks/weave-arm64:latest
ARCH_EXT?=-arm64
# The name of the gcc binary
CC=aarch64-linux-gnu-gcc
# The architecture name to use when downloading a prebuilt QEMU binary
QEMUARCH=aarch64
# In the weaveworks/build image; libpcap libraries for arm64 are placed here
# Tell the gcc linker to search for libpcap here
CGO_LDFLAGS="-L/usr/local/lib/$(CC)"
endif
# The name of the user that this Makefile should produce image artifacts for. Can/should be overridden
DOCKERHUB_USER?=weaveworks
# The default version that's chosen when pushing the images. Can/should be overridden
WEAVE_VERSION?=git-$(shell git rev-parse --short=12 HEAD)
# Paths to all relevant binaries that should be compiled
WEAVER_EXE=prog/weaver/weaver
WEAVEPROXY_EXE=prog/weaveproxy/weaveproxy
SIGPROXY_EXE=prog/sigproxy/sigproxy
KUBEPEERS_EXE=prog/kube-peers/kube-peers
WEAVENPC_EXE=prog/weave-npc/weave-npc
WEAVEWAIT_EXE=prog/weavewait/weavewait
WEAVEWAIT_NOOP_EXE=prog/weavewait/weavewait_noop
WEAVEWAIT_NOMCAST_EXE=prog/weavewait/weavewait_nomcast
WEAVEUTIL_EXE=prog/weaveutil/weaveutil
PLUGIN_EXE=prog/plugin/plugin
RUNNER_EXE=tools/runner/runner
MANIFEST_TOOL_DIR=vendor/github.com/estesp/manifest-tool
MANIFEST_TOOL_EXE=$(MANIFEST_TOOL_DIR)/manifest-tool
TEST_TLS_EXE=test/tls/tls
EXES=$(WEAVER_EXE) $(SIGPROXY_EXE) $(WEAVEPROXY_EXE) $(WEAVEWAIT_EXE) $(WEAVEWAIT_NOOP_EXE) $(WEAVEWAIT_NOMCAST_EXE) $(WEAVEUTIL_EXE) $(PLUGIN_EXE) $(TEST_TLS_EXE)
# All binaries together in a list
EXES=$(WEAVER_EXE) $(SIGPROXY_EXE) $(KUBEPEERS_EXE) $(WEAVENPC_EXE) $(WEAVEPROXY_EXE) $(WEAVEWAIT_EXE) $(WEAVEWAIT_NOOP_EXE) $(WEAVEWAIT_NOMCAST_EXE) $(WEAVEUTIL_EXE) $(PLUGIN_EXE) $(RUNNER_EXE) $(TEST_TLS_EXE) $(MANIFEST_TOOL_EXE)
# These stamp files are used to mark the current state of the build; whether an image has been built or not
BUILD_UPTODATE=.build.uptodate
WEAVER_UPTODATE=.weaver.uptodate
WEAVEEXEC_UPTODATE=.weaveexec.uptodate
PLUGIN_UPTODATE=.plugin.uptodate
WEAVER_UPTODATE=.weaver$(ARCH_EXT).uptodate
WEAVEEXEC_UPTODATE=.weaveexec$(ARCH_EXT).uptodate
PLUGIN_UPTODATE=.plugin$(ARCH_EXT).uptodate
WEAVEKUBE_UPTODATE=.weavekube$(ARCH_EXT).uptodate
WEAVENPC_UPTODATE=.weavenpc$(ARCH_EXT).uptodate
WEAVEDB_UPTODATE=.weavedb.uptodate
IMAGES_UPTODATE=$(WEAVER_UPTODATE) $(WEAVEEXEC_UPTODATE) $(PLUGIN_UPTODATE) $(WEAVEDB_UPTODATE)
IMAGES_UPTODATE=$(WEAVER_UPTODATE) $(WEAVEEXEC_UPTODATE) $(PLUGIN_UPTODATE) $(WEAVEKUBE_UPTODATE) $(WEAVENPC_UPTODATE)
WEAVER_IMAGE=$(DOCKERHUB_USER)/weave
WEAVEEXEC_IMAGE=$(DOCKERHUB_USER)/weaveexec
PLUGIN_IMAGE=$(DOCKERHUB_USER)/plugin
BUILD_IMAGE=$(DOCKERHUB_USER)/weavebuild
# The names of the images. Note that the images for other architectures than amd64 have a suffix in the image name.
WEAVER_IMAGE=$(DOCKERHUB_USER)/weave$(ARCH_EXT)
WEAVEEXEC_IMAGE=$(DOCKERHUB_USER)/weaveexec$(ARCH_EXT)
PLUGIN_IMAGE=$(DOCKERHUB_USER)/plugin$(ARCH_EXT)
WEAVEKUBE_IMAGE=$(DOCKERHUB_USER)/weave-kube$(ARCH_EXT)
WEAVENPC_IMAGE=$(DOCKERHUB_USER)/weave-npc$(ARCH_EXT)
BUILD_IMAGE=weaveworks/weavebuild
WEAVEDB_IMAGE=$(DOCKERHUB_USER)/weavedb
IMAGES=$(WEAVER_IMAGE) $(WEAVEEXEC_IMAGE) $(PLUGIN_IMAGE) $(WEAVEDB_IMAGE)
IMAGES=$(WEAVER_IMAGE) $(WEAVEEXEC_IMAGE) $(PLUGIN_IMAGE) $(WEAVEKUBE_IMAGE) $(WEAVENPC_IMAGE) $(WEAVEDB_IMAGE)
WEAVE_EXPORT=weave.tar.gz
PUBLISH=publish_weave publish_weaveexec publish_plugin publish_weave-kube publish_weave-npc
PUSH_ML=push_ml_weave push_ml_weaveexec push_ml_plugin push_ml_weave-kube push_ml_weave-npc
WEAVEEXEC_DOCKER_VERSION=1.6.2
DOCKER_DISTRIB=prog/weaveexec/docker-$(WEAVEEXEC_DOCKER_VERSION).tgz
DOCKER_DISTRIB_URL=https://get.docker.com/builds/Linux/x86_64/docker-$(WEAVEEXEC_DOCKER_VERSION).tgz
WEAVE_EXPORT=weave$(ARCH_EXT).tar.gz
DOCKER_VERSION=1.10.3
DOCKER_DISTRIB=prog/weaveexec/docker-$(DOCKER_VERSION).tgz
DOCKER_DISTRIB_URL=https://get.docker.com/builds/Linux/$(WEAVEEXEC_DOCKER_ARCH)/docker-$(DOCKER_VERSION).tgz
NETGO_CHECK=@strings $@ | grep cgo_stub\\\.go >/dev/null || { \
rm $@; \
echo "\nYour go standard library was built without the 'netgo' build tag."; \
@@ -55,7 +140,10 @@ NETGO_CHECK=@strings $@ | grep cgo_stub\\\.go >/dev/null || { \
echo " sudo go install -tags netgo std"; \
false; \
}
BUILD_FLAGS=-i -ldflags "-extldflags \"-static\" -X main.version=$(WEAVE_VERSION)" -tags netgo
# The flags we are passing to go build. -extldflags -static for making a static binary,
# -linkmode external for linking external C libraries into the binary, -X main.version for telling the
# Go binary which version it is, -tags netgo for enforcing the native Go DNS resolver
BUILD_FLAGS=-i -ldflags "-linkmode external -extldflags -static -X main.version=$(WEAVE_VERSION)" -tags netgo
PACKAGE_BASE=$(shell go list -e ./)
@@ -65,10 +153,14 @@ testrunner: $(RUNNER_EXE) $(TEST_TLS_EXE)
$(WEAVER_EXE) $(WEAVEPROXY_EXE) $(WEAVEUTIL_EXE): common/*.go common/*/*.go net/*.go net/*/*.go
$(WEAVER_EXE): router/*.go ipam/*.go ipam/*/*.go db/*.go nameserver/*.go prog/weaver/*.go
$(WEAVEPROXY_EXE): proxy/*.go prog/weaveproxy/*.go
$(WEAVEUTIL_EXE): prog/weaveutil/*.go net/*.go
$(WEAVEUTIL_EXE): prog/weaveutil/*.go net/*.go plugin/net/*.go plugin/ipam/*.go db/*.go
$(SIGPROXY_EXE): prog/sigproxy/*.go
$(KUBEPEERS_EXE): prog/kube-peers/*.go
$(WEAVENPC_EXE): prog/weave-npc/*.go npc/*.go npc/*/*.go
$(PLUGIN_EXE): prog/plugin/*.go plugin/*/*.go api/*.go common/*.go common/docker/*.go net/*.go
$(TEST_TLS_EXE): test/tls/*.go
$(RUNNER_EXE): tools/runner/*.go
$(MANIFEST_TOOL_EXE): $(MANIFEST_TOOL_DIR)/*.go
$(WEAVEWAIT_NOOP_EXE): prog/weavewait/*.go
$(WEAVEWAIT_EXE): prog/weavewait/*.go net/*.go
$(WEAVEWAIT_NOMCAST_EXE): prog/weavewait/*.go net/*.go
@@ -77,14 +169,16 @@ lint: tools/.git
ifeq ($(BUILD_IN_CONTAINER),true)
# This make target compiles all binaries inside of the weaveworks/build container
# It bind-mounts the source into the container and passes all important variables
exes $(EXES) tests lint: $(BUILD_UPTODATE)
git submodule update --init
@mkdir -p $(shell pwd)/.pkg
$(SUDO) docker run $(RM) $(RUN_FLAGS) \
-v $(shell pwd):/go/src/github.com/weaveworks/weave \
-v $(shell pwd)/.pkg:/go/pkg \
-e GOARCH -e GOOS -e CIRCLECI -e CIRCLE_BUILD_NUM -e CIRCLE_NODE_TOTAL -e CIRCLE_NODE_INDEX -e COVERDIR -e SLOW \
$(BUILD_IMAGE) COVERAGE=$(COVERAGE) WEAVE_VERSION=$(WEAVE_VERSION) $@
-e GOARCH=$(ARCH) -e CGO_ENABLED=1 -e GOOS=linux -e CIRCLECI -e CIRCLE_BUILD_NUM -e CIRCLE_NODE_TOTAL -e CIRCLE_NODE_INDEX -e COVERDIR -e SLOW -e DEBUG \
$(BUILD_IMAGE) COVERAGE=$(COVERAGE) WEAVE_VERSION=$(WEAVE_VERSION) CC=$(CC) QEMUARCH=$(QEMUARCH) CGO_LDFLAGS=$(CGO_LDFLAGS) $@
else
@@ -99,7 +193,7 @@ else
endif
$(NETGO_CHECK)
$(WEAVEUTIL_EXE):
$(WEAVEUTIL_EXE) $(KUBEPEERS_EXE) $(WEAVENPC_EXE):
go build $(BUILD_FLAGS) -o $@ ./$(@D)
$(NETGO_CHECK)
@@ -113,26 +207,48 @@ $(WEAVEWAIT_NOMCAST_EXE):
# These programs need a separate rule as they fail the netgo check in
# the main build stanza due to not importing net package
$(SIGPROXY_EXE) $(TEST_TLS_EXE) $(WEAVEWAIT_NOOP_EXE):
$(SIGPROXY_EXE) $(TEST_TLS_EXE) $(WEAVEWAIT_NOOP_EXE) $(RUNNER_EXE) $(MANIFEST_TOOL_EXE):
go build $(BUILD_FLAGS) -o $@ ./$(@D)
tests:
./tools/test -no-go-get
./tools/test -no-go-get -netgo -timeout 8m
lint:
./tools/lint -nocomment -notestpackage .
endif
# This rule makes sure the build image is up-to-date.
# It also makes sure the multiarch hooks are reqistered in the kernel so the QEMU emulation works
$(BUILD_UPTODATE): build/*
$(SUDO) docker build -t $(BUILD_IMAGE) build/
$(SUDO) docker run --rm --privileged multiarch/qemu-user-static:register --reset
touch $@
$(WEAVER_UPTODATE): prog/weaver/Dockerfile $(WEAVER_EXE)
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker build -t $(WEAVER_IMAGE) prog/weaver
# Creates the Dockerfile.your-user-here file from the template
# Also replaces all placeholders with real values
# If the architecture is amd64, it deletes all CROSS_BUILD lines
# but otherwise, it only removes the "CROSS_BUILD_" placeholder and downloads QEMU
%/Dockerfile.$(DOCKERHUB_USER): %/Dockerfile.template
echo "DOCKERHUB_USER|$(DOCKERHUB_USER)|g;s|ARCH_EXT|$(ARCH_EXT)|g;s|ALPINE_BASEIMAGE|$(ALPINE_BASEIMAGE)|g;s|QEMUARCH|$(QEMUARCH)"
sed -e "s|DOCKERHUB_USER|$(DOCKERHUB_USER)|g;s|ARCH_EXT|$(ARCH_EXT)|g;s|ALPINE_BASEIMAGE|$(ALPINE_BASEIMAGE)|g;s|QEMUARCH|$(QEMUARCH)|g" $^ > $@
ifeq ($(ARCH),amd64)
# When building "normally" for amd64, remove the whole line, it has no part in the amd64 image
sed -i "/CROSS_BUILD_/d" $@
else
# When cross-building, only the placeholder "CROSS_BUILD_" should be removed
# Register /usr/bin/qemu-ARCH-static as the handler for ARM binaries in the kernel
curl -sSL https://github.com/multiarch/qemu-user-static/releases/download/$(QEMU_VERSION)/x86_64_qemu-$(QEMUARCH)-static.tar.gz | tar -xz -C $(shell dirname $@)
cd $(shell dirname $@) && sha256sum -c $(shell pwd)/build/shasums/qemu-$(QEMUARCH)-static.sha256sum
sed -i "s/CROSS_BUILD_//g" $@
endif
# The targets below builds the weave images
$(WEAVER_UPTODATE): prog/weaver/Dockerfile.$(DOCKERHUB_USER) $(WEAVER_EXE) $(WEAVEEXEC_UPTODATE)
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker build -f prog/weaver/Dockerfile.$(DOCKERHUB_USER) -t $(WEAVER_IMAGE) prog/weaver
touch $@
$(WEAVEEXEC_UPTODATE): prog/weaveexec/Dockerfile prog/weaveexec/symlink $(DOCKER_DISTRIB) weave $(SIGPROXY_EXE) $(WEAVEPROXY_EXE) $(WEAVEWAIT_EXE) $(WEAVEWAIT_NOOP_EXE) $(WEAVEWAIT_NOMCAST_EXE) $(WEAVEUTIL_EXE)
$(WEAVEEXEC_UPTODATE): prog/weaveexec/Dockerfile.$(DOCKERHUB_USER) prog/weaveexec/symlink $(DOCKER_DISTRIB) weave $(SIGPROXY_EXE) $(WEAVEPROXY_EXE) $(WEAVEWAIT_EXE) $(WEAVEWAIT_NOOP_EXE) $(WEAVEWAIT_NOMCAST_EXE) $(WEAVEUTIL_EXE)
cp weave prog/weaveexec/weave
cp $(SIGPROXY_EXE) prog/weaveexec/sigproxy
cp $(WEAVEPROXY_EXE) prog/weaveexec/weaveproxy
@@ -140,49 +256,101 @@ $(WEAVEEXEC_UPTODATE): prog/weaveexec/Dockerfile prog/weaveexec/symlink $(DOCKER
cp $(WEAVEWAIT_NOOP_EXE) prog/weaveexec/weavewait_noop
cp $(WEAVEWAIT_NOMCAST_EXE) prog/weaveexec/weavewait_nomcast
cp $(WEAVEUTIL_EXE) prog/weaveexec/weaveutil
cp $(DOCKER_DISTRIB) prog/weaveexec/docker.tgz
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker build -t $(WEAVEEXEC_IMAGE) prog/weaveexec
tar -xf $(DOCKER_DISTRIB) usr/local/bin/docker -O > prog/weaveexec/docker
chmod +x prog/weaveexec/docker
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker build -f prog/weaveexec/Dockerfile.$(DOCKERHUB_USER) -t $(WEAVEEXEC_IMAGE) prog/weaveexec
touch $@
$(PLUGIN_UPTODATE): prog/plugin/Dockerfile $(PLUGIN_EXE) $(WEAVEEXEC_UPTODATE)
$(SUDO) docker build -t $(PLUGIN_IMAGE) prog/plugin
$(PLUGIN_UPTODATE): prog/plugin/Dockerfile.$(DOCKERHUB_USER) $(PLUGIN_EXE) $(WEAVER_UPTODATE)
$(SUDO) docker build -f prog/plugin/Dockerfile.$(DOCKERHUB_USER) -t $(PLUGIN_IMAGE) prog/plugin
touch $@
$(WEAVEKUBE_UPTODATE): prog/weave-kube/Dockerfile.$(DOCKERHUB_USER) prog/weave-kube/launch.sh $(KUBEPEERS_EXE) $(WEAVER_UPTODATE)
cp $(KUBEPEERS_EXE) prog/weave-kube/
$(SUDO) docker build -f prog/weave-kube/Dockerfile.$(DOCKERHUB_USER) -t $(WEAVEKUBE_IMAGE) prog/weave-kube
touch $@
$(WEAVENPC_UPTODATE): prog/weave-npc/Dockerfile.$(DOCKERHUB_USER) $(WEAVENPC_EXE) prog/weave-npc/ulogd.conf
$(SUDO) docker build -f prog/weave-npc/Dockerfile.$(DOCKERHUB_USER) -t $(WEAVENPC_IMAGE) prog/weave-npc
touch $@
$(WEAVEDB_UPTODATE): prog/weavedb/Dockerfile
$(SUDO) docker build -t $(WEAVEDB_IMAGE) prog/weavedb
touch $@
$(WEAVE_EXPORT): $(IMAGES_UPTODATE)
$(WEAVE_EXPORT): $(IMAGES_UPTODATE) $(WEAVEDB_UPTODATE)
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker save $(addsuffix :latest,$(IMAGES)) | gzip > $@
$(DOCKER_DISTRIB):
curl -o $(DOCKER_DISTRIB) $(DOCKER_DISTRIB_URL)
cd $(shell dirname $@) && sha256sum -c $(shell pwd)/build/shasums/docker-tgz-$(WEAVEEXEC_DOCKER_ARCH).sha256sum
tools/.git:
tools/.git $(MANIFEST_TOOL_DIR)/.git:
git submodule update --init
$(RUNNER_EXE): tools/.git
make -C tools/runner
# CODE FOR PUBLISHING THE IMAGES
$(PUBLISH): publish_%: $(IMAGES_UPTODATE)
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker tag -f $(DOCKERHUB_USER)/$* $(DOCKERHUB_USER)/$*:$(WEAVE_VERSION)
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker push $(DOCKERHUB_USER)/$*:$(WEAVE_VERSION)
ifneq ($(UPDATE_LATEST),false)
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker push $(DOCKERHUB_USER)/$*:latest
# This target first runs "make publish" for each architecture
# Then it pushes the manifest lists
publish: $(addprefix sub-publish-,$(ALL_ARCHITECTURES)) $(WEAVEDB_UPTODATE)
$(MAKE) DOCKER_HOST=$(DOCKER_HOST) DOCKERHUB_USER=$(DOCKERHUB_USER) WEAVE_VERSION=$(WEAVE_VERSION) UPDATE_LATEST=$(UPDATE_LATEST) $(PUSH_ML)
ifeq ($(PUBLISH_WEAVEDB),true)
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker push $(DOCKERHUB_USER)/weavedb:latest
endif
publish: $(PUBLISH)
ifeq ($(PUBLISH_WEAVEDB),true)
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker push $(DOCKERHUB_USER)/weavedb:latest
sub-publish-%:
$(MAKE) ARCH=$* DOCKER_HOST=$(DOCKER_HOST) clean-bin
$(MAKE) ARCH=$* DOCKER_HOST=$(DOCKER_HOST) DOCKERHUB_USER=$(DOCKERHUB_USER) WEAVE_VERSION=$(WEAVE_VERSION) UPDATE_LATEST=$(UPDATE_LATEST) $(IMAGES_UPTODATE)
$(MAKE) ARCH=$* DOCKER_HOST=$(DOCKER_HOST) DOCKERHUB_USER=$(DOCKERHUB_USER) WEAVE_VERSION=$(WEAVE_VERSION) UPDATE_LATEST=$(UPDATE_LATEST) publish-one-arch
publish-one-arch: $(PUBLISH)
# This rule handles the pushing of the built images
$(PUBLISH): publish_%: $(IMAGES_UPTODATE)
# Tag :latest with the real version
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker tag $(DOCKERHUB_USER)/$*$(ARCH_EXT) $(DOCKERHUB_USER)/$*$(ARCH_EXT):$(WEAVE_VERSION)
# Push the image with the arch suffix for arm and arm64, and without suffix for amd64
$(MAKE) DOCKER_HOST=$(DOCKER_HOST) DOCKERHUB_USER=$(DOCKERHUB_USER) WEAVE_VERSION=$(WEAVE_VERSION) UPDATE_LATEST=$(UPDATE_LATEST) push_$*$(ARCH_EXT)
ifeq ($(ARCH),amd64)
# If the architecture is amd64, add the -amd64 suffix.
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker tag $(DOCKERHUB_USER)/$*:$(WEAVE_VERSION) $(DOCKERHUB_USER)/$*-amd64:$(WEAVE_VERSION)
# If the version is latest, tag the -amd64 with latest as well
ifneq ($(UPDATE_LATEST),false)
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker tag $(DOCKERHUB_USER)/$*-amd64:$(WEAVE_VERSION) $(DOCKERHUB_USER)/$*-amd64:latest
endif
# Push the image with the -amd64-suffix so BINARY-ARCH-named images exist for all arches, so manifest lists may be made and ARCH is replaceable in scripts
$(MAKE) DOCKER_HOST=$(DOCKER_HOST) DOCKERHUB_USER=$(DOCKERHUB_USER) WEAVE_VERSION=$(WEAVE_VERSION) UPDATE_LATEST=$(UPDATE_LATEST) push_$*-amd64
endif
# This target pushes an image, and if UPDATE_LATEST is anything but false, also updates the latest tag
# It takes one parameter, the image name
push_%:
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker push $(DOCKERHUB_USER)/$*:$(WEAVE_VERSION)
ifneq ($(UPDATE_LATEST),false)
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker push $(DOCKERHUB_USER)/$*:latest
endif
# This target pushes a manifest list; it takes one parameter, the image name.
# The variable UPDATE_LATEST controls whether it updates the versioned tag and/or the latest tag
$(PUSH_ML): push_ml_%: $(MANIFEST_TOOL_EXE)
ifneq ($(UPDATE_LATEST),latest-only)
$(MANIFEST_TOOL_EXE) push from-args --platforms $(ML_PLATFORMS) --template $(DOCKERHUB_USER)/$*-ARCH:$(WEAVE_VERSION) --target $(DOCKERHUB_USER)/$*:$(WEAVE_VERSION)
endif
ifneq ($(UPDATE_LATEST),false)
# Push the manifest list to :latest as well
$(MANIFEST_TOOL_EXE) push from-args --platforms $(ML_PLATFORMS) --template $(DOCKERHUB_USER)/$*-ARCH:latest --target $(DOCKERHUB_USER)/$*:latest
endif
clean-bin:
-$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker rmi $(IMAGES)
rm -rf $(EXES) $(IMAGES_UPTODATE) $(WEAVE_EXPORT) .pkg
find prog -type f -name "Dockerfile.*" -not -name "Dockerfile.template" -print | xargs rm -f
find prog -type f -name "*qemu-*" -print | xargs rm -f
rm -rf $(EXES) $(IMAGES_UPTODATE) $(WEAVEDB_UPTODATE) weave*.tar.gz $(DOCKER_DISTRIB) prog/weaveexec/docker .pkg
clean: clean-bin
-$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker rmi $(BUILD_IMAGE)
rm -rf test/tls/*.pem test/coverage.* test/coverage $(BUILD_UPTODATE)
rm -rf test/tls/*.pem test/coverage.* test/coverage $(BUILD_UPTODATE) $(MANIFEST_TOOL_EXE)
build:
$(SUDO) go clean -i net
+4 -2
View File
@@ -11,9 +11,11 @@
[Weaveworks](https://www.weave.works) is the company that delivers the most productive way for developers to connect, observe and control
Docker containers.
This repository contains [Weave Net](https://www.weave.works/products/weave-net/), the first product developed by Weaveworks, and with nearly 5 million downloads to date, it enables you to get started with Docker clusters and portable apps in a fraction of the time compared with other solutions.
This repository contains [Weave Net](https://www.weave.works/products/weave-net/), the first product developed by Weaveworks, and with over 8 million downloads to date, it enables you to get started with Docker clusters and portable apps in a fraction of the time compared with other solutions.
Other products from Weaveworks include [Weave Scope](https://www.weave.works/products/weave-scope/), a powerful container monitoring tool that automatically maps Docker containers and their interactions, and [Weave Flux](https://www.weave.works/products/weave-flux/), a microservice router that automates the access of containers as services.
Weaveworks' product [Weave Cloud](https://www.weave.works/solution/cloud/) takes the heavy lifting out of building, integrating and operating open source components, so you don’t have to manage databases, storage and availability.
Weave Cloud is built using these Open Source projects: [Weave Scope](https://www.weave.works/products/weave-scope/), a powerful container monitoring tool that automatically maps Docker containers and their interactions, [Weave Cortex](https://github.com/weaveworks/cortex), a horizontally-scalable version of Prometheus, and [Weave Flux](https://www.weave.works/products/weave-flux/), a continuous deployment tool that works with Kubernetes.
# Weave Net
Vendored
+5
View File
@@ -14,6 +14,7 @@ pkgs = %w(
git
mercurial
bc
jq
)
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
@@ -22,6 +23,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.network "private_network", ip: vm_ip
config.vm.provider :virtualbox do |vb|
vb.memory = 2048
vb.customize ["modifyvm", :id, "--natdnshostresolver1", "off"]
vb.customize ["modifyvm", :id, "--natdnsproxy1", "off"]
end
@@ -29,6 +31,9 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.synced_folder ".", "/vagrant", disabled: true
config.vm.synced_folder ".", "/home/vagrant/src/github.com/weaveworks/weave"
# Set SSH keys up to be able to run smoke tests straightaway:
config.vm.provision "file", source: "~/.vagrant.d/insecure_private_key", destination: "/home/vagrant/src/github.com/weaveworks/weave/test/insecure_private_key"
install_build_deps config.vm, pkgs
install_go_toochain config.vm
tweak_user_env config.vm
+9
View File
@@ -5,6 +5,15 @@ import (
"net"
)
// Special token used in place of a container identifier when:
// - the caller does not know the container ID, or
// - the caller is unsure whether IPAM was previously told the container ID.
//
// While addresses are typically stored under their container IDs, when this
// token is used, the address will be stored under its own string, something
// which should be kept in mind if the entry needs to be removed at any point.
const NoContainerID string = "_"
func (client *Client) ipamOp(ID string, op string) (*net.IPNet, error) {
ip, err := client.httpVerb(op, fmt.Sprintf("/ip/%s", ID), nil)
if err != nil {
+46
View File
@@ -0,0 +1,46 @@
#!/bin/bash
set -e
echo "TEST_AND_PUBLISH=1" > "$STATE"
# Avoid doing a full build if we can. Note if the PR doesn't exist
# when the build is kicked off, we can't run this check so we do a
# full build. Subsequent pushes to the same branch will have the desired behaviour
if [ -n "$CI_PULL_REQUEST" -a "$CI_PULL_REQUEST" = "$CI_PULL_REQUESTS" ] ; then
if PR=$(echo "$CI_PULL_REQUEST" | grep -oP '(?<=^https://github.com/weaveworks/weave/pull/)[0-9]+$') ; then
echo "GH_PR=$PR" >> "$STATE"
if FILES=$(curl -s https://api.github.com/repos/weaveworks/weave/pulls/$PR/files | jq -r '.[]|.filename') ; then
echo "PR touches [$FILES]"
if ! echo "$FILES" | grep -v ^site/ ; then
echo "PR contains site changes only - skipping tests"
echo "TEST_AND_PUBLISH=" >> "$STATE"
else
echo "PR contains non-site changes - running tests"
fi
else
echo "Unable to get files for PR $PR" >&2
fi
else
echo "Unable to extract PR number from $CI_PULL_REQUEST" >&2
fi
fi
source "$STATE"
mkdir -p $(dirname $SRCDIR) && cp -r $(pwd)/ $SRCDIR
if [ -n "$TEST_AND_PUBLISH" ] ; then
[ -z "$SECRET_PASSWORD" ] || bin/setup-circleci-secrets "$SECRET_PASSWORD"
cd $SRCDIR; git submodule update --init
if [ "$CIRCLE_NODE_INDEX" = "0" -a -n "$SECRET_PASSWORD" ] ; then
cd $SRCDIR/test; ./gce.sh make_template
fi
cd $SRCDIR/build
../tools/rebuild-image weaveworks/weavebuild . Dockerfile build.sh
touch $SRCDIR/.build.uptodate
sudo chown -R ubuntu /usr/local/go
cd $SRCDIR
make testrunner
make COVERAGE=true RM= exes all
fi
+43
View File
@@ -0,0 +1,43 @@
#!/bin/bash
set -e
set -o pipefail
source "$STATE"
site_changes() {
curl -s https://api.github.com/repos/weaveworks/weave/pulls/$1/files |
jq -r '.[]|.status + " " + .filename' |
grep -oP '^(added|modified|removed) site/.*(?=\.md$)'
}
format_comment() {
if [ ! -d .git ] || ! BRANCH=$(git symbolic-ref --short HEAD) || [ -z "$BRANCH" ] ; then
echo "Could not determine branch" >&2
return 1
fi
echo "#### Documentation changes:"
while read ACTION PAGE; do
echo "$ACTION [${PAGE#site/}]($WP_DEV_URL/docs/net/${BRANCH#issues/}/${PAGE#site/}/)"
done | sort
}
post_comment() {
jq -s -R '. | tostring | { body: . }' |
curl -s -d @- \
-H "Authorization: Bearer $WP_GH_COMMENT_TOKEN" \
-H 'Content-Type: application/json' \
https://api.github.com/repos/weaveworks/weave/issues/$GH_PR/comments > /dev/null
}
cd $SRCDIR
bin/install-wordepress v1.0.0
bin/publish-site "$WP_DEV_URL" "$WP_DEV_USER" "$WP_DEV_PASSWORD"
if [ -n "$WP_GH_COMMENT_TOKEN" -a -n "$GH_PR" ] ; then
echo ">>> Adding doc changelog to GitHub PR $GH_PR"
if CHANGES=$(site_changes $GH_PR) && [ -n "$CHANGES" ] ; then
echo "$CHANGES" | format_comment | post_comment
fi
fi
+17
View File
@@ -0,0 +1,17 @@
#!/bin/bash
set -e
source "$STATE"
if [ -n "$TEST_AND_PUBLISH" ] ; then
docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS
cd $SRCDIR
make clean-bin
# CircleCI doesn't let us install the qemu module to do ARM docker builds
make publish ALL_ARCHITECTURES=amd64 UPDATE_LATEST=latest-only
fi
cd $SRCDIR
bin/install-wordepress v1.0.0
bin/publish-site "$WP_DEV_URL" "$WP_DEV_USER" "$WP_DEV_PASSWORD"
+7
View File
@@ -0,0 +1,7 @@
#!/bin/bash
set -e
cd $SRCDIR
bin/install-wordepress v1.0.0
bin/publish-site "$WP_LIVE_URL" "$WP_LIVE_USER" "$WP_LIVE_PASSWORD"
+13
View File
@@ -0,0 +1,13 @@
#!/bin/bash
set -e
source "$STATE"
if [ -n "$TEST_AND_PUBLISH" ] ; then
if [ "$CIRCLE_NODE_INDEX" = "0" ] ; then
go get github.com/mattn/goveralls
goveralls -repotoken $COVERALLS_REPO_TOKEN -coverprofile=$SRCDIR/test/profile.cov -service=circleci
cd $SRCDIR/test; cp coverage.* $CIRCLE_ARTIFACTS
fi
fi
+10
View File
@@ -0,0 +1,10 @@
#!/bin/bash
set -e
source "$STATE"
if [ -n "$TEST_AND_PUBLISH" ] ; then
cd $SRCDIR/test
[ -z "$SECRET_PASSWORD" ] || (./gce.sh setup && eval $(./gce.sh hosts) && ./setup.sh)
fi
+14
View File
@@ -0,0 +1,14 @@
#!/bin/bash
set -e
source "$STATE"
if [ -n "$TEST_AND_PUBLISH" ] ; then
[ -n "$SECRET_PASSWORD" ] || { echo "Cannot run smoke tests: no secret key"; exit 1; }
cd $SRCDIR/test
eval $(./gce.sh hosts)
export COVERAGE=true
export WEAVE_NET_SANITY_CHECKS_FILES="$CIRCLE_ARTIFACTS/weave_net_sanity_check_*.log"
./run_all.sh
fi
+11
View File
@@ -0,0 +1,11 @@
#!/bin/bash
set -e
source "$STATE"
if [ -n "$TEST_AND_PUBLISH" ] ; then
cd $SRCDIR/test
[ -z "$SECRET_PASSWORD" ] || ./gce.sh destroy
test "$CIRCLE_NODE_INDEX" != "0" || (cd $SRCDIR/test; ./gen_coverage_reports.sh)
fi
+11
View File
@@ -0,0 +1,11 @@
#!/bin/bash
set -e
source "$STATE"
if [ -n "$TEST_AND_PUBLISH" ] ; then
cd $SRCDIR
make DEBUG=1 lint
COVERDIR=test/coverage make RM= tests
fi
+12
View File
@@ -0,0 +1,12 @@
#!/bin/bash
if [ $# -ne 1 ] ; then
echo USAGE: install-wordepress [COMMIT-ISH] >&2
exit 1
fi
go get github.com/weaveworks/wordepress
cd /home/ubuntu/src/github.com/weaveworks/wordepress
git checkout $1
cd cmd/wordepress
go get
+1 -1
View File
@@ -29,7 +29,7 @@ case "$BRANCH" in
if ! VERSION=$(echo "$DESCRIBE" | grep -oP '(?<=^v)[0-9]+\.[0-9]+\.[0-9]+') ; then
fatal "Could not infer latest $BRANCH version from $DESCRIBE"
fi
TAGS="$VERSION latest"
TAGS="latest"
else
VERSION="$BRANCH"
TAGS="$VERSION"
+56
View File
@@ -157,6 +157,28 @@ draft() {
--name "weave" \
--file "./weave"
github-release release $RELEASE_ARGS \
--user $GITHUB_USER \
--repo weave-kube \
--tag $LATEST_TAG \
--name "$RELEASE_NAME $VERSION" \
--description "$RELEASE_DESCRIPTION"
sed -i -e s/:latest/:$VERSION/ -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset.yaml
github-release upload \
--user $GITHUB_USER \
--repo weave-kube \
--tag $LATEST_TAG \
--name "weave-daemonset.yaml" \
--file "./prog/weave-kube/weave-daemonset.yaml"
github-release upload \
--user $GITHUB_USER \
--repo weave \
--tag $LATEST_TAG \
--name "weave-daemonset.yaml" \
--file "./prog/weave-kube/weave-daemonset.yaml"
echo "** Draft $TYPE $RELEASE_NAME $VERSION created at"
echo -e "\thttps://github.com/$GITHUB_USER/weave/releases/$LATEST_TAG"
}
@@ -236,6 +258,40 @@ publish() {
--name "weave" \
--file "./weave"
github-release publish \
--user $GITHUB_USER \
--repo weave-kube \
--tag $LATEST_TAG
if github-release info --user $GITHUB_USER --repo weave-kube \
--tag latest_release >/dev/null 2>&1; then
github-release delete \
--user $GITHUB_USER \
--repo weave-kube \
--tag latest_release
fi
github-release release \
--user $GITHUB_USER \
--repo weave-kube \
--tag latest_release \
--name "$RELEASE_NAME latest ($VERSION)" \
--description "[Release Notes](https://github.com/$GITHUB_USER/weave/releases/$LATEST_TAG)"
github-release upload \
--user $GITHUB_USER \
--repo weave-kube \
--tag latest_release \
--name "weave-daemonset.yaml" \
--file "./prog/weave-kube/weave-daemonset.yaml"
github-release upload \
--user $GITHUB_USER \
--repo weave \
--tag latest_release \
--name "weave-daemonset.yaml" \
--file "./prog/weave-kube/weave-daemonset.yaml"
echo "** Release $RELEASE_NAME $VERSION published at"
echo -e "\thttps://github.com/$GITHUB_USER/weave/releases/$LATEST_TAG"
echo -e "\thttps://github.com/$GITHUB_USER/weave/releases/latest_release"
-57
View File
@@ -1,57 +0,0 @@
#!/bin/sh
## This is the shape of unencrypted `do-setup-ci-secrets`
##
## cat > /tmp/boto_gsutil_cert.pem << EOF
## -----BEGIN PRIVATE KEY-----
## <...>
## -----END PRIVATE KEY-----
## EOF
##
## cat > ~/.boto << EOF
## [Credentials]
## gs_service_client_id = <...>
## gs_service_key_file = /tmp/boto_gsutil_cert.pem
##
## [Boto]
## https_validate_certificates = True
##
## [GSUtil]
## content_language = en
## default_api_version = 2
## default_project_id = <...>
## EOF
openssl base64 -d << EOF \
| openssl aes-256-cbc -d -K $1 -iv $2 \
-out bin/do-setup-ci-secrets
mOYNzNsAdwva0LbB2YFMY9VgL0SITFu1bPrbOujyLtOrBNjmOYbzR5d/sG+ARMFr
7NZ5OKcvMbItllz0n7TtNkzkCOMztMC870Wcx3nGJzbBephdcYwos4tBlp5bihTU
AXgxLUiDT1broYAFKnbE1aZC/XyNxuLTN+nXJWIWeijaXTgvhkEEm3tab+z7ioCb
tlg71W1BrUuocctAJAuVwH/uTZAaXaJGJj1s2S7F2DrFnG6sFlrp8rnCucPLWKnC
4IwJFC5saR5gxK6wECffwmwbpeXVOoQ58OgzxoZTEyAr9nhVbaBt5UZz3tfHlx8W
Rn5jHehACw5kg5eMtGPqMEksJ63LX4h3mfSTLJXJHEmOrzCRpFrigVrsbA408U2u
8jJTHJmKrGfwBh5ZFzBg6NuV4VplOp+ZquJLgegv2WH/iu/ciopXqB2YDCdx5ZBi
nHV2Puth7kjS4EMCKUGfeqpesjL9Djb8cygzv/J3ZBmLjNH9dqlSXWy2DcFZA1Iy
pFTTHkVU3w5sNz3nYOuT2UPQvULBW0FUndDKX6olyVa0mlxPwGBP9N3yGg918/rw
7rNV/r54lA334F5QMhDrVxar6sl9wfLA+Z+8qemBbNFlLog1uQGhuwWK2nFu1tRM
9uyvQIq0oq5NHKpogWc7NEuk7CPe1JyfRIcbMVj8+ilmKjUPB2HPC43IDmKt9/56
rY3IXAcxZ/ClGfGpeNHXqop9T/WhfaowponOZFcdGSUddG0OswqkTE4KIv71mgTF
jXooMkTQBOG+gBnCe+8bCRdRCG3anxHX74za4dGD58cOJtl6DYWnjWuR91NWnxdT
1Zr3iUe41txg9hCNY9LHo2QHGLPxe6pmNnSClQ1mcFhuY6NF8RmCX3HAGKJQkxJb
vpLGbXTXjAIFgIYgLNgKP2RLvCif/LmSWgkvE3ZU9GXtCUbm6xgJodwOqXiI9uuO
4H4+/vpGHnSFENiclkgMFrLG4yiMu8ArgmnCBzg9E2AoOX5zCrh/2ZRTU8Dk4mt7
jUd5SKQLsjB9QtB+y3tRO7zY9RDvR6iBOPRsjx6t8EJMCfPb06KchfMJw+VGxvMM
48jtmepREFnhd/8XDRGnw5bznjRuwohGik8BToltjIviMkkpifKWaLwlaOiDXaHh
VBFNXnUKvOBwRMU+PZqv4+DP2qff1gSXnGKqA5GIURYrK9P7TqHHNTnmjBdfJLzc
0x+W1DTiYhLT2vrLrkEpZ99o6qrg+lwvjat6IsJF8xoQEo4pLD/ZRPJ0WzoDyctT
oWZ5rMsN1TzTvJrBrTAWIJyhIzZcuNwChMrU6qogMr0fd6TSxWhWn0sOJ5y8AaTR
ej4JHx0qroS/9JPmgFYU61pX3c0ypdef/sSHWG23mcFzLTgwe2d4ty9VakypZy3T
sXCl6EHVVXlUFWhY4zQCjdZpYJv/rtoKL1BL4fPE2NV5WTjCL2GNvaO5SfHR7pA0
yQJR/iU+cS2n8UXsWNjyV+/qEn6+QXuyVHGLbxyH8EeqlliAbyHsc2rzVI8Xctzo
W5DuIqxwHAkNNurhmx27ktIIQ6HhaCp028SWwvLttkbBBgF4v1mmd4u/2bKbKjUd
dOaetaIUx1hU9OAeaePvVkeTDcc3mlFtPARCS9Fqj16hgJQ43onZyC0H1K2WAxmU
GsmzjCHlTNquzFTuuQihYGZKfsWIh9z6HEOkvNJ3VEQ=
EOF
exec sh bin/do-setup-ci-secrets
+77 -6
View File
@@ -1,8 +1,79 @@
FROM golang:1.5.2
ENV GO15VENDOREXPERIMENT 1
RUN apt-get update && apt-get install -y libpcap-dev python-requests time file
RUN go get github.com/golang/lint/golint github.com/fzipp/gocyclo github.com/client9/misspell/cmd/misspell
RUN go clean -i net && go install -tags netgo std
RUN go install -race -tags netgo std
FROM golang:1.7.4
# Support Raspberry Pi 2 and newer
ENV GOARM 7
# The names of the architectures that we're fetching cross-compilers for from the Ubuntu packages
ENV DEB_CROSSPLATFORMS \
armhf \
arm64
# The go platforms we are supporting to cross-compile
ENV GO_CROSSPLATFORMS \
linux/arm \
linux/arm64
# The names of the gcc cross-compilers we have installed
ENV GCC_CROSSCOMPILERS \
arm-linux-gnueabihf \
aarch64-linux-gnu
# Temporarily add the Ubuntu repositories, because we're going to install gcc cross-compilers from there
# Install the build-essential and crossbuild-essential-ARCH packages
RUN echo "deb http://archive.ubuntu.com/ubuntu xenial main universe" > /etc/apt/sources.list.d/cgocrosscompiling.list \
&& apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 40976EAF437D05B5 3B4FE6ACC0B21F32 \
&& apt-get update \
&& apt-get install -y build-essential \
&& for platform in ${DEB_CROSSPLATFORMS}; do apt-get install -y crossbuild-essential-${platform}; done \
&& rm /etc/apt/sources.list.d/cgocrosscompiling.list \
&& apt-get update \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
# Install some required packages
# libpcap is required because we're linking against its C libraries from the prog/weaver binary
# flex and bison are required packages for compiling libpcap manually later
RUN apt-get update \
&& apt-get install -y \
libpcap-dev \
python-requests \
time \
file \
flex \
bison
# Install common Go tools
RUN go get \
github.com/golang/lint/golint \
github.com/fzipp/gocyclo \
github.com/client9/misspell/cmd/misspell
# First clean, because we're gonna rebuild the std both with -race enabled and disabled
# Running go install std twice is intentional and required, as content is written in two different directories
# (/usr/local/go/pkg/linux_amd64 vs /usr/local/go/pkg/linux_amd64_race)
# The other architectures do not have support for -race
RUN go clean -i net \
&& go install -tags netgo std \
&& go install -race -tags netgo std
# Prebuild std for the other architectures
RUN for platform in ${GO_CROSSPLATFORMS}; do \
GOOS=${platform%/*} GOARCH=${platform##*/} \
go install -tags netgo std; done
# The libpcap version from Debian packages is 1.6.2, matching that version here although newer versions of libpcap have been released
# We have to cross-compile the libpcap library for the new architectures, that's what we're doing here
ENV LIBPCAP_CROSS_VERSION=1.6.2
RUN curl -sSL http://www.tcpdump.org/release/libpcap-${LIBPCAP_CROSS_VERSION}.tar.gz | tar -xz \
&& cd libpcap-${LIBPCAP_CROSS_VERSION} \
&& for crosscompiler in ${GCC_CROSSCOMPILERS}; do \
CC=${crosscompiler}-gcc ac_cv_linux_vers=2 ./configure --host=${crosscompiler} --with-pcap=linux \
&& make \
&& export LIB_DIR="/usr/local/lib/${crosscompiler}-gcc" VER="$(cat ./VERSION)" MAJOR_VER="$(sed 's/\([0-9][0-9]*\)\..*/\1/' ./VERSION)" \
&& mkdir -p ${LIB_DIR} \
&& cp -f libpcap.a libpcap.so.${VER} ${LIB_DIR} \
&& ln -sf libpcap.so.${VER} /usr/local/lib/libpcap.so.${MAJOR_VER} \
&& ln -sf libpcap.so.${MAJOR_VER} /usr/local/lib/libpcap.so \
&& make clean; done
COPY build.sh /
ENTRYPOINT ["sh", "/build.sh"]
+3
View File
@@ -25,4 +25,7 @@ echo "weave:x:$uid:$gid::$WEAVE_SRC:/bin/sh" >>/etc/passwd
echo "weave:*:::::::" >>/etc/shadow
echo "weave ALL=(ALL) NOPASSWD: ALL" >>/etc/sudoers
# Allow full write access to the Go folders for the user Weave
chown -R $uid:$gid /usr/local/go
su weave -c "PATH=$PATH make -C $WEAVE_SRC BUILD_IN_CONTAINER=false $*"
+1
View File
@@ -0,0 +1 @@
8f313a9df867c207ae9ceac6e0935d1d2a0360aafce780dd5d1e0687ee98e0c3 docker-1.10.3.tgz
@@ -0,0 +1 @@
7541b5490cee1183d911f909c0e91d3d9d57b2b775e40f14a1a7a6de216ca4a8 docker-1.10.3.tgz
@@ -0,0 +1 @@
c02d861383d035ba020b361ef93bf14beb3964a42a6ae645b505b6148493e7ec qemu-aarch64-static
+1
View File
@@ -0,0 +1 @@
0ff63682b8868620d771aa812d3053dc3c579dc8633ce62d3d7ae7eee83beb06 qemu-arm-static
+20 -40
View File
@@ -2,56 +2,42 @@ general:
branches:
ignore:
- gh\-pages
- /pull\/.*/
machine:
pre:
- curl -sSL https://s3.amazonaws.com/circle-downloads/install-circleci-docker.sh | bash -s -- 1.10.0
services:
- docker
environment:
GOPATH: /home/ubuntu:$GOPATH
SRCDIR: /home/ubuntu/src/github.com/weaveworks/weave
PATH: $PATH:$HOME/.local/bin:$HOME/google-cloud-sdk/bin/
PATH: $PATH:$HOME/.local/bin
CLOUDSDK_CORE_DISABLE_PROMPTS: 1
STATE: /home/ubuntu/state.env
dependencies:
cache_directories:
- "~/docker"
post:
- "sudo apt-get update && sudo apt-get install bc jq"
- curl https://sdk.cloud.google.com | bash
- bin/setup-circleci-secrets "$SECRET_PASSWORD"
- "mkdir -p $(dirname $SRCDIR) && cp -r $(pwd)/ $SRCDIR"
- "cd $SRCDIR; git submodule update --init"
- cd $SRCDIR/test; ./gce.sh make_template:
parallel: false
- "cd $SRCDIR/build; ../tools/rebuild-image weaveworks/weavebuild . Dockerfile build.sh && touch $SRCDIR/.build.uptodate"
- bin/circle-dependencies-post
test:
pre:
- "$SRCDIR/bin/circle-test-pre":
parallel: true
override:
- cd $SRCDIR; make lint:
- "$SRCDIR/bin/circle-test-unit":
parallel: true
- cd $SRCDIR; COVERDIR=test/coverage make RM= tests:
parallel: true
- cd $SRCDIR; make COVERAGE=true RM= exes all:
parallel: true
- cd $SRCDIR; make testrunner:
parallel: true
- cd $SRCDIR/test; ./gce.sh setup && eval $(./gce.sh hosts) && ./setup.sh:
parallel: true
- cd $SRCDIR/test; eval $(./gce.sh hosts); export COVERAGE=true; ./run_all.sh:
- "$SRCDIR/bin/circle-test-smoke":
parallel: true
timeout: 300
post:
- cd $SRCDIR/test; ./gce.sh destroy:
parallel: true
- test "$CIRCLE_NODE_INDEX" != "0" || (cd $SRCDIR/test; ./gen_coverage_reports.sh):
- "$SRCDIR/bin/circle-test-teardown":
parallel: true
teardown:
pre:
- test "$CIRCLE_NODE_INDEX" != "0" || (go get github.com/mattn/goveralls && goveralls -repotoken $COVERALLS_REPO_TOKEN -coverprofile=$SRCDIR/test/profile.cov -service=circleci || true):
parallel: true
- test "$CIRCLE_NODE_INDEX" != "0" || (cd $SRCDIR/test; cp coverage.* $CIRCLE_ARTIFACTS):
- "$SRCDIR/bin/circle-teardown-pre":
parallel: true
deployment:
@@ -59,20 +45,14 @@ deployment:
branch: /[0-9]+\.[0-9]+/
owner: weaveworks
commands:
- go get github.com/weaveworks/wordepress && cd /home/ubuntu/src/github.com/weaveworks/wordepress && git checkout v1.0.0 && cd cmd/wordepress && go get
- cd $SRCDIR; bin/publish-site "$WP_LIVE_URL" "$WP_LIVE_USER" "$WP_LIVE_PASSWORD"
hub:
- "$SRCDIR/bin/circle-deploy-release"
master:
branch: master
owner: weaveworks
commands:
- docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS
- cd $SRCDIR; make clean-bin
- cd $SRCDIR; make exes publish
# - go get github.com/weaveworks/wordepress && cd /home/ubuntu/src/github.com/weaveworks/wordepress && git checkout v1.0.0 && cd cmd/wordepress && go get
# - cd $SRCDIR; bin/publish-site "$WP_DEV_URL" "$WP_DEV_USER" "$WP_DEV_PASSWORD"
# issues:
# branch: /.*/
# owner: weaveworks
# commands:
# - go get github.com/weaveworks/wordepress && cd /home/ubuntu/src/github.com/weaveworks/wordepress && git checkout v1.0.0 && cd cmd/wordepress && go get
# - cd $SRCDIR; bin/publish-site "$WP_DEV_URL" "$WP_DEV_USER" "$WP_DEV_PASSWORD"
- "$SRCDIR/bin/circle-deploy-master"
issues:
branch: /.*/
owner: weaveworks
commands:
- "$SRCDIR/bin/circle-deploy-issues"
-31
View File
@@ -1,31 +0,0 @@
package mflagext
import (
"fmt"
"github.com/docker/docker/pkg/mflag"
)
type listOpts struct {
value *[]string
hasBeenSet bool
}
func ListVar(p *[]string, names []string, value []string, usage string) {
*p = value
mflag.Var(&listOpts{p, false}, names, usage)
}
func (opts *listOpts) Set(value string) error {
if opts.hasBeenSet {
(*opts.value) = append((*opts.value), value)
} else {
(*opts.value) = []string{value}
opts.hasBeenSet = true
}
return nil
}
func (opts *listOpts) String() string {
return fmt.Sprintf("%v", []string(*opts.value))
}
+7 -2
View File
@@ -21,8 +21,13 @@ func CreateDatapath(dpname string) (supported bool, err error) {
defer dpif.Close()
dp, err := dpif.CreateDatapath(dpname)
if err != nil && !odp.IsDatapathNameAlreadyExistsError(err) {
return true, err
if err != nil {
if !odp.IsDatapathNameAlreadyExistsError(err) {
return true, err
}
if dp, err = dpif.LookupDatapath(dpname); err != nil {
return true, err
}
}
// Pick an ephemeral port number to use in probing for vxlan
+27
View File
@@ -0,0 +1,27 @@
package common
import (
"os"
"strconv"
)
func AllPids(procRoot string) ([]int, error) {
fh, err := os.Open(procRoot)
if err != nil {
return nil, err
}
defer fh.Close()
dirNames, err := fh.Readdirnames(-1)
if err != nil {
return nil, err
}
pids := make([]int, len(dirNames))
for _, dirName := range dirNames {
pid, err := strconv.Atoi(dirName)
if err != nil { // Only interested in numeric entries - skip /proc/stat, etc.
continue
}
pids = append(pids, pid)
}
return pids, err
}
-32
View File
@@ -1,32 +0,0 @@
package common
import (
"os"
"os/signal"
"runtime"
"syscall"
)
// A subsystem/server/... that can be stopped or queried about the status with a signal
type SignalReceiver interface {
Stop() error
}
func SignalHandlerLoop(ss ...SignalReceiver) {
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM)
buf := make([]byte, 1<<20)
for {
switch <-sigs {
case syscall.SIGINT, syscall.SIGTERM:
Log.Infof("=== received SIGINT/SIGTERM ===\n*** exiting")
for _, subsystem := range ss {
subsystem.Stop()
}
return
case syscall.SIGQUIT:
stacklen := runtime.Stack(buf, true)
Log.Infof("=== received SIGQUIT ===\n*** goroutine dump...\n%s\n*** end", buf[:stacklen])
}
}
}
+1 -141
View File
@@ -1,17 +1,6 @@
package common
import (
"fmt"
"net"
"os"
"strings"
"github.com/j-keck/arping"
"github.com/vishvananda/netlink"
"github.com/vishvananda/netns"
weavenet "github.com/weaveworks/weave/net"
)
import "strings"
// Assert test is true, panic otherwise
func Assert(test bool) {
@@ -27,132 +16,3 @@ func ErrorMessages(errors []error) string {
}
return strings.Join(result, "\n")
}
type NetDev struct {
Name string
MAC net.HardwareAddr
CIDRs []*net.IPNet
}
// Search the network namespace of a process for interfaces matching a predicate
// Note that the predicate is called while the goroutine is inside the process' netns
func FindNetDevs(processID int, match func(link netlink.Link) bool) ([]NetDev, error) {
var netDevs []NetDev
ns, err := netns.GetFromPid(processID)
if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, err
}
defer ns.Close()
err = weavenet.WithNetNS(ns, func() error {
return forEachLink(func(link netlink.Link) error {
if match(link) {
netDev, err := linkToNetDev(link)
if err != nil {
return err
}
netDevs = append(netDevs, *netDev)
}
return nil
})
})
return netDevs, err
}
func forEachLink(f func(netlink.Link) error) error {
links, err := netlink.LinkList()
if err != nil {
return err
}
for _, link := range links {
if err := f(link); err != nil {
return err
}
}
return nil
}
func linkToNetDev(link netlink.Link) (*NetDev, error) {
addrs, err := netlink.AddrList(link, netlink.FAMILY_V4)
if err != nil {
return nil, err
}
netDev := &NetDev{Name: link.Attrs().Name, MAC: link.Attrs().HardwareAddr}
for _, addr := range addrs {
netDev.CIDRs = append(netDev.CIDRs, addr.IPNet)
}
return netDev, nil
}
// Lookup the weave interface of a container
func GetWeaveNetDevs(processID int) ([]NetDev, error) {
// Bail out if this container is running in the root namespace
nsToplevel, err := netns.GetFromPid(1)
if err != nil {
return nil, fmt.Errorf("unable to open root namespace: %s", err)
}
nsContainr, err := netns.GetFromPid(processID)
if err != nil {
return nil, fmt.Errorf("unable to open process %d namespace: %s", processID, err)
}
if nsToplevel.Equal(nsContainr) {
return nil, nil
}
weaveBridge, err := netlink.LinkByName("weave")
if err != nil {
return nil, fmt.Errorf("Cannot find weave bridge: %s", err)
}
// Scan devices in root namespace to find those attached to weave bridge
indexes := make(map[int]struct{})
err = forEachLink(func(link netlink.Link) error {
if link.Attrs().MasterIndex == weaveBridge.Attrs().Index {
peerIndex := link.Attrs().ParentIndex
if peerIndex == 0 {
// perhaps running on an older kernel where ParentIndex doesn't work.
// as fall-back, assume the indexes are consecutive
peerIndex = link.Attrs().Index - 1
}
indexes[peerIndex] = struct{}{}
}
return nil
})
if err != nil {
return nil, err
}
return FindNetDevs(processID, func(link netlink.Link) bool {
_, isveth := link.(*netlink.Veth)
_, found := indexes[link.Attrs().Index]
return isveth && found
})
}
// Get the weave bridge interface
func GetBridgeNetDev(bridgeName string) ([]NetDev, error) {
return FindNetDevs(1, func(link netlink.Link) bool {
return link.Attrs().Name == bridgeName
})
}
// Do post-attach configuration of all veths we have created
func ConfigureARPforVeths(processID int, prefix string) error {
_, err := FindNetDevs(processID, func(link netlink.Link) bool {
ifName := link.Attrs().Name
if strings.HasPrefix(ifName, prefix) {
weavenet.ConfigureARPCache(ifName)
if addrs, err := netlink.AddrList(link, netlink.FAMILY_V4); err == nil {
for _, addr := range addrs {
arping.GratuitousArpOverIfaceByName(addr.IPNet.IP, ifName)
}
}
}
return false
})
return err
}
+30 -5
View File
@@ -4,6 +4,7 @@ import (
"bytes"
"encoding/gob"
"fmt"
"time"
"github.com/boltdb/bolt"
)
@@ -23,14 +24,39 @@ var (
topBucket = []byte("top")
)
const (
NameIdent = "peername"
FileName = "data.db"
)
func NewBoltDB(dbPathname string) (*BoltDB, error) {
db, err := bolt.Open(dbPathname, 0660, nil)
if err != nil {
return nil, fmt.Errorf("[boltDB] Unable to open %s: %s", dbPathname, err)
}
// check the persistence version
err = db.Update(func(tx *bolt.Tx) error {
err = db.Update(checkVersion(false))
return &BoltDB{db: db}, err
}
func NewBoltDBReadOnly(dbPathname string) (*BoltDB, error) {
options := bolt.Options{Timeout: time.Millisecond * 50, ReadOnly: true}
db, err := bolt.Open(dbPathname, 0660, &options)
if err != nil {
return nil, fmt.Errorf("[boltDB] Unable to open %s: %s", dbPathname, err)
}
err = db.View(checkVersion(true))
if err != nil {
return nil, fmt.Errorf("[boltDB] Cannot use persistence file %s: %s", dbPathname, err)
}
return &BoltDB{db: db}, nil
}
func checkVersion(readOnly bool) func(tx *bolt.Tx) error {
return func(tx *bolt.Tx) error {
if top := tx.Bucket(topBucket); top == nil {
if readOnly {
return fmt.Errorf("no top bucket")
}
top, err := tx.CreateBucket(topBucket)
if err != nil {
return err
@@ -41,13 +67,12 @@ func NewBoltDB(dbPathname string) (*BoltDB, error) {
} else {
if checkVersion := top.Get(versionIdent); checkVersion != nil {
if checkVersion[0] != persistenceVersion[0] {
return fmt.Errorf("[boltDB] Cannot use persistence file %s - version %x", dbPathname, checkVersion)
return fmt.Errorf("mismatched version %x", checkVersion)
}
}
}
return nil
})
return &BoltDB{db: db}, err
}
}
func (d *BoltDB) Load(ident string, data interface{}) (bool, error) {
+154
View File
@@ -0,0 +1,154 @@
This document describes implementation details of the fast datapath encryption.
# Overview
At the high level, we use the ESP protocol ([RFC 2406][esp]) in the Transport
mode. Each packet is encrypted with AES in GCM mode ([RFC 4106][aesgcm]), with
32byte key and 4byte salt. This combo provides the following security
properties:
* Data confidentiality.
* Data origin authentication.
* Integrity.
* Anti-replay service.
* Limited traffic flow confidentiality.
## Notation
* `SAin`: IPsec security association for inbound connections.
* `SAout`: IPsec security association for outbound connections.
* `SPout`: IPsec security policy for outbound connections. Used to match
outbound flows to SAout.
## SA Key Derivation
For each connection direction, a different AES-GCM key and salt is used.
The pairs are derived with HKDF ([RFC 5869][hkdf]):
```
SAin[KeyAndSalt] = HKDF(sha256, ikm=sessionKey, salt=nonceIn, info=localPeerName)
SAout[KeyAndSalt] = HKDF(sha256, ikm=sessionKey, salt=nonceOut, info=remotePeerName)
```
Where:
* the mutual `sessionKey` is derived by the [Mesh][mesh] library during
the control plane connection establishment between the local peer and
the remote peer.
* `nonceIn` and `nonceOut` are randomly generated 32byte nonces which
are exchanged over the encrypted control plane channel.
## SPI
A directional secure connection between two peers is identified with SPI.
The kernel requires the pair of SPI and dst IP to be unique among security
associations. Thus, to avoid collisions, we generate outbound SPI on a remote
peer.
## Connection Establishment
```
Peer A Peer B
-----------------------------------------------------------------------------------------------------------------
fastdp.fwd.Confirm():
install iptables blocking rules, fastdp.fwd.Confirm():
nonce_BA = rand(), install iptables blocking rules,
{key,salt}_BA = hkdf(sessionKey, nonce_BA, A), nonce_AB = rand(),
spi_BA = allocspi(), {key,salt}_AB = hkdf(sessionKey, nonce_AB, B),
create SA_BA(B<-A, spi_BA, key_BA, salt_BA), spi_AB = allocspi(),
send InitSARemote(spi_BA, nonce_BA). --> create SA_AB(A<-B, spi_AB, key_AB, salt_AB),
<-- send InitSARemote(spi_AB, nonce_AB).
--> recv InitSARemote(spi_BA, nonce_BA):
recv InitSARemote(spi_AB, nonce_AB): <-- {key,salt}_BA = hkdf(sessionKey, nonce_BA, A),
{key,salt}_AB = hkdf(sessionKey, nonce_AB, B), create SA_BA(B<-A, spi_BA, key_BA, salt_BA),
create SA_AB(A<-B, spi_AB, key_AB, salt_AB), create SP_BA(B<-A, spi_BA),
create SP_AB(A<-B, spi_AB), install marking rule.
install marking rule.
```
# Implementation Details
## XFRM
The implementation is based on the kernel IP packet transformation framework
called XFRM. Unfortunately, docs are barely existing and the complexity of
the framework is high. The best resource I found is Chapter 10 in
"Linux Kernel Networking: Implementation and Theory" by Rami Rosen.
## iptables Rules
The kernel VXLAN driver does not set a dst port of a tunnel in the ip flow
descriptor, thus XFRM policy lookup cannot match a policy (SPout) which includes
the port. This makes impossible to encrypt only tunneled traffic between
peers. To work around, we mark such outgoing packets with iptables and set
the same mark in the policy selector (funnily enough, `iptables_mangle` module
eventually sets the missing dst port in the flow descriptor). The challenge
here is to pick a mark that it would not interfere with other networking
applications before OUTPUT'ing a packet. For example, Kubernetes by default
uses 1<<14 and 1<<15 marks and we choose 1<<17 (0x20000). Additionally,
such workaround brings the requirement for at least the 4.2 kernel.
The marking rules are the following:
```
iptables -t mangle -A OUTPUT -j WEAVE-IPSEC-OUT
iptables -t mangle -A WEAVE-IPSEC-OUT -s ${LOCAL_PEER_IP} -d ${REMOTE_PEER_IP} \
-p udp --dport ${TUNNEL_PORT} -j WEAVE-IPSEC-OUT-MARK
iptables -t mangle -A WEAVE-IPSEC-OUT-MARK --set-xmark ${MARK} -j MARK
```
As Linux does not implement [IP Security Levels][ipseclevel], we install
additional iptables rules to prevent from accidentally sending unencrypted
traffic between peers which have previously established the secure connection.
For inbound traffic, we mark each ESP packet with the mark and drop non-marked
tunnel traffic:
```
iptables -t mangle -A INPUT -j WEAVE-IPSEC-IN
iptables -t mangle -A WEAVE-IPSEC-IN -s ${REMOTE_PEER_IP} -d ${LOCAL_PEER_IP} \
-m esp --espspi ${SPIin} -j WEAVE-IPSEC-IN-MARK
iptables -t mangle -A WEAVE-IPSEC-IN-MARK --set-xmark ${MARK} -j MARK
iptables -t filter -A INPUT -j WEAVE-IPSEC-IN
iptables -t filter -A WEAVE-IPSEC-IN -s ${REMOTE_PEER_IP} -d ${LOCAL_PEER_IP} \
-p udp --dport ${TUNNEL_PORT} -m mark ! --mark ${MARK} -j DROP
```
For outbound traffic, we drop marked traffic which does not match any SPout:
```
iptables -t filter -A OUTPUT ! -p esp -m policy --dir out --pol none \
-m mark --mark ${MARK} -j DROP
```
## ESN
To prevent from cycling SeqNo which makes replay attacks possible, we use
64-bit extended sequence numbers known as [ESN](esn).
## MTU
In addition to the VXLAN overhead, the MTU calculation should take into account
the ESP overhead which is 34-37 bytes (encrypted Payload is 4 bytes aligned) and
consists of:
* 4 bytes (SPI).
* 4 bytes (Sequence Number).
* 8 bytes (ESP IV).
* 1 byte (Pad Length).
* 1 byte (NextHeader).
* 16 bytes (ICV).
* 0-3 bytes (Padding).
[esp]: https://tools.ietf.org/html/rfc2406
[aesgcm]: https://tools.ietf.org/html/rfc4106
[hkdf]: https://tools.ietf.org/html/rfc5869
[esn]: https://tools.ietf.org/html/rfc4304
[ipseclevel]: https://tools.ietf.org/html/draft-mcdonald-simple-ipsec-api-01)
[mesh]: https://github.com/weaveworks/mesh
+100
View File
@@ -0,0 +1,100 @@
# Overview
# ipsets
The policy controller maintains a number of ipsets which are
subsequently referred to by the iptables rules used to effect network
policy specifications. These ipsets are created, modified and
destroyed automatically in response to Pod, Namespace and
NetworkPolicy object updates from the k8s API server:
* A `hash:ip` set per namespace, containing the IP addresses of all
pods in that namespace
* A `list:set` per distinct (across all network policies in all
namespaces) namespace selector mentioned in a network policy,
containing the names of any of the above hash:ip sets whose
corresponding namespace labels match the selector
* A `hash:ip` set for each distinct (within the scope of the
containing network policy's namespace) pod selector mentioned in a
network policy, containing the IP addresses of all pods in the
namespace whose labels match that selector
ipset names are generated deterministically from a string
representation of the corresponding label selector. Because ipset
names are limited to 31 characters in length, this is done by taking a
SHA hash of the selector string and then printing that out as a base
85 string with a "weave-" prefix e.g.:
weave-k?Z;25^M}|1s7P3|H9i;*;MhG
Because pod selectors are scoped to a namespace, we need to make sure
that if the same selector definition is used in different namespaces
that we maintain distinct ipsets. Consequently, for such selectors the
namespace name is prepended to the label selector string before
hashing to avoid clashes.
# iptables chains
The policy controller maintains two iptables chains in response to
changes to pods, namespaces and network policies. One chain contains
the ingress rules that implement the network policy specifications,
and the other is used to bypass the ingress rules for namespaces which
have an ingress isolation policy of `DefaultAllow`.
## Dynamically maintained `WEAVE-NPC-DEFAULT` chain
The policy controller maintains a rule in this chain for every
namespace whose ingress isolation policy is `DefaultAllow`. The
purpose of this rule is simply to ACCEPT any traffic destined for such
namespaces before it reaches the ingress chain.
```
iptables -A WEAVE-NPC-DEFAULT -m set --match-set $NSIPSET dst -j ACCEPT
```
## Dynamically maintained `WEAVE-NPC-INGRESS` chain
For each namespace network policy ingress rule peer/port combination:
```
iptables -A WEAVE-NPC-INGRESS -p $PROTO [-m set --match-set $SRCSET] -m set --match-set $DSTSET --dport $DPORT -j ACCEPT
```
## Static `WEAVE-NPC` chain
Static configuration:
```
iptables -A WEAVE-NPC -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A WEAVE-NPC -m state --state NEW -j WEAVE-NPC-DEFAULT
iptables -A WEAVE-NPC -m state --state NEW -j WEAVE-NPC-INGRESS
```
# Steering traffic into the policy engine
To direct traffic into the policy engine:
iptables -A FORWARD -o weave -m physdev ! --physdev-out vethwe-bridge -j WEAVE-NPC
iptables -A FORWARD -o weave -m physdev ! --physdev-out vethwe-bridge -j DROP
Note this only affects traffic which egresses the bridge on a physical
port which is not the Weave Net router - in other words, it is
destined for an application container veth. The following traffic is
affected:
* Traffic bridged between local application containers
* Traffic bridged from the router to a local application container
* Traffic originating from the internet destined for nodeports - this
is routed via the FORWARD chain to a container pod IP after DNAT
The following traffic is NOT affected:
* Traffic bridged from a local application container to the router
* Traffic originating from processes in the host network namespace
(e.g. kubelet health checks)
* Traffic routed from an application container to the internet
See these resources for helpful context:
* http://ebtables.netfilter.org/br_fw_ia/br_fw_ia.html
* https://commons.wikimedia.org/wiki/File:Netfilter-packet-flow.svg
+2 -1
View File
@@ -3,6 +3,7 @@ package ipam
import (
"fmt"
"github.com/weaveworks/weave/api"
"github.com/weaveworks/weave/net/address"
)
@@ -43,7 +44,7 @@ func (g *allocate) Try(alloc *Allocator) bool {
if ok, addr := alloc.space.Allocate(g.r.HostRange()); ok {
// If caller hasn't supplied a unique ID, file it under the IP address
// which lets the caller then release the address using DELETE /ip/address
if g.ident == "_" {
if g.ident == api.NoContainerID {
g.ident = addr.String()
}
alloc.debugln("Allocated", addr, "for", g.ident, "in", g.r)
+7 -8
View File
@@ -322,7 +322,7 @@ func (alloc *Allocator) Claim(ident string, cidr address.CIDR, isContainer, noEr
// ContainerDied called from the updater interface. Async.
func (alloc *Allocator) ContainerDied(ident string) {
alloc.actionChan <- func() {
if alloc.hasOwned(ident) {
if alloc.hasOwnedByContainer(ident) {
alloc.debugln("Container", ident, "died; noting to remove later")
alloc.dead[ident] = alloc.now()
}
@@ -335,7 +335,7 @@ func (alloc *Allocator) ContainerDied(ident string) {
// ContainerDestroyed called from the updater interface. Async.
func (alloc *Allocator) ContainerDestroyed(ident string) {
alloc.actionChan <- func() {
if alloc.hasOwned(ident) {
if alloc.hasOwnedByContainer(ident) {
alloc.debugln("Container", ident, "destroyed; removing addresses")
alloc.delete(ident)
delete(alloc.dead, ident)
@@ -920,13 +920,12 @@ func (alloc *Allocator) reportFreeSpace() {
// Persistent data
const (
ringIdent = "ring"
nameIdent = "peername"
ownedIdent = "ownedAddresses"
)
func (alloc *Allocator) persistRing() {
// It would be better if these two Save operations happened in the same transaction
if err := alloc.db.Save(nameIdent, alloc.ourName); err != nil {
if err := alloc.db.Save(db.NameIdent, alloc.ourName); err != nil {
alloc.fatalf("Error persisting ring data: %s", err)
return
}
@@ -938,7 +937,7 @@ func (alloc *Allocator) persistRing() {
// Returns true if persisted data is to be used, otherwise false
func (alloc *Allocator) loadPersistedData() bool {
var checkPeerName mesh.PeerName
nameFound, err := alloc.db.Load(nameIdent, &checkPeerName)
nameFound, err := alloc.db.Load(db.NameIdent, &checkPeerName)
if err != nil {
alloc.fatalf("Error loading persisted peer name: %s", err)
}
@@ -996,9 +995,9 @@ func (alloc *Allocator) persistOwned() {
// Owned addresses
func (alloc *Allocator) hasOwned(ident string) bool {
_, b := alloc.owned[ident]
return b
func (alloc *Allocator) hasOwnedByContainer(ident string) bool {
d, b := alloc.owned[ident]
return b && d.IsContainer
}
// NB: addr must not be owned by ident already
+18 -9
View File
@@ -5,6 +5,7 @@ import (
"github.com/weaveworks/mesh"
"github.com/weaveworks/weave/api"
"github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/net/address"
)
@@ -77,26 +78,34 @@ func (c *claim) Try(alloc *Allocator) bool {
return false
}
if c.ident == "_" { // Special "I don't have a unique ID" identifier
c.ident = c.cidr.Addr.String()
}
// We are the owner, check we haven't given it to another container
switch existingIdent := alloc.findOwner(c.cidr.Addr); existingIdent {
case "":
existingIdent := alloc.findOwner(c.cidr.Addr)
switch {
case existingIdent == "":
// Unused address, we try to claim it:
if err := alloc.space.Claim(c.cidr.Addr); err == nil {
alloc.debugln("Claimed", c.cidr, "for", c.ident)
alloc.addOwned(c.ident, c.cidr, c.isContainer)
if c.ident == api.NoContainerID {
alloc.addOwned(c.cidr.Addr.String(), c.cidr, c.isContainer)
} else {
alloc.addOwned(c.ident, c.cidr, c.isContainer)
}
c.sendResult(nil)
} else {
c.sendResult(err)
}
case c.ident:
case (existingIdent == c.ident) || (c.ident == api.NoContainerID && existingIdent == c.cidr.Addr.String()):
// same identifier is claiming same address; that's OK
alloc.debugln("Re-Claimed", c.cidr, "for", c.ident)
c.sendResult(nil)
case c.cidr.Addr.String():
// Address already allocated via "_" name
case existingIdent == c.cidr.Addr.String():
// Address already allocated via api.NoContainerID name and current ID is a real container ID:
c.sendResult(fmt.Errorf("address %s already in use", c.cidr))
case c.ident == api.NoContainerID:
// We do not know whether this is the same container or another one,
// but we also cannot prove otherwise, so we let it reclaim the address:
alloc.debugln("Re-Claimed", c.cidr, "for ID", c.ident, "having existing ID as", existingIdent)
c.sendResult(nil)
default:
// Addr already owned by container on this machine
c.sendResult(fmt.Errorf("address %s is already owned by %s", c.cidr.String(), existingIdent))
-31
View File
@@ -1,31 +0,0 @@
package ring
/* Exported variables for monitoring and management */
import (
"expvar"
"strconv"
)
var (
expRingSize = expvar.NewMap("ipam.ringSize")
expRingEntries = expvar.NewMap("ipam.ringEntries")
)
type _int int
func (i _int) String() string {
return strconv.Itoa(int(i))
}
type _uint32 uint32
func (i _uint32) String() string {
return strconv.FormatUint(uint64(i), 10)
}
func (r *Ring) updateExportedVariables() {
ringName := r.Start.String()
expRingSize.Set(ringName, _uint32(r.End-r.Start))
expRingEntries.Set(ringName, _int(len(r.Entries)))
}
+4 -8
View File
@@ -41,8 +41,8 @@ var (
ErrNotSorted = errors.New("Ring not sorted")
ErrTokenRepeated = errors.New("Token appears twice in ring")
ErrTokenOutOfRange = errors.New("Token is out of range")
ErrDifferentSeeds = errors.New("Received ring was seeded differently from ours!")
ErrDifferentRange = errors.New("Received range differs from ours!")
ErrDifferentSeeds = errors.New("Received ring was seeded differently from ours")
ErrDifferentRange = errors.New("Received range differs from ours")
)
func errInconsistentEntry(mine, theirs *entry) error {
@@ -114,11 +114,12 @@ func New(start, end address.Address, peer mesh.PeerName, f OnUpdate) *Ring {
common.Assert(start < end)
ring := &Ring{Start: start, End: end, Peer: peer, Entries: make([]*entry, 0), onUpdate: f}
ring.updateExportedVariables()
return ring
}
func (r *Ring) Restore(other *Ring) {
defer r.trackUpdates()()
onUpdate := r.onUpdate
*r = *other
r.onUpdate = onUpdate
@@ -149,7 +150,6 @@ func (r *Ring) GrantRangeToHost(start, end address.Address, peer mesh.PeerName)
r.assertInvariants()
defer r.trackUpdates()()
defer r.assertInvariants()
defer r.updateExportedVariables()
// ----------------- Start of Checks -----------------
@@ -216,7 +216,6 @@ func (r *Ring) GrantRangeToHost(start, end address.Address, peer mesh.PeerName)
func (r *Ring) Merge(gossip Ring) (bool, error) {
r.assertInvariants()
defer r.trackUpdates()()
defer r.updateExportedVariables()
// Don't panic when checking the gossiped in ring.
// In this case just return any error found.
@@ -402,7 +401,6 @@ func (r *Ring) ClaimForPeers(peers []mesh.PeerName) {
defer r.trackUpdates()()
defer r.assertInvariants()
defer r.updateExportedVariables()
defer func() {
e := r.Entries[len(r.Entries)-1]
common.Assert(address.Add(e.Token, address.Offset(e.Free)) == r.End)
@@ -453,7 +451,6 @@ func (r *Ring) String() string {
func (r *Ring) ReportFree(freespace map[address.Address]address.Count) (updated bool) {
r.assertInvariants()
defer r.assertInvariants()
defer r.updateExportedVariables()
common.Assert(!r.Empty())
entries := r.Entries
@@ -562,7 +559,6 @@ func (r *Ring) Transfer(from, to mesh.PeerName) []address.Range {
defer r.trackUpdates()()
defer r.trackUpdatesOfPeer(from)()
defer r.assertInvariants()
defer r.updateExportedVariables()
var newRanges []address.Range
+2 -2
View File
@@ -494,7 +494,7 @@ func TestTransfer(t *testing.T) {
ring1.ClaimItAll()
ring1.GrantRangeToHost(middle, end, peer2name)
ring1.Transfer(peer2name, peer1name)
require.Equal(t, []address.Range{{start, middle}, {middle, end}}, ring1.OwnedRanges())
require.Equal(t, []address.Range{{Start: start, End: middle}, {Start: middle, End: end}}, ring1.OwnedRanges())
// Second test is what happens when a token exists at the end of a range but is transferred
// - does it get resurrected correctly?
@@ -503,7 +503,7 @@ func TestTransfer(t *testing.T) {
ring1.GrantRangeToHost(middle, end, peer2name)
ring1.Transfer(peer2name, peer1name)
ring1.GrantRangeToHost(dot10, middle, peer2name)
require.Equal(t, []address.Range{{start, dot10}, {middle, end}}, ring1.OwnedRanges())
require.Equal(t, []address.Range{{Start: start, End: dot10}, {Start: middle, End: end}}, ring1.OwnedRanges())
}
func TestOwner(t *testing.T) {
+8
View File
@@ -88,6 +88,14 @@ func (s *Space) Claim(addr address.Address) error {
return nil
}
func (s *Space) NumOwnedAddresses() address.Count {
res := address.Count(0)
for i := 0; i < len(s.ours); i += 2 {
res += address.Length(s.ours[i+1], s.ours[i])
}
return res
}
func (s *Space) NumFreeAddresses() address.Count {
res := address.Count(0)
for i := 0; i < len(s.free); i += 2 {
+3
View File
@@ -98,16 +98,19 @@ func TestSpaceAllocate(t *testing.T) {
space1 := makeSpace(start, size)
require.Equal(t, address.Count(20), space1.NumFreeAddresses())
require.Equal(t, address.Count(0), space1.NumOwnedAddresses())
space1.assertInvariants()
_, addr1 := space1.Allocate(address.NewRange(start, size))
require.Equal(t, testAddr1, addr1.String(), "address")
require.Equal(t, address.Count(19), space1.NumFreeAddresses())
require.Equal(t, address.Count(1), space1.NumOwnedAddresses())
space1.assertInvariants()
_, addr2 := space1.Allocate(address.NewRange(start, size))
require.False(t, addr2.String() == testAddr1, "address")
require.Equal(t, address.Count(18), space1.NumFreeAddresses())
require.Equal(t, address.Count(2), space1.NumOwnedAddresses())
require.Equal(t, address.Count(13), space1.NumFreeAddressesInRange(address.Range{Start: ip(testAddr1), End: ip(testAddrx)}))
require.Equal(t, address.Count(18), space1.NumFreeAddressesInRange(address.Range{Start: ip(testAddr1), End: ip(testAddry)}))
space1.assertInvariants()
+2
View File
@@ -10,6 +10,7 @@ type Status struct {
Paxos *paxos.Status
Range string
RangeNumIPs int
ActiveIPs int
DefaultSubnet string
Entries []EntryStatus
PendingClaims []ClaimStatus
@@ -52,6 +53,7 @@ func NewStatus(allocator *Allocator, defaultSubnet address.CIDR) *Status {
paxosStatus,
allocator.universe.String(),
int(allocator.universe.Size()),
int(allocator.space.NumOwnedAddresses()),
defaultSubnet.String(),
newEntryStatusSlice(allocator),
newClaimStatusSlice(allocator),
+8 -9
View File
@@ -21,6 +21,7 @@ package tracker
import (
"fmt"
"net"
"syscall"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/ec2metadata"
@@ -94,14 +95,14 @@ func (t *AWSVPCTracker) HandleUpdate(prevRanges, currRanges []address.Range, loc
for _, cidr := range curr {
cidrStr := cidr.String()
t.debugf("adding route %s to %s", cidrStr, t.instanceID)
_, err := t.createVPCRoute(cidrStr)
if err != nil {
if _, err := t.createVPCRoute(cidrStr); err != nil {
return fmt.Errorf("createVPCRoutes failed: %s", err)
}
if local {
err = t.createHostRoute(cidrStr)
if err != nil {
return fmt.Errorf("createHostRoute failed: %s", err)
if err := t.createHostRoute(cidrStr); err != nil {
if errno, ok := err.(syscall.Errno); !(ok && errno == syscall.EEXIST) {
return fmt.Errorf("createHostRoute failed: %s", err)
}
}
}
}
@@ -110,13 +111,11 @@ func (t *AWSVPCTracker) HandleUpdate(prevRanges, currRanges []address.Range, loc
for _, cidr := range prev {
cidrStr := cidr.String()
t.debugf("removing %s route", cidrStr)
_, err := t.deleteVPCRoute(cidrStr)
if err != nil {
if _, err := t.deleteVPCRoute(cidrStr); err != nil {
return fmt.Errorf("deleteVPCRoute failed: %s", err)
}
if local {
err = t.deleteHostRoute(cidrStr)
if err != nil {
if err := t.deleteHostRoute(cidrStr); err != nil {
return fmt.Errorf("deleteHostRoute failed: %s", err)
}
}
+13 -6
View File
@@ -28,7 +28,7 @@ const (
)
type Upstream interface {
Config() *dns.ClientConfig
Config() (*dns.ClientConfig, error)
}
func NewUpstream(resolvConf, filterAddress string) Upstream {
@@ -48,27 +48,31 @@ type upstream struct {
lastModified time.Time
}
func (u *upstream) Config() *dns.ClientConfig {
func (u *upstream) Config() (*dns.ClientConfig, error) {
u.Lock()
defer u.Unlock()
// If we checked less than five seconds ago return what we already have
now := time.Now()
if now.Sub(u.lastStat) < 5*time.Second {
return u.cachedConfig
return u.cachedConfig, nil
}
u.lastStat = now
// Reread file if it has changed
if fi, err := os.Stat(u.resolvConf); err == nil && fi.ModTime() != u.lastModified {
if fi, err := os.Stat(u.resolvConf); err != nil {
return u.cachedConfig, err
} else if fi.ModTime() != u.lastModified {
if config, err := dns.ClientConfigFromFile(u.resolvConf); err == nil {
config.Servers = filter(config.Servers, u.filterAddress)
u.lastModified = fi.ModTime()
u.cachedConfig = config
} else {
return u.cachedConfig, err
}
}
return u.cachedConfig
return u.cachedConfig, nil
}
func filter(ss []string, s string) []string {
@@ -257,7 +261,10 @@ func (h *handler) handleRecursive(w dns.ResponseWriter, req *dns.Msg) {
}
}
upstreamConfig := h.upstream.Config()
upstreamConfig, err := h.upstream.Config()
if err != nil {
h.ns.errorf("unable to read upstream config: %s", err)
}
for _, server := range upstreamConfig.Servers {
reqCopy := req.Copy()
reqCopy.Id = dns.Id()
+2 -2
View File
@@ -19,8 +19,8 @@ type mockUpstream struct {
config *dns.ClientConfig
}
func (mu *mockUpstream) Config() *dns.ClientConfig {
return mu.config
func (mu *mockUpstream) Config() (*dns.ClientConfig, error) {
return mu.config, nil
}
func startServer(t *testing.T, upstream *dns.ClientConfig) (*DNSServer, *Nameserver, int, int) {
+1 -1
View File
@@ -120,7 +120,7 @@ func (e1 *Entry) tombstone() bool {
func check(es SortableEntries) error {
if !sort.IsSorted(es) {
return fmt.Errorf("Not sorted!")
return fmt.Errorf("Not sorted")
}
for i := 1; i < es.Len(); i++ {
if es.Get(i).equal(es.Get(i - 1)) {
+1 -1
View File
@@ -199,7 +199,7 @@ func (n *Nameserver) receiveGossip(msg []byte) (mesh.GossipData, mesh.GossipData
return nil, nil, err
}
if delta := gossip.Timestamp - now(); delta > gossipWindow || delta < -gossipWindow {
return nil, nil, fmt.Errorf("clock skew of %d detected", delta)
return nil, nil, fmt.Errorf("host clock skew of %ds exceeds %ds limit", delta, gossipWindow)
}
// Filter to remove entries from unknown peers, done before we take
+2 -1
View File
@@ -36,9 +36,10 @@ func NewStatus(ns *Nameserver, dnsServer *DNSServer) *Status {
entry.Tombstone})
}
upstreamConfig, _ := dnsServer.upstream.Config()
return &Status{
dnsServer.domain,
dnsServer.upstream.Config().Servers,
upstreamConfig.Servers,
dnsServer.address,
dnsServer.ttl,
entryStatusSlice}
+57
View File
@@ -1,6 +1,10 @@
package net
import (
"fmt"
"net"
"github.com/Sirupsen/logrus"
"github.com/vishvananda/netlink"
)
@@ -51,3 +55,56 @@ func isDatapath(link netlink.Link) bool {
return false
}
}
func DetectHairpin(portIfName string, log *logrus.Logger) error {
link, err := netlink.LinkByName(portIfName)
if err != nil {
return fmt.Errorf("Unable to find link %q: %s", portIfName, err)
}
ch := make(chan netlink.LinkUpdate)
// See EnsureInterface for why done channel is not passed
if err := netlink.LinkSubscribe(ch, nil); err != nil {
return fmt.Errorf("Unable to subscribe to netlink updates: %s", err)
}
pi, err := netlink.LinkGetProtinfo(link)
if err != nil {
return fmt.Errorf("Unable to get link protinfo %q: %s", portIfName, err)
}
if pi.Hairpin {
return fmt.Errorf("Hairpin mode enabled on %q", portIfName)
}
go func() {
for up := range ch {
if up.Attrs().Name == portIfName && up.Attrs().Protinfo != nil &&
up.Attrs().Protinfo.Hairpin {
log.Errorf("Hairpin mode enabled on %q", portIfName)
}
}
}()
return nil
}
var ErrBridgeNoIP = fmt.Errorf("Bridge has no IP address")
func FindBridgeIP(bridgeName string, subnet *net.IPNet) (net.IP, error) {
netdev, err := GetBridgeNetDev(bridgeName)
if err != nil {
return nil, fmt.Errorf("Failed to get netdev for %q bridge: %s", bridgeName, err)
}
if len(netdev.CIDRs) == 0 {
return nil, ErrBridgeNoIP
}
if subnet != nil {
for _, cidr := range netdev.CIDRs {
if subnet.Contains(cidr.IP) {
return cidr.IP, nil
}
}
}
// No subnet, or none in the required subnet; just return the first one
return netdev.CIDRs[0].IP, nil
}
+20 -12
View File
@@ -6,6 +6,7 @@ import "unsafe"
const (
SIOCETHTOOL = 0x8946 // linux/sockios.h
ETHTOOL_GTXCSUM = 0x00000016 // linux/ethtool.h
ETHTOOL_STXCSUM = 0x00000017 // linux/ethtool.h
IFNAMSIZ = 16 // linux/if.h
)
@@ -22,31 +23,38 @@ type EthtoolValue struct {
Data uint32
}
func ioctlEthtool(fd int, argp uintptr) error {
_, _, errno := syscall.RawSyscall(syscall.SYS_IOCTL, uintptr(fd), uintptr(SIOCETHTOOL), argp)
if errno != 0 {
return errno
}
return nil
}
// Disable TX checksum offload on specified interface
func EthtoolTXOff(name string) error {
if len(name)+1 > IFNAMSIZ {
return fmt.Errorf("name too long")
}
value := EthtoolValue{ETHTOOL_STXCSUM, 0}
request := IFReqData{Data: uintptr(unsafe.Pointer(&value))}
copy(request.Name[:], name)
socket, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, 0)
if err != nil {
return err
}
defer syscall.Close(socket)
_, _, errno := syscall.RawSyscall(syscall.SYS_IOCTL,
uintptr(socket),
uintptr(SIOCETHTOOL),
uintptr(unsafe.Pointer(&request)))
// Request current value
value := EthtoolValue{Cmd: ETHTOOL_GTXCSUM}
request := IFReqData{Data: uintptr(unsafe.Pointer(&value))}
copy(request.Name[:], name)
if errno != 0 {
return errno
if err := ioctlEthtool(socket, uintptr(unsafe.Pointer(&request))); err != nil {
return err
}
if value.Data == 0 { // if already off, don't try to change
return nil
}
return nil
value = EthtoolValue{ETHTOOL_STXCSUM, 0}
return ioctlEthtool(socket, uintptr(unsafe.Pointer(&request)))
}
+562
View File
@@ -0,0 +1,562 @@
// package IPsec provides primitives for establishing IPsec in the fastdp mode.
package ipsec
import (
"crypto/rand"
"crypto/sha256"
"encoding/binary"
"fmt"
"io"
"net"
"strconv"
"sync"
"syscall"
"github.com/Sirupsen/logrus"
"github.com/coreos/go-iptables/iptables"
"github.com/pkg/errors"
"github.com/vishvananda/netlink"
"golang.org/x/crypto/hkdf"
"github.com/weaveworks/mesh"
)
const (
keySize = 36 // AES-GCM key 32 bytes + 4 bytes salt
nonceSize = 32 // HKDF nonce size
mark = uint32(0x1) << 17 // iptables marks
markStr = "0x20000/0x20000" // update if the above mark changes
tableMangle = "mangle"
tableFilter = "filter"
chainIn = "WEAVE-IPSEC-IN"
chainInMark = "WEAVE-IPSEC-IN-MARK"
chainOut = "WEAVE-IPSEC-OUT"
chainOutMark = "WEAVE-IPSEC-OUT-MARK"
)
type SPI uint32
// Used to identify:
// - directional SPIs,
// - ipsec establishments.
type spiID [24]byte
func getSPIId(srcPeer, dstPeer mesh.PeerName, connUID uint64) (id spiID) {
binary.BigEndian.PutUint64(id[:], uint64(srcPeer))
binary.BigEndian.PutUint64(id[8:], uint64(dstPeer))
binary.BigEndian.PutUint64(id[16:], connUID)
return
}
type spiInfo struct {
spi SPI
isDirOut bool
}
// IPSec
type IPSec struct {
sync.RWMutex
ipt *iptables.IPTables
log *logrus.Logger
spiInfo map[spiID]spiInfo
// A reference to spiInfo; spiInfo might be of an expired SPI.
spis map[SPI]*spiInfo
}
func New(log *logrus.Logger) (*IPSec, error) {
ipt, err := iptables.New()
if err != nil {
return nil, errors.Wrap(err, "iptables new")
}
ipsec := &IPSec{
ipt: ipt,
log: log,
spiInfo: make(map[spiID]spiInfo),
spis: make(map[SPI]*spiInfo),
}
return ipsec, nil
}
// InitSALocal initializes inbound ipsec from remotePeer and triggers
// the initialization on remotePeer.
func (ipsec *IPSec) InitSALocal(localPeer, remotePeer mesh.PeerName, connUID uint64, localIP, remoteIP net.IP, udpPort int, sessionKey *[32]byte, initRemote func([]byte) error) error {
// ID of inbound SPI
spiID := getSPIId(remotePeer, localPeer, connUID)
ipsec.Lock()
defer ipsec.Unlock()
// Derive SA key
nonce, err := genNonce()
if err != nil {
return errors.Wrap(err, "generate nonce")
}
key, err := deriveKey(sessionKey[:], nonce, localPeer)
if err != nil {
return errors.Wrap(err, "derive key")
}
// Allocate SA
sa, err := netlink.XfrmStateAllocSpi(xfrmAllocSpiState(remoteIP, localIP))
if err != nil {
return errors.Wrap(err, fmt.Sprintf("ip xfrm state allocspi (in, %s, %s)", remoteIP, localIP))
}
// Use SPI generated by the kernel. The kernel ensures {dstIP, spi} to
// be unique.
spi := SPI(sa.Spi)
ipsec.log.Infof("ipsec: InitSALocal: %s -> %s :%d 0x%x", remoteIP, localIP, udpPort, spi)
// Create SA
if sa, err := xfrmState(remoteIP, localIP, spi, false, key); err == nil {
if err := netlink.XfrmStateUpdate(sa); err != nil {
return errors.Wrap(err, fmt.Sprintf("xfrm state update (in, %s, %s, 0x%x)", sa.Src, sa.Dst, sa.Spi))
}
} else {
return errors.Wrap(err, "new xfrm state (in)")
}
// Install iptables rules
if err := ipsec.installDropNonEncrypted(localIP, remoteIP, udpPort, spi); err != nil {
return errors.Wrap(err, fmt.Sprintf("install protecting rules (%s, %s, %d, 0x%x)", localIP, remoteIP, udpPort, spi))
}
si := spiInfo{spi: spi, isDirOut: false}
ipsec.spiInfo[spiID] = si
ipsec.spis[spi] = &si
// Trigger the initialization on the remote peer
msg := &msgInitSARemote{nonce, spi}
if err := initRemote(msg.serialize()); err != nil {
return errors.Wrap(err, "send InitSARemote")
}
return nil
}
// InitSARemote initializes outbound ipsec to remotePeer.
// Triggered by remotePeer.
func (ipsec *IPSec) InitSARemote(msgInitSARemote []byte, localPeer, remotePeer mesh.PeerName, connUID uint64, localIP, remoteIP net.IP, udpPort int, sessionKey *[32]byte) error {
// ID of outbound SPI
spiID := getSPIId(localPeer, remotePeer, connUID)
msg, err := deserializeMsgInitSARemote(msgInitSARemote)
if err != nil {
return errors.Wrap(err, "deserialize InitSARemote")
}
spi := msg.spi
ipsec.Lock()
defer ipsec.Unlock()
ipsec.log.Infof("ipsec: InitSARemote: %s -> %s :%d 0x%x", localIP, remoteIP, udpPort, spi)
// Derive SA key by using the received nonce
key, err := deriveKey(sessionKey[:], msg.nonce, remotePeer)
if err != nil {
return errors.Wrap(err, "derive key")
}
// Create SA
if sa, err := xfrmState(localIP, remoteIP, spi, true, key); err == nil {
if err := netlink.XfrmStateAdd(sa); err != nil {
return errors.Wrap(err, fmt.Sprintf("xfrm state update (out, %s, %s, 0x%x)", sa.Src, sa.Dst, sa.Spi))
}
} else {
return errors.Wrap(err, "new xfrm state (out)")
}
// Create or update SP
sp := xfrmPolicy(localIP, remoteIP, spi)
if err := netlink.XfrmPolicyUpdate(sp); err != nil {
return errors.Wrap(err, fmt.Sprintf("xfrm policy update (%s, %s, 0x%x)", localIP, remoteIP, spi))
}
si := spiInfo{spi: spi, isDirOut: true}
ipsec.spiInfo[spiID] = si
ipsec.spis[spi] = &si
return nil
}
// Destroy destroys any (inbound / outbound) ipsec establishment between the peers.
func (ipsec *IPSec) Destroy(localPeer, remotePeer mesh.PeerName, connUID uint64, localIP, remoteIP net.IP, udpPort int) error {
outSPIID := getSPIId(localPeer, remotePeer, connUID)
inSPIID := getSPIId(remotePeer, localPeer, connUID)
ipsec.Lock()
defer ipsec.Unlock()
// Destroy inbound
if inSPIInfo, ok := ipsec.spiInfo[inSPIID]; ok {
ipsec.log.Infof("ipsec: destroy: in %s -> %s 0x%x", remoteIP, localIP, inSPIInfo.spi)
inSPI := inSPIInfo.spi
inSA := &netlink.XfrmState{
Src: remoteIP,
Dst: localIP,
Proto: netlink.XFRM_PROTO_ESP,
Spi: int(inSPI),
}
if err := netlink.XfrmStateDel(inSA); err != nil {
ipsec.log.Warnf("ipsec: xfrm state del (in, %s, %s, 0x%x) failed: %s", inSA.Src, inSA.Dst, inSA.Spi, err)
}
if err := ipsec.removeDropNonEncrypted(localIP, remoteIP, udpPort, inSPI); err != nil {
ipsec.log.Warnf("ipsec: remove protecting rules (%s, %s, %d, 0x%x) failed: %s", localIP, remoteIP, udpPort, inSPI, err)
}
delete(ipsec.spiInfo, inSPIID)
delete(ipsec.spis, inSPI)
}
// Destroy outbound
if outSPIInfo, ok := ipsec.spiInfo[outSPIID]; ok {
ipsec.log.Infof("ipsec: destroy: out %s -> %s 0x%x", localIP, remoteIP, outSPIInfo.spi)
if err := netlink.XfrmPolicyDel(xfrmPolicy(localIP, remoteIP, outSPIInfo.spi)); err != nil {
ipsec.log.Warnf("ipsec: xfrm policy del (%s, %s, 0x%x) failed: %s", localIP, remoteIP, outSPIInfo.spi, err)
}
outSA := &netlink.XfrmState{
Src: localIP,
Dst: remoteIP,
Proto: netlink.XFRM_PROTO_ESP,
Spi: int(outSPIInfo.spi),
}
if err := netlink.XfrmStateDel(outSA); err != nil {
ipsec.log.Warnf("ipsec: xfrm state del (out, %s, %s, 0x%x) failed: %s", outSA.Src, outSA.Dst, outSA.Spi, err)
}
delete(ipsec.spiInfo, outSPIID)
delete(ipsec.spis, outSPIInfo.spi)
}
return nil
}
// Flush removes all policies/SAs established by us. Also, it removes chains and
// rules of iptables.
//
// If destroy is true, the chains and the rules won't be re-created.
func (ipsec *IPSec) Flush(destroy bool) error {
ipsec.Lock()
defer ipsec.Unlock()
policies, err := netlink.XfrmPolicyList(syscall.AF_INET)
if err != nil {
return errors.Wrap(err, "xfrm policy list")
}
for _, p := range policies {
if p.Mark != nil && p.Mark.Value == mark && len(p.Tmpls) != 0 {
spi := SPI(p.Tmpls[0].Spi)
if err := netlink.XfrmPolicyDel(&p); err != nil {
return errors.Wrap(err, fmt.Sprintf("xfrm policy del (%s, %s, 0x%x)", p.Src, p.Dst, spi))
}
}
}
states, err := netlink.XfrmStateList(syscall.AF_INET)
if err != nil {
return errors.Wrap(err, "xfrm state list")
}
for _, s := range states {
if _, ok := ipsec.spis[SPI(s.Spi)]; ok {
if err := netlink.XfrmStateDel(&s); err != nil {
return errors.Wrap(err, fmt.Sprintf("xfrm state list (%s, %s, 0x%x)", s.Src, s.Dst, s.Spi))
}
}
}
if err := ipsec.resetIPTables(destroy); err != nil {
return errors.Wrap(err, "reset ip tables")
}
return nil
}
// iptables
type chain struct {
table string
chain string
}
type rule struct {
table string
chain string
rulespec []string
unique bool
}
func (ipsec *IPSec) clearChains(chains []chain) error {
for _, c := range chains {
if err := ipsec.ipt.ClearChain(c.table, c.chain); err != nil {
return errors.Wrap(err, fmt.Sprintf("iptables clear chain (%s, %s)", c.table, c.chain))
}
}
return nil
}
func (ipsec *IPSec) deleteChains(chains []chain) error {
for _, c := range chains {
if err := ipsec.ipt.DeleteChain(c.table, c.chain); err != nil {
return errors.Wrap(err, fmt.Sprintf("iptables delete chain (%s, %s)", c.table, c.chain))
}
}
return nil
}
func (ipsec *IPSec) resetRules(rules []rule, destroy bool) error {
for _, r := range rules {
ok, err := ipsec.ipt.Exists(r.table, r.chain, r.rulespec...)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("iptables exists rule (%s, %s, %s)", r.table, r.chain, r.rulespec))
}
switch {
case !destroy && !ok:
if err := ipsec.ipt.Append(r.table, r.chain, r.rulespec...); err != nil {
return errors.Wrap(err, fmt.Sprintf("iptables append rule (%s, %s, %s)", r.table, r.chain, r.rulespec))
}
case destroy && ok:
if err := ipsec.ipt.Delete(r.table, r.chain, r.rulespec...); err != nil {
return errors.Wrap(err, fmt.Sprintf("iptables delete rule (%s, %s, %s)", r.table, r.chain, r.rulespec))
}
}
}
return nil
}
func (ipsec *IPSec) resetIPTables(destroy bool) error {
chains := []chain{
{tableMangle, chainIn},
{tableMangle, chainInMark},
{tableFilter, chainIn},
{tableMangle, chainOut},
{tableMangle, chainOutMark},
}
rules := []rule{
{tableMangle, "INPUT", []string{"-j", chainIn}, true},
{tableMangle, chainInMark, []string{"-j", "MARK", "--set-xmark", markStr}, true},
{tableFilter, "INPUT", []string{"-j", chainIn}, true},
{tableMangle, "OUTPUT", []string{"-j", chainOut}, true},
{tableMangle, chainOutMark, []string{"-j", "MARK", "--set-xmark", markStr}, true},
{tableFilter, "OUTPUT",
[]string{
"!", "-p", "esp",
"-m", "policy", "--dir", "out", "--pol", "none",
"-m", "mark", "--mark", markStr,
"-j", "DROP"}, true},
}
if err := ipsec.clearChains(chains); err != nil {
return err
}
if err := ipsec.resetRules(rules, destroy); err != nil {
return err
}
if destroy {
if err := ipsec.deleteChains(chains); err != nil {
return err
}
}
return nil
}
func ruleMarkInboundESP(srcIP, dstIP net.IP, inSPI SPI) rule {
return rule{tableMangle, chainIn,
[]string{
"-s", dstIP.String(), "-d", srcIP.String(),
"-p", "esp",
"-m", "esp", "--espspi", "0x" + strconv.FormatUint(uint64(inSPI), 16),
"-j", chainInMark,
}, true}
}
func rulesDropNonEncrypted(srcIP, dstIP net.IP, udpPort int, inSPI SPI) []rule {
udpPortStr := strconv.FormatUint(uint64(udpPort), 10)
return []rule{
ruleMarkInboundESP(srcIP, dstIP, inSPI),
{tableFilter, chainIn,
[]string{
"-s", dstIP.String(), "-d", srcIP.String(),
"-p", "udp", "--dport", udpPortStr,
"-m", "mark", "!", "--mark", markStr,
"-j", "DROP",
}, false},
{tableMangle, chainOut,
[]string{
"-s", srcIP.String(), "-d", dstIP.String(),
"-p", "udp", "--dport", udpPortStr,
"-j", chainOutMark,
}, false},
}
}
func (ipsec *IPSec) installDropNonEncrypted(srcIP, dstIP net.IP, udpPort int, inSPI SPI) error {
rules := rulesDropNonEncrypted(srcIP, dstIP, udpPort, inSPI)
for _, r := range rules {
appendFunc := ipsec.ipt.Append
if r.unique {
appendFunc = ipsec.ipt.AppendUnique
}
if err := appendFunc(r.table, r.chain, r.rulespec...); err != nil {
return errors.Wrap(err, fmt.Sprintf("iptables append (%s, %s, %s)", r.table, r.chain, r.rulespec))
}
}
return nil
}
func (ipsec *IPSec) removeDropNonEncrypted(srcIP, dstIP net.IP, udpPort int, inSPI SPI) error {
rules := rulesDropNonEncrypted(srcIP, dstIP, udpPort, inSPI)
if err := ipsec.resetRules(rules, true); err != nil {
return err
}
return nil
}
func (ipsec *IPSec) removeDropNonEncryptedInbound(srcIP, dstIP net.IP, inSPI SPI) error {
r := ruleMarkInboundESP(srcIP, dstIP, inSPI)
if err := ipsec.ipt.Delete(r.table, r.chain, r.rulespec...); err != nil {
return errors.Wrap(err, fmt.Sprintf("iptables delete unique (%s, %s, %s)", r.table, r.chain, r.rulespec))
}
return nil
}
// xfrm
func xfrmAllocSpiState(srcIP, dstIP net.IP) *netlink.XfrmState {
return &netlink.XfrmState{
Src: srcIP,
Dst: dstIP,
Proto: netlink.XFRM_PROTO_ESP,
Mode: netlink.XFRM_MODE_TRANSPORT,
ReplayWindow: 256,
ESN: true,
}
}
func xfrmState(srcIP, dstIP net.IP, spi SPI, isDirOut bool, key []byte) (*netlink.XfrmState, error) {
if len(key) != keySize {
return nil, fmt.Errorf("key should be %d bytes long", keySize)
}
state := xfrmAllocSpiState(srcIP, dstIP)
state.Spi = int(spi)
state.Aead = &netlink.XfrmStateAlgo{
Name: "rfc4106(gcm(aes))",
Key: key,
ICVLen: 128,
}
return state, nil
}
func xfrmPolicy(srcIP, dstIP net.IP, spi SPI) *netlink.XfrmPolicy {
ipMask := []byte{0xff, 0xff, 0xff, 0xff} // /32
return &netlink.XfrmPolicy{
Src: &net.IPNet{IP: srcIP, Mask: ipMask},
Dst: &net.IPNet{IP: dstIP, Mask: ipMask},
Proto: syscall.IPPROTO_UDP,
Dir: netlink.XFRM_DIR_OUT,
Mark: &netlink.XfrmMark{
Value: mark,
Mask: mark,
},
Tmpls: []netlink.XfrmPolicyTmpl{
{
Src: srcIP,
Dst: dstIP,
Proto: netlink.XFRM_PROTO_ESP,
Mode: netlink.XFRM_MODE_TRANSPORT,
Spi: int(spi),
},
},
}
}
// Key derivation
func genNonce() ([]byte, error) {
buf := make([]byte, nonceSize)
n, err := rand.Read(buf)
if err != nil {
return nil, fmt.Errorf("crypto rand failed: %s", err)
}
if n != nonceSize {
return nil, fmt.Errorf("not enough of random data: %d", n)
}
return buf, nil
}
func deriveKey(sessionKey []byte, nonce []byte, peerName mesh.PeerName) ([]byte, error) {
key := make([]byte, keySize)
info := make([]byte, 8)
binary.BigEndian.PutUint64(info, uint64(peerName))
hkdf := hkdf.New(sha256.New, sessionKey, nonce, info)
n, err := io.ReadFull(hkdf, key)
if err != nil {
return nil, err
}
if n != keySize {
return nil, fmt.Errorf("derived too short key: %d", n)
}
return key, nil
}
// Protocol Messages
type msgInitSARemote struct {
nonce []byte
spi SPI
}
func deserializeMsgInitSARemote(b []byte) (*msgInitSARemote, error) {
if len(b) == 0 {
return nil, fmt.Errorf("empty msg")
}
msg := &msgInitSARemote{}
if len(b) != msg.size() {
return nil, fmt.Errorf("invalid payload size: %d", len(b))
}
msg.nonce = make([]byte, nonceSize)
copy(msg.nonce, b[:nonceSize])
b = b[nonceSize:]
msg.spi = SPI(binary.BigEndian.Uint32(b))
return msg, nil
}
func (msg *msgInitSARemote) size() int {
return nonceSize + 32 // SPI
}
func (msg *msgInitSARemote) serialize() []byte {
b := make([]byte, msg.size())
copy(b[:nonceSize], msg.nonce)
binary.BigEndian.PutUint32(b[nonceSize:], uint32(msg.spi))
return b
}
+38
View File
@@ -0,0 +1,38 @@
package net
import (
"crypto/rand"
"crypto/sha256"
"net"
)
func RandomMAC() (net.HardwareAddr, error) {
mac := make([]byte, 6)
if _, err := rand.Read(mac); err != nil {
return nil, err
}
setUnicastAndLocal(mac)
return net.HardwareAddr(mac), nil
}
func MACfromUUID(uuid []byte) net.HardwareAddr {
hash := sha256.New()
// We salt the input just as a precaution to avoid clashes with
// other applications who might have had the bright idea of
// generating MACs in the same way.
hash.Write([]byte("9oBJ0Jmip-"))
hash.Write(uuid)
sum := hash.Sum(nil)
setUnicastAndLocal(sum)
return net.HardwareAddr(sum[:6])
}
// In the first byte of the MAC, the 'multicast' bit should be
// clear and 'locally administered' bit should be set.
func setUnicastAndLocal(mac []byte) {
mac[0] = (mac[0] & 0xFE) | 0x02
}
+116
View File
@@ -0,0 +1,116 @@
package net
import (
"encoding/json"
"fmt"
"net"
"os"
"strconv"
"github.com/vishvananda/netlink"
"github.com/vishvananda/netns"
)
type Dev struct {
Name string `json:"Name,omitempty"`
MAC net.HardwareAddr `json:"MAC,omitempty"`
CIDRs []*net.IPNet `json:"CIDRs,omitempty"`
}
func LinkToNetDev(link netlink.Link) (Dev, error) {
addrs, err := netlink.AddrList(link, netlink.FAMILY_V4)
if err != nil {
return Dev{}, err
}
netDev := Dev{Name: link.Attrs().Name, MAC: link.Attrs().HardwareAddr}
for _, addr := range addrs {
netDev.CIDRs = append(netDev.CIDRs, addr.IPNet)
}
return netDev, nil
}
// ConnectedToBridgeVethPeerIds returns peer indexes of veth links connected to
// the given bridge. The peer index is used to query from a container netns
// whether the container is connected to the bridge.
func ConnectedToBridgeVethPeerIds(bridgeName string) ([]int, error) {
var ids []int
br, err := netlink.LinkByName(bridgeName)
if err != nil {
return nil, err
}
links, err := netlink.LinkList()
if err != nil {
return nil, err
}
for _, link := range links {
if _, isveth := link.(*netlink.Veth); isveth && link.Attrs().MasterIndex == br.Attrs().Index {
peerID := link.Attrs().ParentIndex
if peerID == 0 {
// perhaps running on an older kernel where ParentIndex doesn't work.
// as fall-back, assume the peers are consecutive
peerID = link.Attrs().Index - 1
}
ids = append(ids, peerID)
}
}
return ids, nil
}
// Lookup the weave interface of a container
func GetWeaveNetDevs(processID int) ([]Dev, error) {
peerIDs, err := ConnectedToBridgeVethPeerIds("weave")
if err != nil {
return nil, err
}
return GetNetDevsByVethPeerIds(processID, peerIDs)
}
func GetNetDevsByVethPeerIds(processID int, peerIDs []int) ([]Dev, error) {
// Bail out if this container is running in the root namespace
netnsRoot, err := netns.GetFromPid(1)
if err != nil {
return nil, fmt.Errorf("unable to open root namespace: %s", err)
}
defer netnsRoot.Close()
netnsContainer, err := netns.GetFromPid(processID)
if err != nil {
// Unable to find a namespace for this process - just return nothing
if os.IsNotExist(err) {
return nil, nil
}
return nil, fmt.Errorf("unable to open process %d namespace: %s", processID, err)
}
defer netnsContainer.Close()
if netnsRoot.Equal(netnsContainer) {
return nil, nil
}
var netdevs []Dev
peersStr := make([]string, len(peerIDs))
for i, id := range peerIDs {
peersStr[i] = strconv.Itoa(id)
}
nds, err := WithNetNSByPid(processID, "list-netdevs", peersStr...)
if err != nil {
return nil, fmt.Errorf("list-netdevs failed: %s", err)
}
err = json.Unmarshal(nds, &netdevs)
return netdevs, err
}
// Get the weave bridge interface.
// NB: Should be called from the root network namespace.
func GetBridgeNetDev(bridgeName string) (Dev, error) {
link, err := netlink.LinkByName(bridgeName)
if err != nil {
return Dev{}, err
}
return LinkToNetDev(link)
}
+50 -3
View File
@@ -1,13 +1,31 @@
package net
import (
"bytes"
"errors"
"fmt"
"os/exec"
"runtime"
"github.com/vishvananda/netlink"
"github.com/vishvananda/netns"
)
func WithNetNS(ns netns.NsHandle, work func() error) error {
var ErrLinkNotFound = errors.New("Link not found")
// NB: The following function is unsafe, because:
// - It changes a network namespace (netns) of an OS thread which runs
// the function. During execution, the Go runtime might clone a new OS thread
// for scheduling other go-routines, thus they might end up running in
// a "wrong" netns.
// - runtime.LockOSThread does not guarantee that a spawned go-routine on
// the locked thread will be run by it. Thus, the work function is
// not allowed to spawn any go-routine which is dependent on the given netns.
// Please see https://github.com/weaveworks/weave/issues/2388#issuecomment-228365069
// for more details and make sure that you understand the implications before
// using the function!
func WithNetNSUnsafe(ns netns.NsHandle, work func() error) error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
@@ -26,12 +44,41 @@ func WithNetNS(ns netns.NsHandle, work func() error) error {
return err
}
func WithNetNSLink(ns netns.NsHandle, ifName string, work func(link netlink.Link) error) error {
return WithNetNS(ns, func() error {
func WithNetNSLinkUnsafe(ns netns.NsHandle, ifName string, work func(link netlink.Link) error) error {
return WithNetNSUnsafe(ns, func() error {
link, err := netlink.LinkByName(ifName)
if err != nil {
if err.Error() == errors.New("Link not found").Error() {
return ErrLinkNotFound
}
return err
}
return work(link)
})
}
var WeaveUtilCmd = "weaveutil"
// A safe version of WithNetNS* which creates a process executing
// "nsenter --net=<ns-path> weaveutil <cmd> [args]".
func WithNetNS(nsPath string, cmd string, args ...string) ([]byte, error) {
var stdout, stderr bytes.Buffer
args = append([]string{"--net=" + nsPath, WeaveUtilCmd, cmd}, args...)
c := exec.Command("nsenter", args...)
c.Stdout = &stdout
c.Stderr = &stderr
if err := c.Run(); err != nil {
return nil, fmt.Errorf("%s: %s", string(stderr.Bytes()), err)
}
return stdout.Bytes(), nil
}
func WithNetNSByPid(pid int, cmd string, args ...string) ([]byte, error) {
return WithNetNS(NSPathByPid(pid), cmd, args...)
}
func NSPathByPid(pid int) string {
return fmt.Sprintf("/proc/%d/ns/net", pid)
}
+2 -2
View File
@@ -13,7 +13,7 @@ import (
func CheckNetworkFree(subnet *net.IPNet, ignoreIfaceNames map[string]struct{}) 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)
return fmt.Errorf("Network %s overlaps with existing route %s on host", subnet, route.Dst)
}
return nil
})
@@ -29,7 +29,7 @@ func overlaps(n1, n2 *net.IPNet) bool {
func CheckAddressOverlap(addr net.IP, ignoreIfaceNames map[string]struct{}) 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)
return fmt.Errorf("Address %s overlaps with existing route %s on host", addr, route.Dst)
}
return nil
})
+84
View File
@@ -0,0 +1,84 @@
package net
import (
"errors"
"io/ioutil"
"net"
"os"
"github.com/weaveworks/mesh"
"github.com/weaveworks/weave/db"
)
func getOldStyleSystemUUID() ([]byte, error) {
uuid, err := ioutil.ReadFile("/sys/class/dmi/id/product_uuid")
if os.IsNotExist(err) {
uuid, err = ioutil.ReadFile("/sys/hypervisor/uuid")
}
return uuid, err
}
func getSystemUUID(hostRoot string) ([]byte, error) {
uuid, err := getOldStyleSystemUUID()
if err != nil && !os.IsNotExist(err) {
return nil, err
}
machineid, err := ioutil.ReadFile(hostRoot + "/etc/machine-id")
if os.IsNotExist(err) {
machineid, err = ioutil.ReadFile(hostRoot + "/var/lib/dbus/machine-id")
}
if err != nil && !os.IsNotExist(err) {
return nil, err
}
if len(uuid) == 0 && len(machineid) == 0 {
return nil, errors.New("All system IDs are blank")
}
return append(machineid, uuid...), nil
}
func getPersistedPeerName(pathName string) (mesh.PeerName, error) {
d, err := db.NewBoltDBReadOnly(pathName)
if err != nil {
return mesh.UnknownPeerName, err
}
defer d.Close()
var peerName mesh.PeerName
nameFound, err := d.Load(db.NameIdent, &peerName)
if err != nil || !nameFound {
return mesh.UnknownPeerName, err
}
return peerName, nil
}
// GetSystemPeerName returns an ID derived from concatenated machine-id
// (either systemd or dbus), the system (aka bios) UUID and the
// hypervisor UUID. It is tweaked and formatted to be usable as a mac address
func GetSystemPeerName(dbPrefix, hostRoot string) (string, error) {
// Check if we have a persisted name that matches the old-style ID for this host
if oldUUID, err := getOldStyleSystemUUID(); err == nil {
pathName := dbPrefix + db.FileName
if _, err := os.Stat(pathName); err == nil {
persistedPeerName, err := getPersistedPeerName(pathName)
if err != nil && !os.IsNotExist(err) {
return "", err
}
if persistedPeerName == mesh.PeerNameFromBin(MACfromUUID(oldUUID)) {
return persistedPeerName.String(), nil
}
}
} else if !os.IsNotExist(err) {
return "", err
}
var mac net.HardwareAddr
if uuid, err := getSystemUUID(hostRoot); err == nil {
mac = MACfromUUID(uuid)
} else if !os.IsNotExist(err) {
return "", err
} else {
mac, err = RandomMAC()
if err != nil {
return "", err
}
}
return mac.String(), nil
}
+125 -19
View File
@@ -3,8 +3,11 @@ package net
import (
"fmt"
"net"
"strings"
"syscall"
"time"
"github.com/coreos/go-iptables/iptables"
"github.com/j-keck/arping"
"github.com/vishvananda/netlink"
"github.com/vishvananda/netns"
@@ -103,16 +106,26 @@ const (
vethPrefix = "v" + VethName // starts with "veth" to suppress UI notifications
)
func interfaceExistsInNamespace(ns netns.NsHandle, ifName string) bool {
err := WithNetNS(ns, func() error {
_, err := netlink.LinkByName(ifName)
return err
})
func interfaceExistsInNamespace(netNSPath string, ifName string) bool {
_, err := WithNetNS(netNSPath, "check-iface", ifName)
return err == nil
}
func AttachContainer(ns netns.NsHandle, id, ifName, bridgeName string, mtu int, withMulticastRoute bool, cidrs []*net.IPNet, keepTXOn bool) error {
if !interfaceExistsInNamespace(ns, ifName) {
// NB: This function can be used only by a process that terminates immediately
// after calling the function as it changes netns via WithNetNSLinkUnsafe.
func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMulticastRoute bool, cidrs []*net.IPNet, keepTXOn bool) error {
ns, err := netns.GetFromPath(netNSPath)
if err != nil {
return err
}
defer ns.Close()
ipt, err := iptables.New()
if err != nil {
return err
}
if !interfaceExistsInNamespace(netNSPath, ifName) {
maxIDLen := IFNAMSIZ - 1 - len(vethPrefix+"pl")
if len(id) > maxIDLen {
id = id[:maxIDLen] // trim passed ID if too long
@@ -122,15 +135,7 @@ func AttachContainer(ns netns.NsHandle, id, ifName, bridgeName string, mtu int,
if err := netlink.LinkSetNsFd(veth, int(ns)); err != nil {
return fmt.Errorf("failed to move veth to container netns: %s", err)
}
if err := WithNetNS(ns, func() error {
if err := netlink.LinkSetName(veth, ifName); err != nil {
return err
}
if err := ConfigureARPCache(ifName); err != nil {
return err
}
return nil
}); err != nil {
if _, err := WithNetNS(netNSPath, "setup-iface", peerName, ifName); err != nil {
return fmt.Errorf("error setting up interface: %s", err)
}
return nil
@@ -140,11 +145,26 @@ func AttachContainer(ns netns.NsHandle, id, ifName, bridgeName string, mtu int,
}
}
if err := WithNetNSLink(ns, ifName, func(veth netlink.Link) error {
if err := WithNetNSLinkUnsafe(ns, ifName, func(veth netlink.Link) error {
newAddresses, err := AddAddresses(veth, cidrs)
if err != nil {
return err
}
// Add multicast ACCEPT rules for new subnets
for _, ipnet := range newAddresses {
acceptRule := []string{"-i", ifName, "-s", subnet(ipnet), "-d", "224.0.0.0/4", "-j", "ACCEPT"}
exists, err := ipt.Exists("filter", "INPUT", acceptRule...)
if err != nil {
return err
}
if !exists {
if err := ipt.Insert("filter", "INPUT", 1, acceptRule...); err != nil {
return err
}
}
}
if err := netlink.LinkSetUp(veth); err != nil {
return err
}
@@ -176,8 +196,21 @@ func AttachContainer(ns netns.NsHandle, id, ifName, bridgeName string, mtu int,
return nil
}
func DetachContainer(ns netns.NsHandle, id, ifName string, cidrs []*net.IPNet) error {
return WithNetNSLink(ns, ifName, func(veth netlink.Link) error {
// NB: This function can be used only by a process that terminates immediately
// after calling the function as it changes netns via WithNetNSLinkUnsafe.
func DetachContainer(netNSPath, id, ifName string, cidrs []*net.IPNet) error {
ns, err := netns.GetFromPath(netNSPath)
if err != nil {
return err
}
defer ns.Close()
ipt, err := iptables.New()
if err != nil {
return err
}
return WithNetNSLinkUnsafe(ns, ifName, func(veth netlink.Link) error {
existingAddrs, err := netlink.AddrList(veth, netlink.FAMILY_V4)
if err != nil {
return fmt.Errorf("failed to get IP address for %q: %v", veth.Attrs().Name, err)
@@ -194,7 +227,31 @@ func DetachContainer(ns netns.NsHandle, id, ifName string, cidrs []*net.IPNet) e
if err != nil {
return fmt.Errorf("failed to get IP address for %q: %v", veth.Attrs().Name, err)
}
// Remove multicast ACCEPT rules for subnets we no longer have addresses in
subnets := subnets(addrs)
rules, err := ipt.List("filter", "INPUT")
if err != nil {
return err
}
for _, rule := range rules {
ps := strings.Split(rule, " ")
if len(ps) == 10 &&
ps[0] == "-A" && ps[2] == "-s" && ps[4] == "-d" && ps[5] == "224.0.0.0/4" &&
ps[6] == "-i" && ps[7] == ifName && ps[8] == "-j" && ps[9] == "ACCEPT" {
if _, found := subnets[ps[3]]; !found {
if err := ipt.Delete("filter", "INPUT", ps[2:]...); err != nil {
return err
}
}
}
}
if len(addrs) == 0 { // all addresses gone: remove the interface
if err := ipt.Delete("filter", "INPUT", "-i", ifName, "-d", "224.0.0.0/4", "-j", "DROP"); err != nil {
return err
}
if err := netlink.LinkDel(veth); err != nil {
return err
}
@@ -202,3 +259,52 @@ func DetachContainer(ns netns.NsHandle, id, ifName string, cidrs []*net.IPNet) e
return nil
})
}
func subnet(ipn *net.IPNet) string {
ones, _ := ipn.Mask.Size()
return fmt.Sprintf("%s/%d", ipn.IP.Mask(ipn.Mask).String(), ones)
}
func subnets(addrs []netlink.Addr) map[string]struct{} {
subnets := make(map[string]struct{})
for _, addr := range addrs {
subnets[subnet(addr.IPNet)] = struct{}{}
}
return subnets
}
func addNatRule(ipt *iptables.IPTables, rulespec ...string) error {
// Loop until we get an exit code other than "temporarily unavailable"
for {
if err := ipt.AppendUnique("nat", "WEAVE", rulespec...); err != nil {
if ierr, ok := err.(*iptables.Error); ok {
if status, ok := ierr.ExitError.Sys().(syscall.WaitStatus); ok {
// (magic exit code 4 found in iptables source code; undocumented)
if status.ExitStatus() == 4 {
continue
}
}
}
return err
}
return nil
}
}
func ExposeNAT(ipnet net.IPNet) error {
ipt, err := iptables.New()
if err != nil {
return err
}
cidr := ipnet.String()
if err := addNatRule(ipt, "-s", cidr, "-d", "224.0.0.0/4", "-j", "RETURN"); err != nil {
return err
}
if err := addNatRule(ipt, "-d", cidr, "!", "-s", cidr, "-j", "MASQUERADE"); err != nil {
return err
}
if err := addNatRule(ipt, "-s", cidr, "!", "-d", cidr, "-j", "MASQUERADE"); err != nil {
return err
}
return nil
}
+114
View File
@@ -0,0 +1,114 @@
package npc
import (
"fmt"
"k8s.io/client-go/pkg/api"
extnapi "k8s.io/client-go/pkg/apis/extensions/v1beta1"
"k8s.io/client-go/pkg/util/intstr"
"github.com/weaveworks/weave/npc/ipset"
)
func (ns *ns) analysePolicy(policy *extnapi.NetworkPolicy) (
rules map[string]*ruleSpec,
nsSelectors, podSelectors map[string]*selectorSpec,
err error) {
nsSelectors = make(map[string]*selectorSpec)
podSelectors = make(map[string]*selectorSpec)
rules = make(map[string]*ruleSpec)
dstSelector, err := newSelectorSpec(&policy.Spec.PodSelector, ns.name, ipset.HashIP)
if err != nil {
return nil, nil, nil, err
}
podSelectors[dstSelector.key] = dstSelector
for _, ingressRule := range policy.Spec.Ingress {
if ingressRule.Ports != nil && len(ingressRule.Ports) == 0 {
// Ports is empty, this rule matches no ports (no traffic matches).
continue
}
if ingressRule.From != nil && len(ingressRule.From) == 0 {
// From is empty, this rule matches no sources (no traffic matches).
continue
}
if ingressRule.From == nil {
// From is not provided, this rule matches all sources (traffic not restricted by source).
if ingressRule.Ports == nil {
// Ports is not provided, this rule matches all ports (traffic not restricted by port).
rule := newRuleSpec(nil, nil, dstSelector, nil)
rules[rule.key] = rule
} else {
// Ports is present and contains at least one item, then this rule allows traffic
// only if the traffic matches at least one port in the ports list.
withNormalisedProtoAndPort(ingressRule.Ports, func(proto, port string) {
rule := newRuleSpec(&proto, nil, dstSelector, &port)
rules[rule.key] = rule
})
}
} else {
// From is present and contains at least on item, this rule allows traffic only if the
// traffic matches at least one item in the from list.
for _, peer := range ingressRule.From {
var srcSelector *selectorSpec
if peer.PodSelector != nil {
srcSelector, err = newSelectorSpec(peer.PodSelector, ns.name, ipset.HashIP)
if err != nil {
return nil, nil, nil, err
}
podSelectors[srcSelector.key] = srcSelector
}
if peer.NamespaceSelector != nil {
srcSelector, err = newSelectorSpec(peer.NamespaceSelector, "", ipset.ListSet)
if err != nil {
return nil, nil, nil, err
}
nsSelectors[srcSelector.key] = srcSelector
}
if ingressRule.Ports == nil {
// Ports is not provided, this rule matches all ports (traffic not restricted by port).
rule := newRuleSpec(nil, srcSelector, dstSelector, nil)
rules[rule.key] = rule
} else {
// Ports is present and contains at least one item, then this rule allows traffic
// only if the traffic matches at least one port in the ports list.
withNormalisedProtoAndPort(ingressRule.Ports, func(proto, port string) {
rule := newRuleSpec(&proto, srcSelector, dstSelector, &port)
rules[rule.key] = rule
})
}
}
}
}
return rules, nsSelectors, podSelectors, nil
}
func withNormalisedProtoAndPort(npps []extnapi.NetworkPolicyPort, f func(proto, port string)) {
for _, npp := range npps {
// If no proto is specified, default to TCP
proto := string(api.ProtocolTCP)
if npp.Protocol != nil {
proto = string(*npp.Protocol)
}
// If no port is specified, match any port. Let iptables executable handle
// service name resolution
port := "0:65535"
if npp.Port != nil {
switch npp.Port.Type {
case intstr.Int:
port = fmt.Sprintf("%d", npp.Port.IntVal)
case intstr.String:
port = npp.Port.StrVal
}
}
f(proto, port)
}
}
+40
View File
@@ -0,0 +1,40 @@
package npc
// These types are defined in https://github.com/kubernetes/kubernetes/blob/master/docs/proposals/network-policy.md
// but not in the k8s API yet. Copies are included here for decoding the `net.beta.kubernetes.io/network-policy`
// annotation specified in the above document.
type IngressIsolationPolicy string
const (
// Deny all ingress traffic to pods in this namespace. Ingress means
// any incoming traffic to pods, whether that be from other pods within this namespace
// or any source outside of this namespace.
DefaultDeny IngressIsolationPolicy = "DefaultDeny"
)
// Standard NamespaceSpec object, modified to include a new
// NamespaceNetworkPolicy field.
type NamespaceSpec struct {
// This is a pointer so that it can be left undefined.
NetworkPolicy *NamespaceNetworkPolicy `json:"networkPolicy,omitempty"`
}
type NamespaceNetworkPolicy struct {
// Ingress configuration for this namespace. This config is
// applied to all pods within this namespace. For now, only
// ingress is supported. This field is optional - if not
// defined, then the cluster default for ingress is applied.
Ingress *NamespaceIngressPolicy `json:"ingress,omitempty"`
}
// Configuration for ingress to pods within this namespace.
// For now, this only supports specifying an isolation policy.
type NamespaceIngressPolicy struct {
// The isolation policy to apply to pods in this namespace.
// Currently this field only supports "DefaultDeny", but could
// be extended to support other policies in the future. When set to DefaultDeny,
// pods in this namespace are denied ingress traffic by default. When not defined,
// the cluster default ingress isolation policy is applied (currently allow all).
Isolation *IngressIsolationPolicy `json:"isolation,omitempty"`
}
+9
View File
@@ -0,0 +1,9 @@
package npc
const (
TableFilter = "filter"
MainChain = "WEAVE-NPC"
DefaultChain = "WEAVE-NPC-DEFAULT"
IngressChain = "WEAVE-NPC-INGRESS"
)
+173
View File
@@ -0,0 +1,173 @@
package npc
import (
"sync"
"github.com/coreos/go-iptables/iptables"
"github.com/pkg/errors"
coreapi "k8s.io/client-go/pkg/api/v1"
extnapi "k8s.io/client-go/pkg/apis/extensions/v1beta1"
"github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/npc/ipset"
)
type NetworkPolicyController interface {
AddNamespace(ns *coreapi.Namespace) error
UpdateNamespace(oldObj, newObj *coreapi.Namespace) error
DeleteNamespace(ns *coreapi.Namespace) error
AddPod(obj *coreapi.Pod) error
UpdatePod(oldObj, newObj *coreapi.Pod) error
DeletePod(obj *coreapi.Pod) error
AddNetworkPolicy(obj *extnapi.NetworkPolicy) error
UpdateNetworkPolicy(oldObj, newObj *extnapi.NetworkPolicy) error
DeleteNetworkPolicy(obj *extnapi.NetworkPolicy) error
}
type controller struct {
sync.Mutex
ipt *iptables.IPTables
ips ipset.Interface
nss map[string]*ns // ns name -> ns struct
nsSelectors *selectorSet // selector string -> nsSelector
}
func New(ipt *iptables.IPTables, ips ipset.Interface) NetworkPolicyController {
c := &controller{
ipt: ipt,
ips: ips,
nss: make(map[string]*ns)}
c.nsSelectors = newSelectorSet(ips, c.onNewNsSelector)
return c
}
func (npc *controller) onNewNsSelector(selector *selector) error {
for _, ns := range npc.nss {
if ns.namespace != nil {
if selector.matches(ns.namespace.ObjectMeta.Labels) {
if err := ns.ips.AddEntry(selector.spec.ipsetName, string(ns.allPods.ipsetName)); err != nil {
return err
}
}
}
}
return nil
}
func (npc *controller) withNS(name string, f func(ns *ns) error) error {
ns, found := npc.nss[name]
if !found {
newNs, err := newNS(name, npc.ipt, npc.ips, npc.nsSelectors)
if err != nil {
return err
}
npc.nss[name] = newNs
ns = newNs
}
if err := f(ns); err != nil {
return err
}
if ns.empty() {
if err := ns.destroy(); err != nil {
return err
}
delete(npc.nss, name)
}
return nil
}
func (npc *controller) AddPod(obj *coreapi.Pod) error {
npc.Lock()
defer npc.Unlock()
common.Log.Debugf("EVENT AddPod %s", js(obj))
return npc.withNS(obj.ObjectMeta.Namespace, func(ns *ns) error {
return errors.Wrap(ns.addPod(obj), "add pod")
})
}
func (npc *controller) UpdatePod(oldObj, newObj *coreapi.Pod) error {
npc.Lock()
defer npc.Unlock()
common.Log.Debugf("EVENT UpdatePod %s %s", js(oldObj), js(newObj))
return npc.withNS(oldObj.ObjectMeta.Namespace, func(ns *ns) error {
return errors.Wrap(ns.updatePod(oldObj, newObj), "update pod")
})
}
func (npc *controller) DeletePod(obj *coreapi.Pod) error {
npc.Lock()
defer npc.Unlock()
common.Log.Debugf("EVENT DeletePod %s", js(obj))
return npc.withNS(obj.ObjectMeta.Namespace, func(ns *ns) error {
return errors.Wrap(ns.deletePod(obj), "delete pod")
})
}
func (npc *controller) AddNetworkPolicy(obj *extnapi.NetworkPolicy) error {
npc.Lock()
defer npc.Unlock()
common.Log.Infof("EVENT AddNetworkPolicy %s", js(obj))
return npc.withNS(obj.ObjectMeta.Namespace, func(ns *ns) error {
return errors.Wrap(ns.addNetworkPolicy(obj), "add network policy")
})
}
func (npc *controller) UpdateNetworkPolicy(oldObj, newObj *extnapi.NetworkPolicy) error {
npc.Lock()
defer npc.Unlock()
common.Log.Infof("EVENT UpdateNetworkPolicy %s %s", js(oldObj), js(newObj))
return npc.withNS(oldObj.ObjectMeta.Namespace, func(ns *ns) error {
return errors.Wrap(ns.updateNetworkPolicy(oldObj, newObj), "update network policy")
})
}
func (npc *controller) DeleteNetworkPolicy(obj *extnapi.NetworkPolicy) error {
npc.Lock()
defer npc.Unlock()
common.Log.Infof("EVENT DeleteNetworkPolicy %s", js(obj))
return npc.withNS(obj.ObjectMeta.Namespace, func(ns *ns) error {
return errors.Wrap(ns.deleteNetworkPolicy(obj), "delete network policy")
})
}
func (npc *controller) AddNamespace(obj *coreapi.Namespace) error {
npc.Lock()
defer npc.Unlock()
common.Log.Infof("EVENT AddNamespace %s", js(obj))
return npc.withNS(obj.ObjectMeta.Name, func(ns *ns) error {
return errors.Wrap(ns.addNamespace(obj), "add namespace")
})
}
func (npc *controller) UpdateNamespace(oldObj, newObj *coreapi.Namespace) error {
npc.Lock()
defer npc.Unlock()
common.Log.Infof("EVENT UpdateNamespace %s %s", js(oldObj), js(newObj))
return npc.withNS(oldObj.ObjectMeta.Name, func(ns *ns) error {
return errors.Wrap(ns.updateNamespace(oldObj, newObj), "update namespace")
})
}
func (npc *controller) DeleteNamespace(obj *coreapi.Namespace) error {
npc.Lock()
defer npc.Unlock()
common.Log.Infof("EVENT DeleteNamespace %s", js(obj))
return npc.withNS(obj.ObjectMeta.Name, func(ns *ns) error {
return errors.Wrap(ns.deleteNamespace(obj), "delete namespace")
})
}
+69
View File
@@ -0,0 +1,69 @@
package ipset
import (
"os/exec"
"github.com/pkg/errors"
)
type Name string
type Type string
const (
ListSet = Type("list:set")
HashIP = Type("hash:ip")
)
type Interface interface {
Create(ipsetName Name, ipsetType Type) error
AddEntry(ipsetName Name, entry string) error
DelEntry(ipsetName Name, entry string) error
Flush(ipsetName Name) error
Destroy(ipsetName Name) error
FlushAll() error
DestroyAll() error
}
type ipset struct {
}
func New() Interface {
return &ipset{}
}
func (i *ipset) Create(ipsetName Name, ipsetType Type) error {
return doExec("create", string(ipsetName), string(ipsetType))
}
func (i *ipset) AddEntry(ipsetName Name, entry string) error {
return doExec("add", string(ipsetName), entry)
}
func (i *ipset) DelEntry(ipsetName Name, entry string) error {
return doExec("del", string(ipsetName), entry)
}
func (i *ipset) Flush(ipsetName Name) error {
return doExec("flush", string(ipsetName))
}
func (i *ipset) FlushAll() error {
return doExec("flush")
}
func (i *ipset) Destroy(ipsetName Name) error {
return doExec("destroy", string(ipsetName))
}
func (i *ipset) DestroyAll() error {
return doExec("destroy")
}
func doExec(args ...string) error {
if output, err := exec.Command("ipset", args...).CombinedOutput(); err != nil {
return errors.Wrapf(err, "ipset %v failed: %s", args, output)
}
return nil
}
+10
View File
@@ -0,0 +1,10 @@
package npc
import (
"encoding/json"
)
func js(v interface{}) string {
a, _ := json.Marshal(v)
return string(a)
}
+111
View File
@@ -0,0 +1,111 @@
package metrics
import (
"net/http"
"os"
"strconv"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcapgo"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/weaveworks/weave/common"
)
var (
blockedConnections = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "weavenpc_blocked_connections_total",
Help: "Connection attempts blocked by policy controller.",
},
[]string{"protocol", "dport"},
)
)
func gatherMetrics() {
pipe, err := os.Open("/var/log/ulogd.pcap")
if err != nil {
common.Log.Fatalf("Failed to open pcap: %v", err)
}
reader, err := pcapgo.NewReader(pipe)
if err != nil {
common.Log.Fatalf("Failed to read pcap header: %v", err)
}
for {
data, _, err := reader.ReadPacketData()
if err != nil {
common.Log.Fatalf("Failed to read pcap packet: %v", err)
}
packet := gopacket.NewPacket(data, layers.LayerTypeIPv4, gopacket.Default)
if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil {
tcp, _ := tcpLayer.(*layers.TCP)
if tcp.SYN && !tcp.ACK { // Only plain SYN constitutes a NEW TCP connection
blockedConnections.With(prometheus.Labels{"protocol": "tcp", "dport": strconv.Itoa(int(tcp.DstPort))}).Inc()
common.Log.Warnf("TCP connection from %v:%d to %v:%d blocked by Weave NPC.", srcIP(packet), tcp.SrcPort, dstIP(packet), tcp.DstPort)
continue
}
}
if udpLayer := packet.Layer(layers.LayerTypeUDP); udpLayer != nil {
udp, _ := udpLayer.(*layers.UDP)
blockedConnections.With(prometheus.Labels{"protocol": "udp", "dport": strconv.Itoa(int(udp.DstPort))}).Inc()
common.Log.Warnf("UDP connection from %v:%d to %v:%d blocked by Weave NPC.", srcIP(packet), udp.SrcPort, dstIP(packet), udp.DstPort)
continue
}
}
}
const unknownIP string = "<unknown IP>"
func srcIP(packet gopacket.Packet) string {
if layer := packet.Layer(layers.LayerTypeIPv4); layer != nil {
if ip, ok := layer.(*layers.IPv4); ok {
return ip.SrcIP.String()
}
}
if layer := packet.Layer(layers.LayerTypeIPv6); layer != nil {
if ip, ok := layer.(*layers.IPv6); ok {
return ip.SrcIP.String()
}
}
return unknownIP
}
func dstIP(packet gopacket.Packet) string {
if layer := packet.Layer(layers.LayerTypeIPv4); layer != nil {
if ip, ok := layer.(*layers.IPv4); ok {
return ip.DstIP.String()
}
}
if layer := packet.Layer(layers.LayerTypeIPv6); layer != nil {
if ip, ok := layer.(*layers.IPv6); ok {
return ip.DstIP.String()
}
}
return unknownIP
}
func Start(addr string) error {
if err := prometheus.Register(blockedConnections); err != nil {
return err
}
http.Handle("/metrics", promhttp.Handler())
go func() {
common.Log.Infof("Serving /metrics on %s", addr)
if err := http.ListenAndServe(addr, nil); err != nil {
common.Log.Fatalf("Failed to bind metrics server: %v", err)
}
}()
go gatherMetrics()
return nil
}
+338
View File
@@ -0,0 +1,338 @@
package npc
import (
"encoding/json"
"github.com/coreos/go-iptables/iptables"
"k8s.io/client-go/pkg/api/unversioned"
coreapi "k8s.io/client-go/pkg/api/v1"
extnapi "k8s.io/client-go/pkg/apis/extensions/v1beta1"
"k8s.io/client-go/pkg/types"
"k8s.io/client-go/pkg/util/uuid"
"github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/npc/ipset"
)
type ns struct {
ipt *iptables.IPTables // interface to iptables
ips ipset.Interface // interface to ipset
name string // k8s Namespace name
namespace *coreapi.Namespace // k8s Namespace object
pods map[types.UID]*coreapi.Pod // k8s Pod objects by UID
policies map[types.UID]*extnapi.NetworkPolicy // k8s NetworkPolicy objects by UID
uid types.UID // surrogate UID to own allPods selector
allPods *selectorSpec // hash:ip ipset of all pod IPs in this namespace
nsSelectors *selectorSet
podSelectors *selectorSet
rules *ruleSet
}
func newNS(name string, ipt *iptables.IPTables, ips ipset.Interface, nsSelectors *selectorSet) (*ns, error) {
allPods, err := newSelectorSpec(&unversioned.LabelSelector{}, name, ipset.HashIP)
if err != nil {
return nil, err
}
ns := &ns{
ipt: ipt,
ips: ips,
name: name,
pods: make(map[types.UID]*coreapi.Pod),
policies: make(map[types.UID]*extnapi.NetworkPolicy),
uid: uuid.NewUUID(),
allPods: allPods,
nsSelectors: nsSelectors,
rules: newRuleSet(ipt)}
ns.podSelectors = newSelectorSet(ips, ns.onNewPodSelector)
if err := ns.podSelectors.provision(ns.uid, nil, map[string]*selectorSpec{ns.allPods.key: ns.allPods}); err != nil {
return nil, err
}
return ns, nil
}
func (ns *ns) empty() bool {
return len(ns.pods) == 0 && len(ns.policies) == 0 && ns.namespace == nil
}
func (ns *ns) destroy() error {
if err := ns.podSelectors.deprovision(ns.uid, map[string]*selectorSpec{ns.allPods.key: ns.allPods}, nil); err != nil {
return err
}
return nil
}
func (ns *ns) onNewPodSelector(selector *selector) error {
for _, pod := range ns.pods {
if hasIP(pod) {
if selector.matches(pod.ObjectMeta.Labels) {
if err := selector.addEntry(pod.Status.PodIP); err != nil {
return err
}
}
}
}
return nil
}
func (ns *ns) addPod(obj *coreapi.Pod) error {
ns.pods[obj.ObjectMeta.UID] = obj
if !hasIP(obj) {
return nil
}
return ns.podSelectors.addToMatching(obj.ObjectMeta.Labels, obj.Status.PodIP)
}
func (ns *ns) updatePod(oldObj, newObj *coreapi.Pod) error {
delete(ns.pods, oldObj.ObjectMeta.UID)
ns.pods[newObj.ObjectMeta.UID] = newObj
if !hasIP(oldObj) && !hasIP(newObj) {
return nil
}
if hasIP(oldObj) && !hasIP(newObj) {
return ns.podSelectors.delFromMatching(oldObj.ObjectMeta.Labels, oldObj.Status.PodIP)
}
if !hasIP(oldObj) && hasIP(newObj) {
return ns.podSelectors.addToMatching(newObj.ObjectMeta.Labels, newObj.Status.PodIP)
}
if !equals(oldObj.ObjectMeta.Labels, newObj.ObjectMeta.Labels) ||
oldObj.Status.PodIP != newObj.Status.PodIP {
for _, ps := range ns.podSelectors.entries {
oldMatch := ps.matches(oldObj.ObjectMeta.Labels)
newMatch := ps.matches(newObj.ObjectMeta.Labels)
if oldMatch == newMatch && oldObj.Status.PodIP == newObj.Status.PodIP {
continue
}
if oldMatch {
if err := ps.delEntry(oldObj.Status.PodIP); err != nil {
return err
}
}
if newMatch {
if err := ps.addEntry(newObj.Status.PodIP); err != nil {
return err
}
}
}
}
return nil
}
func (ns *ns) deletePod(obj *coreapi.Pod) error {
delete(ns.pods, obj.ObjectMeta.UID)
if !hasIP(obj) {
return nil
}
return ns.podSelectors.delFromMatching(obj.ObjectMeta.Labels, obj.Status.PodIP)
}
func (ns *ns) addNetworkPolicy(obj *extnapi.NetworkPolicy) error {
ns.policies[obj.ObjectMeta.UID] = obj
// Analyse policy, determine which rules and ipsets are required
rules, nsSelectors, podSelectors, err := ns.analysePolicy(obj)
if err != nil {
return err
}
// Provision required resources in dependency order
if err := ns.nsSelectors.provision(obj.ObjectMeta.UID, nil, nsSelectors); err != nil {
return err
}
if err := ns.podSelectors.provision(obj.ObjectMeta.UID, nil, podSelectors); err != nil {
return err
}
if err := ns.rules.provision(obj.ObjectMeta.UID, nil, rules); err != nil {
return err
}
return nil
}
func (ns *ns) updateNetworkPolicy(oldObj, newObj *extnapi.NetworkPolicy) error {
delete(ns.policies, oldObj.ObjectMeta.UID)
ns.policies[newObj.ObjectMeta.UID] = newObj
// Analyse the old and the new policy so we can determine differences
oldRules, oldNsSelectors, oldPodSelectors, err := ns.analysePolicy(oldObj)
if err != nil {
return err
}
newRules, newNsSelectors, newPodSelectors, err := ns.analysePolicy(newObj)
if err != nil {
return err
}
// Deprovision unused and provision newly required resources in dependency order
if err := ns.rules.deprovision(oldObj.ObjectMeta.UID, oldRules, newRules); err != nil {
return err
}
if err := ns.nsSelectors.deprovision(oldObj.ObjectMeta.UID, oldNsSelectors, newNsSelectors); err != nil {
return err
}
if err := ns.podSelectors.deprovision(oldObj.ObjectMeta.UID, oldPodSelectors, newPodSelectors); err != nil {
return err
}
if err := ns.nsSelectors.provision(oldObj.ObjectMeta.UID, oldNsSelectors, newNsSelectors); err != nil {
return err
}
if err := ns.podSelectors.provision(oldObj.ObjectMeta.UID, oldPodSelectors, newPodSelectors); err != nil {
return err
}
if err := ns.rules.provision(oldObj.ObjectMeta.UID, oldRules, newRules); err != nil {
return err
}
return nil
}
func (ns *ns) deleteNetworkPolicy(obj *extnapi.NetworkPolicy) error {
delete(ns.policies, obj.ObjectMeta.UID)
// Analyse network policy to free resources
rules, nsSelectors, podSelectors, err := ns.analysePolicy(obj)
if err != nil {
return err
}
// Deprovision unused resources in dependency order
if err := ns.rules.deprovision(obj.ObjectMeta.UID, rules, nil); err != nil {
return err
}
if err := ns.nsSelectors.deprovision(obj.ObjectMeta.UID, nsSelectors, nil); err != nil {
return err
}
if err := ns.podSelectors.deprovision(obj.ObjectMeta.UID, podSelectors, nil); err != nil {
return err
}
return nil
}
func bypassRule(nsIpsetName ipset.Name) []string {
return []string{"-m", "set", "--match-set", string(nsIpsetName), "dst", "-j", "ACCEPT"}
}
func (ns *ns) ensureBypassRule(nsIpsetName ipset.Name) error {
return ns.ipt.Append(TableFilter, DefaultChain, bypassRule(ns.allPods.ipsetName)...)
}
func (ns *ns) deleteBypassRule(nsIpsetName ipset.Name) error {
return ns.ipt.Delete(TableFilter, DefaultChain, bypassRule(ns.allPods.ipsetName)...)
}
func (ns *ns) addNamespace(obj *coreapi.Namespace) error {
ns.namespace = obj
// Insert a rule to bypass policies if namespace is DefaultAllow
if !isDefaultDeny(obj) {
return ns.ensureBypassRule(ns.allPods.ipsetName)
}
// Add namespace ipset to matching namespace selectors
return ns.nsSelectors.addToMatching(obj.ObjectMeta.Labels, string(ns.allPods.ipsetName))
}
func (ns *ns) updateNamespace(oldObj, newObj *coreapi.Namespace) error {
ns.namespace = newObj
// Update bypass rule if ingress default has changed
oldDefaultDeny := isDefaultDeny(oldObj)
newDefaultDeny := isDefaultDeny(newObj)
if oldDefaultDeny != newDefaultDeny {
if oldDefaultDeny {
return ns.ensureBypassRule(ns.allPods.ipsetName)
}
if newDefaultDeny {
return ns.deleteBypassRule(ns.allPods.ipsetName)
}
}
// Re-evaluate namespace selector membership if labels have changed
if !equals(oldObj.ObjectMeta.Labels, newObj.ObjectMeta.Labels) {
for _, selector := range ns.nsSelectors.entries {
oldMatch := selector.matches(oldObj.ObjectMeta.Labels)
newMatch := selector.matches(newObj.ObjectMeta.Labels)
if oldMatch == newMatch {
continue
}
if oldMatch {
if err := selector.delEntry(string(ns.allPods.ipsetName)); err != nil {
return err
}
}
if newMatch {
if err := selector.addEntry(string(ns.allPods.ipsetName)); err != nil {
return err
}
}
}
}
return nil
}
func (ns *ns) deleteNamespace(obj *coreapi.Namespace) error {
ns.namespace = nil
// Remove bypass rule
if !isDefaultDeny(obj) {
return ns.deleteBypassRule(ns.allPods.ipsetName)
}
// Remove namespace ipset from any matching namespace selectors
return ns.nsSelectors.delFromMatching(obj.ObjectMeta.Labels, string(ns.allPods.ipsetName))
}
func hasIP(pod *coreapi.Pod) bool {
// Ensure pod isn't dead, has an IP address and isn't sharing the host network namespace
return pod.Status.Phase != "Succeeded" && pod.Status.Phase != "Failed" &&
len(pod.Status.PodIP) > 0 && !pod.Spec.HostNetwork
}
func equals(a, b map[string]string) bool {
if len(a) != len(b) {
return false
}
for ak, av := range a {
if b[ak] != av {
return false
}
}
return true
}
func isDefaultDeny(namespace *coreapi.Namespace) bool {
nnpJSON, found := namespace.ObjectMeta.Annotations["net.beta.kubernetes.io/network-policy"]
if !found {
return false
}
var nnp NamespaceNetworkPolicy
if err := json.Unmarshal([]byte(nnpJSON), &nnp); err != nil {
common.Log.Warn("Ignoring network policy annotation: unmarshal failed:", err)
// If we can't understand the annotation, behave as if it isn't present
return false
}
return nnp.Ingress != nil &&
nnp.Ingress.Isolation != nil &&
*(nnp.Ingress.Isolation) == DefaultDeny
}
+78
View File
@@ -0,0 +1,78 @@
package npc
import (
"strings"
"github.com/coreos/go-iptables/iptables"
"k8s.io/client-go/pkg/types"
"github.com/weaveworks/weave/common"
)
type ruleSpec struct {
key string
args []string
}
func newRuleSpec(proto *string, srcHost *selectorSpec, dstHost *selectorSpec, dstPort *string) *ruleSpec {
args := []string{}
if proto != nil {
args = append(args, "-p", *proto)
}
if srcHost != nil {
args = append(args, "-m", "set", "--match-set", string(srcHost.ipsetName), "src")
}
if dstHost != nil {
args = append(args, "-m", "set", "--match-set", string(dstHost.ipsetName), "dst")
}
if dstPort != nil {
args = append(args, "--dport", *dstPort)
}
args = append(args, "-j", "ACCEPT")
key := strings.Join(args, " ")
return &ruleSpec{key, args}
}
type ruleSet struct {
ipt *iptables.IPTables
users map[string]map[types.UID]struct{}
}
func newRuleSet(ipt *iptables.IPTables) *ruleSet {
return &ruleSet{ipt, make(map[string]map[types.UID]struct{})}
}
func (rs *ruleSet) deprovision(user types.UID, current, desired map[string]*ruleSpec) error {
for key, spec := range current {
if _, found := desired[key]; !found {
delete(rs.users[key], user)
if len(rs.users[key]) == 0 {
common.Log.Infof("deleting rule: %v", spec.args)
if err := rs.ipt.Delete(TableFilter, IngressChain, spec.args...); err != nil {
return err
}
delete(rs.users, key)
}
}
}
return nil
}
func (rs *ruleSet) provision(user types.UID, current, desired map[string]*ruleSpec) error {
for key, spec := range desired {
if _, found := current[key]; !found {
if _, found := rs.users[key]; !found {
common.Log.Infof("adding rule: %v", spec.args)
if err := rs.ipt.Append(TableFilter, IngressChain, spec.args...); err != nil {
return err
}
rs.users[key] = make(map[types.UID]struct{})
}
rs.users[key][user] = struct{}{}
}
}
return nil
}
+130
View File
@@ -0,0 +1,130 @@
package npc
import (
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/labels"
"k8s.io/client-go/pkg/types"
"github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/npc/ipset"
)
type selectorSpec struct {
key string // string representation (for hash keying/equality comparison)
selector labels.Selector // k8s Selector object (for matching)
ipsetType ipset.Type // type of ipset to provision
ipsetName ipset.Name // generated ipset name
}
func newSelectorSpec(json *unversioned.LabelSelector, nsName string, ipsetType ipset.Type) (*selectorSpec, error) {
selector, err := unversioned.LabelSelectorAsSelector(json)
if err != nil {
return nil, err
}
key := selector.String()
return &selectorSpec{
key: key,
selector: selector,
// We prefix the selector string with the namespace name when generating
// the shortname because you can specify the same selector in multiple
// namespaces - we need those to map to distinct ipsets
ipsetName: ipset.Name("weave-" + shortName(nsName+":"+key)),
ipsetType: ipsetType}, nil
}
type selector struct {
ips ipset.Interface
spec *selectorSpec
}
func (s *selector) matches(labelMap map[string]string) bool {
return s.spec.selector.Matches(labels.Set(labelMap))
}
func (s *selector) addEntry(entry string) error {
common.Log.Infof("adding entry %s to %s", entry, s.spec.ipsetName)
return s.ips.AddEntry(s.spec.ipsetName, entry)
}
func (s *selector) delEntry(entry string) error {
common.Log.Infof("deleting entry %s from %s", entry, s.spec.ipsetName)
return s.ips.DelEntry(s.spec.ipsetName, entry)
}
type selectorFn func(selector *selector) error
type selectorSet struct {
ips ipset.Interface
onNewSelector selectorFn
users map[string]map[types.UID]struct{} // list of users per selector
entries map[string]*selector
}
func newSelectorSet(ips ipset.Interface, onNewSelector selectorFn) *selectorSet {
return &selectorSet{
ips: ips,
onNewSelector: onNewSelector,
users: make(map[string]map[types.UID]struct{}),
entries: make(map[string]*selector)}
}
func (ss *selectorSet) addToMatching(labelMap map[string]string, entry string) error {
for _, s := range ss.entries {
if s.matches(labelMap) {
if err := s.addEntry(entry); err != nil {
return err
}
}
}
return nil
}
func (ss *selectorSet) delFromMatching(labelMap map[string]string, entry string) error {
for _, s := range ss.entries {
if s.matches(labelMap) {
if err := s.delEntry(entry); err != nil {
return err
}
}
}
return nil
}
func (ss *selectorSet) deprovision(user types.UID, current, desired map[string]*selectorSpec) error {
for key, spec := range current {
if _, found := desired[key]; !found {
delete(ss.users[key], user)
if len(ss.users[key]) == 0 {
common.Log.Infof("destroying ipset: %#v", spec)
if err := ss.ips.Destroy(spec.ipsetName); err != nil {
return err
}
delete(ss.entries, key)
delete(ss.users, key)
}
}
}
return nil
}
func (ss *selectorSet) provision(user types.UID, current, desired map[string]*selectorSpec) error {
for key, spec := range desired {
if _, found := current[key]; !found {
if _, found := ss.users[key]; !found {
common.Log.Infof("creating ipset: %#v", spec)
if err := ss.ips.Create(spec.ipsetName, spec.ipsetType); err != nil {
return err
}
selector := &selector{ss.ips, spec}
if err := ss.onNewSelector(selector); err != nil {
return err
}
ss.users[key] = make(map[types.UID]struct{})
ss.entries[key] = selector
}
ss.users[key][user] = struct{}{}
}
}
return nil
}
+36
View File
@@ -0,0 +1,36 @@
package npc
import (
"crypto/sha1"
"math/big"
)
const (
// This array:
// * Must include only printable UTF8 characters that are represented with a single byte
// * Must be at least of length 85 (`len("weave-") + l(2^160)/l(85)` equals 31, the maximum ipset name length)
// * Must not include commas as those are treated specially by `ipset add` when adding a named set to a list:set
// * Should not include space for readability
// * Should not include single quote or backslash to be nice to shell users
ShortNameSymbols = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789(){}[]<>_$%^&*|/?.;:@#~"
)
// sha1 hash an arbitrary string and represent it using the full range of
// printable ascii characters
func shortName(arbitrary string) string {
symbols := []byte(ShortNameSymbols)
sum := sha1.Sum([]byte(arbitrary))
i := big.NewInt(0).SetBytes(sum[:])
base := big.NewInt(int64(len(symbols)))
zero := big.NewInt(0)
result := make([]byte, 0)
for i.Cmp(zero) > 0 {
remainder := new(big.Int).Mod(i, base)
i.Sub(i, remainder)
i.Div(i, base)
result = append(result, symbols[remainder.Int64()])
}
return string(result)
}
+34
View File
@@ -0,0 +1,34 @@
package ulogd
import (
"io"
"os"
"os/exec"
"syscall"
"github.com/weaveworks/weave/common"
)
func waitForExit(cmd *exec.Cmd) {
if err := cmd.Wait(); err != nil {
common.Log.Fatalf("ulogd terminated: %v", err)
}
common.Log.Fatal("ulogd terminated normally")
}
func Start() error {
cmd := exec.Command("/usr/sbin/ulogd", "-v")
cmd.SysProcAttr = &syscall.SysProcAttr{
Pdeathsig: syscall.SIGKILL,
}
stdout, err := cmd.StderrPipe()
if err != nil {
return err
}
if err := cmd.Start(); err != nil {
return err
}
go io.Copy(os.Stdout, stdout)
go waitForExit(cmd)
return nil
}
+3 -4
View File
@@ -72,9 +72,8 @@ func splitPoolID(poolID string) (subnet, iprange *net.IPNet, err error) {
func (i *Ipam) RequestAddress(poolID string, address net.IP, options map[string]string) (ip *net.IPNet, _ map[string]string, err error) {
i.logReq("RequestAddress", poolID, address, options)
defer func() { i.logRes("RequestAddress", err, ip) }()
// If we pass magic string "_" to weave IPAM it stores the address under its own string
if poolID == "weavepool" { // old-style
ip, err = i.weave.AllocateIP("_")
ip, err = i.weave.AllocateIP(api.NoContainerID)
return
}
subnet, iprange, err := splitPoolID(poolID)
@@ -83,12 +82,12 @@ func (i *Ipam) RequestAddress(poolID string, address net.IP, options map[string]
}
if address != nil { // try to claim specific address requested
ip = &net.IPNet{IP: address, Mask: subnet.Mask}
if err = i.weave.ClaimIP("_", ip); err != nil {
if err = i.weave.ClaimIP(api.NoContainerID, ip); err != nil {
return
}
} else {
// We are lying slightly to IPAM here: the range is not a subnet
if ip, err = i.weave.AllocateIPInSubnet("_", iprange); err != nil {
if ip, err = i.weave.AllocateIPInSubnet(api.NoContainerID, iprange); err != nil {
return
}
ip.Mask = subnet.Mask // fix up the subnet we lied about
+46 -44
View File
@@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"net"
"syscall"
"github.com/appc/cni/pkg/ipam"
"github.com/appc/cni/pkg/skel"
@@ -12,7 +13,6 @@ import (
"github.com/vishvananda/netlink"
"github.com/vishvananda/netns"
weaveapi "github.com/weaveworks/weave/api"
"github.com/weaveworks/weave/common"
weavenet "github.com/weaveworks/weave/net"
ipamplugin "github.com/weaveworks/weave/plugin/ipam"
)
@@ -40,6 +40,19 @@ func loadNetConf(bytes []byte) (*NetConf, error) {
return n, nil
}
func (c *CNIPlugin) getIP(ipamType string, args *skel.CmdArgs) (result *types.Result, err error) {
// Default IPAM is Weave's own
if ipamType == "" {
result, err = ipamplugin.NewIpam(c.weave).Allocate(args)
} else {
result, err = ipam.ExecAdd(ipamType, args.StdinData)
}
if err == nil && result.IP4 == nil {
return nil, fmt.Errorf("IPAM plugin failed to allocate IP address")
}
return result, err
}
func (c *CNIPlugin) CmdAdd(args *skel.CmdArgs) error {
conf, err := loadNetConf(args.StdinData)
if err != nil {
@@ -53,24 +66,29 @@ func (c *CNIPlugin) CmdAdd(args *skel.CmdArgs) error {
return fmt.Errorf("IP Masquerading functionality not supported")
}
var result *types.Result
// Default IPAM is Weave's own
if conf.IPAM.Type == "" {
result, err = ipamplugin.NewIpam(c.weave).Allocate(args)
} else {
result, err = ipam.ExecAdd(conf.IPAM.Type, args.StdinData)
}
result, err := c.getIP(conf.IPAM.Type, args)
if err != nil {
return fmt.Errorf("unable to allocate IP address: %s", err)
}
if result.IP4 == nil {
return fmt.Errorf("IPAM plugin failed to allocate IP address")
}
// If config says nothing about routes or gateway, default one will be via the bridge
if result.IP4.Routes == nil && result.IP4.Gateway == nil {
bridgeIP, err := findBridgeIP(conf.BrName, result.IP4.IP)
if err != nil {
bridgeIP, err := weavenet.FindBridgeIP(conf.BrName, &result.IP4.IP)
if err == weavenet.ErrBridgeNoIP {
bridgeArgs := *args
bridgeArgs.ContainerID = "weave:expose"
bridgeIPResult, err := c.getIP(conf.IPAM.Type, &bridgeArgs)
if err != nil {
return fmt.Errorf("unable to allocate IP address for bridge: %s", err)
}
if err := assignBridgeIP(conf.BrName, bridgeIPResult.IP4.IP); err != nil {
return fmt.Errorf("unable to assign IP address to bridge: %s", err)
}
if err := weavenet.ExposeNAT(bridgeIPResult.IP4.IP); err != nil {
return fmt.Errorf("unable to create NAT rules: %s", err)
}
bridgeIP = bridgeIPResult.IP4.IP.IP
} else if err != nil {
return err
}
result.IP4.Gateway = bridgeIP
@@ -78,7 +96,7 @@ func (c *CNIPlugin) CmdAdd(args *skel.CmdArgs) error {
ns, err := netns.GetFromPath(args.Netns)
if err != nil {
return err
return fmt.Errorf("error accessing namespace %q: %s", args.Netns, err)
}
defer ns.Close()
@@ -92,10 +110,10 @@ func (c *CNIPlugin) CmdAdd(args *skel.CmdArgs) error {
id = fmt.Sprintf("%x", data)
}
if err := weavenet.AttachContainer(ns, id, args.IfName, conf.BrName, conf.MTU, false, []*net.IPNet{&result.IP4.IP}, false); err != nil {
if err := weavenet.AttachContainer(args.Netns, id, args.IfName, conf.BrName, conf.MTU, false, []*net.IPNet{&result.IP4.IP}, false); err != nil {
return err
}
if err := weavenet.WithNetNSLink(ns, args.IfName, func(link netlink.Link) error {
if err := weavenet.WithNetNSLinkUnsafe(ns, args.IfName, func(link netlink.Link) error {
return setupRoutes(link, args.IfName, result.IP4.IP, result.IP4.Gateway, result.IP4.Routes)
}); err != nil {
return fmt.Errorf("error setting up routes: %s", err)
@@ -130,24 +148,20 @@ func setupRoutes(link netlink.Link, name string, ipnet net.IPNet, gw net.IP, rou
return nil
}
func findBridgeIP(bridgeName string, subnet net.IPNet) (net.IP, error) {
netdevs, err := common.GetBridgeNetDev(bridgeName)
func assignBridgeIP(bridgeName string, ipnet net.IPNet) error {
link, err := netlink.LinkByName(bridgeName)
if err != nil {
return nil, fmt.Errorf("Failed to get netdev for %q bridge: %s", bridgeName, err)
return err
}
if len(netdevs) == 0 {
return nil, fmt.Errorf("Could not find %q bridge", bridgeName)
}
if len(netdevs[0].CIDRs) == 0 {
return nil, fmt.Errorf("Bridge %q has no IP addresses", bridgeName)
}
for _, cidr := range netdevs[0].CIDRs {
if subnet.Contains(cidr.IP) {
return cidr.IP, nil
if err := netlink.AddrAdd(link, &netlink.Addr{IPNet: &ipnet}); err != nil {
// Treat as non-error if this address is already there
// - maybe another copy of this program just added it
if err == syscall.Errno(syscall.EEXIST) {
return nil
}
return fmt.Errorf("failed to add IP address to %q: %v", bridgeName, err)
}
// None in the required subnet; just return the first one
return netdevs[0].CIDRs[0].IP, nil
return nil
}
func (c *CNIPlugin) CmdDel(args *skel.CmdArgs) error {
@@ -156,20 +170,8 @@ func (c *CNIPlugin) CmdDel(args *skel.CmdArgs) error {
return err
}
ns, err := netns.GetFromPath(args.Netns)
if err != nil {
return err
}
defer ns.Close()
err = weavenet.WithNetNS(ns, func() error {
link, err := netlink.LinkByName(args.IfName)
if err != nil {
return err
}
return netlink.LinkDel(link)
})
if err != nil {
return fmt.Errorf("error removing interface: %s", err)
if _, err = weavenet.WithNetNS(args.Netns, "del-iface", args.IfName); err != nil {
return fmt.Errorf("error removing interface %q: %s", args.IfName, err)
}
// Default IPAM is Weave's own
+26 -13
View File
@@ -8,6 +8,7 @@ import (
"github.com/docker/libnetwork/drivers/remote/api"
"github.com/docker/libnetwork/netlabel"
"github.com/docker/libnetwork/types"
"golang.org/x/sys/unix"
"github.com/vishvananda/netlink"
weaveapi "github.com/weaveworks/weave/api"
@@ -94,11 +95,21 @@ func (driver *driver) DeleteNetwork(delreq *api.DeleteNetworkRequest) error {
func (driver *driver) CreateEndpoint(create *api.CreateEndpointRequest) (*api.CreateEndpointResponse, error) {
driver.logReq("CreateEndpoint", create, create.EndpointID)
common.Log.Debugf("interface %+v", create.Interface)
if create.Interface == nil {
return nil, driver.error("CreateEndpoint", "Not supported: creating an interface from within CreateEndpoint")
}
resp := &api.CreateEndpointResponse{}
// create veths. note we assume endpoint IDs are unique in the first 9 chars
name, peerName := vethPair(create.EndpointID)
if _, err := weavenet.CreateAndAttachVeth(name, peerName, weavenet.WeaveBridgeName, 0, false, nil); err != nil {
return nil, driver.error("JoinEndpoint", "%s", err)
}
// Send back the MAC address
link, _ := netlink.LinkByName(peerName)
resp := &api.CreateEndpointResponse{Interface: &api.EndpointInterface{MacAddress: link.Attrs().HardwareAddr.String()}}
driver.logRes("CreateEndpoint", resp)
return resp, nil
@@ -106,6 +117,17 @@ func (driver *driver) CreateEndpoint(create *api.CreateEndpointRequest) (*api.Cr
func (driver *driver) DeleteEndpoint(deleteReq *api.DeleteEndpointRequest) error {
driver.logReq("DeleteEndpoint", deleteReq, deleteReq.EndpointID)
name, _ := vethPair(deleteReq.EndpointID)
veth := &netlink.Veth{LinkAttrs: netlink.LinkAttrs{Name: name}}
if err := netlink.LinkDel(veth); err != nil {
// Try again using the name construction from earlier plugin version,
// in case user has upgraded with endpoints still extant
veth.Name = "vethwl" + deleteReq.EndpointID[:5]
if err2 := netlink.LinkDel(veth); err2 != nil {
// Note we report the first error
driver.warn("LeaveEndpoint", "unable to delete veth %q: %s", name, err)
}
}
return nil
}
@@ -122,11 +144,7 @@ func (driver *driver) JoinEndpoint(j *api.JoinRequest) (*api.JoinResponse, error
return nil, driver.error("JoinEndpoint", "unable to find network info: %s", err)
}
name, peerName := vethPair(j.EndpointID)
if _, err := weavenet.CreateAndAttachVeth(name, peerName, weavenet.WeaveBridgeName, 0, false, nil); err != nil {
return nil, driver.error("JoinEndpoint", "%s", err)
}
_, peerName := vethPair(j.EndpointID)
response := &api.JoinResponse{
InterfaceName: &api.InterfaceName{
SrcName: peerName,
@@ -186,12 +204,6 @@ func (driver *driver) setupNetworkInfo(id string, isOurs bool, options map[strin
func (driver *driver) LeaveEndpoint(leave *api.LeaveRequest) error {
driver.logReq("LeaveEndpoint", leave, fmt.Sprintf("%s:%s", leave.NetworkID, leave.EndpointID))
name, _ := vethPair(leave.EndpointID)
veth := &netlink.Veth{LinkAttrs: netlink.LinkAttrs{Name: name}}
if err := netlink.LinkDel(veth); err != nil {
driver.warn("LeaveEndpoint", "unable to delete veth: %s", err)
}
return nil
}
@@ -206,7 +218,8 @@ func (driver *driver) DiscoverDelete(disco *api.DiscoveryNotification) error {
}
func vethPair(id string) (string, string) {
return "vethwl" + id[:5], "vethwg" + id[:5]
// IFNAMSIZ is buffer length; subtract 6 for "vethwl" and 1 for terminating nul
return "vethwl" + id[:unix.IFNAMSIZ-7], "vethwg" + id[:unix.IFNAMSIZ-7]
}
// logging
+1 -2
View File
@@ -4,7 +4,6 @@ import (
"fmt"
weaveapi "github.com/weaveworks/weave/api"
"github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/common/docker"
weavenet "github.com/weaveworks/weave/net"
)
@@ -46,7 +45,7 @@ func (w *watcher) ContainerStarted(id string) {
if err := w.weave.RegisterWithDNS(id, fqdn, net.IPAddress); err != nil {
w.driver.warn("ContainerStarted", "unable to register %s with weaveDNS: %s", id, err)
}
if err := common.ConfigureARPforVeths(info.State.Pid, weavenet.VethName); err != nil {
if _, err := weavenet.WithNetNSByPid(info.State.Pid, "configure-arp", weavenet.VethName); err != nil {
w.driver.warn("ContainerStarted", "unable to configure interfaces: %s", err)
}
}
+55
View File
@@ -0,0 +1,55 @@
package main
import (
"fmt"
"log"
"k8s.io/client-go/kubernetes"
api "k8s.io/client-go/pkg/api/v1"
"k8s.io/client-go/rest"
)
func getKubePeers() ([]string, error) {
config, err := rest.InClusterConfig()
if err != nil {
return nil, err
}
c, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, err
}
nodeList, err := c.Nodes().List(api.ListOptions{})
if err != nil {
// Fallback for cases (e.g. from kube-up.sh) where kube-proxy is not running on master
config.Host = "http://localhost:8080"
log.Print("error contacting APIServer: ", err, "; trying with fallback: ", config.Host)
c, err = kubernetes.NewForConfig(config)
if err != nil {
return nil, err
}
nodeList, err = c.Nodes().List(api.ListOptions{})
}
if err != nil {
return nil, err
}
addresses := make([]string, 0, len(nodeList.Items))
for _, peer := range nodeList.Items {
for _, addr := range peer.Status.Addresses {
if addr.Type == "InternalIP" {
addresses = append(addresses, addr.Address)
}
}
}
return addresses, nil
}
func main() {
peers, err := getKubePeers()
if err != nil {
log.Fatalf("Could not get peers: %v", err)
}
for _, addr := range peers {
fmt.Println(addr)
}
}
@@ -1,3 +1,3 @@
FROM weaveworks/weaveexec
FROM DOCKERHUB_USER/weaveARCH_EXT
ADD ./plugin /home/weave/
ENTRYPOINT ["/home/weave/plugin"]
+1 -17
View File
@@ -11,7 +11,6 @@ import (
"strings"
"syscall"
cni "github.com/appc/cni/pkg/skel"
"github.com/docker/libnetwork/ipamapi"
weaveapi "github.com/weaveworks/weave/api"
"github.com/weaveworks/weave/common"
@@ -22,15 +21,13 @@ import (
"github.com/weaveworks/weave/plugin/skel"
)
var version = "(unreleased version)"
var version = "unreleased"
var Log = common.Log
func main() {
var (
justVersion bool
cniNet bool
cniIpam bool
address string
meshAddress string
logLevel string
@@ -38,8 +35,6 @@ func main() {
)
flag.BoolVar(&justVersion, "version", false, "print version and exit")
flag.BoolVar(&cniNet, "cni-net", false, "act as a CNI network plugin")
flag.BoolVar(&cniIpam, "cni-ipam", false, "act as a CNI IPAM plugin")
flag.StringVar(&logLevel, "log-level", "info", "logging level (debug, info, warning, error)")
flag.StringVar(&address, "socket", "/run/docker/plugins/weave.sock", "socket on which to listen")
flag.StringVar(&meshAddress, "meshsocket", "/run/docker/plugins/weavemesh.sock", "socket on which to listen in mesh mode")
@@ -56,17 +51,6 @@ func main() {
weave := weaveapi.NewClient(os.Getenv("WEAVE_HTTP_ADDR"), Log)
switch {
case cniIpam || strings.HasSuffix(os.Args[0], "weave-ipam"):
i := ipamplugin.NewIpam(weave)
cni.PluginMain(i.CmdAdd, i.CmdDel)
os.Exit(0)
case cniNet || strings.HasSuffix(os.Args[0], "weave-net"):
n := netplugin.NewCNIPlugin(weave)
cni.PluginMain(n.CmdAdd, n.CmdDel)
os.Exit(0)
}
// API 1.21 is the first version that supports docker network commands
dockerClient, err := docker.NewVersionedClientFromEnv("1.21")
if err != nil {
+3
View File
@@ -0,0 +1,3 @@
FROM DOCKERHUB_USER/weaveARCH_EXT
ADD ./launch.sh ./kube-peers /home/weave/
ENTRYPOINT ["/home/weave/launch.sh"]
+117
View File
@@ -0,0 +1,117 @@
#!/bin/sh
set -e
# Default if not supplied - same as weave net default
IPALLOC_RANGE=${IPALLOC_RANGE:-10.32.0.0/12}
HTTP_ADDR=${WEAVE_HTTP_ADDR:-127.0.0.1:6784}
STATUS_ADDR=${WEAVE_STATUS_ADDR:-0.0.0.0:6782}
HOST_ROOT=${HOST_ROOT:-/host}
# Check if the IP range overlaps anything existing on the host
/usr/bin/weaveutil netcheck $IPALLOC_RANGE weave
# Default for network policy
EXPECT_NPC=${EXPECT_NPC:-1}
# kube-proxy requires that bridged traffic passes through netfilter
if ! BRIDGE_NF_ENABLED=$(cat /proc/sys/net/bridge/bridge-nf-call-iptables); then
echo "Cannot detect bridge-nf support - network policy and iptables mode kubeproxy may not work reliably" >&2
else
if [ "$BRIDGE_NF_ENABLED" != "1" ]; then
echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables
fi
fi
# Explicitly create the bridge so we can pass --expect-npc
WEAVE_NPC_OPTS="--expect-npc"
if [ "${EXPECT_NPC}" = "0" ]; then
WEAVE_NPC_OPTS=""
fi
export HOST_ROOT=/host
/home/weave/weave --local create-bridge --force $WEAVE_NPC_OPTS
# Kubernetes sets HOSTNAME to the host's hostname
# when running a pod in host namespace.
NICKNAME_ARG=""
if [ -n "$HOSTNAME" ] ; then
NICKNAME_ARG="--nickname=$HOSTNAME"
fi
BRIDGE_OPTIONS="--datapath=datapath"
if [ "$(/home/weave/weave --local bridge-type)" = "bridge" ] ; then
# TODO: Call into weave script to do this
if ! ip link show vethwe-pcap >/dev/null 2>&1 ; then
ip link add name vethwe-bridge type veth peer name vethwe-pcap
ip link set vethwe-bridge up
ip link set vethwe-pcap up
ip link set vethwe-bridge master weave
fi
BRIDGE_OPTIONS="--iface=vethwe-pcap"
fi
if [ -z "$KUBE_PEERS" ]; then
if ! KUBE_PEERS=$(/home/weave/kube-peers) || [ -z "$KUBE_PEERS" ]; then
echo Failed to get peers >&2
exit 1
fi
fi
peer_count() {
echo $#
}
if [ -z "$IPALLOC_INIT" ]; then
IPALLOC_INIT="consensus=$(peer_count $KUBE_PEERS)"
fi
reclaim_ips() {
ID=$1
shift
for CIDR in "$@" ; do
curl -s -S -X PUT "$HTTP_ADDR/ip/$ID/$CIDR" || true
done
}
post_start_actions() {
# Wait for weave process to become responsive
while true ; do
curl $HTTP_ADDR/status >/dev/null 2>&1 && break
sleep 1
done
# Tell the newly-started weave about existing weave bridge IPs
/usr/bin/weaveutil container-addrs weave weave:expose | while read ID IFACE MAC IPS; do
reclaim_ips "weave:expose" $IPS
done
# Tell weave about existing weave process IPs
/usr/bin/weaveutil process-addrs weave | while read ID IFACE MAC IPS; do
reclaim_ips "_" $IPS
done
# Install CNI plugin binary to typical CNI bin location
# with fall-back to CNI directory used by kube-up on GCI OS
if ! mkdir -p $HOST_ROOT/opt/cni/bin ; then
if mkdir -p $HOST_ROOT/home/kubernetes/bin ; then
export WEAVE_CNI_PLUGIN_DIR=$HOST_ROOT/home/kubernetes/bin
else
echo "Failed to install the Weave CNI plugin" >&2
exit 1
fi
fi
mkdir -p $HOST_ROOT/etc/cni/net.d
/home/weave/weave --local setup-cni
# Expose the weave network so host processes can communicate with pods
/home/weave/weave --local expose $WEAVE_EXPOSE_IP
}
post_start_actions &
exec /home/weave/weaver $EXTRA_ARGS --port=6783 $BRIDGE_OPTIONS \
--http-addr=$HTTP_ADDR --status-addr=$STATUS_ADDR --docker-api='' --no-dns \
--ipalloc-range=$IPALLOC_RANGE $NICKNAME_ARG \
--ipalloc-init $IPALLOC_INIT \
"$@" \
$KUBE_PEERS
+75
View File
@@ -0,0 +1,75 @@
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: weave-net
namespace: kube-system
spec:
template:
metadata:
labels:
name: weave-net
annotations:
scheduler.alpha.kubernetes.io/tolerations: |
[
{
"key": "dedicated",
"operator": "Equal",
"value": "master",
"effect": "NoSchedule"
}
]
spec:
hostNetwork: true
hostPID: true
containers:
- name: weave
image: weaveworks/weave-kube:latest
imagePullPolicy: Always
command:
- /home/weave/launch.sh
livenessProbe:
initialDelaySeconds: 30
httpGet:
host: 127.0.0.1
path: /status
port: 6784
securityContext:
privileged: true
volumeMounts:
- name: weavedb
mountPath: /weavedb
- name: cni-bin
mountPath: /host/opt
- name: cni-bin2
mountPath: /host/home
- name: cni-conf
mountPath: /host/etc
- name: dbus
mountPath: /host/var/lib/dbus
resources:
requests:
cpu: 10m
- name: weave-npc
image: weaveworks/weave-npc:latest
imagePullPolicy: Always
resources:
requests:
cpu: 10m
securityContext:
privileged: true
restartPolicy: Always
volumes:
- name: weavedb
emptyDir: {}
- name: cni-bin
hostPath:
path: /opt
- name: cni-bin2
hostPath:
path: /home
- name: cni-conf
hostPath:
path: /etc
- name: dbus
hostPath:
path: /var/lib/dbus
+23
View File
@@ -0,0 +1,23 @@
FROM ALPINE_BASEIMAGE
# If we're building for another architecture than amd64, the CROSS_BUILD_ placeholder is removed so e.g. CROSS_BUILD_COPY turns into COPY
# If we're building normally, for amd64, CROSS_BUILD lines are removed
CROSS_BUILD_COPY qemu-QEMUARCH-static /usr/bin/
LABEL maintainer "Weaveworks Inc <help@weave.works>"
LABEL works.weave.role=system \
org.label-schema.name="Weave Net" \
org.label-schema.description="Weave Net creates a virtual network that connects Docker containers across multiple hosts and enables their automatic discovery" \
org.label-schema.url="https://weave.works" \
org.label-schema.vcs-url="https://github.com/weaveworks/weave" \
org.label-schema.vendor="Weaveworks"
RUN apk add --update \
iptables \
ipset \
ulogd \
&& rm -rf /var/cache/apk/* \
&& mknod /var/log/ulogd.pcap p
COPY ./weave-npc /usr/bin/weave-npc
COPY ./ulogd.conf /etc/ulogd.conf
ENTRYPOINT ["/usr/bin/weave-npc"]
+180
View File
@@ -0,0 +1,180 @@
package main
import (
"os"
"os/signal"
"syscall"
"github.com/coreos/go-iptables/iptables"
"github.com/spf13/cobra"
"k8s.io/client-go/kubernetes"
coreapi "k8s.io/client-go/pkg/api/v1"
extnapi "k8s.io/client-go/pkg/apis/extensions/v1beta1"
"k8s.io/client-go/pkg/fields"
"k8s.io/client-go/pkg/runtime"
"k8s.io/client-go/pkg/util/wait"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/cache"
"github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/npc"
"github.com/weaveworks/weave/npc/ipset"
"github.com/weaveworks/weave/npc/metrics"
"github.com/weaveworks/weave/npc/ulogd"
)
var (
version = "unreleased"
metricsAddr string
logLevel string
allowMcast bool
)
func handleError(err error) { common.CheckFatal(err) }
func makeController(getter cache.Getter, resource string,
objType runtime.Object, handlers cache.ResourceEventHandlerFuncs) *cache.Controller {
listWatch := cache.NewListWatchFromClient(getter, resource, "", fields.Everything())
_, controller := cache.NewInformer(listWatch, objType, 0, handlers)
return controller
}
func resetIPTables(ipt *iptables.IPTables) error {
// Flush chains first so there are no refs to extant ipsets
if err := ipt.ClearChain(npc.TableFilter, npc.IngressChain); err != nil {
return err
}
if err := ipt.ClearChain(npc.TableFilter, npc.DefaultChain); err != nil {
return err
}
if err := ipt.ClearChain(npc.TableFilter, npc.MainChain); err != nil {
return err
}
// Configure main chain static rules
if err := ipt.Append(npc.TableFilter, npc.MainChain,
"-m", "state", "--state", "RELATED,ESTABLISHED", "-j", "ACCEPT"); err != nil {
return err
}
if allowMcast {
if err := ipt.Append(npc.TableFilter, npc.MainChain,
"-d", "224.0.0.0/4", "-j", "ACCEPT"); err != nil {
return err
}
}
if err := ipt.Append(npc.TableFilter, npc.MainChain,
"-m", "state", "--state", "NEW", "-j", string(npc.DefaultChain)); err != nil {
return err
}
if err := ipt.Append(npc.TableFilter, npc.MainChain,
"-m", "state", "--state", "NEW", "-j", string(npc.IngressChain)); err != nil {
return err
}
return nil
}
func resetIPSets(ips ipset.Interface) error {
// TODO should restrict ipset operations to the `weave-` prefix:
if err := ips.FlushAll(); err != nil {
return err
}
if err := ips.DestroyAll(); err != nil {
return err
}
return nil
}
func root(cmd *cobra.Command, args []string) {
common.SetLogLevel(logLevel)
common.Log.Infof("Starting Weaveworks NPC %s", version)
if err := metrics.Start(metricsAddr); err != nil {
common.Log.Fatalf("Failed to start metrics: %v", err)
}
if err := ulogd.Start(); err != nil {
common.Log.Fatalf("Failed to start ulogd: %v", err)
}
config, err := rest.InClusterConfig()
handleError(err)
client, err := kubernetes.NewForConfig(config)
handleError(err)
ipt, err := iptables.New()
handleError(err)
ips := ipset.New()
handleError(resetIPTables(ipt))
handleError(resetIPSets(ips))
npc := npc.New(ipt, ips)
nsController := makeController(client.Core().RESTClient(), "namespaces", &coreapi.Namespace{},
cache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
handleError(npc.AddNamespace(obj.(*coreapi.Namespace)))
},
DeleteFunc: func(obj interface{}) {
handleError(npc.DeleteNamespace(obj.(*coreapi.Namespace)))
},
UpdateFunc: func(old, new interface{}) {
handleError(npc.UpdateNamespace(old.(*coreapi.Namespace), new.(*coreapi.Namespace)))
}})
podController := makeController(client.Core().RESTClient(), "pods", &coreapi.Pod{},
cache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
handleError(npc.AddPod(obj.(*coreapi.Pod)))
},
DeleteFunc: func(obj interface{}) {
handleError(npc.DeletePod(obj.(*coreapi.Pod)))
},
UpdateFunc: func(old, new interface{}) {
handleError(npc.UpdatePod(old.(*coreapi.Pod), new.(*coreapi.Pod)))
}})
npController := makeController(client.Extensions().RESTClient(), "networkpolicies", &extnapi.NetworkPolicy{},
cache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
handleError(npc.AddNetworkPolicy(obj.(*extnapi.NetworkPolicy)))
},
DeleteFunc: func(obj interface{}) {
handleError(npc.DeleteNetworkPolicy(obj.(*extnapi.NetworkPolicy)))
},
UpdateFunc: func(old, new interface{}) {
handleError(npc.UpdateNetworkPolicy(old.(*extnapi.NetworkPolicy), new.(*extnapi.NetworkPolicy)))
}})
go nsController.Run(wait.NeverStop)
go podController.Run(wait.NeverStop)
go npController.Run(wait.NeverStop)
signals := make(chan os.Signal, 1)
signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM)
common.Log.Fatalf("Exiting: %v", <-signals)
}
func main() {
rootCmd := &cobra.Command{
Use: "weave-npc",
Short: "Weaveworks Kubernetes Network Policy Controller",
Run: root}
rootCmd.PersistentFlags().StringVar(&metricsAddr, "metrics-addr", ":6781", "metrics server bind address")
rootCmd.PersistentFlags().StringVar(&logLevel, "log-level", "debug", "logging level (debug, info, warning, error)")
rootCmd.PersistentFlags().BoolVar(&allowMcast, "allow-mcast", true, "allow all multicast traffic")
handleError(rootCmd.Execute())
}
+13
View File
@@ -0,0 +1,13 @@
[global]
logfile="/dev/null"
plugin="/usr/lib/ulogd/ulogd_inppkt_NFLOG.so"
plugin="/usr/lib/ulogd/ulogd_raw2packet_BASE.so"
plugin="/usr/lib/ulogd/ulogd_output_PCAP.so"
stack=log1:NFLOG,base1:BASE,pcap1:PCAP
[log1]
group=86
[pcap1]
file="/var/log/ulogd.pcap"
sync=1
+1 -1
View File
@@ -1,6 +1,6 @@
# This is a nearly-empty image that we use to create a data-only container for persistence
FROM scratch
MAINTAINER Weaveworks Inc <help@weave.works>
LABEL maintainer "Weaveworks Inc <help@weave.works>"
ENTRYPOINT ["data-only"]
# Work round Docker refusing to save an empty image
COPY Dockerfile /
-24
View File
@@ -1,24 +0,0 @@
FROM alpine
MAINTAINER Weaveworks Inc <help@weave.works>
LABEL works.weave.role=system
WORKDIR /home/weave
ENTRYPOINT ["/home/weave/sigproxy", "/home/weave/weave"]
RUN apk add --update \
curl \
ethtool \
iptables \
iproute2 \
util-linux \
conntrack-tools \
bind-tools \
&& rm -rf /var/cache/apk/*
ADD ./weave ./sigproxy ./weaveproxy ./symlink /home/weave/
ADD ./weaveutil /usr/bin/
ADD ./weavewait /w/w
ADD ./weavewait_noop /w-noop/w
ADD ./weavewait_nomcast /w-nomcast/w
ADD ./docker.tgz /
+33
View File
@@ -0,0 +1,33 @@
FROM ALPINE_BASEIMAGE
# If we're building for another architecture than amd64, the CROSS_BUILD_ placeholder is removed so e.g. CROSS_BUILD_COPY turns into COPY
# If we're building normally, for amd64, CROSS_BUILD lines are removed
CROSS_BUILD_COPY qemu-QEMUARCH-static /usr/bin/
LABEL maintainer "Weaveworks Inc <help@weave.works>"
LABEL works.weave.role=system \
org.label-schema.name="Weave Net" \
org.label-schema.description="Weave Net creates a virtual network that connects Docker containers across multiple hosts and enables their automatic discovery" \
org.label-schema.url="https://weave.works" \
org.label-schema.vcs-url="https://github.com/weaveworks/weave" \
org.label-schema.vendor="Weaveworks"
WORKDIR /home/weave
ENTRYPOINT ["/home/weave/sigproxy", "/home/weave/weave"]
RUN apk add --update \
curl \
ethtool \
iptables \
iproute2 \
util-linux \
conntrack-tools \
bind-tools \
&& rm -rf /var/cache/apk/*
ADD ./weave ./sigproxy ./weaveproxy ./symlink /home/weave/
ADD ./weaveutil /usr/bin/
ADD ./weavewait /w/w
ADD ./weavewait_noop /w-noop/w
ADD ./weavewait_nomcast /w-nomcast/w
ADD ./docker /usr/bin/
+5 -4
View File
@@ -5,13 +5,14 @@ import (
"os"
"strings"
"github.com/docker/docker/pkg/mflag"
"github.com/weaveworks/common/mflag"
"github.com/weaveworks/common/mflagext"
"github.com/weaveworks/common/signals"
"github.com/weaveworks/weave/common"
"github.com/weaveworks/weave/common/mflagext"
"github.com/weaveworks/weave/proxy"
)
var version = "(unreleased version)"
var version = "unreleased"
var Log = common.Log
@@ -79,5 +80,5 @@ func main() {
p.AttachExistingContainers()
go p.Serve(listeners)
go p.ListenAndServeStatus("/home/weave/status.sock")
common.SignalHandlerLoop()
signals.SignalHandlerLoop(common.Log)
}
@@ -1,6 +1,4 @@
FROM scratch
MAINTAINER Weaveworks Inc <help@weave.works>
LABEL works.weave.role=system
FROM DOCKERHUB_USER/weaveexecARCH_EXT
WORKDIR /home/weave
ADD ./weaver /home/weave/
ADD weavedata.db /weavedb/
+16 -13
View File
@@ -10,6 +10,7 @@ import (
var checker *checkpoint.Checker
var newVersion atomic.Value
var success atomic.Value
const (
updateCheckPeriod = 6 * time.Hour
@@ -17,9 +18,11 @@ const (
func checkForUpdates(dockerVersion string, network string) {
newVersion.Store("")
success.Store(true)
handleResponse := func(r *checkpoint.CheckResponse, err error) {
if err != nil {
success.Store(false)
Log.Printf("Error checking version: %v", err)
return
}
@@ -32,9 +35,21 @@ func checkForUpdates(dockerVersion string, network string) {
var uts syscall.Utsname
syscall.Uname(&uts)
release := uts.Release[:]
releaseBytes := make([]byte, len(release))
i := 0
for ; i < len(release); i++ {
if release[i] == 0 {
break
}
releaseBytes[i] = uint8(release[i])
}
kernelVersion := string(releaseBytes[:i])
flags := map[string]string{
"docker-version": dockerVersion,
"kernel-version": charsToString(uts.Release[:]),
"kernel-version": kernelVersion,
}
if network != "" {
flags["network"] = network
@@ -49,15 +64,3 @@ func checkForUpdates(dockerVersion string, network string) {
}
checker = checkpoint.CheckInterval(&params, updateCheckPeriod, handleResponse)
}
func charsToString(ca []int8) string {
s := make([]byte, len(ca))
i := 0
for ; i < len(ca); i++ {
if ca[i] == 0 {
break
}
s[i] = uint8(ca[i])
}
return string(s[:i])
}
+41 -23
View File
@@ -19,16 +19,10 @@ import (
weave "github.com/weaveworks/weave/router"
)
var allConnectionStates = []string{"established", "pending", "retrying", "failed", "connecting"}
var rootTemplate = template.New("root").Funcs(map[string]interface{}{
"countDNSEntries": func(entries []nameserver.EntryStatus) int {
count := 0
for _, entry := range entries {
if entry.Tombstone == 0 {
count++
}
}
return count
},
"countDNSEntries": countDNSEntries,
"printList": func(list []string) string {
if len(list) == 0 {
return "none"
@@ -55,27 +49,28 @@ var rootTemplate = template.New("root").Funcs(map[string]interface{}{
s.ips += entry.Size
}
printOwned := func(name string, nickName string, reachable bool, ips uint32) {
reachableStr := ""
if !reachable {
reachableStr = "- unreachable!"
}
printOwned := func(name string, nickName string, info string, ips uint32) {
percentageRanges := float32(ips) * 100.0 / float32(status.RangeNumIPs)
displayName := name + "(" + nickName + ")"
fmt.Fprintf(&buffer, "%-37v %8d IPs (%04.1f%% of total) %s\n",
displayName, ips, percentageRanges, reachableStr)
displayName, ips, percentageRanges, info)
}
// print the local info first
if ourStats := peerStats[router.Name]; ourStats != nil {
printOwned(router.Name, ourStats.nickname, true, ourStats.ips)
activeStr := fmt.Sprintf("(%d active)", status.ActiveIPs)
printOwned(router.Name, ourStats.nickname, activeStr, ourStats.ips)
}
// and then the rest
for peer, stats := range peerStats {
if peer != router.Name {
printOwned(peer, stats.nickname, stats.reachable, stats.ips)
reachableStr := ""
if !stats.reachable {
reachableStr = "- unreachable!"
}
printOwned(peer, stats.nickname, reachableStr, stats.ips)
}
}
@@ -94,7 +89,7 @@ var rootTemplate = template.New("root").Funcs(map[string]interface{}{
for _, conn := range conns {
counts[conn.State]++
}
return printCounts(counts, []string{"established", "pending", "retrying", "failed", "connecting"})
return printCounts(counts, allConnectionStates)
},
"printPeerConnectionCounts": func(peers []mesh.PeerStatus) string {
counts := make(map[string]int)
@@ -118,6 +113,26 @@ var rootTemplate = template.New("root").Funcs(map[string]interface{}{
"trimSuffix": strings.TrimSuffix,
})
func countDNSEntries(entries []nameserver.EntryStatus) int {
count := 0
for _, entry := range entries {
if entry.Tombstone == 0 {
count++
}
}
return count
}
func countDNSEntriesForPeer(peername string, entries []nameserver.EntryStatus) int {
count := 0
for _, entry := range entries {
if entry.Tombstone == 0 && entry.Origin == peername {
count++
}
}
return count
}
// Print counts in a specified order
func printCounts(counts map[string]int, keys []string) string {
var stringCounts []string
@@ -196,7 +211,7 @@ var targetsTemplate = defTemplate("targetsTemplate", `\
var connectionsTemplate = defTemplate("connectionsTemplate", `\
{{range .Router.Connections}}\
{{if .Outbound}}->{{else}}<-{{end}} {{printf "%-21v" .Address}} {{printf "%-11v" .State}} {{.Info}}
{{if .Outbound}}->{{else}}<-{{end}} {{printf "%-21v" .Address}} {{printf "%-11v" .State}} {{.Info}} {{range $key,$element := .Attrs}}{{if ne $key "name"}}{{$key}}={{$element}}{{end}}{{end}}
{{end}}\
`)
@@ -225,6 +240,7 @@ var ipamTemplate = defTemplate("ipamTemplate", `{{printIPAMRanges .Router .IPAM}
type VersionCheck struct {
Enabled bool
Success bool
NewVersion string
NextCheckAt time.Time
}
@@ -236,6 +252,7 @@ func versionCheck() *VersionCheck {
}
v.Enabled = true
v.Success = success.Load().(bool)
v.NewVersion = newVersion.Load().(string)
v.NextCheckAt = checker.NextCheckAt()
@@ -246,12 +263,12 @@ func (v *VersionCheck) String() string {
switch {
case !v.Enabled:
return "version check update disabled"
case !v.Success:
return fmt.Sprintf("failed to check latest version - see logs; next check at %s", v.NextCheckAt.Format("2006/01/02 15:04:05"))
case v.NewVersion != "":
return fmt.Sprintf("version %s available - please upgrade!",
v.NewVersion)
return fmt.Sprintf("version %s available - please upgrade!", v.NewVersion)
default:
return fmt.Sprintf("up to date; next check at %s",
v.NextCheckAt.Format("2006/01/02 15:04:05"))
return fmt.Sprintf("up to date; next check at %s", v.NextCheckAt.Format("2006/01/02 15:04:05"))
}
}
@@ -263,6 +280,7 @@ type WeaveStatus struct {
DNS *nameserver.Status `json:"DNS,omitempty"`
}
// Read-only functions, suitable for exposing on an unprotected socket
func HandleHTTP(muxRouter *mux.Router, version string, router *weave.NetworkRouter, allocator *ipam.Allocator, defaultSubnet address.CIDR, ns *nameserver.Nameserver, dnsserver *nameserver.DNSServer) {
status := func() WeaveStatus {
return WeaveStatus{
+48 -21
View File
@@ -11,9 +11,10 @@ import (
"strings"
"time"
"github.com/docker/docker/pkg/mflag"
"github.com/gorilla/mux"
"github.com/pkg/profile"
"github.com/weaveworks/common/mflag"
"github.com/weaveworks/common/signals"
"github.com/weaveworks/mesh"
"github.com/weaveworks/weave/common"
@@ -27,7 +28,7 @@ import (
weave "github.com/weaveworks/weave/router"
)
var version = "(unreleased version)"
var version = "unreleased"
var Log = common.Log
@@ -132,6 +133,7 @@ func main() {
bufSzMB int
noDiscovery bool
httpAddr string
statusAddr string
ipamConfig ipamConfig
dockerAPI string
peers []string
@@ -165,6 +167,7 @@ func main() {
mflag.BoolVar(&noDiscovery, []string{"#nodiscovery", "#-nodiscovery", "-no-discovery"}, false, "disable peer discovery")
mflag.IntVar(&bufSzMB, []string{"#bufsz", "-bufsz"}, 8, "capture buffer size in MB")
mflag.StringVar(&httpAddr, []string{"#httpaddr", "#-httpaddr", "-http-addr"}, "", "address to bind HTTP interface to (disabled if blank, absolute path indicates unix domain socket)")
mflag.StringVar(&statusAddr, []string{"-status-addr"}, "", "address to bind status+metrics interface to (disabled if blank, absolute path indicates unix domain socket)")
mflag.StringVar(&ipamConfig.Mode, []string{"-ipalloc-init"}, "", "allocator initialisation strategy (consensus, seed or observer)")
mflag.StringVar(&ipamConfig.IPRangeCIDR, []string{"#iprange", "#-iprange", "-ipalloc-range"}, "", "IP address range reserved for automatic allocation, in CIDR notation")
mflag.StringVar(&ipamConfig.IPSubnetCIDR, []string{"#ipsubnet", "#-ipsubnet", "-ipalloc-default-subnet"}, "", "subnet to allocate within by default, in CIDR notation")
@@ -180,7 +183,7 @@ func main() {
mflag.StringVar(&datapathName, []string{"-datapath"}, "", "ODP datapath name")
mflag.StringVar(&trustedSubnetStr, []string{"-trusted-subnets"}, "", "comma-separated list of trusted subnets in CIDR notation")
mflag.StringVar(&dbPrefix, []string{"-db-prefix"}, "/weavedb/weave", "pathname/prefix of filename to store data")
mflag.BoolVar(&isAWSVPC, []string{"#awsvpc", "-awsvpc"}, false, "use AWS VPC for routing")
mflag.BoolVar(&isAWSVPC, []string{"-awsvpc"}, false, "use AWS VPC for routing")
// crude way of detecting that we probably have been started in a
// container, with `weave launch` --> suppress misleading paths in
@@ -194,7 +197,7 @@ func main() {
peers = mflag.Args()
if resume && len(peers) > 0 {
Log.Fatalf("You must not specify an initial peer list in conjuction with --resume")
Log.Fatalf("You must not specify an initial peer list in conjunction with --resume")
}
common.SetLogLevel(logLevel)
@@ -221,10 +224,18 @@ func main() {
networkConfig.PacketLogging = nopPacketLogging{}
}
overlay, bridge := createOverlay(datapathName, ifaceName, isAWSVPC, config.Host, config.Port, bufSzMB)
config.Password = determinePassword(password)
overlay, bridge := createOverlay(datapathName, ifaceName, isAWSVPC, config.Host, config.Port, bufSzMB, config.Password != nil)
networkConfig.Bridge = bridge
name := peerName(routerName, bridge.Interface())
if bridge != nil {
if err := weavenet.DetectHairpin("vethwe-bridge", Log); err != nil {
Log.Errorf("DetectHairpin failed: %s", err)
}
}
name := peerName(routerName)
if nickName == "" {
var err error
@@ -232,7 +243,6 @@ func main() {
checkFatal(err)
}
config.Password = determinePassword(password)
config.TrustedSubnets = parseTrustedSubnets(trustedSubnetStr)
config.PeerDiscovery = !noDiscovery
@@ -240,7 +250,7 @@ func main() {
Log.Fatalf("--awsvpc mode is not compatible with the --password option")
}
db, err := db.NewBoltDB(dbPrefix + "data.db")
db, err := db.NewBoltDB(dbPrefix + db.FileName)
checkFatal(err)
defer db.Close()
@@ -252,6 +262,7 @@ func main() {
}
var dockerCli *docker.Client
dockerVersion := "none"
if dockerAPI != "" {
dc, err := docker.NewClient(dockerAPI)
if err != nil {
@@ -260,13 +271,14 @@ func main() {
Log.Info(dc.Info())
}
dockerCli = dc
dockerVersion = dockerCli.DockerVersion()
}
network := ""
if isAWSVPC {
network = "awsvpc"
}
checkForUpdates(dockerCli.DockerVersion(), network)
checkForUpdates(dockerVersion, network)
observeContainers := func(o docker.ContainerObserver) {
if dockerCli != nil {
@@ -296,9 +308,11 @@ func main() {
}
allocator, defaultSubnet = createAllocator(router, ipamConfig, db, t, isKnownPeer)
observeContainers(allocator)
ids, err := dockerCli.AllContainerIDs()
checkFatal(err)
allocator.PruneOwned(ids)
if dockerCli != nil {
ids, err := dockerCli.AllContainerIDs()
checkFatal(err)
allocator.PruneOwned(ids)
}
}
var (
@@ -318,6 +332,7 @@ func main() {
if errors := router.InitiateConnections(peers, false); len(errors) > 0 {
Log.Fatal(common.ErrorMessages(errors))
}
checkFatal(router.CreateRestartSentinel())
// The weave script always waits for a status call to succeed,
// so there is no point in doing "weave launch --http-addr ''".
@@ -332,12 +347,23 @@ func main() {
}
router.HandleHTTP(muxRouter)
HandleHTTP(muxRouter, version, router, allocator, defaultSubnet, ns, dnsserver)
muxRouter.Methods("GET").Path("/metrics").Handler(metricsHandler(router, allocator, ns, dnsserver))
http.Handle("/", common.LoggingHTTPHandler(muxRouter))
Log.Println("Listening for HTTP control messages on", httpAddr)
go listenAndServeHTTP(httpAddr)
go listenAndServeHTTP(httpAddr, nil)
}
common.SignalHandlerLoop(router)
if statusAddr != "" {
muxRouter := mux.NewRouter()
HandleHTTP(muxRouter, version, router, allocator, defaultSubnet, ns, dnsserver)
muxRouter.Methods("GET").Path("/metrics").Handler(metricsHandler(router, allocator, ns, dnsserver))
statusMux := http.NewServeMux()
statusMux.Handle("/", muxRouter)
Log.Println("Listening for metrics requests on", statusAddr)
go listenAndServeHTTP(statusAddr, statusMux)
}
signals.SignalHandlerLoop(common.Log, router)
}
func options() map[string]string {
@@ -380,7 +406,7 @@ func (nopPacketLogging) LogPacket(string, weave.PacketKey) {
func (nopPacketLogging) LogForwardPacket(string, weave.ForwardPacketKey) {
}
func createOverlay(datapathName string, ifaceName string, isAWSVPC bool, host string, port int, bufSzMB int) (weave.NetworkOverlay, weave.Bridge) {
func createOverlay(datapathName string, ifaceName string, isAWSVPC bool, host string, port int, bufSzMB int, enableEncryption bool) (weave.NetworkOverlay, weave.Bridge) {
overlay := weave.NewOverlaySwitch()
var bridge weave.Bridge
var ignoreSleeve bool
@@ -397,7 +423,7 @@ func createOverlay(datapathName string, ifaceName string, isAWSVPC bool, host st
case datapathName != "":
iface, err := weavenet.EnsureInterface(datapathName)
checkFatal(err)
fastdp, err := weave.NewFastDatapath(iface, port)
fastdp, err := weave.NewFastDatapath(iface, port, enableEncryption)
checkFatal(err)
bridge = fastdp.Bridge()
overlay.Add("fastdp", fastdp.Overlay())
@@ -504,10 +530,11 @@ func determinePassword(password string) []byte {
return []byte(password)
}
func peerName(routerName string, iface *net.Interface) mesh.PeerName {
func peerName(routerName string) mesh.PeerName {
if routerName == "" {
if iface == nil {
Log.Fatal("Either an interface must be specified with --datapath or --iface, or a name with --name")
iface, err := net.InterfaceByName(weavenet.WeaveBridgeName)
if err != nil {
Log.Fatalf("Unable to find bridge %q", weavenet.WeaveBridgeName)
}
routerName = iface.HardwareAddr.String()
}
@@ -550,7 +577,7 @@ func parsePeerNames(s string) ([]mesh.PeerName, error) {
return peerNames, nil
}
func listenAndServeHTTP(httpAddr string) {
func listenAndServeHTTP(httpAddr string, handler http.Handler) {
protocol := "tcp"
if strings.HasPrefix(httpAddr, "/") {
os.Remove(httpAddr) // in case it's there from last time
@@ -560,7 +587,7 @@ func listenAndServeHTTP(httpAddr string) {
if err != nil {
Log.Fatal("Unable to create http listener socket: ", err)
}
err = http.Serve(l, nil)
err = http.Serve(l, handler)
if err != nil {
Log.Fatal("Unable to create http server", err)
}
+123
View File
@@ -0,0 +1,123 @@
package main
import (
"net/http"
"os"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/weaveworks/weave/ipam"
"github.com/weaveworks/weave/nameserver"
"github.com/weaveworks/weave/net/address"
weave "github.com/weaveworks/weave/router"
)
func metricsHandler(router *weave.NetworkRouter, allocator *ipam.Allocator, ns *nameserver.Nameserver, dnsserver *nameserver.DNSServer) http.Handler {
reg := prometheus.NewRegistry()
reg.MustRegister(prometheus.NewProcessCollector(os.Getpid(), ""))
reg.MustRegister(newMetrics(router, allocator, ns, dnsserver))
return promhttp.HandlerFor(reg, promhttp.HandlerOpts{})
}
type collector struct {
router *weave.NetworkRouter
allocator *ipam.Allocator
ns *nameserver.Nameserver
dnsserver *nameserver.DNSServer
}
type metric struct {
*prometheus.Desc
Collect func(WeaveStatus, *prometheus.Desc, chan<- prometheus.Metric)
}
func desc(fqName, help string, variableLabels ...string) *prometheus.Desc {
return prometheus.NewDesc(fqName, help, variableLabels, prometheus.Labels{})
}
func intGauge(desc *prometheus.Desc, val int, labels ...string) prometheus.Metric {
return prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, float64(val), labels...)
}
func uint64Counter(desc *prometheus.Desc, val uint64, labels ...string) prometheus.Metric {
return prometheus.MustNewConstMetric(desc, prometheus.CounterValue, float64(val), labels...)
}
var metrics = []metric{
{desc("weave_connections", "Number of peer-to-peer connections.", "state"),
func(s WeaveStatus, desc *prometheus.Desc, ch chan<- prometheus.Metric) {
counts := make(map[string]int)
for _, conn := range s.Router.Connections {
counts[conn.State]++
}
for _, state := range allConnectionStates {
ch <- intGauge(desc, counts[state], state)
}
}},
{desc("weave_connection_terminations_total", "Number of peer-to-peer connections terminated."),
func(s WeaveStatus, desc *prometheus.Desc, ch chan<- prometheus.Metric) {
ch <- uint64Counter(desc, uint64(s.Router.TerminationCount))
}},
{desc("weave_ips", "Number of IP addresses.", "state"),
func(s WeaveStatus, desc *prometheus.Desc, ch chan<- prometheus.Metric) {
if s.IPAM != nil {
ch <- intGauge(desc, s.IPAM.ActiveIPs, "local-used")
}
}},
{desc("weave_max_ips", "Size of IP address space used by allocator."),
func(s WeaveStatus, desc *prometheus.Desc, ch chan<- prometheus.Metric) {
if s.IPAM != nil {
ch <- intGauge(desc, s.IPAM.RangeNumIPs)
}
}},
{desc("weave_dns_entries", "Number of DNS entries."),
func(s WeaveStatus, desc *prometheus.Desc, ch chan<- prometheus.Metric) {
if s.DNS != nil {
ch <- intGauge(desc, countDNSEntriesForPeer(s.Router.Name, s.DNS.Entries))
}
}},
{desc("weave_flows", "Number of FastDP flows."),
func(s WeaveStatus, desc *prometheus.Desc, ch chan<- prometheus.Metric) {
if metrics := fastDPMetrics(s); metrics != nil {
ch <- intGauge(desc, metrics.Flows)
}
}},
}
func fastDPMetrics(s WeaveStatus) *weave.FastDPMetrics {
if diagMap, ok := s.Router.OverlayDiagnostics.(map[string]interface{}); ok {
if diag, ok := diagMap["fastdp"]; ok {
if fastDPStats, ok := diag.(weave.FastDPStatus); ok {
return fastDPStats.Metrics().(*weave.FastDPMetrics)
}
}
}
return nil
}
func newMetrics(router *weave.NetworkRouter, allocator *ipam.Allocator, ns *nameserver.Nameserver, dnsserver *nameserver.DNSServer) *collector {
return &collector{
router: router,
allocator: allocator,
ns: ns,
dnsserver: dnsserver,
}
}
func (m *collector) Collect(ch chan<- prometheus.Metric) {
status := WeaveStatus{"", nil,
weave.NewNetworkRouterStatus(m.router),
ipam.NewStatus(m.allocator, address.CIDR{}),
nameserver.NewStatus(m.ns, m.dnsserver)}
for _, metric := range metrics {
metric.Collect(status, metric.Desc, ch)
}
}
func (m *collector) Describe(ch chan<- *prometheus.Desc) {
for _, metric := range metrics {
ch <- metric.Desc
}
}
+58 -23
View File
@@ -2,8 +2,10 @@ package main
import (
"fmt"
"github.com/fsouza/go-dockerclient"
"github.com/weaveworks/weave/common"
weavenet "github.com/weaveworks/weave/net"
)
func containerAddrs(args []string) error {
@@ -12,46 +14,79 @@ func containerAddrs(args []string) error {
}
bridgeName := args[0]
c, err := docker.NewVersionedClientFromEnv("1.18")
client, err := docker.NewVersionedClientFromEnv("1.18")
if err != nil {
return err
}
for _, containerID := range args[1:] {
netDevs, err := getNetDevs(bridgeName, c, containerID)
if err != nil {
peerIDs, err := weavenet.ConnectedToBridgeVethPeerIds(bridgeName)
if err != nil {
if err == weavenet.ErrLinkNotFound {
return nil
}
return err
}
var containerIDs []string
containers := make(map[string]*docker.Container)
for _, cid := range args[1:] {
if cid == "weave:expose" {
netDev, err := weavenet.GetBridgeNetDev(bridgeName)
if err != nil {
return err
}
printNetDevs(cid, []weavenet.Dev{netDev})
continue
}
if containers[cid], err = client.InspectContainer(cid); err != nil {
if _, ok := err.(*docker.NoSuchContainer); ok {
continue
}
return err
}
// To output in the right order, we keep the list of container IDs
containerIDs = append(containerIDs, cid)
}
for _, netDev := range netDevs {
fmt.Printf("%12s %s %s", containerID, netDev.Name, netDev.MAC.String())
for _, cidr := range netDev.CIDRs {
prefixLength, _ := cidr.Mask.Size()
fmt.Printf(" %v/%v", cidr.IP, prefixLength)
}
fmt.Println()
for _, cid := range containerIDs {
netDevs, err := getNetDevs(client, containers[cid], peerIDs)
if err != nil {
return err
}
printNetDevs(cid, netDevs)
}
return nil
}
func getNetDevs(bridgeName string, c *docker.Client, containerID string) ([]common.NetDev, error) {
if containerID == "weave:expose" {
return common.GetBridgeNetDev(bridgeName)
}
container, err := c.InspectContainer(containerID)
if err != nil {
return nil, err
}
func getNetDevs(c *docker.Client, container *docker.Container, peerIDs []int) ([]weavenet.Dev, error) {
if container.State.Pid == 0 {
return nil, nil
}
return weavenet.GetNetDevsByVethPeerIds(container.State.Pid, peerIDs)
}
return common.GetWeaveNetDevs(container.State.Pid)
func printNetDevs(cid string, netDevs []weavenet.Dev) {
for _, netDev := range netDevs {
fmt.Printf("%12s %s %s", cid, netDev.Name, netDev.MAC.String())
for _, cidr := range netDev.CIDRs {
prefixLength, _ := cidr.Mask.Size()
fmt.Printf(" %v/%v", cidr.IP, prefixLength)
}
fmt.Println()
}
}
func bridgeIP(args []string) error {
if len(args) < 1 {
cmdUsage("bridge-ip", "<bridgeName>")
}
bridgeName := args[0]
ip, err := weavenet.FindBridgeIP(bridgeName, nil)
if err != nil {
return err
}
fmt.Printf("%v", ip)
return nil
}
+15 -14
View File
@@ -32,14 +32,19 @@ func attach(args []string) error {
}
}
pid, nsContainer, err := containerPidAndNs(args[0])
pid, err := containerPid(args[0])
if err != nil {
return err
}
nsContainer, err := netns.GetFromPid(pid)
if err != nil {
return fmt.Errorf("unable to open namespace for container %s: %s", args[0], err)
}
if nsHost, err := netns.GetFromPid(1); err != nil {
return fmt.Errorf("unable to open host namespace: %s", err)
} else if nsHost.Equal(nsContainer) {
return fmt.Errorf("Container is running in the host network namespace, and therefore cannot be\nconnected to weave. Perhaps the container was started with --net=host.")
return fmt.Errorf("Container is running in the host network namespace, and therefore cannot be\nconnected to weave - perhaps the container was started with --net=host")
}
mtu, err := strconv.Atoi(args[2])
if err != nil && args[3] != "" {
@@ -50,7 +55,7 @@ func attach(args []string) error {
return err
}
err = weavenet.AttachContainer(nsContainer, fmt.Sprint(pid), weavenet.VethName, args[1], mtu, withMulticastRoute, cidrs, keepTXOn)
err = weavenet.AttachContainer(weavenet.NSPathByPid(pid), fmt.Sprint(pid), weavenet.VethName, args[1], mtu, withMulticastRoute, cidrs, keepTXOn)
// If we detected an error but the container has died, tell the user that instead.
if err != nil && !processExists(pid) {
err = fmt.Errorf("Container %s died", args[0])
@@ -58,23 +63,19 @@ func attach(args []string) error {
return err
}
func containerPidAndNs(containerID string) (int, netns.NsHandle, error) {
func containerPid(containerID string) (int, error) {
c, err := docker.NewVersionedClientFromEnv("1.18")
if err != nil {
return 0, 0, fmt.Errorf("unable to connect to docker: %s", err)
return 0, fmt.Errorf("unable to connect to docker: %s", err)
}
container, err := c.InspectContainer(containerID)
if err != nil {
return 0, 0, fmt.Errorf("unable to inspect container %s: %s", containerID, err)
return 0, fmt.Errorf("unable to inspect container %s: %s", containerID, err)
}
if container.State.Pid == 0 {
return 0, 0, fmt.Errorf("container %s not running", containerID)
return 0, fmt.Errorf("container %s not running", containerID)
}
ns, err := netns.GetFromPid(container.State.Pid)
if err != nil {
return 0, 0, fmt.Errorf("unable to open namespace for container %s: %s", containerID, err)
}
return container.State.Pid, ns, nil
return container.State.Pid, nil
}
func processExists(pid int) bool {
@@ -99,7 +100,7 @@ func detach(args []string) error {
cmdUsage("detach-container", "<container-id> <cidr>...")
}
_, ns, err := containerPidAndNs(args[0])
pid, err := containerPid(args[0])
if err != nil {
return err
}
@@ -107,5 +108,5 @@ func detach(args []string) error {
if err != nil {
return err
}
return weavenet.DetachContainer(ns, args[0], weavenet.VethName, cidrs)
return weavenet.DetachContainer(weavenet.NSPathByPid(pid), args[0], weavenet.VethName, cidrs)
}
+26
View File
@@ -0,0 +1,26 @@
package main
import (
"os"
cni "github.com/appc/cni/pkg/skel"
weaveapi "github.com/weaveworks/weave/api"
"github.com/weaveworks/weave/common"
ipamplugin "github.com/weaveworks/weave/plugin/ipam"
netplugin "github.com/weaveworks/weave/plugin/net"
)
func cniNet(args []string) error {
weave := weaveapi.NewClient(os.Getenv("WEAVE_HTTP_ADDR"), common.Log)
n := netplugin.NewCNIPlugin(weave)
cni.PluginMain(n.CmdAdd, n.CmdDel)
return nil
}
func cniIPAM(args []string) error {
weave := weaveapi.NewClient(os.Getenv("WEAVE_HTTP_ADDR"), common.Log)
i := ipamplugin.NewIpam(weave)
cni.PluginMain(i.CmdAdd, i.CmdDel)
return nil
}
+5 -7
View File
@@ -8,6 +8,8 @@ import (
"path/filepath"
"strconv"
"strings"
"github.com/weaveworks/weave/common"
)
func dockerTLSArgs(args []string) error {
@@ -15,18 +17,14 @@ func dockerTLSArgs(args []string) error {
cmdUsage("docker-tls-args", "")
}
procRoot := "/proc"
dirEntries, err := ioutil.ReadDir(procRoot)
pids, err := common.AllPids(procRoot)
if err != nil {
return err
}
for _, dirEntry := range dirEntries {
dirName := dirEntry.Name()
if _, err := strconv.Atoi(dirName); err != nil {
continue
}
for _, pid := range pids {
isDaemon := false
dirName := strconv.Itoa(pid)
if comm, err := ioutil.ReadFile(filepath.Join(procRoot, dirName, "comm")); err != nil {
continue
} else if string(comm) == "dockerd\n" {
+23
View File
@@ -0,0 +1,23 @@
package main
import (
weavenet "github.com/weaveworks/weave/net"
)
func exposeNAT(args []string) error {
if len(args) < 1 {
cmdUsage("expose-nat", "<cidr>...")
}
cidrs, err := parseCIDRs(args)
if err != nil {
return err
}
for _, cidr := range cidrs {
if err := weavenet.ExposeNAT(*cidr); err != nil {
return err
}
}
return nil
}
+33
View File
@@ -4,6 +4,10 @@ package main
import (
"fmt"
"os"
"path/filepath"
"strings"
weavenet "github.com/weaveworks/weave/net"
)
var commands map[string]func([]string) error
@@ -20,12 +24,41 @@ func init() {
"create-plugin-network": createPluginNetwork,
"remove-plugin-network": removePluginNetwork,
"container-addrs": containerAddrs,
"process-addrs": processAddrs,
"attach-container": attach,
"detach-container": detach,
"configure-arp": configureARP,
"check-iface": checkIface,
"del-iface": delIface,
"setup-iface": setupIface,
"list-netdevs": listNetDevs,
"cni-net": cniNet,
"cni-ipam": cniIPAM,
"expose-nat": exposeNAT,
"bridge-ip": bridgeIP,
"unique-id": uniqueID,
}
}
func main() {
// force re-exec of this binary
selfPath, err := filepath.EvalSymlinks("/proc/self/exe")
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
weavenet.WeaveUtilCmd = selfPath
// If no args passed, act as CNI plugin based on executable name
switch {
case len(os.Args) == 1 && strings.HasSuffix(os.Args[0], "weave-ipam"):
cniIPAM(os.Args)
os.Exit(0)
case len(os.Args) == 1 && strings.HasSuffix(os.Args[0], "weave-net"):
cniNet(os.Args)
os.Exit(0)
}
if len(os.Args) < 2 {
usage()
os.Exit(1)
Loaded 100 of 232 files, more files were not shown because too many files have changed in this diff. Show more