Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0aac614c08 | ||
|
|
cd4cbed5a0 | ||
|
|
7a81bc2ddc | ||
|
|
6df2782d73 | ||
|
|
3fc7efa536 | ||
|
|
71e43c2023 | ||
|
|
370f258c3a | ||
|
|
9b32bc2ab3 | ||
|
|
fd5e1970e1 | ||
|
|
a1de7f3eef | ||
|
|
c720ebec02 | ||
|
|
6a528409ab | ||
|
|
c69e140e9e | ||
|
|
8ed0c13645 | ||
|
|
b635f9a994 | ||
|
|
ac4246e1f5 | ||
|
|
3d12e8088e | ||
|
|
aee35b34fe | ||
|
|
c06ccb3b0d | ||
|
|
268bb656fc | ||
|
|
a335c419ec | ||
|
|
48c9547943 | ||
|
|
11f56031f1 | ||
|
|
ebe4c5b8b7 | ||
|
|
9fddb827f9 | ||
|
|
3162009325 | ||
|
|
8c8c6db7dd | ||
|
|
cd94dd0088 | ||
|
|
afc6f49e80 | ||
|
|
c509b6e5bb | ||
|
|
c79b6a8bd7 | ||
|
|
c2083cbce0 | ||
|
|
4157d9298d | ||
|
|
432e10e19f | ||
|
|
601bda3176 | ||
|
|
d9bde790c6 | ||
|
|
96f2eb3ecf | ||
|
|
1c0ffbc177 | ||
|
|
c0592ba1b3 | ||
|
|
0cbf5ca130 | ||
|
|
081b95dfd0 | ||
|
|
faf5b14d8b | ||
|
|
38958049f4 | ||
|
|
7ebf3d7a88 | ||
|
|
e8d823d66b | ||
|
|
ed83efbceb | ||
|
|
223116c4bf | ||
|
|
8056a098a8 | ||
|
|
15a2cba7f8 | ||
|
|
b37bb02a8b | ||
|
|
0c14e5135a | ||
|
|
b06ddeb962 | ||
|
|
f6e6926171 | ||
|
|
25e7868cd5 | ||
|
|
385e6ff9b8 | ||
|
|
3755906689 | ||
|
|
63cbb34dec | ||
|
|
369852a3a7 | ||
|
|
c82be57639 | ||
|
|
092c3a17d1 | ||
|
|
fd0a7efa23 | ||
|
|
acdd739deb | ||
|
|
45e3016c6a | ||
|
|
c1483dbf1f | ||
|
|
bce07b7491 | ||
|
|
8b5741506d | ||
|
|
e642f366f5 | ||
|
|
d794b203f7 | ||
|
|
7ec68119a6 | ||
|
|
93c60395f6 | ||
|
|
af27aa04f2 | ||
|
|
0861d05522 | ||
|
|
89221f117b | ||
|
|
7f5c37ef1e | ||
|
|
05baa566c6 | ||
|
|
e5c23bf9f5 | ||
|
|
0635ed1854 | ||
|
|
4424e877f0 | ||
|
|
aa54d332c2 | ||
|
|
e5aeb4bd05 | ||
|
|
566ed64607 | ||
|
|
83c358c8d2 | ||
|
|
ae95248499 | ||
|
|
53b8c804f2 | ||
|
|
7d0aaea6e8 | ||
|
|
45a66ac517 | ||
|
|
087d948941 | ||
|
|
72e92db96e | ||
|
|
768414534f | ||
|
|
f1ca4854b8 | ||
|
|
6319860230 | ||
|
|
58caf38f07 | ||
|
|
cb4b5fd143 | ||
|
|
7165414fc3 | ||
|
|
d72d3af36e | ||
|
|
f07ed7153b | ||
|
|
6c46af25cc |
No files matched your search
+38
-1
@@ -1,3 +1,40 @@
|
||||
## 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 +45,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,
|
||||
|
||||
@@ -165,10 +165,10 @@ $(RUNNER_EXE): tools/.git
|
||||
make -C tools/runner
|
||||
|
||||
$(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)
|
||||
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker tag $(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
|
||||
$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker push $(DOCKERHUB_USER)/$*:latest
|
||||
endif
|
||||
|
||||
publish: $(PUBLISH)
|
||||
|
||||
+1
-1
@@ -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"
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@ machine:
|
||||
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
|
||||
|
||||
dependencies:
|
||||
@@ -18,13 +18,13 @@ dependencies:
|
||||
- "~/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"
|
||||
- "sudo chown -R ubuntu /usr/local/go"
|
||||
|
||||
test:
|
||||
override:
|
||||
|
||||
+62
-35
@@ -48,14 +48,14 @@ func FindNetDevs(processID int, match func(link netlink.Link) bool) ([]NetDev, e
|
||||
}
|
||||
defer ns.Close()
|
||||
|
||||
err = weavenet.WithNetNS(ns, func() error {
|
||||
err = weavenet.WithNetNSUnsafe(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)
|
||||
netDevs = append(netDevs, netDev)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
@@ -77,67 +77,94 @@ func forEachLink(f func(netlink.Link) error) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func linkToNetDev(link netlink.Link) (*NetDev, error) {
|
||||
func linkToNetDev(link netlink.Link) (NetDev, error) {
|
||||
addrs, err := netlink.AddrList(link, netlink.FAMILY_V4)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return NetDev{}, err
|
||||
}
|
||||
|
||||
netDev := &NetDev{Name: link.Attrs().Name, MAC: link.Attrs().HardwareAddr}
|
||||
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) {
|
||||
// ConnectedToBridgePredicate returns a function which is used to query whether
|
||||
// a given link is a veth interface which one end is connected to a bridge.
|
||||
// The returned function should be called from a container network namespace which
|
||||
// the bridge does NOT belong to.
|
||||
func ConnectedToBridgePredicate(bridgeName string) (func(link netlink.Link) bool, error) {
|
||||
indexes := make(map[int]struct{})
|
||||
|
||||
// Scan devices in root namespace to find those attached to weave bridge
|
||||
err := weavenet.WithNetNSLinkByPidUnsafe(1, bridgeName,
|
||||
func(br netlink.Link) error {
|
||||
return forEachLink(func(link netlink.Link) error {
|
||||
if link.Attrs().MasterIndex == br.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 func(link netlink.Link) bool {
|
||||
_, isveth := link.(*netlink.Veth)
|
||||
_, found := indexes[link.Attrs().Index]
|
||||
return isveth && found
|
||||
}, nil
|
||||
}
|
||||
|
||||
func GetNetDevsWithPredicate(processID int, predicate func(link netlink.Link) bool) ([]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)
|
||||
}
|
||||
defer nsToplevel.Close()
|
||||
nsContainr, err := netns.GetFromPid(processID)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, fmt.Errorf("unable to open process %d namespace: %s", processID, err)
|
||||
}
|
||||
defer nsContainr.Close()
|
||||
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
|
||||
})
|
||||
return FindNetDevs(processID, predicate)
|
||||
}
|
||||
|
||||
// Lookup the weave interface of a container
|
||||
func GetWeaveNetDevs(processID int) ([]NetDev, error) {
|
||||
p, err := ConnectedToBridgePredicate("weave")
|
||||
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
|
||||
})
|
||||
|
||||
return GetNetDevsWithPredicate(processID, p)
|
||||
}
|
||||
|
||||
// Get the weave bridge interface
|
||||
func GetBridgeNetDev(bridgeName string) ([]NetDev, error) {
|
||||
return FindNetDevs(1, func(link netlink.Link) bool {
|
||||
return link.Attrs().Name == bridgeName
|
||||
})
|
||||
// Get the weave bridge interface.
|
||||
// NB: Should be called from the root network namespace.
|
||||
func GetBridgeNetDev(bridgeName string) (NetDev, error) {
|
||||
link, err := netlink.LinkByName(bridgeName)
|
||||
if err != nil {
|
||||
return NetDev{}, err
|
||||
}
|
||||
|
||||
return linkToNetDev(link)
|
||||
}
|
||||
|
||||
// Do post-attach configuration of all veths we have created
|
||||
|
||||
@@ -119,6 +119,8 @@ func New(start, end address.Address, peer mesh.PeerName, f OnUpdate) *Ring {
|
||||
}
|
||||
|
||||
func (r *Ring) Restore(other *Ring) {
|
||||
defer r.trackUpdates()()
|
||||
|
||||
onUpdate := r.onUpdate
|
||||
*r = *other
|
||||
r.onUpdate = onUpdate
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
+20
-12
@@ -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)))
|
||||
}
|
||||
+31
-3
@@ -1,13 +1,28 @@
|
||||
package net
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"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 +41,25 @@ 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)
|
||||
})
|
||||
}
|
||||
|
||||
func WithNetNSLinkByPidUnsafe(pid int, ifName string, work func(link netlink.Link) error) error {
|
||||
ns, err := netns.GetFromPid(pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer ns.Close()
|
||||
|
||||
return WithNetNSLinkUnsafe(ns, ifName, work)
|
||||
}
|
||||
+4
-4
@@ -104,7 +104,7 @@ const (
|
||||
)
|
||||
|
||||
func interfaceExistsInNamespace(ns netns.NsHandle, ifName string) bool {
|
||||
err := WithNetNS(ns, func() error {
|
||||
err := WithNetNSUnsafe(ns, func() error {
|
||||
_, err := netlink.LinkByName(ifName)
|
||||
return err
|
||||
})
|
||||
@@ -122,7 +122,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 := WithNetNSUnsafe(ns, func() error {
|
||||
if err := netlink.LinkSetName(veth, ifName); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -140,7 +140,7 @@ 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
|
||||
@@ -177,7 +177,7 @@ func AttachContainer(ns netns.NsHandle, id, ifName, bridgeName string, mtu int,
|
||||
}
|
||||
|
||||
func DetachContainer(ns netns.NsHandle, id, ifName string, cidrs []*net.IPNet) error {
|
||||
return WithNetNSLink(ns, ifName, func(veth netlink.Link) error {
|
||||
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)
|
||||
|
||||
+46
-21
@@ -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,26 @@ 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 {
|
||||
if err == 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)
|
||||
}
|
||||
bridgeIP = bridgeIPResult.IP4.IP.IP
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
result.IP4.Gateway = bridgeIP
|
||||
@@ -95,7 +110,7 @@ func (c *CNIPlugin) CmdAdd(args *skel.CmdArgs) error {
|
||||
if err := weavenet.AttachContainer(ns, 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 +145,34 @@ func setupRoutes(link netlink.Link, name string, ipnet net.IPNet, gw net.IP, rou
|
||||
return nil
|
||||
}
|
||||
|
||||
func assignBridgeIP(bridgeName string, ipnet net.IPNet) error {
|
||||
link, err := netlink.LinkByName(bridgeName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := netlink.AddrAdd(link, &netlink.Addr{IPNet: &ipnet}); err != nil {
|
||||
return fmt.Errorf("failed to add IP address to %q: %v", bridgeName, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var errBridgeNoIP = fmt.Errorf("Bridge has no IP address")
|
||||
|
||||
func findBridgeIP(bridgeName string, subnet net.IPNet) (net.IP, error) {
|
||||
netdevs, err := common.GetBridgeNetDev(bridgeName)
|
||||
netdev, err := common.GetBridgeNetDev(bridgeName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to get netdev for %q bridge: %s", bridgeName, err)
|
||||
}
|
||||
if len(netdevs) == 0 {
|
||||
return nil, fmt.Errorf("Could not find %q bridge", bridgeName)
|
||||
if len(netdev.CIDRs) == 0 {
|
||||
return nil, errBridgeNoIP
|
||||
}
|
||||
if len(netdevs[0].CIDRs) == 0 {
|
||||
return nil, fmt.Errorf("Bridge %q has no IP addresses", bridgeName)
|
||||
}
|
||||
for _, cidr := range netdevs[0].CIDRs {
|
||||
for _, cidr := range netdev.CIDRs {
|
||||
if subnet.Contains(cidr.IP) {
|
||||
return cidr.IP, nil
|
||||
}
|
||||
}
|
||||
// None in the required subnet; just return the first one
|
||||
return netdevs[0].CIDRs[0].IP, nil
|
||||
return netdev.CIDRs[0].IP, nil
|
||||
}
|
||||
|
||||
func (c *CNIPlugin) CmdDel(args *skel.CmdArgs) error {
|
||||
@@ -161,7 +186,7 @@ func (c *CNIPlugin) CmdDel(args *skel.CmdArgs) error {
|
||||
return err
|
||||
}
|
||||
defer ns.Close()
|
||||
err = weavenet.WithNetNS(ns, func() error {
|
||||
err = weavenet.WithNetNSUnsafe(ns, func() error {
|
||||
link, err := netlink.LinkByName(args.IfName)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
+10
-6
@@ -180,7 +180,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 +194,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)
|
||||
@@ -252,6 +252,7 @@ func main() {
|
||||
}
|
||||
|
||||
var dockerCli *docker.Client
|
||||
dockerVersion := "none"
|
||||
if dockerAPI != "" {
|
||||
dc, err := docker.NewClient(dockerAPI)
|
||||
if err != nil {
|
||||
@@ -260,13 +261,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 +298,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 (
|
||||
|
||||
+49
-22
@@ -2,8 +2,12 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/fsouza/go-dockerclient"
|
||||
"github.com/vishvananda/netlink"
|
||||
|
||||
"github.com/weaveworks/weave/common"
|
||||
weavenet "github.com/weaveworks/weave/net"
|
||||
)
|
||||
|
||||
func containerAddrs(args []string) error {
|
||||
@@ -12,46 +16,69 @@ 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 {
|
||||
pred, err := common.ConnectedToBridgePredicate(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 := common.GetBridgeNetDev(bridgeName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printNetDevs(cid, []common.NetDev{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()
|
||||
// NB: Because network namespaces (netns) are changed many times inside the loop,
|
||||
// it's NOT safe to exec any code depending on the root netns without
|
||||
// wrapping with WithNetNS*.
|
||||
for _, cid := range containerIDs {
|
||||
netDevs, err := getNetDevs(client, containers[cid], pred)
|
||||
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, pred func(netlink.Link) bool) ([]common.NetDev, error) {
|
||||
if container.State.Pid == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return common.GetNetDevsWithPredicate(container.State.Pid, pred)
|
||||
}
|
||||
|
||||
return common.GetWeaveNetDevs(container.State.Pid)
|
||||
func printNetDevs(cid string, netDevs []common.NetDev) {
|
||||
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()
|
||||
}
|
||||
}
|
||||
@@ -10,11 +10,12 @@ import (
|
||||
)
|
||||
|
||||
func createPluginNetwork(args []string) error {
|
||||
if len(args) != 2 {
|
||||
cmdUsage("create-plugin-network", "<network-name> <driver-name>")
|
||||
if len(args) != 3 {
|
||||
cmdUsage("create-plugin-network", "<network-name> <driver-name> <default-subnet>")
|
||||
}
|
||||
networkName := args[0]
|
||||
driverName := args[1]
|
||||
subnet := args[2]
|
||||
d, err := newDockerClient()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -24,8 +25,11 @@ func createPluginNetwork(args []string) error {
|
||||
Name: networkName,
|
||||
CheckDuplicate: true,
|
||||
Driver: driverName,
|
||||
IPAM: docker.IPAMOptions{Driver: driverName},
|
||||
Options: map[string]interface{}{plugin.MulticastOption: "true"},
|
||||
IPAM: docker.IPAMOptions{
|
||||
Driver: driverName,
|
||||
Config: []docker.IPAMConfig{{Subnet: subnet}},
|
||||
},
|
||||
Options: map[string]interface{}{plugin.MulticastOption: "true"},
|
||||
})
|
||||
if err != docker.ErrNetworkAlreadyExists && err != nil {
|
||||
// Despite appearances to the contrary, CreateNetwork does
|
||||
|
||||
+3
-3
@@ -149,14 +149,14 @@ func NewProxy(c Config) (*Proxy, error) {
|
||||
p.client = client.Client
|
||||
|
||||
if !p.WithoutDNS {
|
||||
netDevs, err := common.GetBridgeNetDev(c.DockerBridge)
|
||||
netDev, err := common.GetBridgeNetDev(c.DockerBridge)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(netDevs) != 1 || len(netDevs[0].CIDRs) != 1 {
|
||||
if len(netDev.CIDRs) != 1 {
|
||||
return nil, fmt.Errorf("Could not obtain address of %s", c.DockerBridge)
|
||||
}
|
||||
p.dockerBridgeIP = netDevs[0].CIDRs[0].IP.String()
|
||||
p.dockerBridgeIP = netDev.CIDRs[0].IP.String()
|
||||
}
|
||||
|
||||
p.hostnameMatchRegexp, err = regexp.Compile(c.HostnameMatch)
|
||||
|
||||
+22
-2
@@ -9,6 +9,7 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/vishvananda/netlink"
|
||||
"github.com/weaveworks/go-odp/odp"
|
||||
"github.com/weaveworks/mesh"
|
||||
)
|
||||
@@ -267,9 +268,11 @@ func (fastdp *FastDatapath) bridge(ingress bridgePortID, key PacketKey, lock *fa
|
||||
// If we did, we'd need to delete the flows every time
|
||||
// we learned a new MAC address, or have a more
|
||||
// complicated selective invalidation scheme.
|
||||
log.Debug("fastdp: unknown dst", ingress, key)
|
||||
mfop.Add(vetoFlowCreationFlowOp{})
|
||||
} else {
|
||||
// A real broadcast
|
||||
log.Debug("fastdp: broadcast", ingress, key)
|
||||
mfop.Add(odpEthernetFlowKey(key))
|
||||
}
|
||||
|
||||
@@ -416,14 +419,31 @@ func (fastdp *FastDatapath) getVxlanVportID(udpPort int) (odp.VportID, error) {
|
||||
return vxlanVportID, nil
|
||||
}
|
||||
|
||||
name := fmt.Sprintf("vxlan-%d", udpPort)
|
||||
vxlanVportID, err := fastdp.dp.CreateVport(
|
||||
odp.NewVxlanVportSpec(fmt.Sprintf("vxlan-%d", udpPort), uint16(udpPort)))
|
||||
odp.NewVxlanVportSpec(name, uint16(udpPort)))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// If a netdev for the vxlan vport exists, we need to do an extra check
|
||||
// to bypass the kernel bug which makes the vxlan creation to complete
|
||||
// successfully regardless whether there were any errors when binding
|
||||
// to the given UDP port.
|
||||
if link, err := netlink.LinkByName(name); err == nil {
|
||||
if link.Attrs().Flags&net.FlagUp == 0 {
|
||||
// The netdev interface is down, so most likely bringing it up
|
||||
// has failed due to the UDP port being in use.
|
||||
if err := fastdp.dp.DeleteVport(vxlanVportID); err != nil {
|
||||
log.Warning("Unable to remove vxlan vport %d: %s", vxlanVportID, err)
|
||||
}
|
||||
return 0, odp.NetlinkError(syscall.EADDRINUSE)
|
||||
}
|
||||
}
|
||||
|
||||
fastdp.vxlanVportIDs[udpPort] = vxlanVportID
|
||||
fastdp.missHandlers[vxlanVportID] = func(fks odp.FlowKeys, lock *fastDatapathLock) FlowOp {
|
||||
log.Debug("ODP miss: ", fks, " on port ", vxlanVportID)
|
||||
tunnel := fks[odp.OVS_KEY_ATTR_TUNNEL].(odp.TunnelFlowKey)
|
||||
tunKey := tunnel.Key()
|
||||
|
||||
@@ -939,7 +959,6 @@ func (fastdp *FastDatapath) Error(err error, stopped bool) {
|
||||
|
||||
func (fastdp *FastDatapath) Miss(packet []byte, fks odp.FlowKeys) error {
|
||||
ingress := fks[odp.OVS_KEY_ATTR_IN_PORT].(odp.InPortFlowKey).VportID()
|
||||
log.Debug("ODP miss ", fks, " on port ", ingress)
|
||||
|
||||
lock := fastdp.startLock()
|
||||
defer lock.unlock()
|
||||
@@ -948,6 +967,7 @@ func (fastdp *FastDatapath) Miss(packet []byte, fks odp.FlowKeys) error {
|
||||
|
||||
handler := fastdp.getMissHandler(ingress)
|
||||
if handler == nil {
|
||||
log.Debug("ODP miss (no handler): ", fks, " on port ", ingress)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -82,17 +82,17 @@ func (router *NetworkRouter) Start() {
|
||||
func (router *NetworkRouter) handleCapturedPacket(key PacketKey) FlowOp {
|
||||
router.PacketLogging.LogPacket("Captured", key)
|
||||
srcMac := net.HardwareAddr(key.SrcMAC[:])
|
||||
dstMac := net.HardwareAddr(key.DstMAC[:])
|
||||
|
||||
switch newSrcMac, conflictPeer := router.Macs.Add(srcMac, router.Ourself.Peer); {
|
||||
case newSrcMac:
|
||||
log.Println("Discovered local MAC", srcMac)
|
||||
|
||||
case conflictPeer != nil:
|
||||
// The MAC cache has an entry for the source MAC
|
||||
// associated with another peer. This probably means
|
||||
// we are seeing a frame we injected ourself. That
|
||||
// shouldn't happen, but discard it just in case.
|
||||
log.Error("Captured frame from MAC (", srcMac, ") associated with another peer ", conflictPeer)
|
||||
log.Error("Captured frame from MAC (", srcMac, ") to (", dstMac, ") associated with another peer ", conflictPeer)
|
||||
return DiscardingFlowOp{}
|
||||
}
|
||||
|
||||
@@ -101,7 +101,6 @@ func (router *NetworkRouter) handleCapturedPacket(key PacketKey) FlowOp {
|
||||
return DiscardingFlowOp{}
|
||||
}
|
||||
|
||||
dstMac := net.HardwareAddr(key.DstMAC[:])
|
||||
switch dstPeer := router.Macs.Lookup(dstMac); dstPeer {
|
||||
case router.Ourself.Peer:
|
||||
// The packet is destined for a local MAC. The bridge
|
||||
|
||||
+58
-28
@@ -1,18 +1,19 @@
|
||||
---
|
||||
title: Integrating Kubernetes via the CNI Plugin
|
||||
title: Integrating Kubernetes and Mesos via the CNI Plugin
|
||||
menu_order: 65
|
||||
---
|
||||
|
||||
CNI, the [_Container Network Interface_](https://github.com/appc/cni#cni---the-container-network-interface),
|
||||
CNI, the [_Container Network Interface_](https://github.com/containernetworking/cni),
|
||||
is a proposed standard for configuring network interfaces for Linux
|
||||
application containers. CNI is supported by
|
||||
[Kubernetes](http://kubernetes.io/), an open source container cluster
|
||||
manager built by Google.
|
||||
[Kubernetes](http://kubernetes.io/), [Apache Mesos](mesos.apache.org)
|
||||
and
|
||||
[others](https://github.com/containernetworking/cni#who-is-using-cni).
|
||||
|
||||
###Installing the Weave Net CNI plugin
|
||||
|
||||
The Weave Net CNI plugin is installed when you run `weave setup`, if
|
||||
your machine has the directories normally used to host CNI plugins.
|
||||
If your machine has the directories normally used to host CNI plugins,
|
||||
then the Weave Net CNI plugin is installed when you run `weave setup`.
|
||||
|
||||
To create those directories, run (as root):
|
||||
|
||||
@@ -23,20 +24,44 @@ Then run:
|
||||
|
||||
weave setup
|
||||
|
||||
###Launching Weave Net
|
||||
####Launching Weave Net
|
||||
|
||||
To create a network which can span multiple hosts, the Weave peers must be connected to each other, by specifying the other hosts during `weave launch` or via
|
||||
To create a network that spans multiple hosts, the Weave peers must be connected to each other.
|
||||
This is accomplished by specifying the other hosts during `weave launch` or via
|
||||
[`weave connect`](/site/using-weave/finding-adding-hosts-dynamically.md).
|
||||
|
||||
See [Using Weave Net](/site/using-weave.md#peer-connections) for a discussion on peer connections.
|
||||
|
||||
As well as launching Weave Net, you have to run an extra command to
|
||||
perform some additional configuration of the Weave bridge:
|
||||
See [Creating Peer Connections Between Hosts](/site/using-weave.md#peer-connections)
|
||||
for a discussion on peer connections.
|
||||
|
||||
weave launch <peer hosts>
|
||||
weave expose
|
||||
|
||||
###Configuring Kubernetes to use the CNI Plugin
|
||||
####Using the CNI network configuration file
|
||||
|
||||
All CNI plugins are configured by a JSON file in the directory
|
||||
`/etc/cni/net.d/`. `weave setup` installs a minimal configuration
|
||||
file named `10-weave.conf`, which you can alter to suit your needs.
|
||||
|
||||
See the [CNI Spec](https://github.com/appc/cni/blob/master/SPEC.md#network-configuration)
|
||||
for details on the format and contents of this file.
|
||||
|
||||
By default, the Weave CNI plugin adds a default route out via an IP
|
||||
address on the Weave bridge, so your containers can access resources
|
||||
on the internet. If you do not want this, add a section to the config
|
||||
file that specifies no routes:
|
||||
|
||||
"ipam": {
|
||||
"routes": [ ]
|
||||
}
|
||||
|
||||
The following other fields in the spec are supported:
|
||||
|
||||
- `ipam / type` - default is to use Weave's own IPAM
|
||||
- `ipam / subnet` - default is to use Weave's IPAM default subnet
|
||||
- `ipam / gateway` - default is to use the Weave bridge IP address (allocated by `weave expose`)
|
||||
|
||||
###Using the Weave Net CNI plugin
|
||||
|
||||
####Configuring Kubernetes to use the CNI Plugin
|
||||
|
||||
After you've launched Weave and peered your hosts, you can configure
|
||||
Kubernetes to use Weave, by adding the following options to the
|
||||
@@ -49,26 +74,31 @@ for more details.
|
||||
|
||||
Now, whenever Kubernetes starts a pod, it will be attached to the Weave network.
|
||||
|
||||
###Using the CNI network configuration file
|
||||
####Configuring Mesos to use the CNI plugin
|
||||
|
||||
All CNI plugins are configured by a JSON file in the directory
|
||||
`/etc/cni/net.d/`. `weave setup` installs a minimal configuration
|
||||
file named `10-weave.conf`, which you can alter to suit your needs.
|
||||
To use the CNI plugin, the Mesos Agent must be started with reference
|
||||
to the CNI configuration and binary directories:
|
||||
|
||||
See the [CNI Spec](https://github.com/appc/cni/blob/master/SPEC.md#network-configuration)
|
||||
for details on the format and contents of this file.
|
||||
sudo mesos-slave
|
||||
--network_cni_config_dir=/etc/cni/net.d
|
||||
--network_cni_plugins_dir=/opt/cni/bin
|
||||
...
|
||||
|
||||
By default, the Weave CNI plugin adds a default route out via the Weave bridge, so your containers can access resources on the internet. If you do not want this, add a section to the config file that specifies no routes:
|
||||
To start a container that is connected to the Weave network via CNI,
|
||||
use the name specified in the configuration file. This example starts
|
||||
a alpine container running a `nc` server listening on port 1080 with
|
||||
the `mesos-execute` command. From the Master, run:
|
||||
|
||||
"ipam": {
|
||||
"routes": [ ]
|
||||
}
|
||||
nohup sudo mesos-execute --command="ifconfig; nc -k -l 0.0.0.0 1080" --docker_image=alpine --master=localhost:5050 --name=example --networks=weave --resources=cpus:0.1 --shell </dev/null >test.log 2>&1 &
|
||||
|
||||
The following other fields in the spec are supported:
|
||||
After this task has started, it is possible to obtain the ip address of
|
||||
the container and ping it from any of other agents (which are also
|
||||
connected to the weave network)"
|
||||
|
||||
- `ipam / type` - default is to use Weave's own IPAM
|
||||
- `ipam / subnet` - default is to use Weave's IPAM default subnet
|
||||
- `ipam / gateway` - default is to use the Weave bridge IP address (allocated by `weave expose`)
|
||||
nc -z -v <IP FROM LOGS> 1080
|
||||
|
||||
For more information, see the
|
||||
[Mesos documentation](http://mesos.apache.org/documentation/cni/).
|
||||
|
||||
###Caveats
|
||||
|
||||
|
||||
@@ -88,11 +88,6 @@ Using the Weave plugin enables you to take advantage of [Docker's network functi
|
||||
Also, Weave’s Docker Network plugin doesn't require an external cluster store and you can start and stop containers even
|
||||
when there are network connectivity problems.
|
||||
|
||||
|
||||
|
||||
>*Note:* The plugin is an *alternative* to the proxy, and therefore you do
|
||||
*not* need to run `eval $(weave env)` beforehand.
|
||||
|
||||
See [Using the Weave Docker Network Plugin](/site/plugin.md) for more details.
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -202,4 +202,4 @@ named `weavedb` is used to store this data.
|
||||
**See Also**
|
||||
|
||||
* [Automatic Allocation Across Multiple Subnets](/site/ipam/allocation-multi-ipam.md)
|
||||
* [Plugin Command-line Arguments](/site/plugin/plug-in-command-line.md)
|
||||
* [Integrating Docker via the Network Plugin](/site/plugin.md)
|
||||
@@ -1,5 +1,32 @@
|
||||
---
|
||||
title: Operational Guide
|
||||
menu_order: 35
|
||||
menu_order: 45
|
||||
---
|
||||
Operations manual.
|
||||
This operational guide is intended to give you an overview of how to
|
||||
operate and manage a Weave Network in production. It consists of three
|
||||
main parts:
|
||||
|
||||
* A [glossary of concepts](/site/operational-guide/concepts.md) with
|
||||
which you will need to be familiar
|
||||
* Detailed instructions for safely bootstrapping, growing and
|
||||
shrinking Weave networks in a number of different deployment
|
||||
scenarios:
|
||||
* An [interactive
|
||||
installation](/site/operational-guide/interactive.md), suitable
|
||||
for evaluation and development
|
||||
* A [uniformly configured
|
||||
cluster](/site/operational-guide/uniform-fixed-cluster.md) with
|
||||
a fixed number of initial nodes, suitable for automated
|
||||
provisioning but requiring manual intervention for resizing
|
||||
* A [heterogenous cluster](/site/operational-guide/autoscaling.md)
|
||||
comprising fixed and autoscaling components, suitable for a base
|
||||
load with automated scale-out/scale-in
|
||||
* A [uniformly configured
|
||||
cluster](/site/operational-guide/uniform-dynamic-cluster.md)
|
||||
with dynamic nodes, suitable for automated provisioning and
|
||||
resizing.
|
||||
* A list of [common administrative
|
||||
tasks](/site/operational-guide/tasks.md), such as configuring Weave
|
||||
Net to start on boot, upgrading clusters, cleaning up peers and
|
||||
reclaiming IP address space
|
||||
|
||||
@@ -6,18 +6,30 @@ This section describes some of the essential concepts with which you will
|
||||
need to be familiar before continuing to the example deployment
|
||||
scenarios.
|
||||
|
||||
## Host
|
||||
The following concepts are described:
|
||||
|
||||
* [Host](#host)
|
||||
* [Peer](#peer)
|
||||
* [Peer Discovery](#peer-discovery)
|
||||
* [Network Partition](#network-partition)
|
||||
* [IP Address Manager- IPAM](#ip-address-manager)
|
||||
* [Seeding](#seeding)
|
||||
* [Consensus](#consensus)
|
||||
* [Observers](#observers)
|
||||
* [Persistence](#persistence)
|
||||
|
||||
##<a name="host"></a>Host
|
||||
|
||||
For the purposes of this documentation a host is an
|
||||
installation of the Linux operating system that is running an
|
||||
instance of the Docker Engine. The host may be executing directly on bare
|
||||
hardware or inside a virtual machine.
|
||||
|
||||
## Peer
|
||||
##<a name="peer"></a>Peer
|
||||
|
||||
A peer is a running instance of Weave Net, typically one per host.
|
||||
|
||||
## Peer Name
|
||||
##<a name="peer-name"></a>Peer Name
|
||||
|
||||
Weave Net peers are identified by a 48-bit value formatted like an
|
||||
ethernet MAC address, for example, `01:23:45:67:89:ab`. The 'peer
|
||||
@@ -50,14 +62,14 @@ The appropriate strategy for assigning peer names depends on the type
|
||||
and method of your particular deployment and is discussed in more
|
||||
detail below.
|
||||
|
||||
## Peer Discovery
|
||||
##<a name="peer-discovery"></a>Peer Discovery
|
||||
|
||||
Peer discovery is a mechanism that allows peers to learn about new
|
||||
Weave Net hosts from existing peers without being explicitly told. Peer
|
||||
discovery is
|
||||
[enabled by default](/site/using-weave/finding-adding-hosts-dynamically.md).
|
||||
|
||||
## Network Partition
|
||||
##<a name="network-partition"></a>Network Partition
|
||||
|
||||
A network partition is a transient condition whereby some arbitrary
|
||||
subsets of peers are unable to communicate with each other for the
|
||||
@@ -66,7 +78,7 @@ optic line severed. Weave Net is designed to allow peers and their
|
||||
containers to make maximum safe progress under conditions of
|
||||
partition, healing automatically once the partition is over.
|
||||
|
||||
## IP Address Manager (IPAM)
|
||||
##<a name="ip-address-manager"></a>IP Address Manager (IPAM)
|
||||
|
||||
[IPAM](/site/ipam.md) is the subsystem responsible for dividing up a
|
||||
large contiguous block of IP addresses (known as the IP allocation
|
||||
@@ -77,7 +89,7 @@ When a new network is formed an initial division of the IP allocation
|
||||
range must be made. Two (mutually exclusive) mechanisms with different
|
||||
tradeoffs are provided to perform this task: seeding and consensus.
|
||||
|
||||
### Seeding
|
||||
### <a name="seeding"></a>Seeding
|
||||
|
||||
Seeding requires each peer to be told the list of peer names amongst
|
||||
which the address space is to be divided initially. There are some
|
||||
@@ -100,7 +112,7 @@ scenarios:
|
||||
|
||||
* [Uniform Dynamic Cluster](/site/operational-guide/uniform-dynamic-cluster.md)
|
||||
|
||||
### Consensus
|
||||
###<a name="consensus"></a>Consensus
|
||||
|
||||
Alternatively, when a new network is formed for the first time, peers
|
||||
can be configured to co-ordinate amongst themselves to automatically
|
||||
@@ -116,7 +128,7 @@ scenarios:
|
||||
* [Interactive Deployment](/site/operational-guide/interactive.md)
|
||||
* [Uniform Fixed Cluster](/site/operational-guide/uniform-fixed-cluster.md)
|
||||
|
||||
### Observers
|
||||
###<a name="observers"></a>Observers
|
||||
|
||||
Finally, an option is provided to start a peer as an _observer_. Such
|
||||
peers do not require a seed peer name list or an initial peer
|
||||
@@ -130,7 +142,7 @@ scenarios:
|
||||
|
||||
* [Autoscaling](/site/operational-guide/autoscaling.md)
|
||||
|
||||
## Persistence
|
||||
##<a name="persistence"></a>Persistence
|
||||
|
||||
Certain information is remembered between launches of Weave Net (for
|
||||
example across reboots):
|
||||
|
||||
@@ -52,7 +52,7 @@ following command on any peer:
|
||||
weave status ipam
|
||||
|
||||
This command displays the peer names and nicknames, absolute quantity/percentage of allocation
|
||||
range managed by peer and also identifies the names of unreachable peers. If you are satisifed
|
||||
range managed by peer and also identifies the names of unreachable peers. If you are satisfied
|
||||
that the peer is truly gone, rather than temporarily unreachable due to a
|
||||
partition, you can reclaim their space manually.
|
||||
|
||||
|
||||
@@ -46,14 +46,14 @@ Where
|
||||
On each new peer, at boot, via
|
||||
[systemd](/site/installing-weave/systemd.md):
|
||||
|
||||
hostN$ weave launch --no-restart --name ::N --ipam-seed $SEED $PEERS
|
||||
hostN$ weave launch --no-restart --name ::N --ipalloc-init seed=$SEED $PEERS
|
||||
|
||||
Where,
|
||||
|
||||
* `--no-restart` disables the Docker restart policy, since this will be
|
||||
handled by systemd.
|
||||
* `--name` specifies a unique name for this new peer.
|
||||
* `--ipam-seed` specifies the names of only those peers that were
|
||||
* `--ipalloc-init seed` specifies the names of only those peers that were
|
||||
involved in the initial cluster bootstrap - even if they have been
|
||||
subsequently removed from the cluster. You can view this as a kind
|
||||
of 'cluster identity',where peers may only interoperate in the same
|
||||
|
||||
@@ -25,8 +25,6 @@ After you've launched Weave Net and peered your hosts, you can start containers
|
||||
on any of the hosts, and they can all communicate with each other
|
||||
using any protocol, even multicast.
|
||||
|
||||
>**Warning!** It is inadvisable to attach containers to the Weave network using the Weave Docker Networking Plugin and Weave Docker API Proxy simultaneously. Such containers will end up with two Weave network interfaces and two IP addresses, which is rarely desirable. To ensure that the proxy is not being used, do not run `eval $(weave env)`, or `docker $(weave config) ...`.
|
||||
|
||||
In order to use Weave Net's [Service Discovery](/site/weavedns.md) you
|
||||
must pass the additional arguments `--dns` and `-dns-search`, for
|
||||
which a helper is provided in the Weave script:
|
||||
|
||||
@@ -38,6 +38,5 @@ The plugin accepts the following options via `docker network create ... --opt`:
|
||||
|
||||
**See Also**
|
||||
|
||||
* [Using the Weave Net Docker Network Plugin](/site/plugin.md)
|
||||
* [Plugin Command-line Arguments](/site/plugin/plug-in-command-line.md)
|
||||
* [Integrating Docker via the Network Plugin](/site/plugin.md)
|
||||
|
||||
+31
-6
@@ -29,12 +29,26 @@ Where,
|
||||
* The second line configures the Weave Net environment, so that containers launched via the Docker command line are automatically attached to the Weave network, and,
|
||||
* The third line runs the [application container](/site/faq.md#own-image) using [a Docker command](https://docs.docker.com/engine/reference/run/).
|
||||
|
||||
>**Note:** If the first command results in an error like
|
||||
`http:///var/run/Docker.sock/v1.19/containers/create: dial unix
|
||||
/var/run/Docker.sock: permission denied. Are you trying to connect to a TLS-enabled daemon without TLS?` then you likely need to be 'root' in order to connect to the Docker daemon. If so, run the above and all subsequent commands in a *single* root shell (e.g. one created with `sudo -s`). Do *not* prefix individual commands with `sudo`, since some commands modify environment entries and hence they all need to be executed from the same shell.
|
||||
|
||||
|
||||
>**Important!** if you are running the Weave Docker Network Plugin do not run `eval $(weave env)`. See [Using the Weave Net Docker Network Plugin](/site/plugin.md) for more information.
|
||||
> **Note** If the first command results in an error like
|
||||
> ```
|
||||
> Cannot connect to the Docker daemon. Is the docker daemon running on this host?
|
||||
> ```
|
||||
> or
|
||||
> ```
|
||||
> http:///var/run/docker.sock/v1.19/containers/create: dial unix/var/run/docker.sock: permission denied. Are you trying to connect to a TLS-enabled daemon without TLS?
|
||||
> ```
|
||||
> then you likely need to be 'root' in order to connect to the Docker
|
||||
> daemon. If so, run the above and all subsequent commands in a
|
||||
> *single* root shell:
|
||||
> ```
|
||||
> host1$ sudo -s
|
||||
> host1# weave launch
|
||||
> host1# eval $(weave env)
|
||||
> host1# docker run --name a1 -ti weaveworks/ubuntu
|
||||
> ```
|
||||
> Do *not* prefix individual commands with `sudo`, since some commands
|
||||
> modify environment entries and hence they all need to be executed from
|
||||
> the same shell.
|
||||
|
||||
Weave Net must be launched once per host. The relevant container images will be pulled down from Docker Hub on demand during `weave launch`.
|
||||
|
||||
@@ -69,6 +83,17 @@ For example:
|
||||
|
||||
Peers can also be dynamically added. See [Adding Hosts Dynamically](/site/using-weave/finding-adding-hosts-dynamically.md) for more information.
|
||||
|
||||
####Restricting Access
|
||||
|
||||
By default Weave Net listens on all host IPs (i.e. 0.0.0.0). This
|
||||
can be altered with the `--host` parameter to `weave launch`, for example,
|
||||
to ensure that Weave Net only listens on IPs on an internal network.
|
||||
|
||||
Standard firewall rules can be deployed to restrict access to the
|
||||
Weave Net control and data ports.
|
||||
|
||||
For communication across untrusted networks, connections can be
|
||||
[encrypted](/site/using-weave/security-untrusted-networks.md).
|
||||
|
||||
###<a name="testing"></a>Testing Container Communications
|
||||
|
||||
|
||||
@@ -101,6 +101,4 @@ In AWS-VPC mode you can run the following:
|
||||
**See Also**
|
||||
|
||||
* [Using Weave Net](/site/using-weave.md)
|
||||
* [Performance measurements](/blog/weave-docker-networking-performance-aws-vpc/)
|
||||
|
||||
(that last blog post doesn't exist yet)
|
||||
@@ -28,13 +28,23 @@ To guard against dictionary attacks, the password needs to be reasonably strong
|
||||
|
||||
The same password must be specified for all Weave Net peers, by default both control and data plane traffic will then use authenticated encryption.
|
||||
|
||||
Fast datapath does not support encryption. If you supply a
|
||||
password at `weave launch` the router falls back to a slower
|
||||
`sleeve` mode that does support encryption.
|
||||
[Fast datapath](/site/using-weave/fastdp.md) does not support
|
||||
encryption. If you supply a password at `weave launch`, Weave Net
|
||||
falls back to the slower `sleeve` mode for encrypted communication.
|
||||
|
||||
If some of your peers are co-located in a trusted network (for example within the boundary of your own data center) you can use the `--trusted-subnets` argument to `weave launch` to selectively disable data plane encryption as an optimization.
|
||||
As an optimization, you can selectively disable data plane encryption
|
||||
if some of your peers are co-located in a trusted network, for example
|
||||
within the boundary of your own data center. List these networks using
|
||||
the `--trusted-subnets` argument with `weave launch`:
|
||||
|
||||
>**Note:** Both peers must consider the other to be in a trusted subnet for this to take place - if they do not agree, Weave Net [falls back to a slower method](/site/using-weave/fastdp.md) for transporting data between peers, since fast datapath does not support encryption.
|
||||
weave launch --password wfvAwt7sj --trusted-subnets 10.0.2.0/24,192.168.48.0/24
|
||||
|
||||
If *both* peers at the end of a connection consider the other to be in
|
||||
a trusted subnet, Weave Net attempts to establish fast datapath
|
||||
connectivity, which is unencrypted. Otherwise the slower `sleeve` mode
|
||||
is used and communication is encrypted.
|
||||
|
||||
Configured trusted subnets are shown in [`weave status`](/site/troubleshooting.md#weave-status).
|
||||
|
||||
Be aware that:
|
||||
|
||||
|
||||
@@ -17,18 +17,6 @@ When weaveDNS is queried for a name in the `.weave.local` domain, it
|
||||
looks up the hostname in its memory database and responds with the IPs
|
||||
of all containers for that hostname across the entire cluster.
|
||||
|
||||
###Basic Load Balancing and Fault Tolerance
|
||||
|
||||
WeaveDNS returns IP addresses in random order to facilitate basic
|
||||
load balancing and failure tolerance. Most client side resolvers sort
|
||||
the returned addresses based on reachability, and place local addresses
|
||||
at the top of the list (see [RFC 3484](https://www.ietf.org/rfc/rfc3484.txt)).
|
||||
|
||||
For example, if there is container with the desired hostname on the local
|
||||
machine, the application receives that container's IP address.
|
||||
Otherwise, the application receives the IP address of a random
|
||||
container with the desired hostname.
|
||||
|
||||
When weaveDNS is queried for a name in a domain other than
|
||||
`.weave.local`, it queries the host's configured nameserver, which is
|
||||
the standard behaviour for Docker containers.
|
||||
|
||||
@@ -33,6 +33,14 @@ PING pingme.weave.local (10.32.0.2) 56(84) bytes of data.
|
||||
|
||||
Notice how the ping reaches different addresses.
|
||||
|
||||
However, due to
|
||||
[RFC 3484 address selection](https://tools.ietf.org/html/rfc3484#section-6)
|
||||
most DNS resolver libraries prefer certain addresses over others, to
|
||||
the point where in some circumstances the same address is always
|
||||
chosen. To avoid this behaviour, applications may want to perform
|
||||
their own address selection, e.g. by choosing a random entry from the
|
||||
result of
|
||||
[`getaddrinfo()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getaddrinfo.html).
|
||||
|
||||
## <a name="fault-resilience"></a>Fault Resilience
|
||||
|
||||
|
||||
@@ -23,8 +23,8 @@ assert_raises "! check_restart $HOST1 weave"
|
||||
assert_raises "! check_restart $HOST1 weaveproxy"
|
||||
assert_raises "! check_restart $HOST1 weaveplugin"
|
||||
|
||||
# Relaunch the plugin to prevent the `weave stop` in `end_suite`
|
||||
# Relaunch to prevent the `weave stop` in `end_suite`
|
||||
# timing out trying to remove the plugin network
|
||||
weave_on $HOST1 launch-plugin
|
||||
weave_on $HOST1 launch --no-restart
|
||||
|
||||
end_suite
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
. ./config.sh
|
||||
|
||||
IMAGE="joffrey/docker-py:1.8.1"
|
||||
|
||||
docker_py_test() {
|
||||
SHARD=$1
|
||||
TOTAL_SHARDS=$2
|
||||
@@ -12,9 +14,9 @@ docker_py_test() {
|
||||
# Work round https://github.com/docker/docker-py/issues/852
|
||||
docker_on $HOST1 pull busybox:buildroot-2014.02 >/dev/null
|
||||
# Get a list of the tests for use to shard
|
||||
docker_on $HOST1 pull joffrey/docker-py >/dev/null
|
||||
docker_on $HOST1 pull $IMAGE >/dev/null
|
||||
CANDIDATES=$(docker_on $HOST1 run \
|
||||
joffrey/docker-py \
|
||||
$IMAGE \
|
||||
py.test --collect-only tests/integration/ \
|
||||
| sed -En "s/\s*<Module '([[:print:]]+)'>/\1/p")
|
||||
|
||||
@@ -36,7 +38,7 @@ docker_py_test() {
|
||||
-e DOCKER_HOST=tcp://$DOCKER_BRIDGE_IP:12375 \
|
||||
-v /tmp:/tmp \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
joffrey/docker-py py.test $TESTS ; then
|
||||
$IMAGE py.test $TESTS ; then
|
||||
assert_raises "true"
|
||||
else
|
||||
assert_raises "false"
|
||||
|
||||
@@ -15,10 +15,11 @@ run_on $HOST1 sudo mkdir -p /opt/cni/bin
|
||||
# setup-cni is a subset of 'weave setup', without doing any 'docker pull's
|
||||
weave_on $HOST1 setup-cni
|
||||
weave_on $HOST1 launch
|
||||
weave_on $HOST1 expose
|
||||
|
||||
C1=$(docker_on $HOST1 run --net=none --name=c1 -dt $SMALL_IMAGE /bin/sh)
|
||||
C1=$(docker_on $HOST1 run --net=none --privileged --name=c1 -dt $SMALL_IMAGE /bin/sh)
|
||||
C2=$(docker_on $HOST1 run --net=none --name=c2 -dt $SMALL_IMAGE /bin/sh)
|
||||
# Enable unsolicited ARPs so that ping after the address reuse does not time out
|
||||
exec_on $HOST1 c1 sysctl -w net.ipv4.conf.all.arp_accept=1
|
||||
|
||||
cni_connect $HOST1 c1 <<EOF
|
||||
{
|
||||
@@ -26,6 +27,7 @@ cni_connect $HOST1 c1 <<EOF
|
||||
"type": "weave-net"
|
||||
}
|
||||
EOF
|
||||
|
||||
cni_connect $HOST1 c2 <<EOF
|
||||
{
|
||||
"name": "weave",
|
||||
@@ -45,7 +47,6 @@ assert_raises "exec_on $HOST1 c2 $PING $C1IP"
|
||||
|
||||
# Now remove and start a new container to see if IP address re-use breaks things
|
||||
docker_on $HOST1 rm -f c2
|
||||
sleep 1
|
||||
|
||||
docker_on $HOST1 run --net=none --name=c3 -dt $SMALL_IMAGE /bin/sh
|
||||
|
||||
|
||||
+1
-1
Submodule vendor/github.com/weaveworks/mesh updated: 23749aaef9...50329b4166.
@@ -31,6 +31,10 @@ DOCKER_CLIENT_HOST=${DOCKER_CLIENT_HOST:-$DOCKER_HOST}
|
||||
IP_REGEXP="[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"
|
||||
CIDR_REGEXP="$IP_REGEXP/[0-9]{1,2}"
|
||||
|
||||
######################################################################
|
||||
# helpers that run locally, even without --local
|
||||
######################################################################
|
||||
|
||||
usage_no_exit() {
|
||||
cat >&2 <<EOF
|
||||
Usage:
|
||||
@@ -40,19 +44,21 @@ weave --help | help
|
||||
version
|
||||
|
||||
weave launch <same arguments as 'weave launch-router'>
|
||||
launch-router [--password <pass>] [--name <mac>] [--nickname <nickname>]
|
||||
[--log-level=debug|info|warning|error]
|
||||
[--no-restart] [--ipalloc-init <mode>]
|
||||
launch-router [--password <pass>] [--trusted-subnets <cidr>,...]
|
||||
[--host <ip_address>]
|
||||
[--name <mac>] [--nickname <nickname>]
|
||||
[--no-restart] [--resume] [--no-discovery] [--no-dns]
|
||||
[--ipalloc-init <mode>]
|
||||
[--ipalloc-range <cidr> [--ipalloc-default-subnet <cidr>]]
|
||||
[--no-discovery] [--no-dns]
|
||||
[--trusted-subnets <cidr>,...] [--resume] <peer> ...
|
||||
launch-proxy [-H <endpoint>] [--without-dns] [--no-multicast-route]
|
||||
[--log-level=debug|info|warning|error]
|
||||
<peer> ...
|
||||
launch-proxy [-H <endpoint>] [--without-dns] [--no-multicast-route]
|
||||
[--no-rewrite-hosts] [--no-default-ipalloc] [--no-restart]
|
||||
[--hostname-from-label <labelkey>]
|
||||
[--hostname-match <regexp>]
|
||||
[--hostname-replacement <replacement>]
|
||||
[--rewrite-inspect]
|
||||
[--log-level=debug|info|warning|error]
|
||||
launch-plugin [--no-restart] [--no-multicast-route]
|
||||
[--log-level=debug|info|warning|error]
|
||||
|
||||
@@ -81,7 +87,7 @@ weave dns-add [<ip_address> ...] <container_id> [-h <fqdn>] |
|
||||
<ip_address> ... -h <fqdn>
|
||||
dns-lookup <unqualified_name>
|
||||
|
||||
weave status [targets | connections | peers | dns]
|
||||
weave status [targets | connections | peers | dns | ipam]
|
||||
report [-f <format>]
|
||||
ps [<container_id> ...]
|
||||
|
||||
@@ -129,50 +135,19 @@ docker_run_options() {
|
||||
echo --privileged --net=host $(docker_sock_options)
|
||||
}
|
||||
|
||||
cni_volume_options() {
|
||||
[ "$1" = "setup" -o "$1" = "setup-cni" ] && echo -v /etc/cni:/etc/cni -v /opt/cni:/opt/cni
|
||||
}
|
||||
|
||||
create_cni_script() {
|
||||
cat >"$1" <<EOF
|
||||
#!/bin/sh
|
||||
docker run --rm $(docker_run_options) --pid=host -i \\
|
||||
-e CNI_VERSION -e CNI_COMMAND -e CNI_CONTAINERID -e CNI_NETNS \\
|
||||
-e CNI_IFNAME -e CNI_ARGS -e CNI_PATH $(cni_volume_options setup) \\
|
||||
$PLUGIN_IMAGE $COVERAGE_ARGS $2
|
||||
EOF
|
||||
chmod a+x "$1"
|
||||
}
|
||||
|
||||
create_cni_config() {
|
||||
cat >"$1" <<EOF
|
||||
{
|
||||
"name": "weave",
|
||||
"type": "weave-net"
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
setup_cni() {
|
||||
if [ -d /opt/cni/bin ] ; then
|
||||
create_cni_script /opt/cni/bin/weave-net --cni-net
|
||||
create_cni_script /opt/cni/bin/weave-ipam --cni-ipam
|
||||
fi
|
||||
if [ -d /etc/cni/net.d -a ! -f /etc/cni/net.d/10-weave.conf ] ; then
|
||||
create_cni_config /etc/cni/net.d/10-weave.conf
|
||||
fi
|
||||
}
|
||||
|
||||
launch_router_options() {
|
||||
[ "$1" = "launch" -o "$1" = "launch-router" ] && echo -v /:/host -e HOST_ROOT=/host
|
||||
exec_options() {
|
||||
case "$1" in
|
||||
setup|setup-cni|launch|launch-router)
|
||||
echo -v /:/host -e HOST_ROOT=/host
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
exec_remote() {
|
||||
docker $DOCKER_CLIENT_ARGS run --rm \
|
||||
$(docker_run_options) \
|
||||
--pid=host \
|
||||
$(cni_volume_options "$@") \
|
||||
$(launch_router_options "$@") \
|
||||
$(exec_options "$@") \
|
||||
-e DOCKERHUB_USER="$DOCKERHUB_USER" \
|
||||
-e WEAVE_VERSION \
|
||||
-e WEAVE_DEBUG \
|
||||
@@ -229,50 +204,6 @@ check_docker_version() {
|
||||
fi
|
||||
}
|
||||
|
||||
check_docker_server_api_version() {
|
||||
# Cope with various versions of `docker version` output format
|
||||
if ! DOCKER_API_VERSION=$(docker version -f '{{.Server.APIVersion}}' 2> /dev/null ) ; then
|
||||
if ! DOCKER_API_VERSION=$(docker version -f '{{.Server.ApiVersion}}' 2> /dev/null ) ; then
|
||||
if ! DOCKER_API_VERSION=$(docker version | sed -n -e 's|^Server API version: *\([0-9][0-9]*\.[0-9][0-9]\).*|\1|p') || [ -z "$DOCKER_API_VERSION" ] ; then
|
||||
echo "ERROR: Unable to determine docker version" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if version_lt ${DOCKER_API_VERSION}.0 ${1}.0 ; then
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
enforce_docker_bridge_addr_assign_type() {
|
||||
if ! ADDR_ASSIGN_TYPE=$(cat /sys/class/net/$DOCKER_BRIDGE/addr_assign_type 2>/dev/null) ; then
|
||||
echo "Could not determine address assignment type of $DOCKER_BRIDGE" >&2
|
||||
return
|
||||
fi
|
||||
# From include/uapi/linux/netdevice.h
|
||||
# #define NET_ADDR_PERM 0 /* address is permanent (default) */
|
||||
# #define NET_ADDR_RANDOM 1 /* address is generated randomly */
|
||||
# #define NET_ADDR_STOLEN 2 /* address is stolen from other device */
|
||||
# #define NET_ADDR_SET 3 /* address is set using dev_set_mac_address() */
|
||||
if [ $ADDR_ASSIGN_TYPE != 3 ] ; then
|
||||
echo "Setting $DOCKER_BRIDGE MAC (mitigate https://github.com/docker/docker/issues/14908)" >&2
|
||||
ip link set dev $DOCKER_BRIDGE address $(random_mac) || true
|
||||
fi
|
||||
}
|
||||
|
||||
check_forwarding_rules() {
|
||||
if run_iptables -C FORWARD -j REJECT --reject-with icmp-host-prohibited > /dev/null 2>&1; then
|
||||
cat >&2 <<EOF
|
||||
WARNING: existing iptables rule
|
||||
|
||||
'-A FORWARD -j REJECT --reject-with icmp-host-prohibited'
|
||||
|
||||
will block name resolution via weaveDNS - please reconfigure your firewall.
|
||||
EOF
|
||||
fi
|
||||
}
|
||||
|
||||
is_cidr() {
|
||||
echo "$1" | grep -E "^$CIDR_REGEXP$" >/dev/null
|
||||
}
|
||||
@@ -287,20 +218,6 @@ collect_cidr_args() {
|
||||
done
|
||||
}
|
||||
|
||||
is_ip() {
|
||||
echo "$1" | grep -E "^$IP_REGEXP$" >/dev/null
|
||||
}
|
||||
|
||||
collect_ip_args() {
|
||||
IP_ARGS=""
|
||||
IP_COUNT=0
|
||||
while is_ip "$1" ; do
|
||||
IP_ARGS="$IP_ARGS $1"
|
||||
IP_COUNT=$((IP_COUNT + 1))
|
||||
shift 1
|
||||
done
|
||||
}
|
||||
|
||||
dns_arg_count() {
|
||||
if [ "$1" = "--with-dns" -o "$1" = "--without-dns" ] ; then
|
||||
echo 1
|
||||
@@ -332,6 +249,9 @@ kill_container() {
|
||||
docker kill $1 >/dev/null 2>&1 || true
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# main
|
||||
######################################################################
|
||||
|
||||
check_docker_version
|
||||
|
||||
@@ -403,6 +323,10 @@ if [ -z "$IS_LOCAL" ] ; then
|
||||
exit $?
|
||||
fi
|
||||
|
||||
######################################################################
|
||||
# main (remote and --local) - settings
|
||||
######################################################################
|
||||
|
||||
# Default restart policy for router/proxy/plugin
|
||||
RESTART_POLICY="--restart=always"
|
||||
BASE_IMAGE=$DOCKERHUB_USER/weave
|
||||
@@ -543,6 +467,22 @@ random_mac() {
|
||||
# weave and docker specific helpers
|
||||
######################################################################
|
||||
|
||||
check_docker_server_api_version() {
|
||||
# Cope with various versions of `docker version` output format
|
||||
if ! DOCKER_API_VERSION=$(docker version -f '{{.Server.APIVersion}}' 2> /dev/null ) ; then
|
||||
if ! DOCKER_API_VERSION=$(docker version -f '{{.Server.ApiVersion}}' 2> /dev/null ) ; then
|
||||
if ! DOCKER_API_VERSION=$(docker version | sed -n -e 's|^Server API version: *\([0-9][0-9]*\.[0-9][0-9]\).*|\1|p') || [ -z "$DOCKER_API_VERSION" ] ; then
|
||||
echo "ERROR: Unable to determine docker version" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if version_lt ${DOCKER_API_VERSION}.0 ${1}.0 ; then
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
util_op() {
|
||||
if command_exists weaveutil ; then
|
||||
weaveutil "$@"
|
||||
@@ -552,6 +492,34 @@ util_op() {
|
||||
fi
|
||||
}
|
||||
|
||||
check_forwarding_rules() {
|
||||
if run_iptables -C FORWARD -j REJECT --reject-with icmp-host-prohibited > /dev/null 2>&1; then
|
||||
cat >&2 <<EOF
|
||||
WARNING: existing iptables rule
|
||||
|
||||
'-A FORWARD -j REJECT --reject-with icmp-host-prohibited'
|
||||
|
||||
will block name resolution via weaveDNS - please reconfigure your firewall.
|
||||
EOF
|
||||
fi
|
||||
}
|
||||
|
||||
enforce_docker_bridge_addr_assign_type() {
|
||||
if ! ADDR_ASSIGN_TYPE=$(cat /sys/class/net/$DOCKER_BRIDGE/addr_assign_type 2>/dev/null) ; then
|
||||
echo "Could not determine address assignment type of $DOCKER_BRIDGE" >&2
|
||||
return
|
||||
fi
|
||||
# From include/uapi/linux/netdevice.h
|
||||
# #define NET_ADDR_PERM 0 /* address is permanent (default) */
|
||||
# #define NET_ADDR_RANDOM 1 /* address is generated randomly */
|
||||
# #define NET_ADDR_STOLEN 2 /* address is stolen from other device */
|
||||
# #define NET_ADDR_SET 3 /* address is set using dev_set_mac_address() */
|
||||
if [ $ADDR_ASSIGN_TYPE != 3 ] ; then
|
||||
echo "Setting $DOCKER_BRIDGE MAC (mitigate https://github.com/docker/docker/issues/14908)" >&2
|
||||
ip link set dev $DOCKER_BRIDGE address $(random_mac) || true
|
||||
fi
|
||||
}
|
||||
|
||||
# Detect the current bridge/datapath state. When invoked, the values of
|
||||
# $BRIDGE and $DATAPATH are expected to be distinct. $BRIDGE_TYPE and
|
||||
# $DATAPATH are set correctly on success; failure indicates that the
|
||||
@@ -721,7 +689,7 @@ init_fastdp() {
|
||||
ip link set dev $DATAPATH mtu $MTU
|
||||
}
|
||||
|
||||
init_bridge() {
|
||||
init_bridge_prep() {
|
||||
# Observe any MTU that is already set
|
||||
[ -n "$MTU" ] || MTU=${WEAVE_MTU:-65535}
|
||||
|
||||
@@ -749,12 +717,17 @@ init_bridge() {
|
||||
ip link del dev v${CONTAINER_IFNAME}du
|
||||
}
|
||||
|
||||
init_bridge() {
|
||||
init_bridge_prep
|
||||
create_veth $BRIDGE_IFNAME $PCAP_IFNAME add_iface_bridge $BRIDGE_IFNAME
|
||||
}
|
||||
|
||||
init_bridged_fastdp() {
|
||||
# Initialise the datapath as normal. NB sets MTU for use below
|
||||
init_fastdp
|
||||
|
||||
# Initialise the bridge using fast datapath MTU
|
||||
init_bridge
|
||||
init_bridge_prep
|
||||
|
||||
# Create linking veth pair
|
||||
create_veth $BRIDGE_IFNAME $DATAPATH_IFNAME configure_veth_bridged_fastdp
|
||||
@@ -885,18 +858,6 @@ ask_version() {
|
||||
[ -n "$DOCKERIMAGE" ] && docker run --rm --net=none -e WEAVE_CIDR=none $3 $DOCKERIMAGE $COVERAGE_ARGS --version
|
||||
}
|
||||
|
||||
setup_router_iface_fastdp() {
|
||||
true
|
||||
}
|
||||
|
||||
setup_router_iface_bridge() {
|
||||
create_veth $BRIDGE_IFNAME $PCAP_IFNAME add_iface_bridge $BRIDGE_IFNAME
|
||||
}
|
||||
|
||||
setup_router_iface_bridged_fastdp() {
|
||||
setup_router_iface_fastdp "$@"
|
||||
}
|
||||
|
||||
container_in_host_ns() {
|
||||
[ -h "$CONTAINER_NETNS" -a -h "/proc/self/ns/net" -a "$(readlink $CONTAINER_NETNS)" = "$(readlink /proc/self/ns/net)" ]
|
||||
}
|
||||
@@ -1056,6 +1017,43 @@ peer_args() {
|
||||
echo "$res"
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# CNI helpers
|
||||
######################################################################
|
||||
|
||||
create_cni_script() {
|
||||
cat >"$1" <<EOF
|
||||
#!/bin/sh
|
||||
[ -z "\$CNI_NETNS" -o \$(echo "\$CNI_NETNS" | grep "^/proc/") ] || \\
|
||||
EXTRA_VOLUMES="-v \$(dirname \$CNI_NETNS):\$(dirname \$CNI_NETNS)"
|
||||
docker run --rm $(docker_run_options) --pid=host -i \\
|
||||
-e CNI_VERSION -e CNI_COMMAND -e CNI_CONTAINERID -e CNI_NETNS \\
|
||||
-e CNI_IFNAME -e CNI_ARGS -e CNI_PATH \\
|
||||
-v /etc/cni:/etc/cni -v /opt/cni:/opt/cni \$EXTRA_VOLUMES \\
|
||||
$PLUGIN_IMAGE $COVERAGE_ARGS $2
|
||||
EOF
|
||||
chmod a+x "$1"
|
||||
}
|
||||
|
||||
create_cni_config() {
|
||||
cat >"$1" <<EOF
|
||||
{
|
||||
"name": "weave",
|
||||
"type": "weave-net"
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
setup_cni() {
|
||||
if [ -d $HOST_ROOT/opt/cni/bin ] ; then
|
||||
create_cni_script $HOST_ROOT/opt/cni/bin/weave-net --cni-net
|
||||
create_cni_script $HOST_ROOT/opt/cni/bin/weave-ipam --cni-ipam
|
||||
fi
|
||||
if [ -d $HOST_ROOT/etc/cni/net.d -a ! -f $HOST_ROOT/etc/cni/net.d/10-weave.conf ] ; then
|
||||
create_cni_config $HOST_ROOT/etc/cni/net.d/10-weave.conf
|
||||
fi
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# weaveDNS helpers
|
||||
######################################################################
|
||||
@@ -1240,6 +1238,20 @@ delete_dns_fqdn() {
|
||||
done
|
||||
}
|
||||
|
||||
is_ip() {
|
||||
echo "$1" | grep -E "^$IP_REGEXP$" >/dev/null
|
||||
}
|
||||
|
||||
collect_ip_args() {
|
||||
IP_ARGS=""
|
||||
IP_COUNT=0
|
||||
while is_ip "$1" ; do
|
||||
IP_ARGS="$IP_ARGS $1"
|
||||
IP_COUNT=$((IP_COUNT + 1))
|
||||
shift 1
|
||||
done
|
||||
}
|
||||
|
||||
collect_dns_add_remove_args() {
|
||||
collect_ip_args "$@"
|
||||
shift $IP_COUNT
|
||||
@@ -1463,11 +1475,12 @@ proxy_args() {
|
||||
|
||||
if [ -z "$PROXY_TLS_ENABLED" -a -z "$PROXY_TLS_DETECTION_DISABLED" ] ; then
|
||||
if ! DOCKER_TLS_ARGS=$(util_op docker-tls-args) ; then
|
||||
echo "Unable to auto-detect proxy TLS configuration; you must launch the proxy with" >&2
|
||||
echo "'weave launch-proxy' and supply '--no-detect-tls' or TLS options." >&2
|
||||
exit 1
|
||||
echo -n "Warning: unable to detect proxy TLS configuration. To enable TLS, " >&2
|
||||
echo -n "launch the proxy with 'weave launch-proxy' and supply TLS options. " >&2
|
||||
echo "To suppress this warning, supply the '--no-detect-tls' option." >&2
|
||||
else
|
||||
proxy_parse_args $DOCKER_TLS_ARGS
|
||||
fi
|
||||
proxy_parse_args $DOCKER_TLS_ARGS
|
||||
fi
|
||||
if [ -z "$PROXY_HOST" ] ; then
|
||||
case "$DOCKER_CLIENT_HOST" in
|
||||
@@ -1581,7 +1594,6 @@ launch_router() {
|
||||
--no-dns)
|
||||
DNS_ROUTER_OPTS=
|
||||
NO_DNS_OPT="--no-dns"
|
||||
ARGS="$ARGS $1"
|
||||
;;
|
||||
--no-restart)
|
||||
RESTART_POLICY=
|
||||
@@ -1598,6 +1610,7 @@ launch_router() {
|
||||
done
|
||||
eval "set -- $ARGS"
|
||||
|
||||
setup_cni
|
||||
create_bridge
|
||||
# We set the router name to the bridge MAC, which in turn is
|
||||
# derived from the system UUID (if available), and thus stable
|
||||
@@ -1653,11 +1666,13 @@ launch_router() {
|
||||
--http-addr $HTTP_ADDR \
|
||||
--resolv-conf "/var/run/weave/etc/$RESOLV_CONF_BASE" \
|
||||
"$@")
|
||||
setup_router_iface_$BRIDGE_TYPE
|
||||
wait_for_status $CONTAINER_NAME http_call $HTTP_ADDR
|
||||
setup_awsvpc
|
||||
populate_router
|
||||
}
|
||||
|
||||
setup_awsvpc() {
|
||||
if [ -n "$AWSVPC" ]; then
|
||||
expose_ip
|
||||
# Set proxy_arp on the bridge, so that it could accept packets destined
|
||||
# to containers within the same subnet but running on remote hosts.
|
||||
# Without it, exact routes on each container are required.
|
||||
@@ -1666,6 +1681,7 @@ launch_router() {
|
||||
# placing the request into a bounded queue as it can be seen:
|
||||
# https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/tree/net/ipv4/arp.c?id=refs/tags/v4.6.1#n819
|
||||
echo 0 >/proc/sys/net/ipv4/neigh/$BRIDGE/proxy_delay
|
||||
expose_ip
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -1679,7 +1695,8 @@ fetch_router_args() {
|
||||
populate_router() {
|
||||
if [ -n "$IPRANGE" ] ; then
|
||||
# Tell the newly-started weave IP allocator about existing weave IPs
|
||||
with_container_addresses ipam_reclaim_no_check_alive weave:expose
|
||||
# In the case of AWSVPC, we do expose before calling populate_router
|
||||
[ -n "$AWSVPC" ] || with_container_addresses ipam_reclaim_no_check_alive weave:expose
|
||||
with_container_addresses ipam_reclaim $(docker ps -q --no-trunc)
|
||||
fi
|
||||
if [ -z "$NO_DNS_OPT" ] ; then
|
||||
@@ -1765,7 +1782,8 @@ launch_plugin_if_not_running() {
|
||||
return 1
|
||||
fi
|
||||
wait_for_status $PLUGIN_CONTAINER_NAME http_call_unix $PLUGIN_CONTAINER_NAME status.sock
|
||||
util_op create-plugin-network weave weavemesh
|
||||
WEAVE_IPAM_SUBNET=$(call_weave GET /ipinfo/defaultsubnet)
|
||||
util_op create-plugin-network weave weavemesh $WEAVE_IPAM_SUBNET
|
||||
}
|
||||
|
||||
plugin_disabled() {
|
||||
@@ -1784,44 +1802,9 @@ protect_against_docker_hang() {
|
||||
fi
|
||||
}
|
||||
|
||||
##########################################################################################
|
||||
|
||||
[ $(id -u) = 0 ] || {
|
||||
echo "weave must be run as 'root' when run locally" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
uname -s -r | sed -n -e 's|^\([^ ]*\) \([0-9][0-9]*\)\.\([0-9][0-9]*\).*|\1 \2 \3|p' | {
|
||||
if ! read sys maj min ; then
|
||||
echo "ERROR: Unable to parse operating system version $(uname -s -r)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$sys" != 'Linux' ] ; then
|
||||
echo "ERROR: Operating systems other than Linux are not supported (you have $(uname -s -r))" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [ \( "$maj" -eq 3 -a "$min" -ge 8 \) -o "$maj" -gt 3 ] ; then
|
||||
echo "WARNING: Linux kernel version 3.8 or newer is required (you have ${maj}.${min})" >&2
|
||||
fi
|
||||
}
|
||||
|
||||
if ! command_exists ip ; then
|
||||
echo "ERROR: ip utility is missing. Please install it." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! ip netns list >/dev/null 2>&1 ; then
|
||||
echo "ERROR: $(ip -V) does not support network namespaces." >&2
|
||||
echo " Please install iproute2-ss111010 or later." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command_exists nsenter ; then
|
||||
echo "ERROR: nsenter utility missing. Please install it." >&2
|
||||
exit 1
|
||||
fi
|
||||
######################################################################
|
||||
# argument deprecation handling
|
||||
######################################################################
|
||||
|
||||
deprecation_warning() {
|
||||
echo "Warning: ${1%=*} is deprecated; please use $2" >&2
|
||||
@@ -1881,6 +1864,47 @@ deprecation_warnings() {
|
||||
done
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# main (remote and --local)
|
||||
######################################################################
|
||||
|
||||
[ $(id -u) = 0 ] || {
|
||||
echo "weave must be run as 'root' when run locally" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
uname -s -r | sed -n -e 's|^\([^ ]*\) \([0-9][0-9]*\)\.\([0-9][0-9]*\).*|\1 \2 \3|p' | {
|
||||
if ! read sys maj min ; then
|
||||
echo "ERROR: Unable to parse operating system version $(uname -s -r)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$sys" != 'Linux' ] ; then
|
||||
echo "ERROR: Operating systems other than Linux are not supported (you have $(uname -s -r))" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [ \( "$maj" -eq 3 -a "$min" -ge 8 \) -o "$maj" -gt 3 ] ; then
|
||||
echo "WARNING: Linux kernel version 3.8 or newer is required (you have ${maj}.${min})" >&2
|
||||
fi
|
||||
}
|
||||
|
||||
if ! command_exists ip ; then
|
||||
echo "ERROR: ip utility is missing. Please install it." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! ip netns list >/dev/null 2>&1 ; then
|
||||
echo "ERROR: $(ip -V) does not support network namespaces." >&2
|
||||
echo " Please install iproute2-ss111010 or later." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command_exists nsenter ; then
|
||||
echo "ERROR: nsenter utility missing. Please install it." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
[ $# -gt 0 ] || usage
|
||||
COMMAND=$1
|
||||
shift 1
|
||||
@@ -1906,22 +1930,24 @@ case "$COMMAND" in
|
||||
# intentionally undocumented since it assumes knowledge of weave
|
||||
# internals
|
||||
create-bridge)
|
||||
cat 1>&2 <<EOF
|
||||
if [ "$1" != "--force" ] ; then
|
||||
cat 1>&2 <<EOF
|
||||
WARNING: 'weave create-bridge' is deprecated. Instead use 'weave attach-bridge'
|
||||
to link the docker and weave bridges after both docker and weave have been
|
||||
started. Note that, unlike 'weave create-bridge', 'weave attach-bridge' is
|
||||
compatible with fast data path.
|
||||
EOF
|
||||
# This subcommand may be run without the docker daemon, but
|
||||
# fastdp needs to run the router container to setup the ODP
|
||||
# bridge, hence:
|
||||
if [ -z "$WEAVE_NO_FASTDP" ] ; then
|
||||
cat 1>&2 <<EOF
|
||||
# This subcommand may be run without the docker daemon, but
|
||||
# fastdp needs to run the router container to setup the ODP
|
||||
# bridge, hence:
|
||||
if [ -z "$WEAVE_NO_FASTDP" ] ; then
|
||||
cat 1>&2 <<EOF
|
||||
|
||||
ERROR: 'weave create-bridge' is not compatible with fast data path. If you
|
||||
really want to do this please set the WEAVE_NO_FASTDP environment variable.
|
||||
EOF
|
||||
exit 1
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
create_bridge --without-ethtool
|
||||
;;
|
||||
@@ -1956,10 +1982,12 @@ EOF
|
||||
attach-router)
|
||||
check_running $CONTAINER_NAME
|
||||
enforce_docker_bridge_addr_assign_type
|
||||
# We cannot use detect_awsvpc here, because HTTP server might not be started
|
||||
! docker inspect -f '{{.Config.Cmd}}' $CONTAINER_NAME | grep -q -- "--awsvpc" || AWSVPC=1
|
||||
create_bridge
|
||||
fetch_router_args
|
||||
setup_router_iface_$BRIDGE_TYPE
|
||||
wait_for_status $CONTAINER_NAME http_call $HTTP_ADDR
|
||||
setup_awsvpc
|
||||
populate_router
|
||||
;;
|
||||
launch-proxy)
|
||||
@@ -1969,6 +1997,10 @@ EOF
|
||||
echo $PROXY_CONTAINER
|
||||
;;
|
||||
launch-plugin)
|
||||
if ! check_running $CONTAINER_NAME 2>/dev/null ; then
|
||||
echo "ERROR:" $CONTAINER_NAME "container must be running before plugin can be launched" >&2
|
||||
exit 1
|
||||
fi
|
||||
launch_plugin_if_not_running "$@"
|
||||
echo $PLUGIN_CONTAINER
|
||||
;;
|
||||
|
||||
Reference in new issue
Block a user