From 8061ea40797523b6719b682593ca358d0dd4f7dd Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Fri, 15 Jan 2016 06:21:11 +0000 Subject: [PATCH 1/4] don't attempt to delete the mesh network on plugin termination It's pointless and inconsistent. Firstly, deletion will fail if there are any attached containers. Secondly, we run the plugin with restart=always, so it will get restarted and the network re-created. Removal of the network does still happen on `weave stop|reset`, if possible. --- prog/plugin/main.go | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/prog/plugin/main.go b/prog/plugin/main.go index 01bad7f6..4da2711f 100644 --- a/prog/plugin/main.go +++ b/prog/plugin/main.go @@ -5,9 +5,7 @@ import ( "fmt" "net" "os" - "os/signal" "strings" - "syscall" "github.com/docker/libnetwork/ipamapi" go_docker "github.com/fsouza/go-dockerclient" @@ -90,22 +88,12 @@ func main() { createNetwork(dockerClient, meshNetworkName, meshAddress) } - sigChan := make(chan os.Signal, 1) - signal.Notify(sigChan, os.Interrupt, os.Kill, syscall.SIGTERM) - - 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) - globalListener.Close() - meshListener.Close() - os.Exit(1) - } + err = <-endChan + if err != nil { + Log.Errorf("Error from listener: %s", err) + globalListener.Close() + meshListener.Close() + os.Exit(1) } } From 9578798ec0fcd2c16fcbf123d7f078b3864aab0b Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Fri, 15 Jan 2016 07:12:03 +0000 Subject: [PATCH 2/4] move plugin network removal into weaveutil This does require starting containerised weaveutil with docker.sock volume mounts. --- prog/plugin/main.go | 12 --------- prog/weaveutil/main.go | 1 + prog/weaveutil/plugin_network.go | 43 ++++++++++++++++++++++++++++++++ weave | 13 +++------- 4 files changed, 48 insertions(+), 21 deletions(-) create mode 100644 prog/weaveutil/plugin_network.go diff --git a/prog/plugin/main.go b/prog/plugin/main.go index 4da2711f..62623d84 100644 --- a/prog/plugin/main.go +++ b/prog/plugin/main.go @@ -27,7 +27,6 @@ func main() { logLevel string meshNetworkName string noMulticastRoute bool - removeNetwork bool ) flag.BoolVar(&justVersion, "version", false, "print version and exit") @@ -37,7 +36,6 @@ func main() { flag.StringVar(&meshAddress, "meshsocket", "/run/docker/plugins/weavemesh.sock", "socket on which to listen in mesh mode") flag.StringVar(&meshNetworkName, "mesh-network-name", "weave", "network name to create in mesh mode") flag.BoolVar(&noMulticastRoute, "no-multicast-route", false, "do not add a multicast route to network endpoints") - flag.BoolVar(&removeNetwork, "remove-network", false, "remove mesh network and exit") flag.Parse() @@ -54,16 +52,6 @@ func main() { Log.Fatalf("unable to connect to docker: %s", err) } - if removeNetwork { - if _, err = dockerClient.Client.NetworkInfo(meshNetworkName); err == nil { - err = dockerClient.Client.RemoveNetwork(meshNetworkName) - if err != nil { - Log.Fatalf("unable to remove network: %s", err) - } - } - os.Exit(0) - } - Log.Println("Weave plugin", version, "Command line options:", os.Args[1:]) Log.Info(dockerClient.Info()) diff --git a/prog/weaveutil/main.go b/prog/weaveutil/main.go index 539e5c89..ab2187b0 100644 --- a/prog/weaveutil/main.go +++ b/prog/weaveutil/main.go @@ -16,6 +16,7 @@ func init() { "create-datapath": createDatapath, "delete-datapath": deleteDatapath, "add-datapath-interface": addDatapathInterface, + "remove-plugin-network": removePluginNetwork, } } diff --git a/prog/weaveutil/plugin_network.go b/prog/weaveutil/plugin_network.go new file mode 100644 index 00000000..012a2af6 --- /dev/null +++ b/prog/weaveutil/plugin_network.go @@ -0,0 +1,43 @@ +/* various weave docker network plugin operations */ +package main + +import ( + "fmt" + + "github.com/fsouza/go-dockerclient" +) + +func removePluginNetwork(args []string) error { + if len(args) != 1 { + cmdUsage("remove-plugin-network", "") + } + networkName := args[0] + d, err := newDockerClient() + if err != nil { + return err + } + _, err = d.NetworkInfo(networkName) + if err != nil { + // network probably doesn't exist; TODO check this better + return nil + } + err = d.RemoveNetwork(networkName) + if err != nil { + return fmt.Errorf("unable to remove network: %s", err) + } + return nil +} + +func newDockerClient() (*docker.Client, error) { + // API 1.21 is the first version that supports docker network + // commands + c, err := docker.NewVersionedClientFromEnv("1.21") + if err != nil { + return nil, fmt.Errorf("unable to connect to docker: %s", err) + } + _, err = c.Version() + if err != nil { + return nil, fmt.Errorf("unable to connect to docker: %s", err) + } + return c, nil +} diff --git a/weave b/weave index 88a88763..4ac0b049 100755 --- a/weave +++ b/weave @@ -448,7 +448,8 @@ util_op() { if command_exists weaveutil ; then weaveutil "$@" else - docker run --rm --privileged --net=host -v /proc:/hostproc -e PROCFS=/hostproc \ + docker run --rm --privileged --net=host $(docker_sock_options) \ + -v /proc:/hostproc -e PROCFS=/hostproc \ --entrypoint=/usr/bin/weaveutil $EXEC_IMAGE "$@" fi } @@ -1694,14 +1695,8 @@ plugin_disabled() { [ -n "$WEAVE_NO_PLUGIN" ] || ! check_docker_server_api_version 1.21 } -remove_plugin_network() { - docker run --rm --net=host \ - -v /var/run/docker.sock:/var/run/docker.sock \ - $PLUGIN_IMAGE --remove-network -} - stop_plugin() { - remove_plugin_network + util_op remove-plugin-network weave stop $PLUGIN_CONTAINER_NAME "Plugin" } @@ -2137,7 +2132,7 @@ EOF ;; reset) [ $# -eq 0 ] || usage - plugin_disabled || remove_plugin_network || \ + plugin_disabled || util_op remove-plugin-network weave || \ echo "WARNING: docker may hang in this state; re-launch weave and remove attached containers before shutting down" >&2 warn_if_stopping_proxy_in_env call_weave DELETE /peer >/dev/null 2>&1 || true From 31b303a419c2229d9d3a414b88864a15d72a9f79 Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Fri, 15 Jan 2016 08:10:01 +0000 Subject: [PATCH 3/4] move plugin network creation into weaveutil Note that we remove the ability to set the weavemesh network name, or disabling it altogether. This was always poorly support, since the removal operation only ever operated on the default name. The option was also not listed in the usage, though it was in the docs. --- prog/plugin/main.go | 29 ----------------------------- prog/weaveutil/main.go | 1 + prog/weaveutil/plugin_network.go | 30 ++++++++++++++++++++++++++++++ site/plugin.md | 2 -- weave | 7 +++++-- 5 files changed, 36 insertions(+), 33 deletions(-) diff --git a/prog/plugin/main.go b/prog/plugin/main.go index 62623d84..0415f4c8 100644 --- a/prog/plugin/main.go +++ b/prog/plugin/main.go @@ -5,10 +5,8 @@ import ( "fmt" "net" "os" - "strings" "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" @@ -25,7 +23,6 @@ func main() { nameserver string meshAddress string logLevel string - meshNetworkName string noMulticastRoute bool ) @@ -34,7 +31,6 @@ func main() { 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(&meshAddress, "meshsocket", "/run/docker/plugins/weavemesh.sock", "socket on which to listen in mesh mode") - flag.StringVar(&meshNetworkName, "mesh-network-name", "weave", "network name to create in mesh mode") flag.BoolVar(&noMulticastRoute, "no-multicast-route", false, "do not add a multicast route to network endpoints") flag.Parse() @@ -72,10 +68,6 @@ func main() { defer meshListener.Close() } - if meshNetworkName != "" { - createNetwork(dockerClient, meshNetworkName, meshAddress) - } - err = <-endChan if err != nil { Log.Errorf("Error from listener: %s", err) @@ -116,24 +108,3 @@ func listenAndServe(dockerClient *docker.Client, address, nameserver string, noM return listener, nil } - -func createNetwork(dockerClient *docker.Client, networkName, address string) { - if _, err := dockerClient.Client.NetworkInfo(networkName); err == nil { - Log.Printf("Docker network '%s' already exists", networkName) - } 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: networkName, - 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/prog/weaveutil/main.go b/prog/weaveutil/main.go index ab2187b0..2cdf02d7 100644 --- a/prog/weaveutil/main.go +++ b/prog/weaveutil/main.go @@ -16,6 +16,7 @@ func init() { "create-datapath": createDatapath, "delete-datapath": deleteDatapath, "add-datapath-interface": addDatapathInterface, + "create-plugin-network": createPluginNetwork, "remove-plugin-network": removePluginNetwork, } } diff --git a/prog/weaveutil/plugin_network.go b/prog/weaveutil/plugin_network.go index 012a2af6..ef9ea04a 100644 --- a/prog/weaveutil/plugin_network.go +++ b/prog/weaveutil/plugin_network.go @@ -7,6 +7,36 @@ import ( "github.com/fsouza/go-dockerclient" ) +func createPluginNetwork(args []string) error { + if len(args) != 2 { + cmdUsage("create-plugin-network", " ") + } + networkName := args[0] + driverName := args[1] + d, err := newDockerClient() + if err != nil { + return err + } + _, err = d.NetworkInfo(networkName) + if err == nil { + return nil + } + if _, ok := err.(*docker.NoSuchNetwork); !ok { + return nil // TODO is this right? + } + _, err = d.CreateNetwork( + docker.CreateNetworkOptions{ + Name: networkName, + CheckDuplicate: true, + Driver: driverName, + IPAM: docker.IPAMOptions{Driver: driverName}, + }) + if err != nil { + return fmt.Errorf("unable to create network: %s", err) + } + return nil +} + func removePluginNetwork(args []string) error { if len(args) != 1 { cmdUsage("remove-plugin-network", "") diff --git a/site/plugin.md b/site/plugin.md index 85ab3b2e..b5b449ee 100644 --- a/site/plugin.md +++ b/site/plugin.md @@ -73,8 +73,6 @@ The plugin command-line arguments are: * `--log-level=debug|info|warning|error`, which tells the plugin how much information to emit for debugging. - * `--mesh-network-name=`: set it to blank to disable creation - of a default network, or a name of your own choice. * `--no-multicast-route`: stop weave adding a static IP route for multicast traffic on its interface diff --git a/weave b/weave index 4ac0b049..2de5a231 100755 --- a/weave +++ b/weave @@ -1683,12 +1683,15 @@ launch_plugin_if_not_running() { # Any other kind of error code from check_not_running is a failure. [ $retval -gt 0 ] && return $retval - PLUGIN_CONTAINER=$(docker run --privileged -d --name=$PLUGIN_CONTAINER_NAME \ + if ! PLUGIN_CONTAINER=$(docker run --privileged -d --name=$PLUGIN_CONTAINER_NAME \ --restart=always \ --net=host \ $(docker_sock_options) \ -v /run/docker/plugins:/run/docker/plugins \ - $PLUGIN_IMAGE "$@") + $PLUGIN_IMAGE "$@") ; then + return 1 + fi + util_op create-plugin-network weave weavemesh } plugin_disabled() { From d770532b0841e2fa8510d681851d8a6b0911e375 Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Fri, 15 Jan 2016 08:52:23 +0000 Subject: [PATCH 4/4] improve error handling --- prog/weaveutil/plugin_network.go | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/prog/weaveutil/plugin_network.go b/prog/weaveutil/plugin_network.go index ef9ea04a..a13d85f8 100644 --- a/prog/weaveutil/plugin_network.go +++ b/prog/weaveutil/plugin_network.go @@ -17,13 +17,6 @@ func createPluginNetwork(args []string) error { if err != nil { return err } - _, err = d.NetworkInfo(networkName) - if err == nil { - return nil - } - if _, ok := err.(*docker.NoSuchNetwork); !ok { - return nil // TODO is this right? - } _, err = d.CreateNetwork( docker.CreateNetworkOptions{ Name: networkName, @@ -31,8 +24,14 @@ func createPluginNetwork(args []string) error { Driver: driverName, IPAM: docker.IPAMOptions{Driver: driverName}, }) - if err != nil { - return fmt.Errorf("unable to create network: %s", err) + if err != docker.ErrNetworkAlreadyExists && err != nil { + // Despite appearances to the contrary, CreateNetwork does + // sometimes(always?) *not* return ErrNetworkAlreadyExists + // when the network already exists. Hence we need to check for + // this explicitly. + if _, err2 := d.NetworkInfo(networkName); err2 != nil { + return fmt.Errorf("unable to create network: %s", err) + } } return nil } @@ -46,13 +45,8 @@ func removePluginNetwork(args []string) error { if err != nil { return err } - _, err = d.NetworkInfo(networkName) - if err != nil { - // network probably doesn't exist; TODO check this better - return nil - } err = d.RemoveNetwork(networkName) - if err != nil { + if _, ok := err.(*docker.NoSuchNetwork); !ok && err != nil { return fmt.Errorf("unable to remove network: %s", err) } return nil