Browse code

Make graphdriver plugin use plugin BasePath

Also enables `PropagatedMount` for graphdrivers.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>

Brian Goff authored on 2016/12/11 01:40:01
Showing 6 changed files
... ...
@@ -154,10 +154,12 @@ func GetDriver(name, home string, options []string, uidMaps, gidMaps []idtools.I
154 154
 	if initFunc, exists := drivers[name]; exists {
155 155
 		return initFunc(filepath.Join(home, name), options, uidMaps, gidMaps)
156 156
 	}
157
-	if pluginDriver, err := lookupPlugin(name, home, options, pg); err == nil {
157
+
158
+	pluginDriver, err := lookupPlugin(name, home, options, pg)
159
+	if err == nil {
158 160
 		return pluginDriver, nil
159 161
 	}
160
-	logrus.Errorf("Failed to GetDriver graph %s %s", name, home)
162
+	logrus.WithError(err).WithField("driver", name).WithField("home-dir", home).Error("Failed to GetDriver graph")
161 163
 	return nil, ErrNotSupported
162 164
 }
163 165
 
... ...
@@ -6,6 +6,7 @@ import (
6 6
 	"path/filepath"
7 7
 
8 8
 	"github.com/docker/docker/pkg/plugingetter"
9
+	"github.com/docker/docker/plugin/v2"
9 10
 )
10 11
 
11 12
 type pluginClient interface {
... ...
@@ -26,6 +27,13 @@ func lookupPlugin(name, home string, opts []string, pg plugingetter.PluginGetter
26 26
 }
27 27
 
28 28
 func newPluginDriver(name, home string, opts []string, pl plugingetter.CompatPlugin) (Driver, error) {
29
-	proxy := &graphDriverProxy{name, pl.Client(), pl}
29
+	if !pl.IsV1() {
30
+		if p, ok := pl.(*v2.Plugin); ok {
31
+			if p.PropagatedMount != "" {
32
+				home = p.PluginObj.Config.PropagatedMount
33
+			}
34
+		}
35
+	}
36
+	proxy := &graphDriverProxy{name, pl}
30 37
 	return proxy, proxy.Init(filepath.Join(home, name), opts)
31 38
 }
... ...
@@ -4,15 +4,15 @@ import (
4 4
 	"errors"
5 5
 	"fmt"
6 6
 	"io"
7
+	"path/filepath"
7 8
 
8 9
 	"github.com/docker/docker/pkg/archive"
9 10
 	"github.com/docker/docker/pkg/plugingetter"
10 11
 )
11 12
 
12 13
 type graphDriverProxy struct {
13
-	name   string
14
-	client pluginClient
15
-	p      plugingetter.CompatPlugin
14
+	name string
15
+	p    plugingetter.CompatPlugin
16 16
 }
17 17
 
18 18
 type graphDriverRequest struct {
... ...
@@ -48,7 +48,7 @@ func (d *graphDriverProxy) Init(home string, opts []string) error {
48 48
 		Opts: opts,
49 49
 	}
50 50
 	var ret graphDriverResponse
51
-	if err := d.client.Call("GraphDriver.Init", args, &ret); err != nil {
51
+	if err := d.p.Client().Call("GraphDriver.Init", args, &ret); err != nil {
52 52
 		return err
53 53
 	}
54 54
 	if ret.Err != "" {
... ...
@@ -73,7 +73,7 @@ func (d *graphDriverProxy) CreateReadWrite(id, parent string, opts *CreateOpts)
73 73
 		MountLabel: mountLabel,
74 74
 	}
75 75
 	var ret graphDriverResponse
76
-	if err := d.client.Call("GraphDriver.CreateReadWrite", args, &ret); err != nil {
76
+	if err := d.p.Client().Call("GraphDriver.CreateReadWrite", args, &ret); err != nil {
77 77
 		return err
78 78
 	}
79 79
 	if ret.Err != "" {
... ...
@@ -93,7 +93,7 @@ func (d *graphDriverProxy) Create(id, parent string, opts *CreateOpts) error {
93 93
 		MountLabel: mountLabel,
94 94
 	}
95 95
 	var ret graphDriverResponse
96
-	if err := d.client.Call("GraphDriver.Create", args, &ret); err != nil {
96
+	if err := d.p.Client().Call("GraphDriver.Create", args, &ret); err != nil {
97 97
 		return err
98 98
 	}
99 99
 	if ret.Err != "" {
... ...
@@ -105,7 +105,7 @@ func (d *graphDriverProxy) Create(id, parent string, opts *CreateOpts) error {
105 105
 func (d *graphDriverProxy) Remove(id string) error {
106 106
 	args := &graphDriverRequest{ID: id}
107 107
 	var ret graphDriverResponse
108
-	if err := d.client.Call("GraphDriver.Remove", args, &ret); err != nil {
108
+	if err := d.p.Client().Call("GraphDriver.Remove", args, &ret); err != nil {
109 109
 		return err
110 110
 	}
111 111
 	if ret.Err != "" {
... ...
@@ -120,20 +120,20 @@ func (d *graphDriverProxy) Get(id, mountLabel string) (string, error) {
120 120
 		MountLabel: mountLabel,
121 121
 	}
122 122
 	var ret graphDriverResponse
123
-	if err := d.client.Call("GraphDriver.Get", args, &ret); err != nil {
123
+	if err := d.p.Client().Call("GraphDriver.Get", args, &ret); err != nil {
124 124
 		return "", err
125 125
 	}
126 126
 	var err error
127 127
 	if ret.Err != "" {
128 128
 		err = errors.New(ret.Err)
129 129
 	}
130
-	return ret.Dir, err
130
+	return filepath.Join(d.p.BasePath(), ret.Dir), err
131 131
 }
132 132
 
133 133
 func (d *graphDriverProxy) Put(id string) error {
134 134
 	args := &graphDriverRequest{ID: id}
135 135
 	var ret graphDriverResponse
136
-	if err := d.client.Call("GraphDriver.Put", args, &ret); err != nil {
136
+	if err := d.p.Client().Call("GraphDriver.Put", args, &ret); err != nil {
137 137
 		return err
138 138
 	}
139 139
 	if ret.Err != "" {
... ...
@@ -145,7 +145,7 @@ func (d *graphDriverProxy) Put(id string) error {
145 145
 func (d *graphDriverProxy) Exists(id string) bool {
146 146
 	args := &graphDriverRequest{ID: id}
147 147
 	var ret graphDriverResponse
148
-	if err := d.client.Call("GraphDriver.Exists", args, &ret); err != nil {
148
+	if err := d.p.Client().Call("GraphDriver.Exists", args, &ret); err != nil {
149 149
 		return false
150 150
 	}
151 151
 	return ret.Exists
... ...
@@ -154,7 +154,7 @@ func (d *graphDriverProxy) Exists(id string) bool {
154 154
 func (d *graphDriverProxy) Status() [][2]string {
155 155
 	args := &graphDriverRequest{}
156 156
 	var ret graphDriverResponse
157
-	if err := d.client.Call("GraphDriver.Status", args, &ret); err != nil {
157
+	if err := d.p.Client().Call("GraphDriver.Status", args, &ret); err != nil {
158 158
 		return nil
159 159
 	}
160 160
 	return ret.Status
... ...
@@ -165,7 +165,7 @@ func (d *graphDriverProxy) GetMetadata(id string) (map[string]string, error) {
165 165
 		ID: id,
166 166
 	}
167 167
 	var ret graphDriverResponse
168
-	if err := d.client.Call("GraphDriver.GetMetadata", args, &ret); err != nil {
168
+	if err := d.p.Client().Call("GraphDriver.GetMetadata", args, &ret); err != nil {
169 169
 		return nil, err
170 170
 	}
171 171
 	if ret.Err != "" {
... ...
@@ -184,7 +184,7 @@ func (d *graphDriverProxy) Cleanup() error {
184 184
 
185 185
 	args := &graphDriverRequest{}
186 186
 	var ret graphDriverResponse
187
-	if err := d.client.Call("GraphDriver.Cleanup", args, &ret); err != nil {
187
+	if err := d.p.Client().Call("GraphDriver.Cleanup", args, &ret); err != nil {
188 188
 		return nil
189 189
 	}
190 190
 	if ret.Err != "" {
... ...
@@ -198,7 +198,7 @@ func (d *graphDriverProxy) Diff(id, parent string) (io.ReadCloser, error) {
198 198
 		ID:     id,
199 199
 		Parent: parent,
200 200
 	}
201
-	body, err := d.client.Stream("GraphDriver.Diff", args)
201
+	body, err := d.p.Client().Stream("GraphDriver.Diff", args)
202 202
 	if err != nil {
203 203
 		return nil, err
204 204
 	}
... ...
@@ -211,7 +211,7 @@ func (d *graphDriverProxy) Changes(id, parent string) ([]archive.Change, error)
211 211
 		Parent: parent,
212 212
 	}
213 213
 	var ret graphDriverResponse
214
-	if err := d.client.Call("GraphDriver.Changes", args, &ret); err != nil {
214
+	if err := d.p.Client().Call("GraphDriver.Changes", args, &ret); err != nil {
215 215
 		return nil, err
216 216
 	}
217 217
 	if ret.Err != "" {
... ...
@@ -223,7 +223,7 @@ func (d *graphDriverProxy) Changes(id, parent string) ([]archive.Change, error)
223 223
 
224 224
 func (d *graphDriverProxy) ApplyDiff(id, parent string, diff io.Reader) (int64, error) {
225 225
 	var ret graphDriverResponse
226
-	if err := d.client.SendFile(fmt.Sprintf("GraphDriver.ApplyDiff?id=%s&parent=%s", id, parent), diff, &ret); err != nil {
226
+	if err := d.p.Client().SendFile(fmt.Sprintf("GraphDriver.ApplyDiff?id=%s&parent=%s", id, parent), diff, &ret); err != nil {
227 227
 		return -1, err
228 228
 	}
229 229
 	if ret.Err != "" {
... ...
@@ -238,7 +238,7 @@ func (d *graphDriverProxy) DiffSize(id, parent string) (int64, error) {
238 238
 		Parent: parent,
239 239
 	}
240 240
 	var ret graphDriverResponse
241
-	if err := d.client.Call("GraphDriver.DiffSize", args, &ret); err != nil {
241
+	if err := d.p.Client().Call("GraphDriver.DiffSize", args, &ret); err != nil {
242 242
 		return -1, err
243 243
 	}
244 244
 	if ret.Err != "" {
... ...
@@ -235,6 +235,24 @@ func (s *DockerDaemonSuite) TestVolumePlugin(c *check.C) {
235 235
 	c.Assert(exists, checker.Equals, true)
236 236
 }
237 237
 
238
+func (s *DockerDaemonSuite) TestGraphdriverPlugin(c *check.C) {
239
+	testRequires(c, Network, IsAmd64, DaemonIsLinux, overlaySupported)
240
+
241
+	s.d.Start(c)
242
+
243
+	// install the plugin
244
+	plugin := "cpuguy83/docker-overlay2-graphdriver-plugin"
245
+	out, err := s.d.Cmd("plugin", "install", "--grant-all-permissions", plugin)
246
+	c.Assert(err, checker.IsNil, check.Commentf(out))
247
+
248
+	// restart the daemon with the plugin set as the storage driver
249
+	s.d.Restart(c, "-s", plugin)
250
+
251
+	// run a container
252
+	out, err = s.d.Cmd("run", "--rm", "busybox", "true") // this will pull busybox using the plugin
253
+	c.Assert(err, checker.IsNil, check.Commentf(out))
254
+}
255
+
238 256
 func existsMountpointWithPrefix(mountpointPrefix string) (bool, error) {
239 257
 	mounts, err := mount.GetMounts()
240 258
 	if err != nil {
... ...
@@ -3,7 +3,9 @@
3 3
 package main
4 4
 
5 5
 import (
6
+	"bytes"
6 7
 	"io/ioutil"
8
+	"os/exec"
7 9
 	"strings"
8 10
 
9 11
 	"github.com/docker/docker/pkg/sysinfo"
... ...
@@ -122,6 +124,17 @@ var (
122 122
 		},
123 123
 		"Test cannot be run without a kernel (4.3+) supporting ambient capabilities",
124 124
 	}
125
+	overlaySupported = testRequirement{
126
+		func() bool {
127
+			cmd := exec.Command(dockerBinary, "run", "--rm", "busybox", "/bin/sh", "-c", "cat /proc/filesystems")
128
+			out, err := cmd.CombinedOutput()
129
+			if err != nil {
130
+				return false
131
+			}
132
+			return bytes.Contains(out, []byte("overlay\n"))
133
+		},
134
+		"Test cannot be run wihtout suppport for ovelayfs",
135
+	}
125 136
 )
126 137
 
127 138
 func init() {
... ...
@@ -156,7 +156,7 @@ func (pm *Manager) reload() error {
156 156
 
157 157
 			// We should only enable rootfs propagation for certain plugin types that need it.
158 158
 			for _, typ := range p.PluginObj.Config.Interface.Types {
159
-				if typ.Capability == "volumedriver" && typ.Prefix == "docker" && strings.HasPrefix(typ.Version, "1.") {
159
+				if (typ.Capability == "volumedriver" || typ.Capability == "graphdriver") && typ.Prefix == "docker" && strings.HasPrefix(typ.Version, "1.") {
160 160
 					if p.PluginObj.Config.PropagatedMount != "" {
161 161
 						// TODO: sanitize PropagatedMount and prevent breakout
162 162
 						p.PropagatedMount = filepath.Join(p.Rootfs, p.PluginObj.Config.PropagatedMount)