Merge pull request #2727 from weaveworks/issues/2397-v2-plugin
Create a V2 Docker plugin
This commit is contained in:
commit
8961041469
33 files changed
+804
-307
No files matched your search
@@ -70,3 +70,4 @@ test/coverage.*
|
||||
*qemu-*-static
|
||||
terraform.tfstate
|
||||
terraform.tfstate.backup
|
||||
prog/net-plugin/rootfs/
|
||||
+6
-3
@@ -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
|
||||
+2
-2
@@ -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
|
||||
KUBERNETES_CNI_VERSION=0.5.1
|
||||
@@ -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")
|
||||
@@ -93,36 +93,38 @@ 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
|
||||
PLUGIN_UPTODATE=.net-plugin$(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
|
||||
PLUGIN_IMAGE=$(DOCKERHUB_USER)/net-plugin
|
||||
|
||||
IMAGES=$(WEAVER_IMAGE) $(WEAVEEXEC_IMAGE) $(PLUGIN_IMAGE) $(WEAVEKUBE_IMAGE) $(WEAVENPC_IMAGE) $(WEAVEDB_IMAGE)
|
||||
IMAGES=$(WEAVER_IMAGE) $(WEAVEEXEC_IMAGE) $(WEAVEKUBE_IMAGE) $(WEAVENPC_IMAGE) $(WEAVEDB_IMAGE)
|
||||
|
||||
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
|
||||
PUSH_ML=push_ml_weave push_ml_weaveexec push_ml_plugin push_ml_weave-kube push_ml_weave-npc
|
||||
@@ -152,12 +154,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
|
||||
@@ -187,7 +189,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)/
|
||||
@@ -264,8 +266,21 @@ $(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
|
||||
# Builds Docker plugin.
|
||||
$(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)
|
||||
$(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
|
||||
-$(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)
|
||||
@@ -293,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)
|
||||
@@ -345,13 +367,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 $(PLUGIN_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)
|
||||
|
||||
|
||||
@@ -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{})
|
||||
|
||||
@@ -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 \
|
||||
|
||||
+6
-1
@@ -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))
|
||||
}
|
||||
@@ -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
|
||||
|
||||
+30
-10
@@ -28,19 +28,23 @@ type network struct {
|
||||
}
|
||||
|
||||
type driver struct {
|
||||
name string
|
||||
scope string
|
||||
docker *docker.Client
|
||||
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) (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,
|
||||
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)
|
||||
@@ -61,12 +65,27 @@ 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 &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
|
||||
}
|
||||
|
||||
// Deal with excessively-generic way the options get decoded from JSON
|
||||
func stringOptions(create *api.CreateNetworkRequest) map[string]string {
|
||||
if create.Options != nil {
|
||||
@@ -85,6 +104,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()
|
||||
@@ -173,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) {
|
||||
|
||||
+12
-4
@@ -41,11 +41,19 @@ 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.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)
|
||||
}
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/libnetwork/ipamapi"
|
||||
weaveapi "github.com/weaveworks/weave/api"
|
||||
"github.com/weaveworks/weave/common"
|
||||
"github.com/weaveworks/weave/common/docker"
|
||||
weavenet "github.com/weaveworks/weave/net"
|
||||
ipamplugin "github.com/weaveworks/weave/plugin/ipam"
|
||||
netplugin "github.com/weaveworks/weave/plugin/net"
|
||||
"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) {
|
||||
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); err != nil {
|
||||
Log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
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, dns, isPluginV2)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.Remove(address)
|
||||
defer globalListener.Close()
|
||||
}
|
||||
if meshAddress != "" {
|
||||
meshListener, err := listenAndServe(dockerClient, weave, meshAddress, endChan, "local", true, dns, isPluginV2)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.Remove(meshAddress)
|
||||
defer meshListener.Close()
|
||||
}
|
||||
|
||||
statusListener, err := weavenet.ListenUnixSocket("/home/weave/plugin-status.sock")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go serveStatus(statusListener)
|
||||
|
||||
return <-endChan
|
||||
}
|
||||
|
||||
func listenAndServe(dockerClient *docker.Client, weave *weaveapi.Client, address string, endChan chan<- error, scope string, withIpam, dns bool, isPluginV2 bool) (net.Listener, error) {
|
||||
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
|
||||
}
|
||||
|
||||
var i ipamapi.Ipam
|
||||
if withIpam {
|
||||
i = ipamplugin.NewIpam(weave)
|
||||
}
|
||||
|
||||
listener, err := weavenet.ListenUnixSocket(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 serveStatus(listener net.Listener) {
|
||||
server := &http.Server{Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintln(w, "ok")
|
||||
})}
|
||||
if err := server.Serve(listener); err != nil {
|
||||
Log.Fatalf("ListenAndServeStatus failed: %s", err)
|
||||
}
|
||||
}
|
||||
@@ -26,11 +26,17 @@ 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
|
||||
}
|
||||
|
||||
type IpamCapability interface {
|
||||
GetCapabilities() (RequiresMACAddress bool, RequiresRequestReplay bool, err error)
|
||||
}
|
||||
|
||||
type listener struct {
|
||||
d Driver
|
||||
i ipamapi.Ipam
|
||||
@@ -58,9 +64,12 @@ 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 {
|
||||
handleMethod(ipamReceiver, "GetCapabilities", listener.getIpamCapabilities)
|
||||
handleMethod(ipamReceiver, "GetDefaultAddressSpaces", listener.getDefaultAddressSpaces)
|
||||
handleMethod(ipamReceiver, "RequestPool", listener.requestPool)
|
||||
handleMethod(ipamReceiver, "ReleasePool", listener.releasePool)
|
||||
@@ -163,6 +172,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 {
|
||||
@@ -192,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{
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"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": [
|
||||
{
|
||||
"destination": "/host/proc/",
|
||||
"type": "bind",
|
||||
"source": "/proc/",
|
||||
"options": ["rbind", "rw"]
|
||||
},
|
||||
{
|
||||
"destination": "/var/run/docker.sock",
|
||||
"source": "/var/run/docker.sock",
|
||||
"type": "bind",
|
||||
"options": ["rbind"]
|
||||
},
|
||||
{
|
||||
"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": {
|
||||
"type": "host"
|
||||
},
|
||||
"workdir": ""
|
||||
}
|
||||
Executable
+66
@@ -0,0 +1,66 @@
|
||||
#!/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}
|
||||
WEAVE_DIR="/host/var/lib/weave"
|
||||
|
||||
mkdir $WEAVE_DIR || true
|
||||
|
||||
echo "Starting launch.sh"
|
||||
|
||||
# Check if the IP range overlaps anything existing on the host
|
||||
/usr/bin/weaveutil netcheck $IPALLOC_RANGE weave
|
||||
|
||||
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)
|
||||
# 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
|
||||
|
||||
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
|
||||
IPALLOC_INIT="observer"
|
||||
if [ "$IS_SWARM_MANAGER" == "1" ]; then
|
||||
IPALLOC_INIT="consensus=$(echo $SWARM_MANAGER_PEERS | wc -l)"
|
||||
fi
|
||||
fi
|
||||
|
||||
exec /home/weave/weaver $EXTRA_ARGS --port=6783 $BRIDGE_OPTIONS \
|
||||
--http-addr=$HTTP_ADDR --status-addr=$STATUS_ADDR \
|
||||
--no-dns \
|
||||
--ipalloc-range=$IPALLOC_RANGE \
|
||||
--ipalloc-init $IPALLOC_INIT \
|
||||
--nickname "$(hostname)" \
|
||||
--log-level=debug \
|
||||
--db-prefix="$WEAVE_DIR/weave" \
|
||||
--plugin-v2 \
|
||||
--plugin-mesh-socket='' \
|
||||
$(echo $SWARM_MANAGER_PEERS | tr '\n' ' ')
|
||||
@@ -1,3 +0,0 @@
|
||||
FROM DOCKERHUB_USER/weaveARCH_EXT
|
||||
ADD ./plugin /home/weave/
|
||||
ENTRYPOINT ["/home/weave/plugin"]
|
||||
@@ -1,140 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/docker/libnetwork/ipamapi"
|
||||
weaveapi "github.com/weaveworks/weave/api"
|
||||
"github.com/weaveworks/weave/common"
|
||||
"github.com/weaveworks/weave/common/docker"
|
||||
weavenet "github.com/weaveworks/weave/net"
|
||||
ipamplugin "github.com/weaveworks/weave/plugin/ipam"
|
||||
netplugin "github.com/weaveworks/weave/plugin/net"
|
||||
"github.com/weaveworks/weave/plugin/skel"
|
||||
)
|
||||
|
||||
var version = "unreleased"
|
||||
|
||||
var Log = common.Log
|
||||
|
||||
func main() {
|
||||
var (
|
||||
justVersion bool
|
||||
address string
|
||||
meshAddress string
|
||||
logLevel string
|
||||
noMulticastRoute 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(&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)
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
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())
|
||||
|
||||
err = run(dockerClient, weave, address, meshAddress)
|
||||
if err != nil {
|
||||
Log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
defer os.Remove(address)
|
||||
defer globalListener.Close()
|
||||
}
|
||||
if meshAddress != "" {
|
||||
meshListener, err := listenAndServe(dockerClient, weave, meshAddress, endChan, "local", true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.Remove(meshAddress)
|
||||
defer meshListener.Close()
|
||||
}
|
||||
|
||||
statusListener, err := weavenet.ListenUnixSocket("/home/weave/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
|
||||
}
|
||||
}
|
||||
|
||||
func listenAndServe(dockerClient *docker.Client, weave *weaveapi.Client, address string, endChan chan<- error, scope string, withIpam bool) (net.Listener, error) {
|
||||
name := strings.TrimSuffix(path.Base(address), ".sock")
|
||||
d, err := netplugin.New(dockerClient, weave, name, scope)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var i ipamapi.Ipam
|
||||
if withIpam {
|
||||
i = ipamplugin.NewIpam(weave)
|
||||
}
|
||||
|
||||
listener, err := weavenet.ListenUnixSocket(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 serveStatus(listener net.Listener) {
|
||||
server := &http.Server{Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintln(w, "ok")
|
||||
})}
|
||||
if err := server.Serve(listener); err != nil {
|
||||
Log.Fatalf("ListenAndServeStatus failed: %s", err)
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
weavetest "github.com/weaveworks/weave/testing"
|
||||
)
|
||||
|
||||
func TestMain(t *testing.T) {
|
||||
weavetest.TrimTestArgs()
|
||||
main()
|
||||
}
|
||||
@@ -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
|
||||
enablePlugin bool
|
||||
enablePluginV2 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 (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")
|
||||
|
||||
// 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,10 @@ func main() {
|
||||
go listenAndServeHTTP(statusAddr, statusMux)
|
||||
}
|
||||
|
||||
if enablePlugin || enablePluginV2 {
|
||||
go plugin.Start(httpAddr, dockerCli, pluginSocket, pluginMeshSocket, !noDNS, enablePluginV2)
|
||||
}
|
||||
|
||||
signals.SignalHandlerLoop(common.Log, router)
|
||||
}
|
||||
|
||||
|
||||
+26
-23
@@ -14,29 +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,
|
||||
"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,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,37 @@ while Weave is not running`, networkName, containers)
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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", "<plugin-name>")
|
||||
}
|
||||
|
||||
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 +115,6 @@ func newDockerClient() (*docker.Client, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to connect to docker: %s", err)
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"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
|
||||
}
|
||||
|
||||
// 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")
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
+23
-2
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
|
||||
docker_on $HOST1 run --name c1 -dt $SMALL_IMAGE /bin/sh
|
||||
weave_on $HOST1 attach --no-multicast-route c1
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
Executable
+128
@@ -0,0 +1,128 @@
|
||||
#! /bin/bash
|
||||
|
||||
. "$(dirname "$0")/config.sh"
|
||||
|
||||
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"
|
||||
|
||||
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/net-plugin" $HOST1:~/
|
||||
$SSH $HOST1<<EOF
|
||||
docker rmi $build_plugin_img 2>/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/weave true
|
||||
docker export $build_plugin_img | tar -x -C \${WORK_DIR}/rootfs
|
||||
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
|
||||
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
|
||||
EOF
|
||||
}
|
||||
|
||||
setup_worker() {
|
||||
$SSH $HOST2<<EOF
|
||||
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"
|
||||
docker plugin install --disable --grant-all-permissions $PLUGIN_NAME
|
||||
|
||||
[ -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
|
||||
EOF
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
for h in $@; do
|
||||
$SSH $h<<EOF
|
||||
sudo sed -i '/weave-ci-registry/d' /etc/hosts
|
||||
docker service rm $SERVICE || true
|
||||
docker swarm leave --force || true
|
||||
docker network rm $NETWORK || true
|
||||
docker plugin disable -f $PLUGIN_NAME || true
|
||||
docker plugin remove -f $PLUGIN_NAME || true
|
||||
EOF
|
||||
done
|
||||
}
|
||||
|
||||
wait_for_network() {
|
||||
for i in $(seq 10); do
|
||||
if docker_on $1 network inspect $2 >/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"
|
||||
|
||||
#cleanup $HOST1 $HOST2
|
||||
#exit 1
|
||||
|
||||
setup_master
|
||||
setup_worker $($SSH $HOST1 docker swarm join-token --quiet worker)
|
||||
|
||||
echo "Creating network and service..."
|
||||
|
||||
# Create network and service
|
||||
$SSH $HOST1<<EOF
|
||||
docker plugin ls
|
||||
docker network create --driver="${PLUGIN_NAME}:latest" $NETWORK || true
|
||||
# Otherwise no containers will be scheduled on host2
|
||||
sleep 20
|
||||
docker service create --name=$SERVICE --network=$NETWORK --replicas=2 nginx || true
|
||||
journalctl -r -u docker.service -n30
|
||||
EOF
|
||||
|
||||
wait_for_service $HOST1 $SERVICE 2
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
|
||||
end_suite
|
||||
+1
-1
Submodule vendor/github.com/docker/docker updated: 4dc5990d75...092cba3727.
+1
Submodule vendor/github.com/docker/go-units added at 0dadbb0345.
+1
-1
Submodule vendor/github.com/docker/libnetwork updated: ca6760d6c9...1861587d0f.
+1
-1
Submodule vendor/github.com/fsouza/go-dockerclient updated: 03cbd2b15b...364c822d28.
@@ -49,6 +49,7 @@ weave launch <same arguments as 'weave launch-router'>
|
||||
[--no-restart] [--resume] [--no-discovery] [--no-dns]
|
||||
[--ipalloc-init <mode>]
|
||||
[--ipalloc-range <cidr> [--ipalloc-default-subnet <cidr>]]
|
||||
[--plugin]
|
||||
[--log-level=debug|info|warning|error]
|
||||
<peer> ...
|
||||
launch-proxy [-H <endpoint>] [--without-dns] [--no-multicast-route]
|
||||
@@ -58,8 +59,6 @@ weave launch <same arguments as 'weave launch-router'>
|
||||
[--hostname-replacement <replacement>]
|
||||
[--rewrite-inspect]
|
||||
[--log-level=debug|info|warning|error]
|
||||
launch-plugin [--no-restart] [--no-multicast-route]
|
||||
[--log-level=debug|info|warning|error]
|
||||
|
||||
weave prime
|
||||
|
||||
@@ -90,7 +89,6 @@ weave status [targets | connections | peers | dns | ipam]
|
||||
weave stop
|
||||
stop-router
|
||||
stop-proxy
|
||||
stop-plugin
|
||||
|
||||
weave reset [--force]
|
||||
rmpeer <peer_id> ...
|
||||
@@ -163,7 +161,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 \
|
||||
@@ -262,15 +259,13 @@ 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_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
|
||||
@@ -291,6 +286,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 --"
|
||||
|
||||
@@ -372,9 +368,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
|
||||
@@ -655,8 +651,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
|
||||
|
||||
@@ -810,6 +808,25 @@ 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
|
||||
@@ -1527,6 +1544,10 @@ launch_router() {
|
||||
AWSVPC_ARGS="--awsvpc"
|
||||
AWSVPC=1
|
||||
;;
|
||||
--plugin)
|
||||
PLUGIN_ARGS="--plugin"
|
||||
ENABLE_PLUGIN=1
|
||||
;;
|
||||
*)
|
||||
ARGS="$ARGS '$(echo "$1" | sed "s|'|'\"'\"'|g")'"
|
||||
;;
|
||||
@@ -1589,6 +1610,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 \
|
||||
@@ -1598,6 +1620,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" \
|
||||
@@ -1605,6 +1628,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() {
|
||||
@@ -1612,11 +1640,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
|
||||
}
|
||||
@@ -1639,6 +1667,7 @@ populate_router() {
|
||||
}
|
||||
|
||||
stop_router() {
|
||||
! 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
|
||||
}
|
||||
@@ -1680,53 +1709,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_plugin_v2_enabled 2>/dev/null ; then
|
||||
rm -f /run/docker/plugins/weave.sock /run/docker/plugins/weavemesh.sock
|
||||
fi
|
||||
}
|
||||
@@ -1842,7 +1827,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
|
||||
@@ -1854,11 +1839,26 @@ 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
|
||||
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 <<EOF
|
||||
WARNING: 'weave create-bridge' is deprecated. Instead use 'weave attach-bridge'
|
||||
@@ -1880,6 +1880,7 @@ EOF
|
||||
else
|
||||
shift 1
|
||||
fi
|
||||
|
||||
create_bridge --without-ethtool "$@"
|
||||
;;
|
||||
attach-bridge)
|
||||
@@ -1898,15 +1899,15 @@ 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
|
||||
check_not_running_plugin_v2
|
||||
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 "$@"
|
||||
check_not_running router $CONTAINER_NAME $BASE_IMAGE
|
||||
check_not_running_plugin_v2
|
||||
launch_router "$@"
|
||||
echo $ROUTER_CONTAINER
|
||||
;;
|
||||
@@ -1924,17 +1925,10 @@ EOF
|
||||
launch-proxy)
|
||||
deprecation_warnings "$@"
|
||||
check_not_running proxy $PROXY_CONTAINER_NAME $BASE_EXEC_IMAGE
|
||||
check_not_running_plugin_v2
|
||||
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
|
||||
@@ -1976,10 +1970,14 @@ 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_plugin_v1_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 ]
|
||||
@@ -2119,7 +2117,6 @@ EOF
|
||||
;;
|
||||
stop)
|
||||
[ $# -eq 0 ] || usage
|
||||
plugin_disabled || stop_plugin
|
||||
stop_router
|
||||
stop_proxy
|
||||
;;
|
||||
@@ -2131,13 +2128,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_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=$?
|
||||
@@ -2155,7 +2148,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
|
||||
|
||||
Reference in new issue
Block a user