Explorar o código

Make graphdriver plugin use plugin BasePath

Also enables `PropagatedMount` for graphdrivers.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
(cherry picked from commit 500210475f6d841b2eacb42fb495e90108db2733)
Signed-off-by: Victor Vieux <vieux@docker.com>
Brian Goff %!s(int64=8) %!d(string=hai) anos
pai
achega
caaee2ebab

+ 4 - 2
daemon/graphdriver/driver.go

@@ -154,10 +154,12 @@ func GetDriver(name, home string, options []string, uidMaps, gidMaps []idtools.I
 	if initFunc, exists := drivers[name]; exists {
 	if initFunc, exists := drivers[name]; exists {
 		return initFunc(filepath.Join(home, name), options, uidMaps, gidMaps)
 		return initFunc(filepath.Join(home, name), options, uidMaps, gidMaps)
 	}
 	}
-	if pluginDriver, err := lookupPlugin(name, home, options, pg); err == nil {
+
+	pluginDriver, err := lookupPlugin(name, home, options, pg)
+	if err == nil {
 		return pluginDriver, nil
 		return pluginDriver, nil
 	}
 	}
-	logrus.Errorf("Failed to GetDriver graph %s %s", name, home)
+	logrus.WithError(err).WithField("driver", name).WithField("home-dir", home).Error("Failed to GetDriver graph")
 	return nil, ErrNotSupported
 	return nil, ErrNotSupported
 }
 }
 
 

+ 9 - 1
daemon/graphdriver/plugin.go

@@ -6,6 +6,7 @@ import (
 	"path/filepath"
 	"path/filepath"
 
 
 	"github.com/docker/docker/pkg/plugingetter"
 	"github.com/docker/docker/pkg/plugingetter"
+	"github.com/docker/docker/plugin/v2"
 )
 )
 
 
 type pluginClient interface {
 type pluginClient interface {
@@ -26,6 +27,13 @@ func lookupPlugin(name, home string, opts []string, pg plugingetter.PluginGetter
 }
 }
 
 
 func newPluginDriver(name, home string, opts []string, pl plugingetter.CompatPlugin) (Driver, error) {
 func newPluginDriver(name, home string, opts []string, pl plugingetter.CompatPlugin) (Driver, error) {
-	proxy := &graphDriverProxy{name, pl.Client(), pl}
+	if !pl.IsV1() {
+		if p, ok := pl.(*v2.Plugin); ok {
+			if p.PropagatedMount != "" {
+				home = p.PluginObj.Config.PropagatedMount
+			}
+		}
+	}
+	proxy := &graphDriverProxy{name, pl}
 	return proxy, proxy.Init(filepath.Join(home, name), opts)
 	return proxy, proxy.Init(filepath.Join(home, name), opts)
 }
 }

+ 18 - 18
daemon/graphdriver/proxy.go

@@ -4,15 +4,15 @@ import (
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
 	"io"
 	"io"
+	"path/filepath"
 
 
 	"github.com/docker/docker/pkg/archive"
 	"github.com/docker/docker/pkg/archive"
 	"github.com/docker/docker/pkg/plugingetter"
 	"github.com/docker/docker/pkg/plugingetter"
 )
 )
 
 
 type graphDriverProxy struct {
 type graphDriverProxy struct {
-	name   string
-	client pluginClient
-	p      plugingetter.CompatPlugin
+	name string
+	p    plugingetter.CompatPlugin
 }
 }
 
 
 type graphDriverRequest struct {
 type graphDriverRequest struct {
@@ -48,7 +48,7 @@ func (d *graphDriverProxy) Init(home string, opts []string) error {
 		Opts: opts,
 		Opts: opts,
 	}
 	}
 	var ret graphDriverResponse
 	var ret graphDriverResponse
-	if err := d.client.Call("GraphDriver.Init", args, &ret); err != nil {
+	if err := d.p.Client().Call("GraphDriver.Init", args, &ret); err != nil {
 		return err
 		return err
 	}
 	}
 	if ret.Err != "" {
 	if ret.Err != "" {
@@ -73,7 +73,7 @@ func (d *graphDriverProxy) CreateReadWrite(id, parent string, opts *CreateOpts)
 		MountLabel: mountLabel,
 		MountLabel: mountLabel,
 	}
 	}
 	var ret graphDriverResponse
 	var ret graphDriverResponse
-	if err := d.client.Call("GraphDriver.CreateReadWrite", args, &ret); err != nil {
+	if err := d.p.Client().Call("GraphDriver.CreateReadWrite", args, &ret); err != nil {
 		return err
 		return err
 	}
 	}
 	if ret.Err != "" {
 	if ret.Err != "" {
@@ -93,7 +93,7 @@ func (d *graphDriverProxy) Create(id, parent string, opts *CreateOpts) error {
 		MountLabel: mountLabel,
 		MountLabel: mountLabel,
 	}
 	}
 	var ret graphDriverResponse
 	var ret graphDriverResponse
-	if err := d.client.Call("GraphDriver.Create", args, &ret); err != nil {
+	if err := d.p.Client().Call("GraphDriver.Create", args, &ret); err != nil {
 		return err
 		return err
 	}
 	}
 	if ret.Err != "" {
 	if ret.Err != "" {
@@ -105,7 +105,7 @@ func (d *graphDriverProxy) Create(id, parent string, opts *CreateOpts) error {
 func (d *graphDriverProxy) Remove(id string) error {
 func (d *graphDriverProxy) Remove(id string) error {
 	args := &graphDriverRequest{ID: id}
 	args := &graphDriverRequest{ID: id}
 	var ret graphDriverResponse
 	var ret graphDriverResponse
-	if err := d.client.Call("GraphDriver.Remove", args, &ret); err != nil {
+	if err := d.p.Client().Call("GraphDriver.Remove", args, &ret); err != nil {
 		return err
 		return err
 	}
 	}
 	if ret.Err != "" {
 	if ret.Err != "" {
@@ -120,20 +120,20 @@ func (d *graphDriverProxy) Get(id, mountLabel string) (string, error) {
 		MountLabel: mountLabel,
 		MountLabel: mountLabel,
 	}
 	}
 	var ret graphDriverResponse
 	var ret graphDriverResponse
-	if err := d.client.Call("GraphDriver.Get", args, &ret); err != nil {
+	if err := d.p.Client().Call("GraphDriver.Get", args, &ret); err != nil {
 		return "", err
 		return "", err
 	}
 	}
 	var err error
 	var err error
 	if ret.Err != "" {
 	if ret.Err != "" {
 		err = errors.New(ret.Err)
 		err = errors.New(ret.Err)
 	}
 	}
-	return ret.Dir, err
+	return filepath.Join(d.p.BasePath(), ret.Dir), err
 }
 }
 
 
 func (d *graphDriverProxy) Put(id string) error {
 func (d *graphDriverProxy) Put(id string) error {
 	args := &graphDriverRequest{ID: id}
 	args := &graphDriverRequest{ID: id}
 	var ret graphDriverResponse
 	var ret graphDriverResponse
-	if err := d.client.Call("GraphDriver.Put", args, &ret); err != nil {
+	if err := d.p.Client().Call("GraphDriver.Put", args, &ret); err != nil {
 		return err
 		return err
 	}
 	}
 	if ret.Err != "" {
 	if ret.Err != "" {
@@ -145,7 +145,7 @@ func (d *graphDriverProxy) Put(id string) error {
 func (d *graphDriverProxy) Exists(id string) bool {
 func (d *graphDriverProxy) Exists(id string) bool {
 	args := &graphDriverRequest{ID: id}
 	args := &graphDriverRequest{ID: id}
 	var ret graphDriverResponse
 	var ret graphDriverResponse
-	if err := d.client.Call("GraphDriver.Exists", args, &ret); err != nil {
+	if err := d.p.Client().Call("GraphDriver.Exists", args, &ret); err != nil {
 		return false
 		return false
 	}
 	}
 	return ret.Exists
 	return ret.Exists
@@ -154,7 +154,7 @@ func (d *graphDriverProxy) Exists(id string) bool {
 func (d *graphDriverProxy) Status() [][2]string {
 func (d *graphDriverProxy) Status() [][2]string {
 	args := &graphDriverRequest{}
 	args := &graphDriverRequest{}
 	var ret graphDriverResponse
 	var ret graphDriverResponse
-	if err := d.client.Call("GraphDriver.Status", args, &ret); err != nil {
+	if err := d.p.Client().Call("GraphDriver.Status", args, &ret); err != nil {
 		return nil
 		return nil
 	}
 	}
 	return ret.Status
 	return ret.Status
@@ -165,7 +165,7 @@ func (d *graphDriverProxy) GetMetadata(id string) (map[string]string, error) {
 		ID: id,
 		ID: id,
 	}
 	}
 	var ret graphDriverResponse
 	var ret graphDriverResponse
-	if err := d.client.Call("GraphDriver.GetMetadata", args, &ret); err != nil {
+	if err := d.p.Client().Call("GraphDriver.GetMetadata", args, &ret); err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
 	if ret.Err != "" {
 	if ret.Err != "" {
@@ -184,7 +184,7 @@ func (d *graphDriverProxy) Cleanup() error {
 
 
 	args := &graphDriverRequest{}
 	args := &graphDriverRequest{}
 	var ret graphDriverResponse
 	var ret graphDriverResponse
-	if err := d.client.Call("GraphDriver.Cleanup", args, &ret); err != nil {
+	if err := d.p.Client().Call("GraphDriver.Cleanup", args, &ret); err != nil {
 		return nil
 		return nil
 	}
 	}
 	if ret.Err != "" {
 	if ret.Err != "" {
@@ -198,7 +198,7 @@ func (d *graphDriverProxy) Diff(id, parent string) (io.ReadCloser, error) {
 		ID:     id,
 		ID:     id,
 		Parent: parent,
 		Parent: parent,
 	}
 	}
-	body, err := d.client.Stream("GraphDriver.Diff", args)
+	body, err := d.p.Client().Stream("GraphDriver.Diff", args)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -211,7 +211,7 @@ func (d *graphDriverProxy) Changes(id, parent string) ([]archive.Change, error)
 		Parent: parent,
 		Parent: parent,
 	}
 	}
 	var ret graphDriverResponse
 	var ret graphDriverResponse
-	if err := d.client.Call("GraphDriver.Changes", args, &ret); err != nil {
+	if err := d.p.Client().Call("GraphDriver.Changes", args, &ret); err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
 	if ret.Err != "" {
 	if ret.Err != "" {
@@ -223,7 +223,7 @@ func (d *graphDriverProxy) Changes(id, parent string) ([]archive.Change, error)
 
 
 func (d *graphDriverProxy) ApplyDiff(id, parent string, diff io.Reader) (int64, error) {
 func (d *graphDriverProxy) ApplyDiff(id, parent string, diff io.Reader) (int64, error) {
 	var ret graphDriverResponse
 	var ret graphDriverResponse
-	if err := d.client.SendFile(fmt.Sprintf("GraphDriver.ApplyDiff?id=%s&parent=%s", id, parent), diff, &ret); err != nil {
+	if err := d.p.Client().SendFile(fmt.Sprintf("GraphDriver.ApplyDiff?id=%s&parent=%s", id, parent), diff, &ret); err != nil {
 		return -1, err
 		return -1, err
 	}
 	}
 	if ret.Err != "" {
 	if ret.Err != "" {
@@ -238,7 +238,7 @@ func (d *graphDriverProxy) DiffSize(id, parent string) (int64, error) {
 		Parent: parent,
 		Parent: parent,
 	}
 	}
 	var ret graphDriverResponse
 	var ret graphDriverResponse
-	if err := d.client.Call("GraphDriver.DiffSize", args, &ret); err != nil {
+	if err := d.p.Client().Call("GraphDriver.DiffSize", args, &ret); err != nil {
 		return -1, err
 		return -1, err
 	}
 	}
 	if ret.Err != "" {
 	if ret.Err != "" {

+ 18 - 0
integration-cli/docker_cli_daemon_plugins_test.go

@@ -257,6 +257,24 @@ func (s *DockerDaemonSuite) TestVolumePlugin(c *check.C) {
 	c.Assert(exists, checker.Equals, true)
 	c.Assert(exists, checker.Equals, true)
 }
 }
 
 
+func (s *DockerDaemonSuite) TestGraphdriverPlugin(c *check.C) {
+	testRequires(c, Network, IsAmd64, DaemonIsLinux, overlaySupported)
+
+	s.d.Start()
+
+	// install the plugin
+	plugin := "cpuguy83/docker-overlay2-graphdriver-plugin"
+	out, err := s.d.Cmd("plugin", "install", "--grant-all-permissions", plugin)
+	c.Assert(err, checker.IsNil, check.Commentf(out))
+
+	// restart the daemon with the plugin set as the storage driver
+	s.d.Restart("-s", plugin)
+
+	// run a container
+	out, err = s.d.Cmd("run", "--rm", "busybox", "true") // this will pull busybox using the plugin
+	c.Assert(err, checker.IsNil, check.Commentf(out))
+}
+
 func existsMountpointWithPrefix(mountpointPrefix string) (bool, error) {
 func existsMountpointWithPrefix(mountpointPrefix string) (bool, error) {
 	mounts, err := mount.GetMounts()
 	mounts, err := mount.GetMounts()
 	if err != nil {
 	if err != nil {

+ 13 - 0
integration-cli/requirements_unix.go

@@ -3,7 +3,9 @@
 package main
 package main
 
 
 import (
 import (
+	"bytes"
 	"io/ioutil"
 	"io/ioutil"
+	"os/exec"
 	"strings"
 	"strings"
 
 
 	"github.com/docker/docker/pkg/sysinfo"
 	"github.com/docker/docker/pkg/sysinfo"
@@ -122,6 +124,17 @@ var (
 		},
 		},
 		"Test cannot be run without a kernel (4.3+) supporting ambient capabilities",
 		"Test cannot be run without a kernel (4.3+) supporting ambient capabilities",
 	}
 	}
+	overlaySupported = testRequirement{
+		func() bool {
+			cmd := exec.Command(dockerBinary, "run", "--rm", "busybox", "/bin/sh", "-c", "cat /proc/filesystems")
+			out, err := cmd.CombinedOutput()
+			if err != nil {
+				return false
+			}
+			return bytes.Contains(out, []byte("overlay\n"))
+		},
+		"Test cannot be run wihtout suppport for ovelayfs",
+	}
 )
 )
 
 
 func init() {
 func init() {

+ 1 - 1
plugin/manager.go

@@ -156,7 +156,7 @@ func (pm *Manager) reload() error {
 
 
 			// We should only enable rootfs propagation for certain plugin types that need it.
 			// We should only enable rootfs propagation for certain plugin types that need it.
 			for _, typ := range p.PluginObj.Config.Interface.Types {
 			for _, typ := range p.PluginObj.Config.Interface.Types {
-				if typ.Capability == "volumedriver" && typ.Prefix == "docker" && strings.HasPrefix(typ.Version, "1.") {
+				if (typ.Capability == "volumedriver" || typ.Capability == "graphdriver") && typ.Prefix == "docker" && strings.HasPrefix(typ.Version, "1.") {
 					if p.PluginObj.Config.PropagatedMount != "" {
 					if p.PluginObj.Config.PropagatedMount != "" {
 						// TODO: sanitize PropagatedMount and prevent breakout
 						// TODO: sanitize PropagatedMount and prevent breakout
 						p.PropagatedMount = filepath.Join(p.Rootfs, p.PluginObj.Config.PropagatedMount)
 						p.PropagatedMount = filepath.Join(p.Rootfs, p.PluginObj.Config.PropagatedMount)