From b709cdeab532df260b3d8a42f78dc5ce23012018 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Sun, 29 Nov 2015 17:59:26 +0000 Subject: [PATCH] Create local and global network from the same driver and create local-scope weave network by default on `weave launch` --- prog/plugin/main.go | 125 +++++++++++++++++++++++++++++++++----------- weave | 24 ++++++++- 2 files changed, 117 insertions(+), 32 deletions(-) diff --git a/prog/plugin/main.go b/prog/plugin/main.go index 71d8a3ac..3c3b97af 100644 --- a/prog/plugin/main.go +++ b/prog/plugin/main.go @@ -6,8 +6,11 @@ import ( "net" "os" "os/signal" + "strings" "syscall" + "github.com/docker/libnetwork/ipamapi" + go_docker "github.com/fsouza/go-dockerclient" . "github.com/weaveworks/weave/common" "github.com/weaveworks/weave/common/docker" ipamplugin "github.com/weaveworks/weave/plugin/ipam" @@ -17,20 +20,26 @@ import ( var version = "(unreleased version)" +const ( + meshNetworkName = "weave" +) + func main() { var ( - justVersion bool - address string - nameserver string - logLevel string - scope string + justVersion bool + address string + nameserver string + meshAddress string + logLevel string + createDefault bool ) flag.BoolVar(&justVersion, "version", false, "print version and exit") flag.StringVar(&logLevel, "log-level", "info", "logging level (debug, info, warning, error)") flag.StringVar(&address, "socket", "/run/docker/plugins/weave.sock", "socket on which to listen") flag.StringVar(&nameserver, "nameserver", "", "nameserver to provide to containers") - flag.StringVar(&scope, "scope", "global", "plugin scope (local or global)") + flag.StringVar(&meshAddress, "meshsocket", "", "socket on which to listen for mesh mode") + flag.BoolVar(&createDefault, "create-default-network", false, "create default network") flag.Parse() @@ -39,53 +48,107 @@ func main() { os.Exit(0) } + if createDefault && meshAddress == "" { + meshAddress = "/run/docker/plugins/weavemesh.sock" + } SetLogLevel(logLevel) - Log.Println("Weave plugin", version, "Command line options:", os.Args) + Log.Println("Weave plugin", version, "Command line options:", os.Args[1:]) dockerClient, err := docker.NewClient("unix:///var/run/docker.sock") if err != nil { Log.Fatalf("unable to connect to docker: %s", err) } - d, err := netplugin.New(dockerClient, version, nameserver, scope) - if err != nil { - Log.Fatalf("unable to create driver: %s", err) + var globalListener, meshListener net.Listener + endChan := make(chan error, 1) + if address != "" { + globalListener, err := listenAndServe(dockerClient, address, nameserver, endChan, "global", false) + if err != nil { + Log.Fatalf("unable to create driver: %s", err) + } + defer globalListener.Close() + } + if meshAddress != "" { + meshListener, err := listenAndServe(dockerClient, meshAddress, nameserver, endChan, "local", true) + if err != nil { + Log.Fatalf("unable to create driver: %s", err) + } + defer meshListener.Close() } - i, err := ipamplugin.NewIpam(dockerClient, version) - if err != nil { - Log.Fatalf("unable to create driver: %s", err) + if createDefault { + createNetwork(dockerClient, meshAddress) } - var listener net.Listener - - // remove socket from last invocation - if err := os.Remove(address); err != nil && !os.IsNotExist(err) { - Log.Fatal(err) - } - listener, err = net.Listen("unix", address) - if err != nil { - Log.Fatal(err) - } - defer listener.Close() - sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, os.Interrupt, os.Kill, syscall.SIGTERM) - endChan := make(chan error, 1) - go func() { - endChan <- skel.Listen(listener, d, i) - }() - select { case sig := <-sigChan: Log.Debugf("Caught signal %s; shutting down", sig) + if err := dockerClient.Client.RemoveNetwork(meshNetworkName); err != nil { + Log.Fatal(err) + } case err := <-endChan: if err != nil { Log.Errorf("Error from listener: %s", err) - listener.Close() + globalListener.Close() + meshListener.Close() os.Exit(1) } } } + +func listenAndServe(dockerClient *docker.Client, address, nameserver string, endChan chan<- error, scope string, withIpam bool) (net.Listener, error) { + d, err := netplugin.New(dockerClient, version, nameserver, scope) + if err != nil { + return nil, err + } + + var i ipamapi.Ipam + if withIpam { + if i, err = ipamplugin.NewIpam(dockerClient, version); err != nil { + return nil, err + } + } + + var listener net.Listener + + // remove sockets from last invocation + if err := os.Remove(address); err != nil && !os.IsNotExist(err) { + return nil, err + } + listener, err = net.Listen("unix", address) + if err != nil { + return nil, err + } + Log.Printf("Listening on %s for %s scope", address, scope) + + go func() { + endChan <- skel.Listen(listener, d, i) + }() + + return listener, nil +} + +func createNetwork(dockerClient *docker.Client, address string) { + if _, err := dockerClient.Client.NetworkInfo(meshNetworkName); err == nil { + Log.Printf("Docker network '%s' already exists", meshNetworkName) + } else if _, ok := err.(*go_docker.NoSuchNetwork); ok { + driverName := strings.TrimSuffix(address, ".sock") + if i := strings.LastIndex(driverName, "/"); i >= 0 { + driverName = driverName[i+1:] + } + options := go_docker.CreateNetworkOptions{ + Name: meshNetworkName, + CheckDuplicate: true, + Driver: driverName, + IPAM: go_docker.IPAMOptions{Driver: driverName}, + } + _, err := dockerClient.Client.CreateNetwork(options) + if err != nil { + Log.Fatalf("Error creating network: %s", err) + } + } +} diff --git a/weave b/weave index 38d862d5..ce795ca9 100755 --- a/weave +++ b/weave @@ -111,6 +111,7 @@ 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 \ @@ -152,6 +153,22 @@ check_docker_version() { fi } +check_docker_server_api_version() { + # Cope with various versions of `docker version` output format + if ! DOCKER_API_VERSION=$(docker version -f '{{.Server.APIVersion}}' 2> /dev/null ) ; then + if ! DOCKER_API_VERSION=$(docker version -f '{{.Server.ApiVersion}}' 2> /dev/null ) ; then + if ! DOCKER_API_VERSION=$(docker version | sed -n -e 's|^Server API version: *\([0-9][0-9]*\.[0-9][0-9]\).*|\1|p') ; then + echo "ERROR: Unable to determine docker version" >&2 + exit 1 + fi + fi + fi + + if version_lt ${DOCKER_API_VERSION}.0 ${1}.0 ; then + return 1 + fi +} + enforce_docker_bridge_addr_assign_type() { if ! ADDR_ASSIGN_TYPE=$(cat /sys/class/net/$DOCKER_BRIDGE/addr_assign_type 2>/dev/null) ; then echo "Could not determine address assignment type of $DOCKER_BRIDGE" >&2 @@ -1812,6 +1829,10 @@ EOF COMMON_ARGS=$(common_launch_args "$@") launch_router "$@" launch_proxy $COMMON_ARGS + if [ -z $WEAVE_NO_PLUGIN ] && check_docker_server_api_version 1.21 ; then + check_not_running $PLUGIN_CONTAINER_NAME $BASE_PLUGIN_IMAGE + launch_plugin $COMMON_ARGS --create-default-network + fi ;; launch-router) deprecation_warnings "$@" @@ -2088,6 +2109,7 @@ EOF ;; stop) [ $# -eq 0 ] || usage + stop_plugin stop_router stop_proxy ;; @@ -2107,7 +2129,7 @@ EOF [ $# -eq 0 ] || usage warn_if_stopping_proxy_in_env call_weave DELETE /peer >/dev/null 2>&1 || true - for NAME in $CONTAINER_NAME $PROXY_CONTAINER_NAME ; do + for NAME in $PLUGIN_CONTAINER_NAME $CONTAINER_NAME $PROXY_CONTAINER_NAME ; do docker stop $NAME >/dev/null 2>&1 || true docker rm -f $NAME >/dev/null 2>&1 || true done