From 53cc270f4717bf344928599db5212ae5b0719a44 Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Thu, 10 Nov 2016 11:24:11 -0800 Subject: [PATCH 01/36] Make compatible with Docker Swarmkit Implement (empty) endpoints for new NetworkAllocate and NetworkFree calls Also update libnetwork and docker dependencies --- plugin/net/driver.go | 10 ++++++++++ plugin/skel/listener.go | 24 ++++++++++++++++++++++++ vendor/github.com/docker/docker | 2 +- vendor/github.com/docker/libnetwork | 2 +- 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/plugin/net/driver.go b/plugin/net/driver.go index 3a9740af..e1560bc5 100644 --- a/plugin/net/driver.go +++ b/plugin/net/driver.go @@ -67,6 +67,16 @@ func (driver *driver) CreateNetwork(create *api.CreateNetworkRequest) error { return err } +func (driver *driver) NetworkAllocate(alloc *api.AllocateNetworkRequest) (*api.AllocateNetworkResponse, error) { + driver.logReq("NetworkAllocate", alloc, alloc.NetworkID) + return nil, nil +} + +func (driver *driver) NetworkFree(free *api.FreeNetworkRequest) (*api.FreeNetworkResponse, error) { + driver.logReq("NetworkFree", free, free.NetworkID) + return nil, nil +} + // Deal with excessively-generic way the options get decoded from JSON func stringOptions(create *api.CreateNetworkRequest) map[string]string { if create.Options != nil { diff --git a/plugin/skel/listener.go b/plugin/skel/listener.go index afe0584e..a253ac94 100644 --- a/plugin/skel/listener.go +++ b/plugin/skel/listener.go @@ -26,6 +26,8 @@ type Driver interface { DeleteEndpoint(delete *api.DeleteEndpointRequest) error EndpointInfo(req *api.EndpointInfoRequest) (*api.EndpointInfoResponse, error) JoinEndpoint(j *api.JoinRequest) (response *api.JoinResponse, error error) + NetworkAllocate(*api.AllocateNetworkRequest) (*api.AllocateNetworkResponse, error) + NetworkFree(*api.FreeNetworkRequest) (*api.FreeNetworkResponse, error) LeaveEndpoint(leave *api.LeaveRequest) error DiscoverNew(discover *api.DiscoveryNotification) error DiscoverDelete(delete *api.DiscoveryNotification) error @@ -58,6 +60,8 @@ func Listen(socket net.Listener, driver Driver, ipamDriver ipamapi.Ipam) error { handleMethod(networkReceiver, "EndpointOperInfo", listener.infoEndpoint) handleMethod(networkReceiver, "Join", listener.joinEndpoint) handleMethod(networkReceiver, "Leave", listener.leaveEndpoint) + handleMethod(networkReceiver, "AllocateNetwork", listener.networkAllocate) + handleMethod(networkReceiver, "FreeNetwork", listener.networkFree) } if ipamDriver != nil { @@ -163,6 +167,26 @@ func (listener *listener) joinEndpoint(w http.ResponseWriter, r *http.Request) { objectOrErrorResponse(w, res, err) } +func (listener *listener) networkAllocate(w http.ResponseWriter, r *http.Request) { + var alloc api.AllocateNetworkRequest + if err := json.NewDecoder(r.Body).Decode(&alloc); err != nil { + sendError(w, "Could not decode JSON encode payload", http.StatusBadRequest) + return + } + res, err := listener.d.NetworkAllocate(&alloc) + objectOrErrorResponse(w, res, err) +} + +func (listener *listener) networkFree(w http.ResponseWriter, r *http.Request) { + var free api.FreeNetworkRequest + if err := json.NewDecoder(r.Body).Decode(&free); err != nil { + sendError(w, "Could not decode JSON encode payload", http.StatusBadRequest) + return + } + res, err := listener.d.NetworkFree(&free) + objectOrErrorResponse(w, res, err) +} + func (listener *listener) leaveEndpoint(w http.ResponseWriter, r *http.Request) { var l api.LeaveRequest if err := json.NewDecoder(r.Body).Decode(&l); err != nil { diff --git a/vendor/github.com/docker/docker b/vendor/github.com/docker/docker index 4dc5990d..c13bf5ba 160000 --- a/vendor/github.com/docker/docker +++ b/vendor/github.com/docker/docker @@ -1 +1 @@ -Subproject commit 4dc5990d7565a4a15d641bc6a0bc50a02cfcf302 +Subproject commit c13bf5ba51c4f6a1ba5e5c0da0d4f85d2d5b9116 diff --git a/vendor/github.com/docker/libnetwork b/vendor/github.com/docker/libnetwork index ca6760d6..1861587d 160000 --- a/vendor/github.com/docker/libnetwork +++ b/vendor/github.com/docker/libnetwork @@ -1 +1 @@ -Subproject commit ca6760d6c9d18caea324a1217f6c7032f527f44e +Subproject commit 1861587d0fe7cdf85b89160ed36f20b81e96528d From 090878c1577f5a4de2f798967fabc8888364b10a Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Thu, 5 Jan 2017 17:38:05 +0000 Subject: [PATCH 02/36] Implement GetCapabilities on IPAM interface to eliminate warning message --- plugin/ipam/driver.go | 5 +++++ plugin/skel/listener.go | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/plugin/ipam/driver.go b/plugin/ipam/driver.go index 417e468f..78a650e7 100644 --- a/plugin/ipam/driver.go +++ b/plugin/ipam/driver.go @@ -19,6 +19,11 @@ func NewIpam(weave *api.Client) *Ipam { return &Ipam{weave: weave} } +func (i *Ipam) GetCapabilities() (RequiresMACAddress bool, RequiresRequestReplay bool, err error) { + i.logReq("GetCapabilities") + return false, false, nil +} + func (i *Ipam) GetDefaultAddressSpaces() (string, string, error) { i.logReq("GetDefaultAddressSpaces") return "weavelocal", "weaveglobal", nil diff --git a/plugin/skel/listener.go b/plugin/skel/listener.go index a253ac94..1ad98ba8 100644 --- a/plugin/skel/listener.go +++ b/plugin/skel/listener.go @@ -33,6 +33,10 @@ type Driver interface { DiscoverDelete(delete *api.DiscoveryNotification) error } +type IpamCapability interface { + GetCapabilities() (RequiresMACAddress bool, RequiresRequestReplay bool, err error) +} + type listener struct { d Driver i ipamapi.Ipam @@ -65,6 +69,7 @@ func Listen(socket net.Listener, driver Driver, ipamDriver ipamapi.Ipam) error { } if ipamDriver != nil { + handleMethod(ipamReceiver, "GetCapabilities", listener.getIpamCapabilities) handleMethod(ipamReceiver, "GetDefaultAddressSpaces", listener.getDefaultAddressSpaces) handleMethod(ipamReceiver, "RequestPool", listener.requestPool) handleMethod(ipamReceiver, "ReleasePool", listener.releasePool) @@ -216,6 +221,20 @@ func (listener *listener) discoverDelete(w http.ResponseWriter, r *http.Request) // === +func (listener *listener) getIpamCapabilities(w http.ResponseWriter, r *http.Request) { + c, ok := listener.i.(IpamCapability) + if !ok { + http.NotFound(w, r) + return + } + requiresMACAddress, requiresRequestReplay, err := c.GetCapabilities() + response := &ipamapi.Capability{ + RequiresMACAddress: requiresMACAddress, + RequiresRequestReplay: requiresRequestReplay, + } + objectOrErrorResponse(w, response, err) +} + func (listener *listener) getDefaultAddressSpaces(w http.ResponseWriter, r *http.Request) { local, global, err := listener.i.GetDefaultAddressSpaces() response := &iapi.GetAddressSpacesResponse{ From 5bbd886e6f195c45035f90805236aac81d6a90be Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Fri, 6 Jan 2017 18:08:37 +0000 Subject: [PATCH 03/36] Build a 'v2' Docker plugin Redirect output to specific log files, because there doesn't seem to be a 'docker logs' for plugins --- .gitignore | 1 + Makefile | 25 ++++++++++++++-- prog/v2-plugin/config.json | 24 ++++++++++++++++ prog/v2-plugin/launch.sh | 58 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 prog/v2-plugin/config.json create mode 100755 prog/v2-plugin/launch.sh diff --git a/.gitignore b/.gitignore index 3a7f66ad..0e410022 100644 --- a/.gitignore +++ b/.gitignore @@ -70,3 +70,4 @@ test/coverage.* *qemu-*-static terraform.tfstate terraform.tfstate.backup +prog/plugin-v2/rootfs/ diff --git a/Makefile b/Makefile index cf3bc69e..e3e5f21e 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ .DEFAULT: all -.PHONY: all exes testrunner update tests lint publish-one-arch $(PUBLISH) clean clean-bin prerequisites build run-smoketests +.PHONY: all exes testrunner update tests lint publish-one-arch $(PUBLISH) clean clean-bin clean-work-dir 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") @@ -107,6 +107,7 @@ BUILD_UPTODATE=.build.uptodate WEAVER_UPTODATE=.weaver$(ARCH_EXT).uptodate WEAVEEXEC_UPTODATE=.weaveexec$(ARCH_EXT).uptodate PLUGIN_UPTODATE=.plugin$(ARCH_EXT).uptodate +PLUGINV2_UPTODATE=.pluginv2$(ARCH_EXT).uptodate WEAVEKUBE_UPTODATE=.weavekube$(ARCH_EXT).uptodate WEAVENPC_UPTODATE=.weavenpc$(ARCH_EXT).uptodate WEAVEDB_UPTODATE=.weavedb.uptodate @@ -121,9 +122,12 @@ 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 +PLUGINV2_IMAGE=$(DOCKERHUB_USER)/pluginv2$(ARCH_EXT) IMAGES=$(WEAVER_IMAGE) $(WEAVEEXEC_IMAGE) $(PLUGIN_IMAGE) $(WEAVEKUBE_IMAGE) $(WEAVENPC_IMAGE) $(WEAVEDB_IMAGE) +PLUGINV2_WORK_DIR="prog/plugin-v2/rootfs" + 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 @@ -268,6 +272,20 @@ $(PLUGIN_UPTODATE): prog/plugin/Dockerfile.$(DOCKERHUB_USER) $(PLUGIN_EXE) $(WEA $(SUDO) docker build -f prog/plugin/Dockerfile.$(DOCKERHUB_USER) -t $(PLUGIN_IMAGE) prog/plugin touch $@ +# TODO(mp) cleanup! +pluginv2: prog/plugin-v2/launch.sh prog/plugin-v2/config.json $(PLUGIN_UPTODATE) + -$(SUDO) docker rm -f buildpluginv2 + $(SUDO) docker create --name=buildpluginv2 $(PLUGIN_IMAGE) true + rm -rf $(PLUGINV2_WORK_DIR) + mkdir $(PLUGINV2_WORK_DIR) + docker export buildpluginv2 | tar -x -C $(PLUGINV2_WORK_DIR) + docker rm buildpluginv2 + cp prog/plugin-v2/launch.sh $(PLUGINV2_WORK_DIR)/home/weave/launch.sh + -docker plugin disable $(PLUGINV2_IMAGE) + -docker plugin rm $(PLUGINV2_IMAGE) + docker plugin create $(PLUGINV2_IMAGE) prog/plugin-v2 + #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 @@ -345,13 +363,16 @@ ifneq ($(UPDATE_LATEST),false) $(MANIFEST_TOOL_EXE) push from-args --platforms $(ML_PLATFORMS) --template $(DOCKERHUB_USER)/$*-ARCH:latest --target $(DOCKERHUB_USER)/$*:latest endif +clean-work-dir: + rm -rf $(PLUGINV2_WORK_DIR) + clean-bin: -$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker rmi $(IMAGES) 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 +clean: clean-bin clean-work-dir -$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker rmi $(BUILD_IMAGE) rm -rf test/tls/*.pem test/coverage.* test/coverage $(BUILD_UPTODATE) $(MANIFEST_TOOL_EXE) diff --git a/prog/v2-plugin/config.json b/prog/v2-plugin/config.json new file mode 100644 index 00000000..7aad2c84 --- /dev/null +++ b/prog/v2-plugin/config.json @@ -0,0 +1,24 @@ +{ + "description": "Weave Net plugin for Docker", + "documentation": "https://weave.works", + "entrypoint": [ + "/home/weave/launch.sh" + ], + "interface": { + "socket": "weave.sock", + "types": [ + "docker.networkdriver/1.0" + ] + }, + "linux": { + "capabilities": [ + "CAP_SYS_ADMIN", + "CAP_NET_ADMIN" + ] + }, + "mounts": [], + "network": { + "type": "host" + }, + "workdir": "" +} diff --git a/prog/v2-plugin/launch.sh b/prog/v2-plugin/launch.sh new file mode 100755 index 00000000..ea2608e2 --- /dev/null +++ b/prog/v2-plugin/launch.sh @@ -0,0 +1,58 @@ +#!/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} +LOG_FILE=/tmp/weaver.log + +echo "Starting launch.sh" >>$LOG_FILE + +# Check if the IP range overlaps anything existing on the host +/usr/bin/weaveutil netcheck $IPALLOC_RANGE weave + +/home/weave/weave --local create-bridge --force >>$LOG_FILE 2>&1 + +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 "$IPALLOC_INIT" ]; then + # ideally we would know the peer count + IPALLOC_INIT="consensus" +fi + +/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 \ + --ipalloc-init $IPALLOC_INIT \ + --nickname "$(hostname)" \ + >>$LOG_FILE 2>&1 & +WEAVE_PID=$! + +# Wait for weave process to become responsive +while true; do + curl $HTTP_ADDR/status >/dev/null 2>&1 && break + if ! kill -0 $WEAVE_PID >/dev/null 2>&1; then + echo Weave process has died >&2 + exit 1 + fi + sleep 1 +done + +/home/weave/plugin --meshsocket='' --docker-api='' >/tmp/plugin.log 2>&1 & + +echo "End of launch.sh" >>$LOG_FILE + +wait $WEAVE_PID From 0af2111535dbdac657d6f58bd4e1cf1bbe088c42 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Thu, 5 Jan 2017 18:02:00 +0000 Subject: [PATCH 04/36] Mention swarm mode in docs --- site/plugin.md | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/site/plugin.md b/site/plugin.md index 832387c8..32a4a452 100644 --- a/site/plugin.md +++ b/site/plugin.md @@ -59,8 +59,29 @@ then run your containers using the Docker command-line: Docker enables you to create multiple independent networks and attach different sets of containers to each network. However, coordinating -this between hosts, Docker requires that you configure a -["key-value store"](https://docs.docker.com/engine/userguide/networking/get-started-overlay/#step-1-set-up-a-key-value-store). +this between hosts requires that you run Docker in ["swarm mode"](https://docs.docker.com/engine/swarm/swarm-mode/) or configure a +["key-value store"](https://docs.docker.com/engine/userguide/networking/get-started-overlay/#/set-up-a-key-value-store). + +Docker swarm mode requires Docker version 1.13 or later to work with +plugins such as Weave Net. + +To create a new network for services in swarm mode, run: + + $ docker network create --driver=weaveworks/net-plugin:2.0.0 mynetwork + +then use it to create a service: + + $ docker service create --network=mynetwork --name myservice ... + + +To create a new network to attach containers in swarm mode, run: + + $ docker network create --driver=weave --attachable mynetwork + +then use it to connect a container: + + $ docker run --net=mynetwork ... + If your Docker installation has a key-value store, create a network based on Weave Net as follows: From 0c23e4712421c51a2678a5fd44914fd4fafd7feb Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Mon, 9 Jan 2017 14:53:24 +0000 Subject: [PATCH 05/36] Allow docker API location to be specified or blanked --- prog/plugin/main.go | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/prog/plugin/main.go b/prog/plugin/main.go index 6e36d8ec..3084f219 100644 --- a/prog/plugin/main.go +++ b/prog/plugin/main.go @@ -28,14 +28,22 @@ var Log = common.Log func main() { var ( justVersion bool + dockerAPI string address string meshAddress string logLevel string noMulticastRoute bool + + defaultDockerHost = "unix:///var/run/docker.sock" ) + if val := os.Getenv("DOCKER_HOST"); val != "" { + defaultDockerHost = val + } + flag.BoolVar(&justVersion, "version", false, "print version and exit") flag.StringVar(&logLevel, "log-level", "info", "logging level (debug, info, warning, error)") + flag.StringVar(&dockerAPI, "docker-api", defaultDockerHost, "Docker API endpoint") 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") flag.BoolVar(&noMulticastRoute, "no-multicast-route", false, "deprecated (this is now the default)") @@ -51,17 +59,25 @@ func main() { weave := weaveapi.NewClient(os.Getenv("WEAVE_HTTP_ADDR"), Log) - // API 1.21 is the first version that supports docker network commands - dockerClient, err := docker.NewVersionedClientFromEnv("1.21") - if err != nil { - Log.Fatalf("unable to connect to docker: %s", err) + var dockerClient *docker.Client + var err error + if dockerAPI != "" { + // API 1.21 is the first version that supports docker network commands + dockerClient, err = docker.NewVersionedClient(dockerAPI, "1.21") + if err != nil { + Log.Fatalf("unable to connect to docker: %s", err) + } } Log.Println("Weave plugin", version, "Command line options:", os.Args[1:]) if noMulticastRoute { Log.Warning("--no-multicast-route option has been removed; multicast is off by default") } - Log.Info(dockerClient.Info()) + if dockerClient == nil { + Log.Info("Running without Docker API connection") + } else { + Log.Info(dockerClient.Info()) + } err = run(dockerClient, weave, address, meshAddress) if err != nil { From b048b6deb0c744365feeb68780c9b2931cc40de8 Mon Sep 17 00:00:00 2001 From: Marc CARRE Date: Thu, 16 Feb 2017 13:13:20 +0000 Subject: [PATCH 06/36] Bind-mount /proc in V2 plugin container. This allows to pass ARP settings from the host, e.g.: ``` $ sudo docker-runc exec 512af90f342f16dddebc7b7245985d5eb67557e76798b4033eed2ff7adaa4eb5 cat /proc/sys/net/ipv4/neigh/weave/ucast_solicit 3 $ cat /proc/sys/net/ipv4/neigh/weave/ucast_solicit 3 $ cat /proc/sys/net/ipv4/neigh/weave/ucast_solicit 1 $ sudo docker-runc exec 512af90f342f16dddebc7b7245985d5eb67557e76798b4033eed2ff7adaa4eb5 cat /proc/sys/net/ipv4/neigh/weave/ucast_solicit 1 ``` --- prog/v2-plugin/config.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/prog/v2-plugin/config.json b/prog/v2-plugin/config.json index 7aad2c84..7f1e0b2a 100644 --- a/prog/v2-plugin/config.json +++ b/prog/v2-plugin/config.json @@ -16,7 +16,13 @@ "CAP_NET_ADMIN" ] }, - "mounts": [], + "mounts": [ + { + "destination": "/procmount", + "type": "proc", + "source": "proc" + } + ], "network": { "type": "host" }, From eb5435d2751538b294abe314417a601bf9e51dd7 Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Mon, 20 Feb 2017 16:20:46 +0000 Subject: [PATCH 07/36] Bump Docker CI version to 1.13.1 --- DEPENDENCIES | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index c93ed026..32a099ba 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -1,3 +1,3 @@ -DOCKER_VERSION=1.11.2 +DOCKER_VERSION=1.13.1 KUBERNETES_VERSION=1.6.1 -KUBERNETES_CNI_VERSION=0.5.1 \ No newline at end of file +KUBERNETES_CNI_VERSION=0.5.1 From 2ba8764615c0164ed9eaec1b866ee865024ef06b Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Mon, 13 Mar 2017 10:02:22 +0000 Subject: [PATCH 08/36] Do not run "docker kill" inside smoke tests, because Docker 1.13.1 Otherwise test suites hang if run with Docker 1.13.1. See: https://github.com/docker/docker/issues/31447 --- test/335_rmpeer_3_test.sh | 5 ++++- test/620_proxy_entrypoint_command_test.sh | 8 ++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/test/335_rmpeer_3_test.sh b/test/335_rmpeer_3_test.sh index ffdfc85b..eb8f916e 100755 --- a/test/335_rmpeer_3_test.sh +++ b/test/335_rmpeer_3_test.sh @@ -14,7 +14,10 @@ weave_on $HOST3 launch $HOST1 weave_on $HOST3 prime # nuke 1st peer -docker_on $HOST1 kill weave +# NOTE: docker-kill hangs (https://github.com/docker/docker/issues/31447), so we +# kill directly the weaver process instead. +WEAVER_PID=$(container_pid $HOST1 weave) +run_on $HOST1 "sudo kill -9 $WEAVER_PID" # transfer its space to the 2nd weave_on $HOST2 rmpeer $PEER1 diff --git a/test/620_proxy_entrypoint_command_test.sh b/test/620_proxy_entrypoint_command_test.sh index 1085bcac..748c415a 100755 --- a/test/620_proxy_entrypoint_command_test.sh +++ b/test/620_proxy_entrypoint_command_test.sh @@ -15,7 +15,7 @@ run_container() { } start_suite "Proxy uses correct entrypoint and command with weavewait" -weave_on $HOST1 launch-proxy +weave_on $HOST1 launch-proxy --no-restart build_image check-ethwe-up '["grep"]' '["^1$", "/sys/class/net/ethwe/carrier"]' run_container "check-ethwe-up" @@ -27,7 +27,11 @@ build_image false '["/bin/false"]' '' run_container "--entrypoint='grep' false ^1$ /sys/class/net/ethwe/carrier" weave_on $HOST1 launch-router --ipalloc-range 10.2.2.0/24 -docker_on $HOST1 kill weaveproxy +# NOTE: docker-kill hangs (https://github.com/docker/docker/issues/31447), so we +# kill directly the weaveproxy process instead. +WEAVEPROXY_PID=$(container_pid $HOST1 weaveproxy) +$SSH $HOST1 "ps aux | grep weaveproxy" +run_on $HOST1 "sudo kill -9 $WEAVEPROXY_PID" weave_on $HOST1 launch-proxy assert_raises "proxy docker_on $HOST1 run check-ethwe-up" From 889dc856af351c9254437fe6652a654dee54468f Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Tue, 21 Feb 2017 17:08:13 +0000 Subject: [PATCH 09/36] Update fsouza/go-dockerclient The updated dep requires adding the following new deps: - vendor/github.com/fsouza/go-dockerclient - vendor/golang.org/x/net --- .gitmodules | 9 ++++++--- vendor/github.com/docker/go-units | 1 + vendor/github.com/fsouza/go-dockerclient | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) create mode 160000 vendor/github.com/docker/go-units diff --git a/.gitmodules b/.gitmodules index cb055f87..21de8218 100644 --- a/.gitmodules +++ b/.gitmodules @@ -124,9 +124,12 @@ [submodule "vendor/github.com/containernetworking/cni"] path = vendor/github.com/containernetworking/cni url = https://github.com/containernetworking/cni -[submodule "vendor/golang.org/x/net"] - path = vendor/golang.org/x/net - url = https://go.googlesource.com/net [submodule "vendor/google.golang.org/grpc"] path = vendor/google.golang.org/grpc url = https://github.com/grpc/grpc-go +[submodule "vendor/github.com/docker/go-units"] + path = vendor/github.com/docker/go-units + url = https://github.com/docker/go-units +[submodule "vendor/golang.org/x/net"] + path = vendor/golang.org/x/net + url = https://github.com/golang/net diff --git a/vendor/github.com/docker/go-units b/vendor/github.com/docker/go-units new file mode 160000 index 00000000..0dadbb03 --- /dev/null +++ b/vendor/github.com/docker/go-units @@ -0,0 +1 @@ +Subproject commit 0dadbb0345b35ec7ef35e228dabb8de89a65bf52 diff --git a/vendor/github.com/fsouza/go-dockerclient b/vendor/github.com/fsouza/go-dockerclient index 03cbd2b1..364c822d 160000 --- a/vendor/github.com/fsouza/go-dockerclient +++ b/vendor/github.com/fsouza/go-dockerclient @@ -1 +1 @@ -Subproject commit 03cbd2b15b2a68937f9c752aae8ee7dc95172f17 +Subproject commit 364c822d280c4f34afc3339e50d4fc0129d6b5ec From 82b56848a985bdac450fef582be80b82a2d829c5 Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Tue, 21 Feb 2017 17:59:17 +0000 Subject: [PATCH 10/36] Add peer discovery for Docker Swarm The peer discovery relies on "GET /info" API call which returns list of master nodes. The peer list is passed to weaver when launching it. If node is a master, then we pass "--ipalloc-alloc consensus=$(MASTER_NODES_COUNT)" to weaver. Otherwise, we pass "--ipalloc-alloc observer". --- prog/v2-plugin/config.json | 12 +++++++ prog/v2-plugin/launch.sh | 15 ++++++--- prog/weaveutil/main.go | 2 ++ prog/weaveutil/swarm.go | 64 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 89 insertions(+), 4 deletions(-) create mode 100644 prog/weaveutil/swarm.go diff --git a/prog/v2-plugin/config.json b/prog/v2-plugin/config.json index 7f1e0b2a..ca04a7a8 100644 --- a/prog/v2-plugin/config.json +++ b/prog/v2-plugin/config.json @@ -21,6 +21,18 @@ "destination": "/procmount", "type": "proc", "source": "proc" + }, + { + "destination": "/var/run/docker.sock", + "source": "/var/run/docker.sock", + "type": "bind", + "options": ["rbind"] + }, + { + "destination": "/var/lib/weave", + "source": "/var/lib/weave", + "type": "bind", + "options": ["rbind"] } ], "network": { diff --git a/prog/v2-plugin/launch.sh b/prog/v2-plugin/launch.sh index ea2608e2..03bdd08a 100755 --- a/prog/v2-plugin/launch.sh +++ b/prog/v2-plugin/launch.sh @@ -7,13 +7,16 @@ 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} -LOG_FILE=/tmp/weaver.log +LOG_FILE=/var/lib/weave/weaver.log echo "Starting launch.sh" >>$LOG_FILE # Check if the IP range overlaps anything existing on the host /usr/bin/weaveutil netcheck $IPALLOC_RANGE weave +SWARM_PEERS=$(/usr/bin/weaveutil swarm-manager-peers 2>>$LOG_FILE) +! /usr/bin/weaveutil is-swarm-manager 2>>$LOG_FILE || IS_SWARM_MANAGER=1 + /home/weave/weave --local create-bridge --force >>$LOG_FILE 2>&1 BRIDGE_OPTIONS="--datapath=datapath" @@ -29,8 +32,11 @@ if [ "$(/home/weave/weave --local bridge-type)" = "bridge" ]; then fi if [ -z "$IPALLOC_INIT" ]; then - # ideally we would know the peer count - IPALLOC_INIT="consensus" + if [ $IS_SWARM_MANAGER == "1" ]; then + IPALLOC_INIT="consensus=$(echo $SWARM_PEERS | wc -l)" + else + IPALLOC_INIT="observer" + fi fi /home/weave/weaver $EXTRA_ARGS --port=6783 $BRIDGE_OPTIONS \ @@ -38,6 +44,7 @@ fi --ipalloc-range=$IPALLOC_RANGE \ --ipalloc-init $IPALLOC_INIT \ --nickname "$(hostname)" \ + $(echo $SWARM_PEERS | tr '\n' ' ') \ >>$LOG_FILE 2>&1 & WEAVE_PID=$! @@ -51,7 +58,7 @@ while true; do sleep 1 done -/home/weave/plugin --meshsocket='' --docker-api='' >/tmp/plugin.log 2>&1 & +/home/weave/plugin --meshsocket='' --docker-api='' >/var/lib/weave/plugin.log 2>&1 & echo "End of launch.sh" >>$LOG_FILE diff --git a/prog/weaveutil/main.go b/prog/weaveutil/main.go index 9e8ea815..103bd047 100644 --- a/prog/weaveutil/main.go +++ b/prog/weaveutil/main.go @@ -37,6 +37,8 @@ func init() { "expose-nat": exposeNAT, "bridge-ip": bridgeIP, "unique-id": uniqueID, + "swarm-manager-peers": swarmManagerPeers, + "is-swarm-manager": isSwarmManager, } } diff --git a/prog/weaveutil/swarm.go b/prog/weaveutil/swarm.go new file mode 100644 index 00000000..fbec29e9 --- /dev/null +++ b/prog/weaveutil/swarm.go @@ -0,0 +1,64 @@ +package main + +import ( + "fmt" + "strings" + + "github.com/fsouza/go-dockerclient" + "github.com/pkg/errors" +) + +const DOCKER_API_VERSION = "1.26" + +func isSwarmManager(args []string) error { + info, err := dockerInfo() + if err != nil { + return err + } + + if !info.Swarm.ControlAvailable { + return fmt.Errorf("node is not a manager") + } + + return nil +} + +func swarmManagerPeers(args []string) error { + info, err := dockerInfo() + if err != nil { + return err + } + + for _, managerNode := range info.Swarm.RemoteManagers { + ip, err := ipFromAddr(managerNode.Addr) + if err != nil { + return errors.Wrap(err, "ipFromAddr") + } + fmt.Println(ip) + } + + return nil +} + +func dockerInfo() (*docker.DockerInfo, error) { + client, err := docker.NewVersionedClientFromEnv(DOCKER_API_VERSION) + if err != nil { + return nil, errors.Wrap(err, "docker.NewVersionedClientFromEnv") + } + + info, err := client.Info() + if err != nil { + return nil, errors.Wrap(err, "docker.Info") + } + + return info, nil +} + +func ipFromAddr(addr string) (string, error) { + parts := strings.Split(addr, ":") + if len(parts) != 2 { + return "", fmt.Errorf("invalid address: %q", addr) + } + + return parts[0], nil +} From 4916badcc40f31cd0d16a2147d9bb3b1220a917c Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Tue, 7 Mar 2017 16:40:11 +0000 Subject: [PATCH 11/36] Move prog/v2-plugin to prog/plugin-v2 --- prog/{v2-plugin => plugin-v2}/config.json | 0 prog/{v2-plugin => plugin-v2}/launch.sh | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename prog/{v2-plugin => plugin-v2}/config.json (100%) rename prog/{v2-plugin => plugin-v2}/launch.sh (100%) diff --git a/prog/v2-plugin/config.json b/prog/plugin-v2/config.json similarity index 100% rename from prog/v2-plugin/config.json rename to prog/plugin-v2/config.json diff --git a/prog/v2-plugin/launch.sh b/prog/plugin-v2/launch.sh similarity index 100% rename from prog/v2-plugin/launch.sh rename to prog/plugin-v2/launch.sh From 4f42029228143a7a27a70ed4dfed10d678e3eb3f Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Tue, 7 Mar 2017 16:46:52 +0000 Subject: [PATCH 12/36] Enable WEAVE_{MTU,PASSWORD} env vars, persistence and ARP settings in plugin-v2 The vars can be customized before enabling the plugin with e.g.: docker plugin set $PLUGIN_NAME set WEAVE_MTU=8160 The ARP settings apply to "weave" bridge. In order to manipulate them, we bind mount the host's /proc to /host/proc. (The mount type of /proc changed to bind, Otherwise (when type = "proc"), the kernel does not propagate pids of host processes as the plugin runs in a separate PID ns.) Persistence relies on weave.db which is stored under /var/lib/weave/weave.db on the host. NOTE: we do not persist peer list for plugin-v2, as it gets restored from existing alive master nodes during the peer discovery. --- prog/plugin-v2/config.json | 43 +++++++++++++++++++++++++++++++++----- prog/plugin-v2/launch.sh | 28 ++++++++++++++++++------- weave | 34 +++++++++++++++++++++++------- 3 files changed, 85 insertions(+), 20 deletions(-) diff --git a/prog/plugin-v2/config.json b/prog/plugin-v2/config.json index ca04a7a8..74601b08 100644 --- a/prog/plugin-v2/config.json +++ b/prog/plugin-v2/config.json @@ -18,9 +18,10 @@ }, "mounts": [ { - "destination": "/procmount", - "type": "proc", - "source": "proc" + "destination": "/host/proc/", + "type": "bind", + "source": "/proc/", + "options": ["rbind", "rw"] }, { "destination": "/var/run/docker.sock", @@ -29,10 +30,42 @@ "options": ["rbind"] }, { - "destination": "/var/lib/weave", - "source": "/var/lib/weave", + "destination": "/host/var/lib/", + "source": "/var/lib/", "type": "bind", "options": ["rbind"] + }, + { + "destination": "/host/etc/", + "source": "/etc/", + "type": "bind", + "options": ["rbind"] + } + ], + "env": [ + { + "description": "Extra args to `weaver` and `plugin`", + "name": "EXTRA_ARGS", + "settable": [ + "value" + ], + "value": "" + }, + { + "description": "Encryption password", + "name": "WEAVE_PASSWORD", + "settable": [ + "value" + ], + "value": "" + }, + { + "description": "MTU", + "name": "WEAVE_MTU", + "settable": [ + "value" + ], + "value": "" } ], "network": { diff --git a/prog/plugin-v2/launch.sh b/prog/plugin-v2/launch.sh index 03bdd08a..c5bfc3b3 100755 --- a/prog/plugin-v2/launch.sh +++ b/prog/plugin-v2/launch.sh @@ -7,17 +7,26 @@ 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} -LOG_FILE=/var/lib/weave/weaver.log +WEAVE_DIR="/host/var/lib/weave" +LOG_FILE_WEAVER="$WEAVE_DIR/weaver.log" +LOG_FILE_PLUGIN="$WEAVE_DIR/plugin.log" -echo "Starting launch.sh" >>$LOG_FILE +mkdir $WEAVE_DIR || true + +echo "Starting launch.sh" >>$LOG_FILE_WEAVER # Check if the IP range overlaps anything existing on the host /usr/bin/weaveutil netcheck $IPALLOC_RANGE weave -SWARM_PEERS=$(/usr/bin/weaveutil swarm-manager-peers 2>>$LOG_FILE) -! /usr/bin/weaveutil is-swarm-manager 2>>$LOG_FILE || IS_SWARM_MANAGER=1 +SWARM_PEERS=$(/usr/bin/weaveutil swarm-manager-peers 2>>$LOG_FILE_WEAVER) +! /usr/bin/weaveutil is-swarm-manager 2>>$LOG_FILE_WEAVER || IS_SWARM_MANAGER=1 +# Prevent from restoring from a persisted peers list +rm -f "/restart.sentinel" -/home/weave/weave --local create-bridge --force >>$LOG_FILE 2>&1 +/home/weave/weave --local create-bridge \ + --proc-path=/host/proc \ + --weavedb-dir-path=$WEAVE_DIR \ + --force >>$LOG_FILE_WEAVER 2>&1 BRIDGE_OPTIONS="--datapath=datapath" if [ "$(/home/weave/weave --local bridge-type)" = "bridge" ]; then @@ -44,8 +53,10 @@ fi --ipalloc-range=$IPALLOC_RANGE \ --ipalloc-init $IPALLOC_INIT \ --nickname "$(hostname)" \ + --log-level=debug \ + --db-prefix="$WEAVE_DIR/weave" \ $(echo $SWARM_PEERS | tr '\n' ' ') \ - >>$LOG_FILE 2>&1 & + >>$LOG_FILE_WEAVER 2>&1 & WEAVE_PID=$! # Wait for weave process to become responsive @@ -58,8 +69,9 @@ while true; do sleep 1 done -/home/weave/plugin --meshsocket='' --docker-api='' >/var/lib/weave/plugin.log 2>&1 & +# TODO(mp) docker api? +/home/weave/plugin $EXTRA_ARGS --log-level=debug --meshsocket='' --docker-api='' >>$LOG_FILE_PLUGIN 2>&1 & -echo "End of launch.sh" >>$LOG_FILE +echo "End of launch.sh" >>$LOG_FILE_WEAVER wait $WEAVE_PID diff --git a/weave b/weave index dd12f351..623141ce 100755 --- a/weave +++ b/weave @@ -361,6 +361,7 @@ HTTP_ADDR=${WEAVE_HTTP_ADDR:-127.0.0.1:6784} STATUS_ADDR=${WEAVE_STATUS_ADDR:-127.0.0.1:6782} PROXY_PORT=12375 PROXY_CONTAINER_NAME=weaveproxy +PROC_PATH="/proc" COVERAGE_ARGS="" [ -n "$COVERAGE" ] && COVERAGE_ARGS="-test.coverprofile=/home/weave/cover.prof --" @@ -442,9 +443,9 @@ delete_iptables_rule() { # makes containers react more quickly to a change in the MAC address # associated with an IP address. configure_arp_cache() { - $2 sh -c "echo 5 >/proc/sys/net/ipv4/neigh/$1/base_reachable_time && - echo 2 >/proc/sys/net/ipv4/neigh/$1/delay_first_probe_time && - echo 1 >/proc/sys/net/ipv4/neigh/$1/ucast_solicit" + $2 sh -c "echo 5 >$PROC_PATH/sys/net/ipv4/neigh/$1/base_reachable_time && + echo 2 >$PROC_PATH/sys/net/ipv4/neigh/$1/delay_first_probe_time && + echo 1 >$PROC_PATH/sys/net/ipv4/neigh/$1/ucast_solicit" } # Send out an ARP announcement @@ -725,8 +726,10 @@ init_bridge_prep() { # Running this from 'weave --local' when weaveexec is not on the # path will run it as a Docker container that does not have access # to /etc/machine-id, so will not give the full range of persistent IDs - WEAVEDB_PATH=$(docker inspect -f '{{with index .Mounts 0}}{{.Source}}{{end}}' $DB_CONTAINER_NAME 2>/dev/null) - MAC=$(util_op unique-id "$HOST_ROOT/$WEAVEDB_PATH/weave" "$HOST_ROOT") + if [ -z "$WEAVEDB_DIR_PATH" ]; then + WEAVEDB_DIR_PATH="$HOST_ROOT/$(docker inspect -f '{{with index .Mounts 0}}{{.Source}}{{end}}' $DB_CONTAINER_NAME 2>/dev/null)" + fi + MAC=$(util_op unique-id "$WEAVEDB_DIR_PATH/weave" "$HOST_ROOT") ip link set dev $BRIDGE address $MAC @@ -1698,11 +1701,11 @@ setup_awsvpc() { # 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. - echo 1 >/proc/sys/net/ipv4/conf/$BRIDGE/proxy_arp + echo 1 >$PROC_PATH/sys/net/ipv4/conf/$BRIDGE/proxy_arp # Avoid delaying the first ARP request. Also, setting it to 0 avoids # 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 + echo 0 >$PROC_PATH/sys/net/ipv4/neigh/$BRIDGE/proxy_delay expose_ip fi } @@ -1945,6 +1948,22 @@ case "$COMMAND" in # intentionally undocumented since it assumes knowledge of weave # internals create-bridge) + while [ $# -gt 0 ]; do + case "$1" in + --proc-path=*) + PROC_PATH="${1#*=}" + shift + ;; + --weavedb-dir-path=*) + WEAVEDB_DIR_PATH="${1#*=}" + shift + ;; + *) + break + ;; + esac + done + if [ "$1" != "--force" ] ; then cat 1>&2 < Date: Tue, 7 Mar 2017 16:52:08 +0000 Subject: [PATCH 13/36] Add smoke test for plugin-v2 --- test/850_plugin_v2_cross_hosts_2_test.sh | 133 +++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100755 test/850_plugin_v2_cross_hosts_2_test.sh diff --git a/test/850_plugin_v2_cross_hosts_2_test.sh b/test/850_plugin_v2_cross_hosts_2_test.sh new file mode 100755 index 00000000..3c8bab54 --- /dev/null +++ b/test/850_plugin_v2_cross_hosts_2_test.sh @@ -0,0 +1,133 @@ +#! /bin/bash + +. "$(dirname "$0")/config.sh" + +PLUGIN_NAME="weave-ci-registry:5000/weaveworks/plugin-v2" +HOST1_IP=$($SSH $HOST1 getent ahosts $HOST1 | grep "RAW" | cut -d' ' -f1) +SERVICE="weave-850-service" +NETWORK="weave-850-network" + +setup_master() { + # Setup Docker image registry on $HOST1 + docker_on $HOST1 run -p 5000:5000 -d registry:2 + + # Build plugin-v2 on $HOST1, because Circle "CI" runs only ancient + # version of Docker which does not support v2 plugins. + build_plugin_img="buildpluginv2-ci" + rsync -az -e "$SSH" "$(dirname $0)/../prog/plugin-v2" $HOST1:~/ + $SSH $HOST1</dev/null + docker plugin disable $PLUGIN_NAME >/dev/null + docker plugin remove $PLUGIN_NAME 2>/dev/null + + WORK_DIR=$(mktemp -d) + mkdir -p \${WORK_DIR}/rootfs + + docker create --name=$build_plugin_img weaveworks/plugin true + docker export $build_plugin_img | tar -x -C \${WORK_DIR}/rootfs + cp \${HOME}/plugin-v2/launch.sh \${WORK_DIR}/rootfs/home/weave/launch.sh + cp \${HOME}/plugin-v2/config.json \${WORK_DIR} + docker plugin create $PLUGIN_NAME \${WORK_DIR} + + echo "$HOST1_IP weave-ci-registry" | sudo tee -a /etc/hosts + docker plugin push $PLUGIN_NAME + + # Start Swarm Manager and enable the plugin + docker swarm init --advertise-addr=$HOST1_IP + + [ -n "$COVERAGE" ] && docker plugin set $PLUGIN_NAME EXTRA_ARGS="-test.coverprofile=/home/weave/cover.prof --" + #docker plugin set $PLUGIN_NAME WEAVE_PASSWORD="foobar" + docker plugin enable $PLUGIN_NAME + ps aux | grep weave + cat /var/lib/weave/weaver.log +EOF +} + +setup_worker() { + $SSH $HOST2</dev/null 2>&1; then + return + fi + echo "Waiting for \"$2\" network" + sleep 2 + done + echo "Failed to wait for \"$2\" network" >&2 + return 1 +} + +wait_for_service() { + for i in $(seq 60); do + replicas=$($SSH $1 docker service ls -f="name=$2" | awk '{print $4}' | grep -v REPLICAS) + if [ "$replicas" == "$3/$3" ]; then + return + fi + echo "Waiting for \"$2\" service" + sleep 2 + done + echo "Failed to wait for \"$2\" service" >&2 + return 1 +} + +start_suite "Test Docker plugin-v2" + +setup_master +#sleep 20 # registry seems to be async :( +setup_worker $($SSH $HOST1 docker swarm join-token --quiet worker) + +echo "Creating network and service..." + +# Create network and service +$SSH $HOST1< Date: Wed, 1 Mar 2017 15:11:58 +0000 Subject: [PATCH 14/36] Upgrade docker-py to 1.9.0-rc2 to fix test #602. Since 1.12.0, `docker inspect -f "{{ .NetworkSettings.Networks..Aliases }}"` also returns the container's short ID. See also: https://github.com/docker/docker/blob/master/CHANGELOG.md > 1.12.0 (2016-07-28) > Networking > Add container's short-id as default network alias #21901 Upgrading `docker/docker-py` to 1.9.0-rc2 effectively relaxes test assertions for: - `tests/integration/network_test.py#test_connect_with_aliases` - `tests/integration/network_test.py#test_create_with_aliases` which do something equivalent to: ``` $ docker network create net1 $ docker run --name c1 -d busybox top $ docker network connect --alias foo --alias bar net1 c1 $ docker inspect -f "{{ .NetworkSettings.Networks.net1.Aliases }}" c1 [foo bar e52bf50e5ee7] ``` allowing us to be consistent with the above change. In 1.8.1, the below fails as the container's short ID would be present: ``` self.assertEqual( container_data['NetworkSettings']['Networks'][net_name]['Aliases'], ['foo', 'bar']) ``` In 1.9.0-rc2, the below passes as the container's short ID is ignored: ``` aliases = ( container_data['NetworkSettings']['Networks'][net_name]['Aliases'] ) assert 'foo' in aliases assert 'bar' in aliases ``` --- test/600_proxy_docker_py.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/600_proxy_docker_py.sh b/test/600_proxy_docker_py.sh index f0a55222..8e54f2c1 100755 --- a/test/600_proxy_docker_py.sh +++ b/test/600_proxy_docker_py.sh @@ -3,7 +3,7 @@ . "$(dirname "$0")/config.sh" -IMAGE="joffrey/docker-py:1.8.1" +IMAGE="joffrey/docker-py:1.9.0-rc2" docker_py_test() { SHARD=$1 From 8c917eeb1735bc846388b31cd7e97ac83e13fd94 Mon Sep 17 00:00:00 2001 From: Marc CARRE Date: Mon, 6 Mar 2017 10:24:11 +0000 Subject: [PATCH 15/36] weave --local status now reports plugin. Prints the following when running: ``` Service: plugin DriverName: weave ``` See also: - https://weaveworks.slack.com/archives/net/p1488563299009870 - https://weaveworks.slack.com/archives/net/p1488539841009756 --- weave | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/weave b/weave index 623141ce..aaf830a6 100755 --- a/weave +++ b/weave @@ -341,6 +341,7 @@ CONTAINER_NAME=${WEAVE_CONTAINER_NAME:-weave} BASE_PLUGIN_IMAGE=$DOCKERHUB_USER/plugin PLUGIN_IMAGE=$BASE_PLUGIN_IMAGE:$IMAGE_VERSION PLUGIN_CONTAINER_NAME=weaveplugin +PLUGIN_V2_NAME="$DOCKERHUB_USER/pluginv2" CNI_PLUGIN_NAME="weave-plugin-$IMAGE_VERSION" CNI_PLUGIN_DIR=${WEAVE_CNI_PLUGIN_DIR:-$HOST_ROOT/opt/cni/bin} # Note VOLUMES_CONTAINER which is for weavewait should change when you upgrade Weave @@ -1211,6 +1212,10 @@ check_running() { fi } +is_docker_plugin_enabled() { + [ "$(docker plugin inspect -f '{{ .Enabled }}' "$1" 2>/dev/null)" = "true" ] +} + # Execute $@ only if the weave container is running when_weave_running() { ! check_running $CONTAINER_NAME 2>/dev/null || "$@" @@ -2082,7 +2087,7 @@ EOF echo " Service: proxy" echo " Address: $PROXY_ADDRS" fi - if [ -z "$SUB_STATUS" ] && check_running $PLUGIN_CONTAINER_NAME 2>/dev/null ; then + if [ -z "$SUB_STATUS" ] && ( is_docker_plugin_enabled "$PLUGIN_V2_NAME" || check_running $PLUGIN_CONTAINER_NAME 2>/dev/null ) ; then echo echo " Service: plugin" echo " DriverName: weave" From 1f42a9d2f9c7a5f9bcde9e4e03ecf5bae81b1ff0 Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Mon, 13 Mar 2017 09:59:51 +0000 Subject: [PATCH 16/36] Merge plugin into weaver This simplifies the following: - plugin-v2 does not need to start "plugin" as a separate process, thus Docker is able to properly restart plugin-v2 in a case of any child process failing. - No need for weaveplugin container. plugin is enabled by default when running "weave launch". when starting only the router, you should pass "--plugin" parameter to enable it. The env var WEAVE_NO_PLUGIN is no more. --- Makefile | 21 ++--- api/weaveapi.go | 15 ++++ prog/plugin/main.go => plugin/plugin.go | 64 +++----------- prog/plugin-v2/launch.sh | 40 +++------ prog/plugin/Dockerfile.template | 3 - prog/plugin/main_test.go | 12 --- prog/weaver/main.go | 15 ++++ test/090_docker_restart_policy_2_test.sh | 6 +- test/195_no_multicast_route_1_test.sh | 3 +- test/850_plugin_v2_cross_hosts_2_test.sh | 7 +- weave | 101 ++++++----------------- 11 files changed, 93 insertions(+), 194 deletions(-) rename prog/plugin/main.go => plugin/plugin.go (60%) delete mode 100644 prog/plugin/Dockerfile.template delete mode 100644 prog/plugin/main_test.go diff --git a/Makefile b/Makefile index e3e5f21e..44754692 100644 --- a/Makefile +++ b/Makefile @@ -93,38 +93,35 @@ 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 # 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) +EXES=$(WEAVER_EXE) $(SIGPROXY_EXE) $(KUBEPEERS_EXE) $(WEAVENPC_EXE) $(WEAVEPROXY_EXE) $(WEAVEWAIT_EXE) $(WEAVEWAIT_NOOP_EXE) $(WEAVEWAIT_NOMCAST_EXE) $(WEAVEUTIL_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$(ARCH_EXT).uptodate WEAVEEXEC_UPTODATE=.weaveexec$(ARCH_EXT).uptodate -PLUGIN_UPTODATE=.plugin$(ARCH_EXT).uptodate PLUGINV2_UPTODATE=.pluginv2$(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) $(WEAVEKUBE_UPTODATE) $(WEAVENPC_UPTODATE) +IMAGES_UPTODATE=$(WEAVER_UPTODATE) $(WEAVEEXEC_UPTODATE) $(WEAVEKUBE_UPTODATE) $(WEAVENPC_UPTODATE) # 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 PLUGINV2_IMAGE=$(DOCKERHUB_USER)/pluginv2$(ARCH_EXT) -IMAGES=$(WEAVER_IMAGE) $(WEAVEEXEC_IMAGE) $(PLUGIN_IMAGE) $(WEAVEKUBE_IMAGE) $(WEAVENPC_IMAGE) $(WEAVEDB_IMAGE) +IMAGES=$(WEAVER_IMAGE) $(WEAVEEXEC_IMAGE) $(WEAVEKUBE_IMAGE) $(WEAVENPC_IMAGE) $(WEAVEDB_IMAGE) PLUGINV2_WORK_DIR="prog/plugin-v2/rootfs" @@ -156,12 +153,12 @@ 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 +$(WEAVER_EXE): api/*.go plugin/*.go plugin/*/* $(WEAVEPROXY_EXE): proxy/*.go prog/weaveproxy/*.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 @@ -191,7 +188,7 @@ else exes: $(EXES) -$(WEAVER_EXE) $(WEAVEPROXY_EXE) $(PLUGIN_EXE): +$(WEAVER_EXE) $(WEAVEPROXY_EXE): ifeq ($(COVERAGE),true) $(eval COVERAGE_MODULES := $(shell (go list ./$(@D); go list -f '{{join .Deps "\n"}}' ./$(@D) | grep "^$(PACKAGE_BASE)/") | grep -v "^$(PACKAGE_BASE)/vendor/" | paste -s -d,)) go test -c -o ./$@ $(BUILD_FLAGS) -v -covermode=atomic -coverpkg $(COVERAGE_MODULES) ./$(@D)/ @@ -268,14 +265,10 @@ $(WEAVEEXEC_UPTODATE): prog/weaveexec/Dockerfile.$(DOCKERHUB_USER) prog/weaveexe $(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker build -f prog/weaveexec/Dockerfile.$(DOCKERHUB_USER) -t $(WEAVEEXEC_IMAGE) prog/weaveexec touch $@ -$(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 $@ - # TODO(mp) cleanup! -pluginv2: prog/plugin-v2/launch.sh prog/plugin-v2/config.json $(PLUGIN_UPTODATE) +pluginv2: prog/plugin-v2/launch.sh prog/plugin-v2/config.json $(WEAVER_UPTODATE) -$(SUDO) docker rm -f buildpluginv2 - $(SUDO) docker create --name=buildpluginv2 $(PLUGIN_IMAGE) true + $(SUDO) docker create --name=buildpluginv2 $(WEAVER_IMAGE) true rm -rf $(PLUGINV2_WORK_DIR) mkdir $(PLUGINV2_WORK_DIR) docker export buildpluginv2 | tar -x -C $(PLUGINV2_WORK_DIR) diff --git a/api/weaveapi.go b/api/weaveapi.go index 210618a8..19a567a2 100644 --- a/api/weaveapi.go +++ b/api/weaveapi.go @@ -8,6 +8,7 @@ import ( "net/http" "net/url" "strings" + "time" ) const ( @@ -76,6 +77,20 @@ func (client *Client) Connect(remote string) error { return err } +// IsReady returns true if the API server is up and running +func (client *Client) IsReady() bool { + _, err := client.httpVerb("GET", "/status", nil) + + return err == nil +} + +// WaitAPIServer waits until the API server is ready to serve. +func (client *Client) WaitAPIServer(n int) { + for i := 0; i < n && !client.IsReady(); i++ { + time.Sleep(2 * time.Second) + } +} + type Logger interface { Infof(string, ...interface{}) Debugf(string, ...interface{}) diff --git a/prog/plugin/main.go b/plugin/plugin.go similarity index 60% rename from prog/plugin/main.go rename to plugin/plugin.go index 3084f219..70876c04 100644 --- a/prog/plugin/main.go +++ b/plugin/plugin.go @@ -1,15 +1,12 @@ -package main +package plugin import ( - "flag" "fmt" "net" "net/http" "os" - "os/signal" "path" "strings" - "syscall" "github.com/docker/libnetwork/ipamapi" weaveapi "github.com/weaveworks/weave/api" @@ -21,55 +18,21 @@ import ( "github.com/weaveworks/weave/plugin/skel" ) -var version = "unreleased" - var Log = common.Log -func main() { - var ( - justVersion bool - dockerAPI string - address string - meshAddress string - logLevel string - noMulticastRoute bool - - defaultDockerHost = "unix:///var/run/docker.sock" - ) - - if val := os.Getenv("DOCKER_HOST"); val != "" { - defaultDockerHost = val - } - - flag.BoolVar(&justVersion, "version", false, "print version and exit") - flag.StringVar(&logLevel, "log-level", "info", "logging level (debug, info, warning, error)") - flag.StringVar(&dockerAPI, "docker-api", defaultDockerHost, "Docker API endpoint") - 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") - flag.BoolVar(&noMulticastRoute, "no-multicast-route", false, "deprecated (this is now the default)") - - flag.Parse() - - if justVersion { - fmt.Printf("weave plugin %s\n", version) - os.Exit(0) - } - - common.SetLogLevel(logLevel) - - weave := weaveapi.NewClient(os.Getenv("WEAVE_HTTP_ADDR"), Log) +func Start(weaveAPIAddr string, dockerAPIAddr string, address string, meshAddress string, noMulticastRoute bool) { + weave := weaveapi.NewClient(weaveAPIAddr, Log) var dockerClient *docker.Client var err error - if dockerAPI != "" { + if dockerAPIAddr != "" { // API 1.21 is the first version that supports docker network commands - dockerClient, err = docker.NewVersionedClient(dockerAPI, "1.21") + dockerClient, err = docker.NewVersionedClient(dockerAPIAddr, "1.21") if err != nil { Log.Fatalf("unable to connect to docker: %s", err) } } - Log.Println("Weave plugin", version, "Command line options:", os.Args[1:]) if noMulticastRoute { Log.Warning("--no-multicast-route option has been removed; multicast is off by default") } @@ -79,6 +42,10 @@ func main() { Log.Info(dockerClient.Info()) } + Log.Info("Waiting for Weave API Server...") + weave.WaitAPIServer(30) + Log.Info("Finished waiting for Weave API Server") + err = run(dockerClient, weave, address, meshAddress) if err != nil { Log.Fatal(err) @@ -87,6 +54,7 @@ func main() { func run(dockerClient *docker.Client, weave *weaveapi.Client, address, meshAddress string) error { endChan := make(chan error, 1) + if address != "" { globalListener, err := listenAndServe(dockerClient, weave, address, endChan, "global", false) if err != nil { @@ -104,21 +72,13 @@ func run(dockerClient *docker.Client, weave *weaveapi.Client, address, meshAddre defer meshListener.Close() } - statusListener, err := weavenet.ListenUnixSocket("/home/weave/status.sock") + statusListener, err := weavenet.ListenUnixSocket("/home/weave/plugin-status.sock") if err != nil { return err } go serveStatus(statusListener) - sigChan := make(chan os.Signal, 1) - signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM) - select { - case sig := <-sigChan: - Log.Debugf("Caught signal %s; shutting down", sig) - return nil - case err := <-endChan: - return err - } + return <-endChan } func listenAndServe(dockerClient *docker.Client, weave *weaveapi.Client, address string, endChan chan<- error, scope string, withIpam bool) (net.Listener, error) { diff --git a/prog/plugin-v2/launch.sh b/prog/plugin-v2/launch.sh index c5bfc3b3..28decd7f 100755 --- a/prog/plugin-v2/launch.sh +++ b/prog/plugin-v2/launch.sh @@ -8,25 +8,23 @@ 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} WEAVE_DIR="/host/var/lib/weave" -LOG_FILE_WEAVER="$WEAVE_DIR/weaver.log" -LOG_FILE_PLUGIN="$WEAVE_DIR/plugin.log" mkdir $WEAVE_DIR || true -echo "Starting launch.sh" >>$LOG_FILE_WEAVER +echo "Starting launch.sh" # Check if the IP range overlaps anything existing on the host /usr/bin/weaveutil netcheck $IPALLOC_RANGE weave -SWARM_PEERS=$(/usr/bin/weaveutil swarm-manager-peers 2>>$LOG_FILE_WEAVER) -! /usr/bin/weaveutil is-swarm-manager 2>>$LOG_FILE_WEAVER || IS_SWARM_MANAGER=1 +SWARM_MANAGER_PEERS=$(/usr/bin/weaveutil swarm-manager-peers) +! /usr/bin/weaveutil is-swarm-manager || IS_SWARM_MANAGER=1 # Prevent from restoring from a persisted peers list rm -f "/restart.sentinel" /home/weave/weave --local create-bridge \ - --proc-path=/host/proc \ - --weavedb-dir-path=$WEAVE_DIR \ - --force >>$LOG_FILE_WEAVER 2>&1 + --proc-path=/host/proc \ + --weavedb-dir-path=$WEAVE_DIR \ + --force BRIDGE_OPTIONS="--datapath=datapath" if [ "$(/home/weave/weave --local bridge-type)" = "bridge" ]; then @@ -42,36 +40,18 @@ fi if [ -z "$IPALLOC_INIT" ]; then if [ $IS_SWARM_MANAGER == "1" ]; then - IPALLOC_INIT="consensus=$(echo $SWARM_PEERS | wc -l)" + IPALLOC_INIT="consensus=$(echo $SWARM_MANAGER_PEERS | wc -l)" else IPALLOC_INIT="observer" fi fi -/home/weave/weaver $EXTRA_ARGS --port=6783 $BRIDGE_OPTIONS \ +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 \ --ipalloc-init $IPALLOC_INIT \ --nickname "$(hostname)" \ --log-level=debug \ --db-prefix="$WEAVE_DIR/weave" \ - $(echo $SWARM_PEERS | tr '\n' ' ') \ - >>$LOG_FILE_WEAVER 2>&1 & -WEAVE_PID=$! - -# Wait for weave process to become responsive -while true; do - curl $HTTP_ADDR/status >/dev/null 2>&1 && break - if ! kill -0 $WEAVE_PID >/dev/null 2>&1; then - echo Weave process has died >&2 - exit 1 - fi - sleep 1 -done - -# TODO(mp) docker api? -/home/weave/plugin $EXTRA_ARGS --log-level=debug --meshsocket='' --docker-api='' >>$LOG_FILE_PLUGIN 2>&1 & - -echo "End of launch.sh" >>$LOG_FILE_WEAVER - -wait $WEAVE_PID + --plugin \ + $(echo $SWARM_MANAGER_PEERS | tr '\n' ' ') diff --git a/prog/plugin/Dockerfile.template b/prog/plugin/Dockerfile.template deleted file mode 100644 index 4de1c580..00000000 --- a/prog/plugin/Dockerfile.template +++ /dev/null @@ -1,3 +0,0 @@ -FROM DOCKERHUB_USER/weaveARCH_EXT -ADD ./plugin /home/weave/ -ENTRYPOINT ["/home/weave/plugin"] diff --git a/prog/plugin/main_test.go b/prog/plugin/main_test.go deleted file mode 100644 index 1873f4a3..00000000 --- a/prog/plugin/main_test.go +++ /dev/null @@ -1,12 +0,0 @@ -package main - -import ( - "testing" - - weavetest "github.com/weaveworks/weave/testing" -) - -func TestMain(t *testing.T) { - weavetest.TrimTestArgs() - main() -} diff --git a/prog/weaver/main.go b/prog/weaver/main.go index 8b077da3..d1b1515b 100644 --- a/prog/weaver/main.go +++ b/prog/weaver/main.go @@ -25,6 +25,7 @@ import ( "github.com/weaveworks/weave/nameserver" weavenet "github.com/weaveworks/weave/net" "github.com/weaveworks/weave/net/address" + "github.com/weaveworks/weave/plugin" weave "github.com/weaveworks/weave/router" ) @@ -150,6 +151,10 @@ func main() { discoveryEndpoint string token string advertiseAddress string + pluginSocket string + pluginMeshSocket string + noMulticastRoute bool + enablePlugin bool defaultDockerHost = "unix:///var/run/docker.sock" ) @@ -195,6 +200,11 @@ func main() { mflag.StringVar(&token, []string{"-token"}, "", "token for peer discovery") mflag.StringVar(&advertiseAddress, []string{"-advertise-address"}, "", "address to advertise for peer discovery") + mflag.BoolVar(&enablePlugin, []string{"-plugin"}, false, "enable Docker plugin") + mflag.StringVar(&pluginSocket, []string{"-plugin-socket"}, "/run/docker/plugins/weave.sock", "plugin socket on which to listen") + mflag.StringVar(&pluginMeshSocket, []string{"-plugin-mesh-socket"}, "/run/docker/plugins/weavemesh.sock", "plugin socket on which to listen in mesh mode") + mflag.BoolVar(&noMulticastRoute, []string{"-no-multicast-route"}, false, "deprecated (this is now the default)") + // crude way of detecting that we probably have been started in a // container, with `weave launch` --> suppress misleading paths in // mflags error messages. @@ -396,6 +406,11 @@ func main() { go listenAndServeHTTP(statusAddr, statusMux) } + if enablePlugin { + // TODO(mp) do not pass pluginMeshSocket if plugin-v2 is in use + go plugin.Start(httpAddr, dockerAPI, pluginSocket, pluginMeshSocket, noMulticastRoute) + } + signals.SignalHandlerLoop(common.Log, router) } diff --git a/test/090_docker_restart_policy_2_test.sh b/test/090_docker_restart_policy_2_test.sh index b4cc76cd..e1630bc9 100755 --- a/test/090_docker_restart_policy_2_test.sh +++ b/test/090_docker_restart_policy_2_test.sh @@ -6,22 +6,20 @@ start_suite "Test docker restart policy" weave_on $HOST1 launch -assert "docker_on $HOST1 inspect -f '{{.HostConfig.RestartPolicy.Name}}' weave weaveproxy weaveplugin" "always\nalways\nalways" +assert "docker_on $HOST1 inspect -f '{{.HostConfig.RestartPolicy.Name}}' weave weaveproxy" "always\nalways" assert_raises "check_restart $HOST1 weave" assert_raises "check_restart $HOST1 weaveproxy" -assert_raises "check_restart $HOST1 weaveplugin" # stop + launch tests that restart policy changes result # in the old containers being removed and new ones created weave_on $HOST1 stop weave_on $HOST1 launch --no-restart -assert "docker_on $HOST1 inspect -f '{{.HostConfig.RestartPolicy.Name}}' weave weaveproxy weaveplugin" "no\nno\nno" +assert "docker_on $HOST1 inspect -f '{{.HostConfig.RestartPolicy.Name}}' weave weaveproxy" "no\nno" assert_raises "! check_restart $HOST1 weave" assert_raises "! check_restart $HOST1 weaveproxy" -assert_raises "! check_restart $HOST1 weaveplugin" # Relaunch to prevent the `weave stop` in `end_suite` # timing out trying to remove the plugin network diff --git a/test/195_no_multicast_route_1_test.sh b/test/195_no_multicast_route_1_test.sh index 740be6d6..2342582b 100755 --- a/test/195_no_multicast_route_1_test.sh +++ b/test/195_no_multicast_route_1_test.sh @@ -12,9 +12,8 @@ start_suite "--no-multicast-route operation" $SSH $HOST1 docker network rm testmcasttrue testmcastfalse >/dev/null 2>&1 || true # Ensure containers run either way have no multicast route -weave_on $HOST1 launch-router +weave_on $HOST1 launch-router --plugin weave_on $HOST1 launch-proxy --no-multicast-route -weave_on $HOST1 launch-plugin # plugin defaults to multicast off except for 'net=weave' start_container $HOST1 --no-multicast-route --name c1 proxy_start_container $HOST1 --name c2 diff --git a/test/850_plugin_v2_cross_hosts_2_test.sh b/test/850_plugin_v2_cross_hosts_2_test.sh index 3c8bab54..e5db1c2b 100755 --- a/test/850_plugin_v2_cross_hosts_2_test.sh +++ b/test/850_plugin_v2_cross_hosts_2_test.sh @@ -23,7 +23,7 @@ setup_master() { WORK_DIR=$(mktemp -d) mkdir -p \${WORK_DIR}/rootfs - docker create --name=$build_plugin_img weaveworks/plugin true + docker create --name=$build_plugin_img weaveworks/weave true docker export $build_plugin_img | tar -x -C \${WORK_DIR}/rootfs cp \${HOME}/plugin-v2/launch.sh \${WORK_DIR}/rootfs/home/weave/launch.sh cp \${HOME}/plugin-v2/config.json \${WORK_DIR} @@ -38,8 +38,6 @@ setup_master() { [ -n "$COVERAGE" ] && docker plugin set $PLUGIN_NAME EXTRA_ARGS="-test.coverprofile=/home/weave/cover.prof --" #docker plugin set $PLUGIN_NAME WEAVE_PASSWORD="foobar" docker plugin enable $PLUGIN_NAME - ps aux | grep weave - cat /var/lib/weave/weaver.log EOF } @@ -98,6 +96,9 @@ wait_for_service() { start_suite "Test Docker plugin-v2" +#cleanup $HOST1 $HOST2 +#exit 1 + setup_master #sleep 20 # registry seems to be async :( setup_worker $($SSH $HOST1 docker swarm join-token --quiet worker) diff --git a/weave b/weave index aaf830a6..0553197d 100755 --- a/weave +++ b/weave @@ -49,6 +49,7 @@ weave launch [--no-restart] [--resume] [--no-discovery] [--no-dns] [--ipalloc-init ] [--ipalloc-range [--ipalloc-default-subnet ]] + [--plugin [--no-multicast-route]] [--log-level=debug|info|warning|error] ... launch-proxy [-H ] [--without-dns] [--no-multicast-route] @@ -58,8 +59,6 @@ weave launch [--hostname-replacement ] [--rewrite-inspect] [--log-level=debug|info|warning|error] - launch-plugin [--no-restart] [--no-multicast-route] - [--log-level=debug|info|warning|error] weave prime @@ -93,7 +92,6 @@ weave status [targets | connections | peers | dns | ipam] weave stop stop-router stop-proxy - stop-plugin weave reset [--force] rmpeer ... @@ -166,7 +164,6 @@ exec_remote() { -e WEAVE_MTU \ -e WEAVE_NO_FASTDP \ -e WEAVE_NO_BRIDGED_FASTDP \ - -e WEAVE_NO_PLUGIN \ -e DOCKER_BRIDGE \ -e DOCKER_CLIENT_HOST="$DOCKER_CLIENT_HOST" \ -e DOCKER_CLIENT_ARGS \ @@ -332,15 +329,12 @@ fi # main (remote and --local) - settings ###################################################################### -# Default restart policy for router/proxy/plugin +# Default restart policy for router/proxy RESTART_POLICY="--restart=always" BASE_IMAGE=$DOCKERHUB_USER/weave IMAGE=$BASE_IMAGE:$IMAGE_VERSION CONTAINER_NAME=${WEAVE_CONTAINER_NAME:-weave} -BASE_PLUGIN_IMAGE=$DOCKERHUB_USER/plugin -PLUGIN_IMAGE=$BASE_PLUGIN_IMAGE:$IMAGE_VERSION -PLUGIN_CONTAINER_NAME=weaveplugin PLUGIN_V2_NAME="$DOCKERHUB_USER/pluginv2" CNI_PLUGIN_NAME="weave-plugin-$IMAGE_VERSION" CNI_PLUGIN_DIR=${WEAVE_CNI_PLUGIN_DIR:-$HOST_ROOT/opt/cni/bin} @@ -1212,10 +1206,17 @@ check_running() { fi } +# Docker Plugin V2 is_docker_plugin_enabled() { [ "$(docker plugin inspect -f '{{ .Enabled }}' "$1" 2>/dev/null)" = "true" ] } +# Docker Plugin (part of weaver process, so V2 or V1). +# Assumes that plugin is running inside Docker container. +is_plugin_enabled() { + docker inspect -f '{{.Config.Cmd}}' $CONTAINER_NAME | grep -q -- "--plugin" +} + # Execute $@ only if the weave container is running when_weave_running() { ! check_running $CONTAINER_NAME 2>/dev/null || "$@" @@ -1621,6 +1622,10 @@ launch_router() { AWSVPC_ARGS="--awsvpc" AWSVPC=1 ;; + --plugin) + PLUGIN_ARGS="--plugin" + ENABLE_PLUGIN=1 + ;; *) ARGS="$ARGS '$(echo "$1" | sed "s|'|'\"'\"'|g")'" ;; @@ -1683,6 +1688,7 @@ launch_router() { --pid=host \ --volumes-from $DB_CONTAINER_NAME \ -v $RESOLV_CONF_DIR:/var/run/weave/etc \ + -v /run/docker/plugins:/run/docker/plugins \ -e WEAVE_PASSWORD \ -e CHECKPOINT_DISABLE \ $WEAVE_DOCKER_ARGS $IMAGE $COVERAGE_ARGS \ @@ -1692,6 +1698,7 @@ launch_router() { --dns-effective-listen-address $DOCKER_BRIDGE_IP \ $DNS_ROUTER_OPTS $NO_DNS_OPT \ $AWSVPC_ARGS \ + $PLUGIN_ARGS \ --http-addr $HTTP_ADDR \ --status-addr $STATUS_ADDR \ --resolv-conf "/var/run/weave/etc/$RESOLV_CONF_BASE" \ @@ -1699,6 +1706,11 @@ launch_router() { wait_for_status $CONTAINER_NAME http_call $HTTP_ADDR setup_awsvpc populate_router + + if [ -n "$ENABLE_PLUGIN" ]; then + wait_for_status $CONTAINER_NAME http_call_unix $CONTAINER_NAME plugin-status.sock + util_op create-plugin-network weave weavemesh $IPRANGE + fi } setup_awsvpc() { @@ -1733,6 +1745,7 @@ populate_router() { } stop_router() { + ! is_plugin_enabled || util_op remove-plugin-network weave || true stop $CONTAINER_NAME "Weave" conntrack -D -p udp --dport $PORT >/dev/null 2>&1 || true } @@ -1774,53 +1787,9 @@ stop_proxy() { stop $PROXY_CONTAINER_NAME "Proxy" } -launch_plugin_if_not_running() { - while [ $# -gt 0 ]; do - case "$1" in - --no-restart) - RESTART_POLICY= - ;; - *) - break - ;; - esac - shift - done - - retval=0 - check_not_running plugin $PLUGIN_CONTAINER_NAME $BASE_PLUGIN_IMAGE || retval=$? - # If an existing plugin is running (we start it with restart=always), return its ID - [ $retval = 1 ] && PLUGIN_CONTAINER=$(container_id $PLUGIN_CONTAINER_NAME) && return 0 - # Any other kind of error code from check_not_running is a failure. - [ $retval -gt 0 ] && return $retval - - if ! PLUGIN_CONTAINER=$(docker run -d --name=$PLUGIN_CONTAINER_NAME \ - $(docker_run_options) \ - $RESTART_POLICY \ - --pid=host \ - -v /run/docker/plugins:/run/docker/plugins \ - -e WEAVE_HTTP_ADDR \ - $WEAVEPLUGIN_DOCKER_ARGS $PLUGIN_IMAGE $COVERAGE_ARGS \ - "$@") ; then - return 1 - fi - wait_for_status $PLUGIN_CONTAINER_NAME http_call_unix $PLUGIN_CONTAINER_NAME status.sock - WEAVE_IPAM_SUBNET=$(call_weave GET /ipinfo/defaultsubnet) - util_op create-plugin-network weave weavemesh $WEAVE_IPAM_SUBNET -} - -plugin_disabled() { - [ -n "$WEAVE_NO_PLUGIN" ] || ! check_docker_server_api_version 1.21 -} - -stop_plugin() { - util_op remove-plugin-network weave || true - stop $PLUGIN_CONTAINER_NAME "Plugin" -} - protect_against_docker_hang() { # If the plugin is not running, remove its socket so Docker doesn't try to talk to it - if ! check_running $PLUGIN_CONTAINER_NAME 2>/dev/null ; then + if ! is_docker_plugin_enabled 2>/dev/null ; then rm -f /run/docker/plugins/weave.sock /run/docker/plugins/weavemesh.sock fi } @@ -1936,7 +1905,7 @@ handle_help_arg "$1" case "$COMMAND" in setup) - for img in $IMAGE $EXEC_IMAGE $PLUGIN_IMAGE $WEAVEDB_IMAGE ; do + for img in $IMAGE $EXEC_IMAGE $WEAVEDB_IMAGE ; do docker pull $img done setup_cni @@ -1948,7 +1917,6 @@ case "$COMMAND" in [ $# -eq 0 ] || usage ask_version $CONTAINER_NAME $IMAGE || true ask_version $PROXY_CONTAINER_NAME $EXEC_IMAGE --entrypoint=/home/weave/weaveproxy || true - ask_version $PLUGIN_CONTAINER_NAME $PLUGIN_IMAGE || true ;; # intentionally undocumented since it assumes knowledge of weave # internals @@ -2009,11 +1977,9 @@ EOF deprecation_warnings "$@" check_not_running router $CONTAINER_NAME $BASE_IMAGE check_not_running proxy $PROXY_CONTAINER_NAME $BASE_EXEC_IMAGE - check_not_running plugin $PLUGIN_CONTAINER_NAME $BASE_PLUGIN_IMAGE COMMON_ARGS=$(common_launch_args "$@") - launch_router "$@" + launch_router --plugin "$@" launch_proxy $COMMON_ARGS - plugin_disabled || launch_plugin_if_not_running $COMMON_ARGS ;; launch-router) deprecation_warnings "$@" @@ -2038,14 +2004,6 @@ EOF launch_proxy "$@" 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 - ;; env|proxy-env) [ "$COMMAND" = "env" ] || deprecation_warning "$COMMAND" "'weave env'" if PROXY_ADDR=$(proxy_addr) ; then @@ -2087,7 +2045,7 @@ EOF echo " Service: proxy" echo " Address: $PROXY_ADDRS" fi - if [ -z "$SUB_STATUS" ] && ( is_docker_plugin_enabled "$PLUGIN_V2_NAME" || check_running $PLUGIN_CONTAINER_NAME 2>/dev/null ) ; then + if [ -z "$SUB_STATUS" ] && ( is_docker_plugin_enabled "$PLUGIN_V2_NAME" || is_plugin_enabled ) ; then echo echo " Service: plugin" echo " DriverName: weave" @@ -2276,7 +2234,6 @@ EOF ;; stop) [ $# -eq 0 ] || usage - plugin_disabled || stop_plugin stop_router stop_proxy ;; @@ -2288,13 +2245,9 @@ EOF [ $# -eq 0 ] || usage stop_proxy ;; - stop-plugin) - [ $# -eq 0 ] || usage - stop_plugin - ;; reset) [ $# -eq 0 ] || [ $# -eq 1 -a "$1" = "--force" ] || usage - plugin_disabled || util_op remove-plugin-network weave || true + ! is_plugin_enabled || util_op remove-plugin-network weave || true warn_if_stopping_proxy_in_env res=0 [ "$1" = "--force" ] || check_running $CONTAINER_NAME 2>/dev/null || res=$? @@ -2312,7 +2265,7 @@ EOF exit 1 ;; esac - for NAME in $PLUGIN_CONTAINER_NAME $CONTAINER_NAME $PROXY_CONTAINER_NAME ; do + for NAME in $CONTAINER_NAME $PROXY_CONTAINER_NAME ; do docker stop $NAME >/dev/null 2>&1 || true docker rm -f $NAME >/dev/null 2>&1 || true done From d7306c66f701d2385df2faa670cf677bb3d5395e Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Mon, 13 Mar 2017 11:47:24 +0000 Subject: [PATCH 17/36] Get rid of deprecated --no-multicast-route --- plugin/plugin.go | 5 +---- prog/weaver/main.go | 5 +---- weave | 2 +- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/plugin/plugin.go b/plugin/plugin.go index 70876c04..48ba067f 100644 --- a/plugin/plugin.go +++ b/plugin/plugin.go @@ -20,7 +20,7 @@ import ( var Log = common.Log -func Start(weaveAPIAddr string, dockerAPIAddr string, address string, meshAddress string, noMulticastRoute bool) { +func Start(weaveAPIAddr string, dockerAPIAddr string, address string, meshAddress string) { weave := weaveapi.NewClient(weaveAPIAddr, Log) var dockerClient *docker.Client @@ -33,9 +33,6 @@ func Start(weaveAPIAddr string, dockerAPIAddr string, address string, meshAddres } } - if noMulticastRoute { - Log.Warning("--no-multicast-route option has been removed; multicast is off by default") - } if dockerClient == nil { Log.Info("Running without Docker API connection") } else { diff --git a/prog/weaver/main.go b/prog/weaver/main.go index d1b1515b..ba38d666 100644 --- a/prog/weaver/main.go +++ b/prog/weaver/main.go @@ -153,7 +153,6 @@ func main() { advertiseAddress string pluginSocket string pluginMeshSocket string - noMulticastRoute bool enablePlugin bool defaultDockerHost = "unix:///var/run/docker.sock" @@ -203,7 +202,6 @@ func main() { mflag.BoolVar(&enablePlugin, []string{"-plugin"}, false, "enable Docker plugin") mflag.StringVar(&pluginSocket, []string{"-plugin-socket"}, "/run/docker/plugins/weave.sock", "plugin socket on which to listen") mflag.StringVar(&pluginMeshSocket, []string{"-plugin-mesh-socket"}, "/run/docker/plugins/weavemesh.sock", "plugin socket on which to listen in mesh mode") - mflag.BoolVar(&noMulticastRoute, []string{"-no-multicast-route"}, false, "deprecated (this is now the default)") // crude way of detecting that we probably have been started in a // container, with `weave launch` --> suppress misleading paths in @@ -407,8 +405,7 @@ func main() { } if enablePlugin { - // TODO(mp) do not pass pluginMeshSocket if plugin-v2 is in use - go plugin.Start(httpAddr, dockerAPI, pluginSocket, pluginMeshSocket, noMulticastRoute) + go plugin.Start(httpAddr, dockerAPI, pluginSocket, pluginMeshSocket) } signals.SignalHandlerLoop(common.Log, router) diff --git a/weave b/weave index 0553197d..56992ff8 100755 --- a/weave +++ b/weave @@ -49,7 +49,7 @@ weave launch [--no-restart] [--resume] [--no-discovery] [--no-dns] [--ipalloc-init ] [--ipalloc-range [--ipalloc-default-subnet ]] - [--plugin [--no-multicast-route]] + [--plugin] [--log-level=debug|info|warning|error] ... launch-proxy [-H ] [--without-dns] [--no-multicast-route] From d3d2de5f1f93bb427f94afaf2b5751017cc96db1 Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Mon, 13 Mar 2017 16:48:49 +0000 Subject: [PATCH 18/36] Make NetworkAllocate to return original options NetworkAllocate is called on Swarm master node which creates a network. The return option map is used to describe the network, and is passed to CreateNetwork which is called on all nodes when a service is created. Returning nil instead the actual options made Docker to omit the "works.weave.multicast" flag, thus no multicast could be used in Swarm. --- plugin/net/driver.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/plugin/net/driver.go b/plugin/net/driver.go index e1560bc5..fe46f594 100644 --- a/plugin/net/driver.go +++ b/plugin/net/driver.go @@ -61,17 +61,22 @@ func (driver *driver) GetCapabilities() (*api.GetCapabilityResponse, error) { return caps, nil } +// In Swarm mode, CreateNetwork is called on each Swarm node when a new service +// is created. func (driver *driver) CreateNetwork(create *api.CreateNetworkRequest) error { driver.logReq("CreateNetwork", create, create.NetworkID) _, err := driver.setupNetworkInfo(create.NetworkID, true, stringOptions(create)) return err } +// NetworkAllocate is called on a Swarm node (master) which creates the network. +// The returned options are passed to CreateNetwork. func (driver *driver) NetworkAllocate(alloc *api.AllocateNetworkRequest) (*api.AllocateNetworkResponse, error) { driver.logReq("NetworkAllocate", alloc, alloc.NetworkID) - return nil, nil + return &api.AllocateNetworkResponse{Options: alloc.Options}, nil } +// NetworkFree is called on a Swarm master node which created the network. func (driver *driver) NetworkFree(free *api.FreeNetworkRequest) (*api.FreeNetworkResponse, error) { driver.logReq("NetworkFree", free, free.NetworkID) return nil, nil @@ -95,6 +100,7 @@ func stringOptions(create *api.CreateNetworkRequest) map[string]string { return nil } +// In Swarm mode, DeleteNetwork is called after a service has been removed. func (driver *driver) DeleteNetwork(delreq *api.DeleteNetworkRequest) error { driver.logReq("DeleteNetwork", delreq, delreq.NetworkID) driver.Lock() From 303137244292af8fce353eb8060a31dd9a83dacb Mon Sep 17 00:00:00 2001 From: Marc CARRE Date: Mon, 6 Mar 2017 11:13:45 +0000 Subject: [PATCH 19/36] weave --local launch* with V2 plugin on exits with error. For example: ``` $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES $ docker plugin ls ID NAME DESCRIPTION ENABLED e80beb4367a6 weaveworks/pluginv2:latest Weave Net plugin for Docker true $ weave --local launch weaveworks/pluginv2 is already running. $ weave --local launch-proxy weaveworks/pluginv2 is already running. $ weave --local launch-router weaveworks/pluginv2 is already running. $ weave --local launch-plugin ``` --- weave | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/weave b/weave index 56992ff8..569a5e0d 100755 --- a/weave +++ b/weave @@ -1206,6 +1206,10 @@ check_running() { fi } +check_not_running_v2_plugin() { + is_docker_plugin_enabled "$1" && echo "$1 is already running." >&2 && return 1 +} + # Docker Plugin V2 is_docker_plugin_enabled() { [ "$(docker plugin inspect -f '{{ .Enabled }}' "$1" 2>/dev/null)" = "true" ] @@ -1977,6 +1981,7 @@ EOF deprecation_warnings "$@" check_not_running router $CONTAINER_NAME $BASE_IMAGE check_not_running proxy $PROXY_CONTAINER_NAME $BASE_EXEC_IMAGE + check_not_running_v2_plugin "$PLUGIN_V2_NAME" COMMON_ARGS=$(common_launch_args "$@") launch_router --plugin "$@" launch_proxy $COMMON_ARGS @@ -1984,6 +1989,7 @@ EOF launch-router) deprecation_warnings "$@" check_not_running router $CONTAINER_NAME $BASE_IMAGE + check_not_running_v2_plugin "$PLUGIN_V2_NAME" launch_router "$@" echo $ROUTER_CONTAINER ;; @@ -2001,6 +2007,7 @@ EOF launch-proxy) deprecation_warnings "$@" check_not_running proxy $PROXY_CONTAINER_NAME $BASE_EXEC_IMAGE + check_not_running_v2_plugin "$PLUGIN_V2_NAME" launch_proxy "$@" echo $PROXY_CONTAINER ;; From b3866ebd945863ffa6df3871ee07a11bbac823a8 Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Tue, 14 Mar 2017 17:56:55 +0000 Subject: [PATCH 20/36] Update vendor/github.com/docker/docker to v1.13.1 --- vendor/github.com/docker/docker | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/github.com/docker/docker b/vendor/github.com/docker/docker index c13bf5ba..092cba37 160000 --- a/vendor/github.com/docker/docker +++ b/vendor/github.com/docker/docker @@ -1 +1 @@ -Subproject commit c13bf5ba51c4f6a1ba5e5c0da0d4f85d2d5b9116 +Subproject commit 092cba3727bb9b4a2f0e922cd6c0f93ea270e363 From 0ff37d3492a03484518335d645b19c9b7d22f9fe Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Tue, 14 Mar 2017 18:24:41 +0000 Subject: [PATCH 21/36] Do "docker plugin inspect" inside weaveutil We cannot do it from weaveexec, because the latter is distributed with an old version of Docker client which does not support Plugins API. --- prog/weaveutil/main.go | 51 ++++++++++++++++---------------- prog/weaveutil/plugin_network.go | 31 +++++++++++++++++++ weave | 41 +++++++++++++------------ 3 files changed, 79 insertions(+), 44 deletions(-) diff --git a/prog/weaveutil/main.go b/prog/weaveutil/main.go index 103bd047..bc954761 100644 --- a/prog/weaveutil/main.go +++ b/prog/weaveutil/main.go @@ -14,31 +14,32 @@ var commands map[string]func([]string) error func init() { commands = map[string]func([]string) error{ - "help": help, - "netcheck": netcheck, - "docker-tls-args": dockerTLSArgs, - "create-datapath": createDatapath, - "delete-datapath": deleteDatapath, - "check-datapath": checkDatapath, - "add-datapath-interface": addDatapathInterface, - "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, - "swarm-manager-peers": swarmManagerPeers, - "is-swarm-manager": isSwarmManager, + "help": help, + "netcheck": netcheck, + "docker-tls-args": dockerTLSArgs, + "create-datapath": createDatapath, + "delete-datapath": deleteDatapath, + "check-datapath": checkDatapath, + "add-datapath-interface": addDatapathInterface, + "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, + "swarm-manager-peers": swarmManagerPeers, + "is-swarm-manager": isSwarmManager, + "is-docker-plugin-enabled": isDockerPluginEnabled, } } diff --git a/prog/weaveutil/plugin_network.go b/prog/weaveutil/plugin_network.go index 33c3a79a..3d604c5a 100644 --- a/prog/weaveutil/plugin_network.go +++ b/prog/weaveutil/plugin_network.go @@ -2,8 +2,10 @@ package main import ( + "context" "fmt" + "github.com/docker/docker/client" docker "github.com/fsouza/go-dockerclient" "github.com/weaveworks/weave/plugin/net" @@ -71,6 +73,34 @@ while Weave is not running`, networkName, containers) return nil } +// Exits with 0 if the given plugin (v2) is enabled. +func isDockerPluginEnabled(args []string) error { + if len(args) != 1 { + cmdUsage("is-docker-plugin-enabled", "") + } + + pluginName := args[0] + + // This is messed up: we are using docker/docker/client instead of + // fsouza/go-dockerclient because the latter does not support plugins. + c, err := client.NewEnvClient() + if err != nil { + return fmt.Errorf("unable to connect to docker: %s", err) + } + + ctx := context.Background() + p, _, err := c.PluginInspectWithRaw(ctx, pluginName) + if err != nil { + return err + } + + if !p.Enabled { + return fmt.Errorf("plugin %q is disabled", pluginName) + } + + return nil +} + func newDockerClient() (*docker.Client, error) { // API 1.21 is the first version that supports docker network // commands @@ -82,5 +112,6 @@ func newDockerClient() (*docker.Client, error) { if err != nil { return nil, fmt.Errorf("unable to connect to docker: %s", err) } + return c, nil } diff --git a/weave b/weave index 569a5e0d..d81e5f74 100755 --- a/weave +++ b/weave @@ -883,6 +883,24 @@ attach() { util_op attach-container $ATTACH_ARGS $CONTAINER $BRIDGE $MTU "$@" } +check_not_running_v2_plugin() { + if is_docker_plugin_enabled $PLUGIN_V2_NAME; then + echo "Docker plugin \"$PLUGIN_V2_NAME\" is already running." >&2 + return 1 + fi +} + +# Docker Plugin V2 +is_docker_plugin_enabled() { + util_op is-docker-plugin-enabled $PLUGIN_V2_NAME 2>/dev/null +} + +# Docker Plugin (part of weaver process, so V2 or V1). +# Assumes that plugin is running inside Docker container. +is_plugin_enabled() { + docker inspect -f '{{.Config.Cmd}}' $CONTAINER_NAME | grep -q -- "--plugin" +} + ###################################################################### # functions for interacting with containers ###################################################################### @@ -1206,21 +1224,6 @@ check_running() { fi } -check_not_running_v2_plugin() { - is_docker_plugin_enabled "$1" && echo "$1 is already running." >&2 && return 1 -} - -# Docker Plugin V2 -is_docker_plugin_enabled() { - [ "$(docker plugin inspect -f '{{ .Enabled }}' "$1" 2>/dev/null)" = "true" ] -} - -# Docker Plugin (part of weaver process, so V2 or V1). -# Assumes that plugin is running inside Docker container. -is_plugin_enabled() { - docker inspect -f '{{.Config.Cmd}}' $CONTAINER_NAME | grep -q -- "--plugin" -} - # Execute $@ only if the weave container is running when_weave_running() { ! check_running $CONTAINER_NAME 2>/dev/null || "$@" @@ -1981,7 +1984,7 @@ EOF deprecation_warnings "$@" check_not_running router $CONTAINER_NAME $BASE_IMAGE check_not_running proxy $PROXY_CONTAINER_NAME $BASE_EXEC_IMAGE - check_not_running_v2_plugin "$PLUGIN_V2_NAME" + check_not_running_v2_plugin COMMON_ARGS=$(common_launch_args "$@") launch_router --plugin "$@" launch_proxy $COMMON_ARGS @@ -1989,7 +1992,7 @@ EOF launch-router) deprecation_warnings "$@" check_not_running router $CONTAINER_NAME $BASE_IMAGE - check_not_running_v2_plugin "$PLUGIN_V2_NAME" + check_not_running_v2_plugin launch_router "$@" echo $ROUTER_CONTAINER ;; @@ -2007,7 +2010,7 @@ EOF launch-proxy) deprecation_warnings "$@" check_not_running proxy $PROXY_CONTAINER_NAME $BASE_EXEC_IMAGE - check_not_running_v2_plugin "$PLUGIN_V2_NAME" + check_not_running_v2_plugin launch_proxy "$@" echo $PROXY_CONTAINER ;; @@ -2052,7 +2055,7 @@ EOF echo " Service: proxy" echo " Address: $PROXY_ADDRS" fi - if [ -z "$SUB_STATUS" ] && ( is_docker_plugin_enabled "$PLUGIN_V2_NAME" || is_plugin_enabled ) ; then + if [ -z "$SUB_STATUS" ] && ( is_docker_plugin_enabled || is_plugin_enabled ) ; then echo echo " Service: plugin" echo " DriverName: weave" From e852ae99ca8a1573239a9120ccc70c46f59a7c2c Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Wed, 15 Mar 2017 12:12:00 +0000 Subject: [PATCH 22/36] Report correct plugin driver name in "weave status" --- weave | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/weave b/weave index d81e5f74..65fc8bdf 100755 --- a/weave +++ b/weave @@ -2055,7 +2055,11 @@ EOF echo " Service: proxy" echo " Address: $PROXY_ADDRS" fi - if [ -z "$SUB_STATUS" ] && ( is_docker_plugin_enabled || is_plugin_enabled ) ; then + if [ -z "$SUB_STATUS" ] && is_docker_plugin_enabled ; then + echo + echo " Service: plugin" + echo " DriverName: $PLUGIN_V2_NAME" + elif [ -z "$SUB_STATUS" ] && is_plugin_enabled ; then echo echo " Service: plugin" echo " DriverName: weave" From 16062ea62debf01a65ac6743c8dea89a6cedbecd Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Wed, 15 Mar 2017 16:47:08 +0000 Subject: [PATCH 23/36] Rename weaveworks/pluginv2 to weaveworks/net-plugin --- Makefile | 34 +++++++++++++++++----------------- weave | 10 +++++----- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/Makefile b/Makefile index 44754692..a4f88024 100644 --- a/Makefile +++ b/Makefile @@ -105,7 +105,7 @@ EXES=$(WEAVER_EXE) $(SIGPROXY_EXE) $(KUBEPEERS_EXE) $(WEAVENPC_EXE) $(WEAVEPROXY BUILD_UPTODATE=.build.uptodate WEAVER_UPTODATE=.weaver$(ARCH_EXT).uptodate WEAVEEXEC_UPTODATE=.weaveexec$(ARCH_EXT).uptodate -PLUGINV2_UPTODATE=.pluginv2$(ARCH_EXT).uptodate +PLUGIN_UPTODATE=.net-plugin$(ARCH_EXT).uptodate WEAVEKUBE_UPTODATE=.weavekube$(ARCH_EXT).uptodate WEAVENPC_UPTODATE=.weavenpc$(ARCH_EXT).uptodate WEAVEDB_UPTODATE=.weavedb.uptodate @@ -119,11 +119,12 @@ 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 -PLUGINV2_IMAGE=$(DOCKERHUB_USER)/pluginv2$(ARCH_EXT) +PLUGIN_IMAGE=$(DOCKERHUB_USER)/net-plugin IMAGES=$(WEAVER_IMAGE) $(WEAVEEXEC_IMAGE) $(WEAVEKUBE_IMAGE) $(WEAVENPC_IMAGE) $(WEAVEDB_IMAGE) -PLUGINV2_WORK_DIR="prog/plugin-v2/rootfs" +PLUGIN_WORK_DIR="prog/plugin-v2/rootfs" +PLUGIN_BUILD_IMG="plugin-builder" 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 @@ -265,19 +266,18 @@ $(WEAVEEXEC_UPTODATE): prog/weaveexec/Dockerfile.$(DOCKERHUB_USER) prog/weaveexe $(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker build -f prog/weaveexec/Dockerfile.$(DOCKERHUB_USER) -t $(WEAVEEXEC_IMAGE) prog/weaveexec touch $@ -# TODO(mp) cleanup! -pluginv2: prog/plugin-v2/launch.sh prog/plugin-v2/config.json $(WEAVER_UPTODATE) - -$(SUDO) docker rm -f buildpluginv2 - $(SUDO) docker create --name=buildpluginv2 $(WEAVER_IMAGE) true - rm -rf $(PLUGINV2_WORK_DIR) - mkdir $(PLUGINV2_WORK_DIR) - docker export buildpluginv2 | tar -x -C $(PLUGINV2_WORK_DIR) - docker rm buildpluginv2 - cp prog/plugin-v2/launch.sh $(PLUGINV2_WORK_DIR)/home/weave/launch.sh - -docker plugin disable $(PLUGINV2_IMAGE) - -docker plugin rm $(PLUGINV2_IMAGE) - docker plugin create $(PLUGINV2_IMAGE) prog/plugin-v2 - #touch $@ +$(PLUGIN_UPTODATE): prog/plugin-v2/launch.sh prog/plugin-v2/config.json $(WEAVER_UPTODATE) + -$(SUDO) docker rm -f $(PLUGIN_BUILD_IMG) 2>/dev/null + $(SUDO) docker create --name=$(PLUGIN_BUILD_IMG) $(WEAVER_IMAGE) true + rm -rf $(PLUGIN_WORK_DIR) + mkdir $(PLUGIN_WORK_DIR) + docker export $(PLUGIN_BUILD_IMG) | tar -x -C $(PLUGIN_WORK_DIR) + docker rm -f $(PLUGIN_BUILD_IMG) + cp prog/plugin-v2/launch.sh $(PLUGIN_WORK_DIR)/home/weave/launch.sh + -docker plugin disable $(PLUGIN_IMAGE) 2>/dev/null + -docker plugin rm $(PLUGIN_IMAGE) 2>/dev/null + docker plugin create $(PLUGIN_IMAGE) prog/plugin-v2 + touch $@ $(WEAVEKUBE_UPTODATE): prog/weave-kube/Dockerfile.$(DOCKERHUB_USER) prog/weave-kube/launch.sh $(KUBEPEERS_EXE) $(WEAVER_UPTODATE) cp $(KUBEPEERS_EXE) prog/weave-kube/ @@ -357,7 +357,7 @@ ifneq ($(UPDATE_LATEST),false) endif clean-work-dir: - rm -rf $(PLUGINV2_WORK_DIR) + rm -rf $(PLUGIN_WORK_DIR) clean-bin: -$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker rmi $(IMAGES) diff --git a/weave b/weave index 65fc8bdf..66f512fc 100755 --- a/weave +++ b/weave @@ -335,7 +335,7 @@ BASE_IMAGE=$DOCKERHUB_USER/weave IMAGE=$BASE_IMAGE:$IMAGE_VERSION CONTAINER_NAME=${WEAVE_CONTAINER_NAME:-weave} -PLUGIN_V2_NAME="$DOCKERHUB_USER/pluginv2" +PLUGIN_NAME="$DOCKERHUB_USER/net-plugin" CNI_PLUGIN_NAME="weave-plugin-$IMAGE_VERSION" CNI_PLUGIN_DIR=${WEAVE_CNI_PLUGIN_DIR:-$HOST_ROOT/opt/cni/bin} # Note VOLUMES_CONTAINER which is for weavewait should change when you upgrade Weave @@ -884,15 +884,15 @@ attach() { } check_not_running_v2_plugin() { - if is_docker_plugin_enabled $PLUGIN_V2_NAME; then - echo "Docker plugin \"$PLUGIN_V2_NAME\" is already running." >&2 + if is_docker_plugin_enabled $PLUGIN_NAME; then + echo "Docker plugin \"$PLUGIN_NAME\" is already running." >&2 return 1 fi } # Docker Plugin V2 is_docker_plugin_enabled() { - util_op is-docker-plugin-enabled $PLUGIN_V2_NAME 2>/dev/null + util_op is-docker-plugin-enabled $PLUGIN_NAME 2>/dev/null } # Docker Plugin (part of weaver process, so V2 or V1). @@ -2058,7 +2058,7 @@ EOF if [ -z "$SUB_STATUS" ] && is_docker_plugin_enabled ; then echo echo " Service: plugin" - echo " DriverName: $PLUGIN_V2_NAME" + echo " DriverName: $PLUGIN_NAME" elif [ -z "$SUB_STATUS" ] && is_plugin_enabled ; then echo echo " Service: plugin" From 7fc56e54b33a932a8ce444ace0037a93b51b8870 Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Thu, 16 Mar 2017 22:09:03 +0000 Subject: [PATCH 24/36] Add plugin_publish target to Makefile "docker plugin" does not support tagging plugin images, therefore we need to build plugin images two times - one for :latest and for :$(WEAVE_VERSION). Pushing of :latest happens only if $UPDATE_LATEST is not false. --- Makefile | 17 ++++++++++++++--- bin/release | 8 ++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index a4f88024..d21be2b1 100644 --- a/Makefile +++ b/Makefile @@ -266,6 +266,7 @@ $(WEAVEEXEC_UPTODATE): prog/weaveexec/Dockerfile.$(DOCKERHUB_USER) prog/weaveexe $(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker build -f prog/weaveexec/Dockerfile.$(DOCKERHUB_USER) -t $(WEAVEEXEC_IMAGE) prog/weaveexec touch $@ +# Builds Docker plugin. $(PLUGIN_UPTODATE): prog/plugin-v2/launch.sh prog/plugin-v2/config.json $(WEAVER_UPTODATE) -$(SUDO) docker rm -f $(PLUGIN_BUILD_IMG) 2>/dev/null $(SUDO) docker create --name=$(PLUGIN_BUILD_IMG) $(WEAVER_IMAGE) true @@ -274,9 +275,12 @@ $(PLUGIN_UPTODATE): prog/plugin-v2/launch.sh prog/plugin-v2/config.json $(WEAVER docker export $(PLUGIN_BUILD_IMG) | tar -x -C $(PLUGIN_WORK_DIR) docker rm -f $(PLUGIN_BUILD_IMG) cp prog/plugin-v2/launch.sh $(PLUGIN_WORK_DIR)/home/weave/launch.sh - -docker plugin disable $(PLUGIN_IMAGE) 2>/dev/null - -docker plugin rm $(PLUGIN_IMAGE) 2>/dev/null - docker plugin create $(PLUGIN_IMAGE) prog/plugin-v2 + -docker plugin disable $(PLUGIN_IMAGE):$(WEAVE_VERSION) 2>/dev/null + -docker plugin rm $(PLUGIN_IMAGE):$(WEAVE_VERSION) 2>/dev/null + docker plugin create $(PLUGIN_IMAGE):$(WEAVE_VERSION) prog/plugin-v2 + -docker plugin disable $(PLUGIN_IMAGE):latest 2>/dev/null + -docker plugin rm $(PLUGIN_IMAGE):latest 2>/dev/null + docker plugin create $(PLUGIN_IMAGE):latest prog/plugin-v2 touch $@ $(WEAVEKUBE_UPTODATE): prog/weave-kube/Dockerfile.$(DOCKERHUB_USER) prog/weave-kube/launch.sh $(KUBEPEERS_EXE) $(WEAVER_UPTODATE) @@ -304,6 +308,13 @@ tools/.git $(MANIFEST_TOOL_DIR)/.git: # CODE FOR PUBLISHING THE IMAGES +# Push plugin +plugin_publish: $(PLUGIN_UPTODATE) + $(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker plugin push $(PLUGIN_IMAGE):$(WEAVE_VERSION) +ifneq ($(UPDATE_LATEST),false) + $(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker plugin push $(PLUGIN_IMAGE):latest +endif + # This target first runs "make publish" for each architecture # Then it pushes the manifest lists publish: $(addprefix sub-publish-,$(ALL_ARCHITECTURES)) $(WEAVEDB_UPTODATE) diff --git a/bin/release b/bin/release index 6bfad988..89f1c68f 100755 --- a/bin/release +++ b/bin/release @@ -191,6 +191,10 @@ publish() { make UPDATE_LATEST=$IS_MAINLINE SUDO=$SUDO WEAVE_VERSION=$VERSION DOCKERHUB_USER=$DOCKERHUB_USER publish echo "** Docker images tagged and pushed" + echo "== Building and pushing plugin" + make UPDATE_LATEST=$IS_MAINLINE SUDO=$SUDO WEAVE_VERSION=$VERSION DOCKERHUB_USER=$DOCKERHUB_USER plugin_publish + echo "** Plugin built and pushed" + echo "== Publishing pre-release on GitHub" github-release publish \ @@ -223,6 +227,10 @@ publish() { make PUBLISH_WEAVEDB=$IS_MAINLINE UPDATE_LATEST=$IS_MAINLINE SUDO=$SUDO WEAVE_VERSION=$VERSION DOCKERHUB_USER=$DOCKERHUB_USER publish echo "** Docker images tagged and pushed" + echo "== Building and pushing plugin" + make UPDATE_LATEST=$IS_MAINLINE SUDO=$SUDO WEAVE_VERSION=$VERSION DOCKERHUB_USER=$DOCKERHUB_USER plugin_publish + echo "** Plugin built and pushed" + echo "== Publishing release on GitHub" github-release publish \ From 2ba360f33a1949b62ef7f06bc27ac5ee36e707b7 Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Tue, 4 Apr 2017 15:25:02 +0100 Subject: [PATCH 25/36] Better plugin detection functions in weave script Renamed to "is_plugin_v1_enabled" and "is_plugin_v2_enabled". Improve weave status and weave launch* err message when plugin-v2 is running ``` $ weave launch Docker plugin "weaveworks/net-plugin" is running; Aborting. $ weave status <..> Service: plugin (v2) DriverName: weaveworks/net-plugin ``` --- test/850_plugin_v2_cross_hosts_2_test.sh | 14 ++---- weave | 61 ++++++++++++------------ 2 files changed, 35 insertions(+), 40 deletions(-) diff --git a/test/850_plugin_v2_cross_hosts_2_test.sh b/test/850_plugin_v2_cross_hosts_2_test.sh index e5db1c2b..58892f0b 100755 --- a/test/850_plugin_v2_cross_hosts_2_test.sh +++ b/test/850_plugin_v2_cross_hosts_2_test.sh @@ -2,7 +2,7 @@ . "$(dirname "$0")/config.sh" -PLUGIN_NAME="weave-ci-registry:5000/weaveworks/plugin-v2" +PLUGIN_NAME="weave-ci-registry:5000/weaveworks/net-plugin" HOST1_IP=$($SSH $HOST1 getent ahosts $HOST1 | grep "RAW" | cut -d' ' -f1) SERVICE="weave-850-service" NETWORK="weave-850-network" @@ -46,9 +46,7 @@ setup_worker() { echo "$HOST1_IP weave-ci-registry" | sudo tee -a /etc/hosts ping -nq -W 2 -c 1 weave-ci-registry docker swarm join --token "$1" "${HOST1_IP}:2377" - echo "Installing..." docker plugin install --disable --grant-all-permissions $PLUGIN_NAME - echo "Done" [ -n "$COVERAGE" ] && docker plugin set $PLUGIN_NAME EXTRA_ARGS="-test.coverprofile=/home/weave/cover.prof --" #docker plugin set $PLUGIN_NAME WEAVE_PASSWORD="foobar" @@ -100,7 +98,6 @@ start_suite "Test Docker plugin-v2" #exit 1 setup_master -#sleep 20 # registry seems to be async :( setup_worker $($SSH $HOST1 docker swarm join-token --quiet worker) echo "Creating network and service..." @@ -117,17 +114,14 @@ EOF wait_for_service $HOST1 $SERVICE 2 -$SSH $HOST1 "docker service ls" -$SSH $HOST1 "docker ps" -$SSH $HOST2 "docker ps" - C1=$($SSH $HOST1 weave ps | grep -v weave:expose | awk '{print $1}') C2_IP=$($SSH $HOST2 weave ps | grep -v weave:expose | awk '{print $3}' | cut -d/ -f1) -# TODO test for encryption - assert_raises "exec_on $HOST1 $C1 $PING $C2_IP" +# We do not test "weave {status,launch}", because the weave script does not detect +# plugin-v2 if its name is prefixed with a registry name. + # Failing to cleanup will make the rest of the tests to fail cleanup $HOST1 $HOST2 diff --git a/weave b/weave index 66f512fc..4cc57d9b 100755 --- a/weave +++ b/weave @@ -883,28 +883,29 @@ attach() { util_op attach-container $ATTACH_ARGS $CONTAINER $BRIDGE $MTU "$@" } -check_not_running_v2_plugin() { - if is_docker_plugin_enabled $PLUGIN_NAME; then - echo "Docker plugin \"$PLUGIN_NAME\" is already running." >&2 - return 1 - fi -} - -# Docker Plugin V2 -is_docker_plugin_enabled() { - util_op is-docker-plugin-enabled $PLUGIN_NAME 2>/dev/null -} - -# Docker Plugin (part of weaver process, so V2 or V1). -# Assumes that plugin is running inside Docker container. -is_plugin_enabled() { - docker inspect -f '{{.Config.Cmd}}' $CONTAINER_NAME | grep -q -- "--plugin" -} - ###################################################################### # functions for interacting with containers ###################################################################### +# Docker Plugin V1 runs in a Docker container. +is_plugin_v1_enabled() { + docker inspect -f '{{.Config.Cmd}}' $CONTAINER_NAME 2>/dev/null | grep -q -- "--plugin" +} + +# The presence of Docker Plugin V2 can be checked only via 'docker plugin', +# as v2 plugins do not run as regular containers. +is_plugin_v2_enabled() { + util_op is-docker-plugin-enabled $PLUGIN_NAME 2>/dev/null +} + +# Check that plugin (v2) is not running. +check_not_running_plugin_v2() { + if is_plugin_v2_enabled; then + echo "Docker plugin \"$PLUGIN_NAME\" is running; Aborting." >&2 + return 1 + fi +} + # Check that a container for component $1 named $2 with image $3 is not running check_not_running() { RUN_STATUS=$(docker inspect --format='{{.State.Running}} {{.State.Status}} {{.Config.Image}}' $2 2>/dev/null) || true @@ -1752,7 +1753,7 @@ populate_router() { } stop_router() { - ! is_plugin_enabled || util_op remove-plugin-network weave || true + ! is_plugin_v1_enabled || util_op remove-plugin-network weave || true stop $CONTAINER_NAME "Weave" conntrack -D -p udp --dport $PORT >/dev/null 2>&1 || true } @@ -1796,7 +1797,7 @@ stop_proxy() { protect_against_docker_hang() { # If the plugin is not running, remove its socket so Docker doesn't try to talk to it - if ! is_docker_plugin_enabled 2>/dev/null ; then + if ! is_plugin_v2_enabled 2>/dev/null ; then rm -f /run/docker/plugins/weave.sock /run/docker/plugins/weavemesh.sock fi } @@ -1984,7 +1985,7 @@ EOF deprecation_warnings "$@" check_not_running router $CONTAINER_NAME $BASE_IMAGE check_not_running proxy $PROXY_CONTAINER_NAME $BASE_EXEC_IMAGE - check_not_running_v2_plugin + check_not_running_plugin_v2 COMMON_ARGS=$(common_launch_args "$@") launch_router --plugin "$@" launch_proxy $COMMON_ARGS @@ -1992,7 +1993,7 @@ EOF launch-router) deprecation_warnings "$@" check_not_running router $CONTAINER_NAME $BASE_IMAGE - check_not_running_v2_plugin + check_not_running_plugin_v2 launch_router "$@" echo $ROUTER_CONTAINER ;; @@ -2010,7 +2011,7 @@ EOF launch-proxy) deprecation_warnings "$@" check_not_running proxy $PROXY_CONTAINER_NAME $BASE_EXEC_IMAGE - check_not_running_v2_plugin + check_not_running_plugin_v2 launch_proxy "$@" echo $PROXY_CONTAINER ;; @@ -2055,14 +2056,14 @@ EOF echo " Service: proxy" echo " Address: $PROXY_ADDRS" fi - if [ -z "$SUB_STATUS" ] && is_docker_plugin_enabled ; then + if [ -z "$SUB_STATUS" ] && is_plugin_v1_enabled ; then echo - echo " Service: plugin" - echo " DriverName: $PLUGIN_NAME" - elif [ -z "$SUB_STATUS" ] && is_plugin_enabled ; then - echo - echo " Service: plugin" + echo " Service: plugin (v1)" echo " DriverName: weave" + elif [ -z "$SUB_STATUS" ] && is_plugin_v2_enabled ; then + echo + echo " Service: plugin (v2)" + echo " DriverName: $PLUGIN_NAME" fi [ -n "$SUB_STATUS" ] || echo [ $res -eq 0 ] @@ -2261,7 +2262,7 @@ EOF ;; reset) [ $# -eq 0 ] || [ $# -eq 1 -a "$1" = "--force" ] || usage - ! is_plugin_enabled || util_op remove-plugin-network weave || true + ! is_plugin_v1_enabled || util_op remove-plugin-network weave || true warn_if_stopping_proxy_in_env res=0 [ "$1" = "--force" ] || check_running $CONTAINER_NAME 2>/dev/null || res=$? From 3c11c8aa3846b83d18bbd951cfbb3d93bc14c8f4 Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Tue, 4 Apr 2017 16:01:49 +0100 Subject: [PATCH 26/36] Add comment about failures to is-docker-plugin-enabled cmd --- prog/weaveutil/plugin_network.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/prog/weaveutil/plugin_network.go b/prog/weaveutil/plugin_network.go index 3d604c5a..79d96b65 100644 --- a/prog/weaveutil/plugin_network.go +++ b/prog/weaveutil/plugin_network.go @@ -74,6 +74,9 @@ while Weave is not running`, networkName, containers) } // Exits with 0 if the given plugin (v2) is enabled. +// +// Any failure due to missing plugin support is non-harmful as plugin (v2) +// cannot be enabled when Docker does not support it. func isDockerPluginEnabled(args []string) error { if len(args) != 1 { cmdUsage("is-docker-plugin-enabled", "") From 568290afb7a9abf380f10310dcef0be46218149f Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Wed, 5 Apr 2017 17:27:08 +0100 Subject: [PATCH 27/36] Do not start local scope plugin (mesh) in plugin-v2 Currently, plugin-v2 works only in "swarm" scope, as it depends on swarm for peer discovery. --- prog/plugin-v2/launch.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/prog/plugin-v2/launch.sh b/prog/plugin-v2/launch.sh index 28decd7f..f57631d1 100755 --- a/prog/plugin-v2/launch.sh +++ b/prog/plugin-v2/launch.sh @@ -54,4 +54,5 @@ exec /home/weave/weaver $EXTRA_ARGS --port=6783 $BRIDGE_OPTIONS \ --log-level=debug \ --db-prefix="$WEAVE_DIR/weave" \ --plugin \ + --plugin-mesh-socket='' \ $(echo $SWARM_MANAGER_PEERS | tr '\n' ' ') From 332762201a8fcd46e2f50f747405f434abab0afe Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Wed, 5 Apr 2017 17:33:23 +0100 Subject: [PATCH 28/36] Reuse docker client instance in plugin Instead of creating a new one, reuse one created in weaver. The change removes the pinning of client API versions (1.21 in our case). --- plugin/plugin.go | 21 ++------------------- prog/plugin-v2/launch.sh | 3 ++- prog/weaver/main.go | 2 +- 3 files changed, 5 insertions(+), 21 deletions(-) diff --git a/plugin/plugin.go b/plugin/plugin.go index 48ba067f..efc6a389 100644 --- a/plugin/plugin.go +++ b/plugin/plugin.go @@ -20,31 +20,14 @@ import ( var Log = common.Log -func Start(weaveAPIAddr string, dockerAPIAddr string, address string, meshAddress string) { +func Start(weaveAPIAddr string, dockerClient *docker.Client, address string, meshAddress string) { weave := weaveapi.NewClient(weaveAPIAddr, Log) - var dockerClient *docker.Client - var err error - if dockerAPIAddr != "" { - // API 1.21 is the first version that supports docker network commands - dockerClient, err = docker.NewVersionedClient(dockerAPIAddr, "1.21") - if err != nil { - Log.Fatalf("unable to connect to docker: %s", err) - } - } - - if dockerClient == nil { - Log.Info("Running without Docker API connection") - } else { - Log.Info(dockerClient.Info()) - } - Log.Info("Waiting for Weave API Server...") weave.WaitAPIServer(30) Log.Info("Finished waiting for Weave API Server") - err = run(dockerClient, weave, address, meshAddress) - if err != nil { + if err := run(dockerClient, weave, address, meshAddress); err != nil { Log.Fatal(err) } } diff --git a/prog/plugin-v2/launch.sh b/prog/plugin-v2/launch.sh index f57631d1..7693da00 100755 --- a/prog/plugin-v2/launch.sh +++ b/prog/plugin-v2/launch.sh @@ -47,7 +47,8 @@ if [ -z "$IPALLOC_INIT" ]; then fi exec /home/weave/weaver $EXTRA_ARGS --port=6783 $BRIDGE_OPTIONS \ - --http-addr=$HTTP_ADDR --status-addr=$STATUS_ADDR --docker-api='' --no-dns \ + --http-addr=$HTTP_ADDR --status-addr=$STATUS_ADDR \ + --no-dns \ --ipalloc-range=$IPALLOC_RANGE \ --ipalloc-init $IPALLOC_INIT \ --nickname "$(hostname)" \ diff --git a/prog/weaver/main.go b/prog/weaver/main.go index ba38d666..0341749c 100644 --- a/prog/weaver/main.go +++ b/prog/weaver/main.go @@ -405,7 +405,7 @@ func main() { } if enablePlugin { - go plugin.Start(httpAddr, dockerAPI, pluginSocket, pluginMeshSocket) + go plugin.Start(httpAddr, dockerCli, pluginSocket, pluginMeshSocket) } signals.SignalHandlerLoop(common.Log, router) From 01bfa602add284dddce86d5c55fb528d0fd0002b Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Thu, 6 Apr 2017 16:48:21 +0100 Subject: [PATCH 29/36] Pass noDNS and isPluginV2 flags to plugin - "noDNS" controls whether upon ContainerStarted event a container should be registered within the Weave DNS. - "isPluginV2" will be used to determine a path to host's /proc. --- plugin/net/driver.go | 20 ++++++++++++-------- plugin/net/watcher.go | 8 +++++--- plugin/plugin.go | 15 ++++++++------- prog/plugin-v2/launch.sh | 9 +++++---- prog/weaver/main.go | 8 +++++--- 5 files changed, 35 insertions(+), 25 deletions(-) diff --git a/plugin/net/driver.go b/plugin/net/driver.go index fe46f594..4d555a80 100644 --- a/plugin/net/driver.go +++ b/plugin/net/driver.go @@ -28,19 +28,23 @@ type network struct { } type driver struct { - name string - scope string - docker *docker.Client + name string + scope string + docker *docker.Client + noDNS bool + isPluginV2 bool sync.RWMutex networks map[string]network } -func New(client *docker.Client, weave *weaveapi.Client, name, scope string) (skel.Driver, error) { +func New(client *docker.Client, weave *weaveapi.Client, name, scope string, noDNS, isPluginV2 bool) (skel.Driver, error) { driver := &driver{ - name: name, - scope: scope, - docker: client, - networks: make(map[string]network), + name: name, + scope: scope, + docker: client, + noDNS: noDNS, + isPluginV2: isPluginV2, + networks: make(map[string]network), } _, err := NewWatcher(client, weave, driver) diff --git a/plugin/net/watcher.go b/plugin/net/watcher.go index b9d04f5a..45dd28c7 100644 --- a/plugin/net/watcher.go +++ b/plugin/net/watcher.go @@ -41,9 +41,11 @@ func (w *watcher) ContainerStarted(id string) { continue } if network.isOurs { - fqdn := fmt.Sprintf("%s.%s", info.Config.Hostname, info.Config.Domainname) - 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 !w.driver.noDNS { + fqdn := fmt.Sprintf("%s.%s", info.Config.Hostname, info.Config.Domainname) + 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 := weavenet.WithNetNSByPid(info.State.Pid, "configure-arp", weavenet.VethName); err != nil { w.driver.warn("ContainerStarted", "unable to configure interfaces: %s", err) diff --git a/plugin/plugin.go b/plugin/plugin.go index efc6a389..e850d567 100644 --- a/plugin/plugin.go +++ b/plugin/plugin.go @@ -20,23 +20,23 @@ import ( var Log = common.Log -func Start(weaveAPIAddr string, dockerClient *docker.Client, address string, meshAddress string) { +func Start(weaveAPIAddr string, dockerClient *docker.Client, address string, meshAddress string, noDNS bool, isPluginV2 bool) { weave := weaveapi.NewClient(weaveAPIAddr, Log) Log.Info("Waiting for Weave API Server...") weave.WaitAPIServer(30) Log.Info("Finished waiting for Weave API Server") - if err := run(dockerClient, weave, address, meshAddress); err != nil { + if err := run(dockerClient, weave, address, meshAddress, noDNS, isPluginV2); err != nil { Log.Fatal(err) } } -func run(dockerClient *docker.Client, weave *weaveapi.Client, address, meshAddress string) error { +func run(dockerClient *docker.Client, weave *weaveapi.Client, address, meshAddress string, noDNS, isPluginV2 bool) error { endChan := make(chan error, 1) if address != "" { - globalListener, err := listenAndServe(dockerClient, weave, address, endChan, "global", false) + globalListener, err := listenAndServe(dockerClient, weave, address, endChan, "global", false, noDNS, isPluginV2) if err != nil { return err } @@ -44,7 +44,7 @@ func run(dockerClient *docker.Client, weave *weaveapi.Client, address, meshAddre defer globalListener.Close() } if meshAddress != "" { - meshListener, err := listenAndServe(dockerClient, weave, meshAddress, endChan, "local", true) + meshListener, err := listenAndServe(dockerClient, weave, meshAddress, endChan, "local", true, noDNS, isPluginV2) if err != nil { return err } @@ -61,9 +61,10 @@ func run(dockerClient *docker.Client, weave *weaveapi.Client, address, meshAddre return <-endChan } -func listenAndServe(dockerClient *docker.Client, weave *weaveapi.Client, address string, endChan chan<- error, scope string, withIpam bool) (net.Listener, error) { +func listenAndServe(dockerClient *docker.Client, weave *weaveapi.Client, address string, endChan chan<- error, scope string, withIpam, noDNS bool, isPluginV2 bool) (net.Listener, error) { name := strings.TrimSuffix(path.Base(address), ".sock") - d, err := netplugin.New(dockerClient, weave, name, scope) + // TODO(mp) fix plugin name, as it is used to determine whether network is our + d, err := netplugin.New(dockerClient, weave, name, scope, noDNS, isPluginV2) if err != nil { return nil, err } diff --git a/prog/plugin-v2/launch.sh b/prog/plugin-v2/launch.sh index 7693da00..818f66f7 100755 --- a/prog/plugin-v2/launch.sh +++ b/prog/plugin-v2/launch.sh @@ -16,6 +16,8 @@ echo "Starting launch.sh" # Check if the IP range overlaps anything existing on the host /usr/bin/weaveutil netcheck $IPALLOC_RANGE weave +# TODO(mp) add wait for swarm + SWARM_MANAGER_PEERS=$(/usr/bin/weaveutil swarm-manager-peers) ! /usr/bin/weaveutil is-swarm-manager || IS_SWARM_MANAGER=1 # Prevent from restoring from a persisted peers list @@ -39,10 +41,9 @@ if [ "$(/home/weave/weave --local bridge-type)" = "bridge" ]; then fi if [ -z "$IPALLOC_INIT" ]; then - if [ $IS_SWARM_MANAGER == "1" ]; then + IPALLOC_INIT="observer" + if [ "$IS_SWARM_MANAGER" == "1" ]; then IPALLOC_INIT="consensus=$(echo $SWARM_MANAGER_PEERS | wc -l)" - else - IPALLOC_INIT="observer" fi fi @@ -54,6 +55,6 @@ exec /home/weave/weaver $EXTRA_ARGS --port=6783 $BRIDGE_OPTIONS \ --nickname "$(hostname)" \ --log-level=debug \ --db-prefix="$WEAVE_DIR/weave" \ - --plugin \ + --plugin-v2 \ --plugin-mesh-socket='' \ $(echo $SWARM_MANAGER_PEERS | tr '\n' ' ') diff --git a/prog/weaver/main.go b/prog/weaver/main.go index 0341749c..926630e3 100644 --- a/prog/weaver/main.go +++ b/prog/weaver/main.go @@ -154,6 +154,7 @@ func main() { pluginSocket string pluginMeshSocket string enablePlugin bool + enablePluginV2 bool defaultDockerHost = "unix:///var/run/docker.sock" ) @@ -199,7 +200,8 @@ func main() { mflag.StringVar(&token, []string{"-token"}, "", "token for peer discovery") mflag.StringVar(&advertiseAddress, []string{"-advertise-address"}, "", "address to advertise for peer discovery") - mflag.BoolVar(&enablePlugin, []string{"-plugin"}, false, "enable Docker plugin") + mflag.BoolVar(&enablePlugin, []string{"-plugin"}, false, "enable Docker plugin (v1)") + mflag.BoolVar(&enablePluginV2, []string{"-plugin-v2"}, false, "enable Docker plugin (v2)") mflag.StringVar(&pluginSocket, []string{"-plugin-socket"}, "/run/docker/plugins/weave.sock", "plugin socket on which to listen") mflag.StringVar(&pluginMeshSocket, []string{"-plugin-mesh-socket"}, "/run/docker/plugins/weavemesh.sock", "plugin socket on which to listen in mesh mode") @@ -404,8 +406,8 @@ func main() { go listenAndServeHTTP(statusAddr, statusMux) } - if enablePlugin { - go plugin.Start(httpAddr, dockerCli, pluginSocket, pluginMeshSocket) + if enablePlugin || enablePluginV2 { + go plugin.Start(httpAddr, dockerCli, pluginSocket, pluginMeshSocket, noDNS, enablePluginV2) } signals.SignalHandlerLoop(common.Log, router) From 7478e78ab777780843c09c8ae6458e24354b9fc9 Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Thu, 6 Apr 2017 16:45:05 +0100 Subject: [PATCH 30/36] Add NSPathByPidWithRoot The function is used in a case when /proc is bind mounted to other than /proc dir. --- net/netns.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/netns.go b/net/netns.go index 971baf63..3bd4a1c2 100644 --- a/net/netns.go +++ b/net/netns.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "os/exec" + "path/filepath" "runtime" "github.com/vishvananda/netlink" @@ -80,5 +81,9 @@ func WithNetNSByPid(pid int, cmd string, args ...string) ([]byte, error) { } func NSPathByPid(pid int) string { - return fmt.Sprintf("/proc/%d/ns/net", pid) + return NSPathByPidWithRoot("/", pid) +} + +func NSPathByPidWithRoot(root string, pid int) string { + return filepath.Join(root, fmt.Sprintf("/proc/%d/ns/net", pid)) } From 735a7f9154537040189ffaad6a8f767164922976 Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Thu, 6 Apr 2017 16:52:42 +0100 Subject: [PATCH 31/36] Use correct path to netns of container in plugin-v2 Used when configuring ARP settings of a container upon ContainerStarted event. --- plugin/net/watcher.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/plugin/net/watcher.go b/plugin/net/watcher.go index 45dd28c7..c0d38f79 100644 --- a/plugin/net/watcher.go +++ b/plugin/net/watcher.go @@ -47,7 +47,13 @@ func (w *watcher) ContainerStarted(id string) { w.driver.warn("ContainerStarted", "unable to register %s with weaveDNS: %s", id, err) } } - if _, err := weavenet.WithNetNSByPid(info.State.Pid, "configure-arp", weavenet.VethName); err != nil { + rootDir := "/" + if w.driver.isPluginV2 { + // We bind mount host's /proc to /host/proc for plugin-v2 + rootDir = "/host" + } + netNSPath := weavenet.NSPathByPidWithRoot(rootDir, info.State.Pid) + if _, err := weavenet.WithNetNS(netNSPath, "configure-arp", weavenet.VethName); err != nil { w.driver.warn("ContainerStarted", "unable to configure interfaces: %s", err) } } From 4a708c2a82219831a9d4b80282a18e46f6a95122 Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Fri, 7 Apr 2017 11:56:11 +0100 Subject: [PATCH 32/36] Rename prog/plugin-v2 to prog/net-plugin Consensus was to call the plugin-v2 as weaveworks/net-plugin. --- .gitignore | 2 +- Makefile | 10 +++++----- prog/{plugin-v2 => net-plugin}/config.json | 0 prog/{plugin-v2 => net-plugin}/launch.sh | 0 test/850_plugin_v2_cross_hosts_2_test.sh | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) rename prog/{plugin-v2 => net-plugin}/config.json (100%) rename prog/{plugin-v2 => net-plugin}/launch.sh (100%) diff --git a/.gitignore b/.gitignore index 0e410022..6aece654 100644 --- a/.gitignore +++ b/.gitignore @@ -70,4 +70,4 @@ test/coverage.* *qemu-*-static terraform.tfstate terraform.tfstate.backup -prog/plugin-v2/rootfs/ +prog/net-plugin/rootfs/ diff --git a/Makefile b/Makefile index d21be2b1..d563ec12 100644 --- a/Makefile +++ b/Makefile @@ -123,7 +123,7 @@ PLUGIN_IMAGE=$(DOCKERHUB_USER)/net-plugin IMAGES=$(WEAVER_IMAGE) $(WEAVEEXEC_IMAGE) $(WEAVEKUBE_IMAGE) $(WEAVENPC_IMAGE) $(WEAVEDB_IMAGE) -PLUGIN_WORK_DIR="prog/plugin-v2/rootfs" +PLUGIN_WORK_DIR="prog/net-plugin/rootfs" PLUGIN_BUILD_IMG="plugin-builder" PUBLISH=publish_weave publish_weaveexec publish_plugin publish_weave-kube publish_weave-npc @@ -267,20 +267,20 @@ $(WEAVEEXEC_UPTODATE): prog/weaveexec/Dockerfile.$(DOCKERHUB_USER) prog/weaveexe touch $@ # Builds Docker plugin. -$(PLUGIN_UPTODATE): prog/plugin-v2/launch.sh prog/plugin-v2/config.json $(WEAVER_UPTODATE) +$(PLUGIN_UPTODATE): prog/net-plugin/launch.sh prog/net-plugin/config.json $(WEAVER_UPTODATE) -$(SUDO) docker rm -f $(PLUGIN_BUILD_IMG) 2>/dev/null $(SUDO) docker create --name=$(PLUGIN_BUILD_IMG) $(WEAVER_IMAGE) true rm -rf $(PLUGIN_WORK_DIR) mkdir $(PLUGIN_WORK_DIR) docker export $(PLUGIN_BUILD_IMG) | tar -x -C $(PLUGIN_WORK_DIR) docker rm -f $(PLUGIN_BUILD_IMG) - cp prog/plugin-v2/launch.sh $(PLUGIN_WORK_DIR)/home/weave/launch.sh + cp prog/net-plugin/launch.sh $(PLUGIN_WORK_DIR)/home/weave/launch.sh -docker plugin disable $(PLUGIN_IMAGE):$(WEAVE_VERSION) 2>/dev/null -docker plugin rm $(PLUGIN_IMAGE):$(WEAVE_VERSION) 2>/dev/null - docker plugin create $(PLUGIN_IMAGE):$(WEAVE_VERSION) prog/plugin-v2 + docker plugin create $(PLUGIN_IMAGE):$(WEAVE_VERSION) prog/net-plugin -docker plugin disable $(PLUGIN_IMAGE):latest 2>/dev/null -docker plugin rm $(PLUGIN_IMAGE):latest 2>/dev/null - docker plugin create $(PLUGIN_IMAGE):latest prog/plugin-v2 + docker plugin create $(PLUGIN_IMAGE):latest prog/net-plugin touch $@ $(WEAVEKUBE_UPTODATE): prog/weave-kube/Dockerfile.$(DOCKERHUB_USER) prog/weave-kube/launch.sh $(KUBEPEERS_EXE) $(WEAVER_UPTODATE) diff --git a/prog/plugin-v2/config.json b/prog/net-plugin/config.json similarity index 100% rename from prog/plugin-v2/config.json rename to prog/net-plugin/config.json diff --git a/prog/plugin-v2/launch.sh b/prog/net-plugin/launch.sh similarity index 100% rename from prog/plugin-v2/launch.sh rename to prog/net-plugin/launch.sh diff --git a/test/850_plugin_v2_cross_hosts_2_test.sh b/test/850_plugin_v2_cross_hosts_2_test.sh index 58892f0b..64e5e2b6 100755 --- a/test/850_plugin_v2_cross_hosts_2_test.sh +++ b/test/850_plugin_v2_cross_hosts_2_test.sh @@ -14,7 +14,7 @@ setup_master() { # Build plugin-v2 on $HOST1, because Circle "CI" runs only ancient # version of Docker which does not support v2 plugins. build_plugin_img="buildpluginv2-ci" - rsync -az -e "$SSH" "$(dirname $0)/../prog/plugin-v2" $HOST1:~/ + rsync -az -e "$SSH" "$(dirname $0)/../prog/net-plugin" $HOST1:~/ $SSH $HOST1</dev/null docker plugin disable $PLUGIN_NAME >/dev/null @@ -25,8 +25,8 @@ setup_master() { docker create --name=$build_plugin_img weaveworks/weave true docker export $build_plugin_img | tar -x -C \${WORK_DIR}/rootfs - cp \${HOME}/plugin-v2/launch.sh \${WORK_DIR}/rootfs/home/weave/launch.sh - cp \${HOME}/plugin-v2/config.json \${WORK_DIR} + cp \${HOME}/net-plugin/launch.sh \${WORK_DIR}/rootfs/home/weave/launch.sh + cp \${HOME}/net-plugin/config.json \${WORK_DIR} docker plugin create $PLUGIN_NAME \${WORK_DIR} echo "$HOST1_IP weave-ci-registry" | sudo tee -a /etc/hosts From 09606db9c3646d7b5a675960dfb7694351448afc Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Fri, 7 Apr 2017 15:34:30 +0100 Subject: [PATCH 33/36] Exit when launching plugin-v2 if node is not active in Swarm We retrieve the list of swarm masters for peer discovery when launching plugin-v2, thus the node should belong to any Swarm when enabling the plugin. --- prog/net-plugin/launch.sh | 10 ++++++++-- prog/weaveutil/swarm.go | 7 +++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/prog/net-plugin/launch.sh b/prog/net-plugin/launch.sh index 818f66f7..a372be13 100755 --- a/prog/net-plugin/launch.sh +++ b/prog/net-plugin/launch.sh @@ -16,10 +16,16 @@ echo "Starting launch.sh" # Check if the IP range overlaps anything existing on the host /usr/bin/weaveutil netcheck $IPALLOC_RANGE weave -# TODO(mp) add wait for swarm +STATUS=0 +/usr/bin/weaveutil is-swarm-manager 2>/dev/null || STATUS=$? +if [ $STATUS -eq 0 ]; then + IS_SWARM_MANAGER=1 +elif [ $STATUS -eq 20 ]; then + echo "Host swarm is not \"active\"; exiting." >&2 + exit 1 +fi SWARM_MANAGER_PEERS=$(/usr/bin/weaveutil swarm-manager-peers) -! /usr/bin/weaveutil is-swarm-manager || IS_SWARM_MANAGER=1 # Prevent from restoring from a persisted peers list rm -f "/restart.sentinel" diff --git a/prog/weaveutil/swarm.go b/prog/weaveutil/swarm.go index fbec29e9..6131b3a9 100644 --- a/prog/weaveutil/swarm.go +++ b/prog/weaveutil/swarm.go @@ -2,8 +2,10 @@ package main import ( "fmt" + "os" "strings" + "github.com/docker/docker/api/types/swarm" "github.com/fsouza/go-dockerclient" "github.com/pkg/errors" ) @@ -16,6 +18,11 @@ func isSwarmManager(args []string) error { return err } + // hack-y way to denote that a node does not belong to any swarm + if info.Swarm.LocalNodeState != swarm.LocalNodeStateActive { + os.Exit(20) + } + if !info.Swarm.ControlAvailable { return fmt.Errorf("node is not a manager") } From 1a3537a8f4b4c7b760bb394a44335c983f93c917 Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Tue, 11 Apr 2017 21:48:39 +0100 Subject: [PATCH 34/36] Replace noDNS by dns in plugin Just to avoid double negation. --- plugin/net/driver.go | 6 +++--- plugin/net/watcher.go | 2 +- plugin/plugin.go | 14 +++++++------- prog/weaver/main.go | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/plugin/net/driver.go b/plugin/net/driver.go index 4d555a80..14a301a7 100644 --- a/plugin/net/driver.go +++ b/plugin/net/driver.go @@ -31,18 +31,18 @@ type driver struct { name string scope string docker *docker.Client - noDNS bool + dns bool isPluginV2 bool sync.RWMutex networks map[string]network } -func New(client *docker.Client, weave *weaveapi.Client, name, scope string, noDNS, isPluginV2 bool) (skel.Driver, error) { +func New(client *docker.Client, weave *weaveapi.Client, name, scope string, dns, isPluginV2 bool) (skel.Driver, error) { driver := &driver{ name: name, scope: scope, docker: client, - noDNS: noDNS, + dns: dns, isPluginV2: isPluginV2, networks: make(map[string]network), } diff --git a/plugin/net/watcher.go b/plugin/net/watcher.go index c0d38f79..736751d7 100644 --- a/plugin/net/watcher.go +++ b/plugin/net/watcher.go @@ -41,7 +41,7 @@ func (w *watcher) ContainerStarted(id string) { continue } if network.isOurs { - if !w.driver.noDNS { + if w.driver.dns { fqdn := fmt.Sprintf("%s.%s", info.Config.Hostname, info.Config.Domainname) if err := w.weave.RegisterWithDNS(id, fqdn, net.IPAddress); err != nil { w.driver.warn("ContainerStarted", "unable to register %s with weaveDNS: %s", id, err) diff --git a/plugin/plugin.go b/plugin/plugin.go index e850d567..8a9c48f6 100644 --- a/plugin/plugin.go +++ b/plugin/plugin.go @@ -20,23 +20,23 @@ import ( var Log = common.Log -func Start(weaveAPIAddr string, dockerClient *docker.Client, address string, meshAddress string, noDNS bool, isPluginV2 bool) { +func Start(weaveAPIAddr string, dockerClient *docker.Client, address string, meshAddress string, dns bool, isPluginV2 bool) { weave := weaveapi.NewClient(weaveAPIAddr, Log) Log.Info("Waiting for Weave API Server...") weave.WaitAPIServer(30) Log.Info("Finished waiting for Weave API Server") - if err := run(dockerClient, weave, address, meshAddress, noDNS, isPluginV2); err != nil { + if err := run(dockerClient, weave, address, meshAddress, dns, isPluginV2); err != nil { Log.Fatal(err) } } -func run(dockerClient *docker.Client, weave *weaveapi.Client, address, meshAddress string, noDNS, isPluginV2 bool) error { +func run(dockerClient *docker.Client, weave *weaveapi.Client, address, meshAddress string, dns, isPluginV2 bool) error { endChan := make(chan error, 1) if address != "" { - globalListener, err := listenAndServe(dockerClient, weave, address, endChan, "global", false, noDNS, isPluginV2) + globalListener, err := listenAndServe(dockerClient, weave, address, endChan, "global", false, dns, isPluginV2) if err != nil { return err } @@ -44,7 +44,7 @@ func run(dockerClient *docker.Client, weave *weaveapi.Client, address, meshAddre defer globalListener.Close() } if meshAddress != "" { - meshListener, err := listenAndServe(dockerClient, weave, meshAddress, endChan, "local", true, noDNS, isPluginV2) + meshListener, err := listenAndServe(dockerClient, weave, meshAddress, endChan, "local", true, dns, isPluginV2) if err != nil { return err } @@ -61,10 +61,10 @@ func run(dockerClient *docker.Client, weave *weaveapi.Client, address, meshAddre return <-endChan } -func listenAndServe(dockerClient *docker.Client, weave *weaveapi.Client, address string, endChan chan<- error, scope string, withIpam, noDNS bool, isPluginV2 bool) (net.Listener, error) { +func listenAndServe(dockerClient *docker.Client, weave *weaveapi.Client, address string, endChan chan<- error, scope string, withIpam, dns bool, isPluginV2 bool) (net.Listener, error) { name := strings.TrimSuffix(path.Base(address), ".sock") // TODO(mp) fix plugin name, as it is used to determine whether network is our - d, err := netplugin.New(dockerClient, weave, name, scope, noDNS, isPluginV2) + d, err := netplugin.New(dockerClient, weave, name, scope, dns, isPluginV2) if err != nil { return nil, err } diff --git a/prog/weaver/main.go b/prog/weaver/main.go index 926630e3..7982a2fb 100644 --- a/prog/weaver/main.go +++ b/prog/weaver/main.go @@ -407,7 +407,7 @@ func main() { } if enablePlugin || enablePluginV2 { - go plugin.Start(httpAddr, dockerCli, pluginSocket, pluginMeshSocket, noDNS, enablePluginV2) + go plugin.Start(httpAddr, dockerCli, pluginSocket, pluginMeshSocket, !noDNS, enablePluginV2) } signals.SignalHandlerLoop(common.Log, router) From bdfa06dbe97f73bc18ef4a262e787b9cb2d41b38 Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Tue, 11 Apr 2017 22:07:13 +0100 Subject: [PATCH 35/36] Use $(SUDO) for each docker cmd when building net-plugin --- Makefile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index d563ec12..7b1bac40 100644 --- a/Makefile +++ b/Makefile @@ -272,15 +272,15 @@ $(PLUGIN_UPTODATE): prog/net-plugin/launch.sh prog/net-plugin/config.json $(WEAV $(SUDO) docker create --name=$(PLUGIN_BUILD_IMG) $(WEAVER_IMAGE) true rm -rf $(PLUGIN_WORK_DIR) mkdir $(PLUGIN_WORK_DIR) - docker export $(PLUGIN_BUILD_IMG) | tar -x -C $(PLUGIN_WORK_DIR) - docker rm -f $(PLUGIN_BUILD_IMG) + $(SUDO) docker export $(PLUGIN_BUILD_IMG) | tar -x -C $(PLUGIN_WORK_DIR) + $(SUDO) docker rm -f $(PLUGIN_BUILD_IMG) cp prog/net-plugin/launch.sh $(PLUGIN_WORK_DIR)/home/weave/launch.sh - -docker plugin disable $(PLUGIN_IMAGE):$(WEAVE_VERSION) 2>/dev/null - -docker plugin rm $(PLUGIN_IMAGE):$(WEAVE_VERSION) 2>/dev/null - docker plugin create $(PLUGIN_IMAGE):$(WEAVE_VERSION) prog/net-plugin - -docker plugin disable $(PLUGIN_IMAGE):latest 2>/dev/null - -docker plugin rm $(PLUGIN_IMAGE):latest 2>/dev/null - docker plugin create $(PLUGIN_IMAGE):latest prog/net-plugin + -$(SUDO) docker plugin disable $(PLUGIN_IMAGE):$(WEAVE_VERSION) 2>/dev/null + -$(SUDO) docker plugin rm $(PLUGIN_IMAGE):$(WEAVE_VERSION) 2>/dev/null + $(SUDO) docker plugin create $(PLUGIN_IMAGE):$(WEAVE_VERSION) prog/net-plugin + -$(SUDO) docker plugin disable $(PLUGIN_IMAGE):latest 2>/dev/null + -$(SUDO) docker plugin rm $(PLUGIN_IMAGE):latest 2>/dev/null + $(SUDO) docker plugin create $(PLUGIN_IMAGE):latest prog/net-plugin touch $@ $(WEAVEKUBE_UPTODATE): prog/weave-kube/Dockerfile.$(DOCKERHUB_USER) prog/weave-kube/launch.sh $(KUBEPEERS_EXE) $(WEAVER_UPTODATE) From cfe26ae346b62095c8aeb31bde92b5152f5c99ed Mon Sep 17 00:00:00 2001 From: Martynas Pumputis Date: Tue, 11 Apr 2017 22:29:11 +0100 Subject: [PATCH 36/36] Add an ugly way to match whether network is ours to plugin Docker Plugin V2 does not expose a plugin name to the plugin, so we check for "net-plugin" within driver name of a network to detect whether network is ours. --- plugin/net/driver.go | 28 ++++++++++++++-------------- plugin/plugin.go | 18 +++++++++++++++--- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/plugin/net/driver.go b/plugin/net/driver.go index 14a301a7..6ddadb07 100644 --- a/plugin/net/driver.go +++ b/plugin/net/driver.go @@ -28,23 +28,23 @@ type network struct { } type driver struct { - name string - scope string - docker *docker.Client - dns bool - isPluginV2 bool sync.RWMutex - networks map[string]network + scope string + docker *docker.Client + dns bool + isPluginV2 bool + networks map[string]network + isNetworkOur func(driverName string) bool } -func New(client *docker.Client, weave *weaveapi.Client, name, scope string, dns, isPluginV2 bool) (skel.Driver, error) { +func New(client *docker.Client, weave *weaveapi.Client, scope string, dns, isPluginV2 bool, isNetworkOur func(string) bool) (skel.Driver, error) { driver := &driver{ - name: name, - scope: scope, - docker: client, - dns: dns, - isPluginV2: isPluginV2, - networks: make(map[string]network), + scope: scope, + docker: client, + dns: dns, + isPluginV2: isPluginV2, + networks: make(map[string]network), + isNetworkOur: isNetworkOur, } _, err := NewWatcher(client, weave, driver) @@ -193,7 +193,7 @@ func (driver *driver) findNetworkInfo(id string) (network, error) { if err != nil { return network, err } - return driver.setupNetworkInfo(id, info.Driver == driver.name, info.Options) + return driver.setupNetworkInfo(id, driver.isNetworkOur(info.Driver), info.Options) } func (driver *driver) setupNetworkInfo(id string, isOurs bool, options map[string]string) (network, error) { diff --git a/plugin/plugin.go b/plugin/plugin.go index 8a9c48f6..3343a902 100644 --- a/plugin/plugin.go +++ b/plugin/plugin.go @@ -18,6 +18,8 @@ import ( "github.com/weaveworks/weave/plugin/skel" ) +const pluginV2Name = "net-plugin" + var Log = common.Log func Start(weaveAPIAddr string, dockerClient *docker.Client, address string, meshAddress string, dns bool, isPluginV2 bool) { @@ -62,9 +64,19 @@ func run(dockerClient *docker.Client, weave *weaveapi.Client, address, meshAddre } func listenAndServe(dockerClient *docker.Client, weave *weaveapi.Client, address string, endChan chan<- error, scope string, withIpam, dns bool, isPluginV2 bool) (net.Listener, error) { - name := strings.TrimSuffix(path.Base(address), ".sock") - // TODO(mp) fix plugin name, as it is used to determine whether network is our - d, err := netplugin.New(dockerClient, weave, name, scope, dns, isPluginV2) + var isNetworkOur func(string) bool + if isPluginV2 { + isNetworkOur = func(driverName string) bool { + return strings.Contains(driverName, pluginV2Name) + } + } else { + name := strings.TrimSuffix(path.Base(address), ".sock") + isNetworkOur = func(driverName string) bool { + return driverName == name + } + } + + d, err := netplugin.New(dockerClient, weave, scope, dns, isPluginV2, isNetworkOur) if err != nil { return nil, err }