diff --git a/plugin/plugin.go b/plugin/plugin.go index ddbc7327..c1890193 100644 --- a/plugin/plugin.go +++ b/plugin/plugin.go @@ -18,47 +18,69 @@ import ( const ( pluginV2Name = "net-plugin" + defaultNetwork = "weave" MulticastOption = netplugin.MulticastOption ) var Log = common.Log -func Start(weaveAPIAddr string, dockerClient *docker.Client, address string, meshAddress string, dns bool, isPluginV2, forceMulticast bool, defaultSubnet string, ready func()) { +type Config struct { + Socket string + MeshSocket string + Enable bool + EnableV2 bool + EnableV2Multicast bool + DNS bool + DefaultSubnet string +} + +type Plugin struct { + Config +} + +func NewPlugin(config Config) *Plugin { + if !config.Enable && !config.EnableV2 { + return nil + } + plugin := &Plugin{Config: config} + return plugin +} + +func (plugin *Plugin) Start(weaveAPIAddr string, dockerClient *docker.Client, ready func()) { 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, dns, isPluginV2, forceMulticast, defaultSubnet, ready); err != nil { + if err := plugin.run(dockerClient, weave, ready); err != nil { Log.Fatal(err) } } -func run(dockerClient *docker.Client, weave *weaveapi.Client, address, meshAddress string, dns, isPluginV2, forceMulticast bool, defaultSubnet string, ready func()) error { +func (plugin *Plugin) run(dockerClient *docker.Client, weave *weaveapi.Client, ready func()) error { endChan := make(chan error, 1) - if address != "" { - globalListener, err := listenAndServe(dockerClient, weave, address, endChan, "global", false, dns, isPluginV2, forceMulticast) + if plugin.Socket != "" { + globalListener, err := listenAndServe(dockerClient, weave, plugin.Socket, endChan, "global", false, plugin.DNS, plugin.EnableV2, plugin.EnableV2Multicast) if err != nil { return err } - defer os.Remove(address) + defer os.Remove(plugin.Socket) defer globalListener.Close() } - if meshAddress != "" { - meshListener, err := listenAndServe(dockerClient, weave, meshAddress, endChan, "local", true, dns, isPluginV2, forceMulticast) + if plugin.MeshSocket != "" { + meshListener, err := listenAndServe(dockerClient, weave, plugin.MeshSocket, endChan, "local", true, plugin.DNS, plugin.EnableV2, plugin.EnableV2Multicast) if err != nil { return err } - defer os.Remove(meshAddress) + defer os.Remove(plugin.MeshSocket) defer meshListener.Close() - } - if !isPluginV2 { - Log.Println("Creating default 'weave' network") - options := map[string]interface{}{MulticastOption: "true"} - // TODO: the driver name should be extracted from pluginMeshSocket - dockerClient.EnsureNetwork("weave", "weavemesh", defaultSubnet, options) + if !plugin.EnableV2 { + Log.Printf("Creating default %q network", defaultNetwork) + options := map[string]interface{}{MulticastOption: "true"} + dockerClient.EnsureNetwork(defaultNetwork, pluginNameFromAddress(plugin.MeshSocket), plugin.DefaultSubnet, options) + } } ready() @@ -70,7 +92,7 @@ func listenAndServe(dockerClient *docker.Client, weave *weaveapi.Client, address if isPluginV2 { name = pluginV2Name } else { - name = strings.TrimSuffix(path.Base(address), ".sock") + name = pluginNameFromAddress(address) } d, err := netplugin.New(dockerClient, weave, name, scope, dns, isPluginV2, forceMulticast) @@ -95,3 +117,8 @@ func listenAndServe(dockerClient *docker.Client, weave *weaveapi.Client, address return listener, nil } + +// Take a socket address like "/run/docker/plugins/weavemesh.sock" and extract the plugin name "weavemesh" +func pluginNameFromAddress(address string) string { + return strings.TrimSuffix(path.Base(address), ".sock") +} diff --git a/plugin/status.go b/plugin/status.go new file mode 100644 index 00000000..bdaf894c --- /dev/null +++ b/plugin/status.go @@ -0,0 +1,19 @@ +package plugin + +type Status struct { + Config Config + DriverName string + MeshDriverName string `json:"MeshDriverName,omitempty"` +} + +func (plugin *Plugin) NewStatus() *Status { + if plugin == nil { + return nil + } + status := &Status{ + DriverName: pluginNameFromAddress(plugin.Socket), + MeshDriverName: pluginNameFromAddress(plugin.MeshSocket), + Config: plugin.Config, + } + return status +} diff --git a/prog/weaver/http.go b/prog/weaver/http.go index f18ac745..ce59a843 100644 --- a/prog/weaver/http.go +++ b/prog/weaver/http.go @@ -17,6 +17,8 @@ import ( "github.com/weaveworks/weave/ipam" "github.com/weaveworks/weave/nameserver" "github.com/weaveworks/weave/net/address" + "github.com/weaveworks/weave/plugin" + "github.com/weaveworks/weave/proxy" weave "github.com/weaveworks/weave/router" ) @@ -203,6 +205,20 @@ var statusTemplate = defTemplate("status", `\ TTL: {{.DNS.TTL}} Entries: {{countDNSEntries .DNS.Entries}} {{end}}\ +{{if .Proxy}}\ + + Service: proxy + Address: {{printList .Proxy.Addresses}} +{{end}}\ +{{if .Plugin}}\ + +{{if .Plugin.Config.EnableV2}}\ + Service: plugin (v2) +{{else}}\ + Service: plugin (legacy) + DriverName: {{.Plugin.DriverName}} +{{end}}\ +{{end}}\ `) var targetsTemplate = defTemplate("targetsTemplate", `\ @@ -280,10 +296,12 @@ type WeaveStatus struct { Router *weave.NetworkRouterStatus `json:"Router,omitempty"` IPAM *ipam.Status `json:"IPAM,omitempty"` DNS *nameserver.Status `json:"DNS,omitempty"` + Proxy *proxy.Status `json:"Proxy,omitempty"` + Plugin *plugin.Status `json:"Plugin,omitempty"` } // Read-only functions, suitable for exposing on an unprotected socket -func HandleHTTP(muxRouter *mux.Router, version string, router *weave.NetworkRouter, allocator *ipam.Allocator, defaultSubnet address.CIDR, ns *nameserver.Nameserver, dnsserver *nameserver.DNSServer, waitReady *common.WaitGroup) { +func HandleHTTP(muxRouter *mux.Router, version string, router *weave.NetworkRouter, allocator *ipam.Allocator, defaultSubnet address.CIDR, ns *nameserver.Nameserver, dnsserver *nameserver.DNSServer, prxy *proxy.Proxy, plugin *plugin.Plugin, waitReady *common.WaitGroup) { status := func() WeaveStatus { return WeaveStatus{ waitReady.IsDone(), @@ -291,7 +309,10 @@ func HandleHTTP(muxRouter *mux.Router, version string, router *weave.NetworkRout versionCheck(), weave.NewNetworkRouterStatus(router), ipam.NewStatus(allocator, defaultSubnet), - nameserver.NewStatus(ns, dnsserver)} + nameserver.NewStatus(ns, dnsserver), + proxy.NewStatus(prxy), + plugin.NewStatus(), + } } muxRouter.Methods("GET").Path("/report").Headers("Accept", "application/json").HandlerFunc( func(w http.ResponseWriter, r *http.Request) { diff --git a/prog/weaver/main.go b/prog/weaver/main.go index 7e7d5dcf..51f1df97 100644 --- a/prog/weaver/main.go +++ b/prog/weaver/main.go @@ -132,40 +132,36 @@ func main() { runtime.GOMAXPROCS(procs) var ( - justVersion bool - config mesh.Config - bridgeConfig weavenet.BridgeConfig - networkConfig weave.NetworkConfig - protocolMinVersion int - resume bool - routerName string - nickName string - password string - pktdebug bool - logLevel = "info" - prof string - bufSzMB int - noDiscovery bool - httpAddr string - statusAddr string - ipamConfig ipamConfig - dockerAPI string - peers []string - noDNS bool - dnsConfig dnsConfig - trustedSubnetStr string - dbPrefix string - hostRoot string - procPath string - discoveryEndpoint string - token string - advertiseAddress string - pluginSocket string - pluginMeshSocket string - enablePlugin bool - enablePluginV2 bool - enablePluginV2Multicast bool - defaultDockerHost = getenvOrDefault("DOCKER_HOST", "unix:///var/run/docker.sock") + justVersion bool + config mesh.Config + bridgeConfig weavenet.BridgeConfig + networkConfig weave.NetworkConfig + protocolMinVersion int + resume bool + routerName string + nickName string + password string + pktdebug bool + logLevel = "info" + prof string + bufSzMB int + noDiscovery bool + httpAddr string + statusAddr string + ipamConfig ipamConfig + dockerAPI string + peers []string + noDNS bool + dnsConfig dnsConfig + trustedSubnetStr string + dbPrefix string + hostRoot string + procPath string + discoveryEndpoint string + token string + advertiseAddress string + pluginConfig plugin.Config + defaultDockerHost = getenvOrDefault("DOCKER_HOST", "unix:///var/run/docker.sock") ) mflag.BoolVar(&justVersion, []string{"#version", "-version"}, false, "print version and exit") @@ -211,11 +207,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 (v1)") - mflag.BoolVar(&enablePluginV2, []string{"-plugin-v2"}, false, "enable Docker plugin (v2)") - mflag.BoolVar(&enablePluginV2Multicast, []string{"-plugin-v2-multicast"}, false, "enable multicast for 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") + mflag.BoolVar(&pluginConfig.Enable, []string{"-plugin"}, false, "enable Docker plugin (v1)") + mflag.BoolVar(&pluginConfig.EnableV2, []string{"-plugin-v2"}, false, "enable Docker plugin (v2)") + mflag.BoolVar(&pluginConfig.EnableV2Multicast, []string{"-plugin-v2-multicast"}, false, "enable multicast for Docker plugin (v2)") + mflag.StringVar(&pluginConfig.Socket, []string{"-plugin-socket"}, "/run/docker/plugins/weave.sock", "plugin socket on which to listen") + mflag.StringVar(&pluginConfig.MeshSocket, []string{"-plugin-mesh-socket"}, "/run/docker/plugins/weavemesh.sock", "plugin socket on which to listen in mesh mode") proxyConfig := configureProxy(version, defaultDockerHost) if bridgeConfig.AWSVPC { @@ -427,6 +423,10 @@ func main() { } checkFatal(router.CreateRestartSentinel()) + pluginConfig.DNS = !noDNS + pluginConfig.DefaultSubnet = defaultSubnet.String() + plugin := plugin.NewPlugin(pluginConfig) + // The weave script always waits for a status call to succeed, // so there is no point in doing "weave launch --http-addr ''". // This is here to support stand-alone use of weaver. @@ -439,7 +439,7 @@ func main() { ns.HandleHTTP(muxRouter, dockerCli) } router.HandleHTTP(muxRouter) - HandleHTTP(muxRouter, version, router, allocator, defaultSubnet, ns, dnsserver, &waitReady) + HandleHTTP(muxRouter, version, router, allocator, defaultSubnet, ns, dnsserver, proxy, plugin, &waitReady) HandleHTTPPeer(muxRouter, allocator, discoveryEndpoint, token, name.String()) muxRouter.Methods("GET").Path("/metrics").Handler(metricsHandler(router, allocator, ns, dnsserver)) if proxy != nil { @@ -452,7 +452,7 @@ func main() { if statusAddr != "" { muxRouter := mux.NewRouter() - HandleHTTP(muxRouter, version, router, allocator, defaultSubnet, ns, dnsserver, &waitReady) + HandleHTTP(muxRouter, version, router, allocator, defaultSubnet, ns, dnsserver, proxy, plugin, &waitReady) muxRouter.Methods("GET").Path("/metrics").Handler(metricsHandler(router, allocator, ns, dnsserver)) statusMux := http.NewServeMux() statusMux.Handle("/", muxRouter) @@ -460,8 +460,8 @@ func main() { go listenAndServeHTTP(statusAddr, statusMux) } - if enablePlugin || enablePluginV2 { - go plugin.Start(httpAddr, dockerCli, pluginSocket, pluginMeshSocket, !noDNS, enablePluginV2, enablePluginV2Multicast, defaultSubnet.String(), waitReady.Add()) + if plugin != nil { + go plugin.Start(httpAddr, dockerCli, waitReady.Add()) } if bridgeConfig.AWSVPC { diff --git a/proxy/status.go b/proxy/status.go new file mode 100644 index 00000000..802ed88c --- /dev/null +++ b/proxy/status.go @@ -0,0 +1,15 @@ +package proxy + +type Status struct { + Addresses []string +} + +func NewStatus(proxy *Proxy) *Status { + if proxy == nil { + return nil + } + status := &Status{ + Addresses: proxy.normalisedAddrs, + } + return status +} diff --git a/weave b/weave index 4034599d..29a39b88 100755 --- a/weave +++ b/weave @@ -581,25 +581,6 @@ attach() { # 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 @@ -1310,7 +1291,7 @@ launch() { } stop() { - ! is_plugin_v1_enabled || util_op remove-plugin-network weave || true + util_op remove-plugin-network weave || true warn_if_stopping_proxy_in_env docker stop $CONTAINER_NAME >/dev/null 2>&1 || echo "Weave is not running." >&2 # In case user has upgraded from /dev/null 2>&1 ; then + echo "Weave Net is already running" >&2 + exit 1 + fi # Plugin and proxy are started by default. Should users additionally pass --plugin=false or --proxy=false, their overrides will take precedence when parsed by Go. launch --plugin --proxy "$@" echo "$WEAVE_CONTAINER" @@ -1455,20 +1437,6 @@ case "$COMMAND" in echo "Invalid 'weave status' sub-command: $SUB_COMMAND" >&2 usage fi - if [ -z "$SUB_STATUS" ] && PROXY_ADDRS=$(proxy_addrs 2>/dev/null) ; then - echo - echo " Service: proxy" - echo " Address: $PROXY_ADDRS" - fi - if [ -z "$SUB_STATUS" ] && is_plugin_v1_enabled ; then - echo - echo " Service: plugin (v1)" - echo " DriverName: weave" - elif [ -z "$SUB_STATUS" ] && PLUGIN_FULL_NAME=$(is_plugin_v2_enabled) ; then - echo - echo " Service: plugin (v2)" - echo " DriverName: $PLUGIN_FULL_NAME" - fi [ -n "$SUB_STATUS" ] || echo [ $res -eq 0 ] ;;