Browse code

Merge pull request #20525 from Microsoft/sjw/update-graphdriver-create

Adding readOnly parameter to graphdriver Create method

John Howard authored on 2016/04/09 12:44:03
Showing 14 changed files
... ...
@@ -194,6 +194,12 @@ func (a *Driver) Exists(id string) bool {
194 194
 	return true
195 195
 }
196 196
 
197
+// CreateReadWrite creates a layer that is writable for use as a container
198
+// file system.
199
+func (a *Driver) CreateReadWrite(id, parent, mountLabel string, storageOpt map[string]string) error {
200
+	return a.Create(id, parent, mountLabel, storageOpt)
201
+}
202
+
197 203
 // Create three folders for each id
198 204
 // mnt, layers, and diff
199 205
 func (a *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) error {
... ...
@@ -320,7 +320,7 @@ func TestGetDiff(t *testing.T) {
320 320
 	d := newDriver(t)
321 321
 	defer os.RemoveAll(tmp)
322 322
 
323
-	if err := d.Create("1", "", "", nil); err != nil {
323
+	if err := d.CreateReadWrite("1", "", "", nil); err != nil {
324 324
 		t.Fatal(err)
325 325
 	}
326 326
 
... ...
@@ -357,7 +357,7 @@ func TestChanges(t *testing.T) {
357 357
 	if err := d.Create("1", "", "", nil); err != nil {
358 358
 		t.Fatal(err)
359 359
 	}
360
-	if err := d.Create("2", "1", "", nil); err != nil {
360
+	if err := d.CreateReadWrite("2", "1", "", nil); err != nil {
361 361
 		t.Fatal(err)
362 362
 	}
363 363
 
... ...
@@ -403,7 +403,7 @@ func TestChanges(t *testing.T) {
403 403
 		t.Fatalf("Change kind should be ChangeAdd got %s", change.Kind)
404 404
 	}
405 405
 
406
-	if err := d.Create("3", "2", "", nil); err != nil {
406
+	if err := d.CreateReadWrite("3", "2", "", nil); err != nil {
407 407
 		t.Fatal(err)
408 408
 	}
409 409
 	mntPoint, err = d.Get("3", "")
... ...
@@ -448,7 +448,7 @@ func TestDiffSize(t *testing.T) {
448 448
 	d := newDriver(t)
449 449
 	defer os.RemoveAll(tmp)
450 450
 
451
-	if err := d.Create("1", "", "", nil); err != nil {
451
+	if err := d.CreateReadWrite("1", "", "", nil); err != nil {
452 452
 		t.Fatal(err)
453 453
 	}
454 454
 
... ...
@@ -490,7 +490,7 @@ func TestChildDiffSize(t *testing.T) {
490 490
 	defer os.RemoveAll(tmp)
491 491
 	defer d.Cleanup()
492 492
 
493
-	if err := d.Create("1", "", "", nil); err != nil {
493
+	if err := d.CreateReadWrite("1", "", "", nil); err != nil {
494 494
 		t.Fatal(err)
495 495
 	}
496 496
 
... ...
@@ -592,7 +592,7 @@ func TestApplyDiff(t *testing.T) {
592 592
 	defer os.RemoveAll(tmp)
593 593
 	defer d.Cleanup()
594 594
 
595
-	if err := d.Create("1", "", "", nil); err != nil {
595
+	if err := d.CreateReadWrite("1", "", "", nil); err != nil {
596 596
 		t.Fatal(err)
597 597
 	}
598 598
 
... ...
@@ -671,7 +671,7 @@ func testMountMoreThan42Layers(t *testing.T, mountPath string) {
671 671
 		}
672 672
 		current = hash(current)
673 673
 
674
-		if err := d.Create(current, parent, "", nil); err != nil {
674
+		if err := d.CreateReadWrite(current, parent, "", nil); err != nil {
675 675
 			t.Logf("Current layer %d", i)
676 676
 			t.Error(err)
677 677
 		}
... ...
@@ -246,6 +246,12 @@ func (d *Driver) subvolumesDirID(id string) string {
246 246
 	return path.Join(d.subvolumesDir(), id)
247 247
 }
248 248
 
249
+// CreateReadWrite creates a layer that is writable for use as a container
250
+// file system.
251
+func (d *Driver) CreateReadWrite(id, parent, mountLabel string, storageOpt map[string]string) error {
252
+	return d.Create(id, parent, mountLabel, storageOpt)
253
+}
254
+
249 255
 // Create the filesystem with given id.
250 256
 func (d *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) error {
251 257
 
... ...
@@ -30,7 +30,7 @@ func TestBtrfsCreateSnap(t *testing.T) {
30 30
 
31 31
 func TestBtrfsSubvolDelete(t *testing.T) {
32 32
 	d := graphtest.GetDriver(t, "btrfs")
33
-	if err := d.Create("test", "", "", nil); err != nil {
33
+	if err := d.CreateReadWrite("test", "", "", nil); err != nil {
34 34
 		t.Fatal(err)
35 35
 	}
36 36
 	defer graphtest.PutDriver(t)
... ...
@@ -117,6 +117,12 @@ func (d *Driver) Cleanup() error {
117 117
 	return err
118 118
 }
119 119
 
120
+// CreateReadWrite creates a layer that is writable for use as a container
121
+// file system.
122
+func (d *Driver) CreateReadWrite(id, parent, mountLabel string, storageOpt map[string]string) error {
123
+	return d.Create(id, parent, mountLabel, storageOpt)
124
+}
125
+
120 126
 // Create adds a device with a given id and the parent.
121 127
 func (d *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) error {
122 128
 	if err := d.DeviceSet.AddDevice(id, parent, storageOpt); err != nil {
... ...
@@ -46,6 +46,9 @@ type InitFunc func(root string, options []string, uidMaps, gidMaps []idtools.IDM
46 46
 type ProtoDriver interface {
47 47
 	// String returns a string representation of this driver.
48 48
 	String() string
49
+	// CreateReadWrite creates a new, empty filesystem layer that is ready
50
+	// to be used as the storage for a container.
51
+	CreateReadWrite(id, parent, mountLabel string, storageOpt map[string]string) error
49 52
 	// Create creates a new, empty, filesystem layer with the
50 53
 	// specified id and parent and mountLabel. Parent and mountLabel may be "".
51 54
 	Create(id, parent, mountLabel string, storageOpt map[string]string) error
... ...
@@ -215,7 +215,7 @@ func createBase(t *testing.T, driver graphdriver.Driver, name string) {
215 215
 	oldmask := syscall.Umask(0)
216 216
 	defer syscall.Umask(oldmask)
217 217
 
218
-	if err := driver.Create(name, "", "", nil); err != nil {
218
+	if err := driver.CreateReadWrite(name, "", "", nil); err != nil {
219 219
 		t.Fatal(err)
220 220
 	}
221 221
 
... ...
@@ -223,6 +223,12 @@ func (d *Driver) Cleanup() error {
223 223
 	return nil
224 224
 }
225 225
 
226
+// CreateReadWrite creates a layer that is writable for use as a container
227
+// file system.
228
+func (d *Driver) CreateReadWrite(id, parent, mountLabel string, storageOpt map[string]string) error {
229
+	return d.Create(id, parent, mountLabel, storageOpt)
230
+}
231
+
226 232
 // Create is used to create the upper, lower, and merge directories required for overlay fs for a given id.
227 233
 // The parent filesystem is used to configure these directories for the overlay.
228 234
 func (d *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) (retErr error) {
... ...
@@ -54,6 +54,22 @@ func (d *graphDriverProxy) String() string {
54 54
 	return d.name
55 55
 }
56 56
 
57
+func (d *graphDriverProxy) CreateReadWrite(id, parent, mountLabel string, storageOpt map[string]string) error {
58
+	args := &graphDriverRequest{
59
+		ID:         id,
60
+		Parent:     parent,
61
+		MountLabel: mountLabel,
62
+	}
63
+	var ret graphDriverResponse
64
+	if err := d.client.Call("GraphDriver.CreateReadWrite", args, &ret); err != nil {
65
+		return err
66
+	}
67
+	if ret.Err != "" {
68
+		return errors.New(ret.Err)
69
+	}
70
+	return nil
71
+}
72
+
57 73
 func (d *graphDriverProxy) Create(id, parent, mountLabel string, storageOpt map[string]string) error {
58 74
 	args := &graphDriverRequest{
59 75
 		ID:         id,
... ...
@@ -68,6 +68,12 @@ func (d *Driver) Cleanup() error {
68 68
 	return nil
69 69
 }
70 70
 
71
+// CreateReadWrite creates a layer that is writable for use as a container
72
+// file system.
73
+func (d *Driver) CreateReadWrite(id, parent, mountLabel string, storageOpt map[string]string) error {
74
+	return d.Create(id, parent, mountLabel, storageOpt)
75
+}
76
+
71 77
 // Create prepares the filesystem for the VFS driver and copies the directory for the given id under the parent.
72 78
 func (d *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) error {
73 79
 	if len(storageOpt) != 0 {
... ...
@@ -107,8 +107,18 @@ func (d *Driver) Exists(id string) bool {
107 107
 	return result
108 108
 }
109 109
 
110
-// Create creates a new layer with the given id.
110
+// CreateReadWrite creates a layer that is writable for use as a container
111
+// file system.
112
+func (d *Driver) CreateReadWrite(id, parent, mountLabel string, storageOpt map[string]string) error {
113
+	return d.create(id, parent, mountLabel, false, storageOpt)
114
+}
115
+
116
+// Create creates a new read-only layer with the given id.
111 117
 func (d *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) error {
118
+	return d.create(id, parent, mountLabel, true, storageOpt)
119
+}
120
+
121
+func (d *Driver) create(id, parent, mountLabel string, readOnly bool, storageOpt map[string]string) error {
112 122
 	if len(storageOpt) != 0 {
113 123
 		return fmt.Errorf("--storage-opt is not supported for windows")
114 124
 	}
... ...
@@ -125,27 +135,30 @@ func (d *Driver) Create(id, parent, mountLabel string, storageOpt map[string]str
125 125
 
126 126
 	var layerChain []string
127 127
 
128
-	parentIsInit := strings.HasSuffix(rPId, "-init")
129
-
130
-	if !parentIsInit && rPId != "" {
128
+	if rPId != "" {
131 129
 		parentPath, err := hcsshim.GetLayerMountPath(d.info, rPId)
132 130
 		if err != nil {
133 131
 			return err
134 132
 		}
135
-		layerChain = []string{parentPath}
133
+		if _, err := os.Stat(filepath.Join(parentPath, "Files")); err == nil {
134
+			// This is a legitimate parent layer (not the empty "-init" layer),
135
+			// so include it in the layer chain.
136
+			layerChain = []string{parentPath}
137
+		}
136 138
 	}
137 139
 
138 140
 	layerChain = append(layerChain, parentChain...)
139 141
 
140
-	if parentIsInit {
141
-		if len(layerChain) == 0 {
142
-			return fmt.Errorf("Cannot create a read/write layer without a parent layer.")
143
-		}
144
-		if err := hcsshim.CreateSandboxLayer(d.info, id, layerChain[0], layerChain); err != nil {
142
+	if readOnly {
143
+		if err := hcsshim.CreateLayer(d.info, id, rPId); err != nil {
145 144
 			return err
146 145
 		}
147 146
 	} else {
148
-		if err := hcsshim.CreateLayer(d.info, id, rPId); err != nil {
147
+		var parentPath string
148
+		if len(layerChain) != 0 {
149
+			parentPath = layerChain[0]
150
+		}
151
+		if err := hcsshim.CreateSandboxLayer(d.info, id, parentPath, layerChain); err != nil {
149 152
 			return err
150 153
 		}
151 154
 	}
... ...
@@ -240,6 +240,12 @@ func (d *Driver) mountPath(id string) string {
240 240
 	return path.Join(d.options.mountPath, "graph", getMountpoint(id))
241 241
 }
242 242
 
243
+// CreateReadWrite creates a layer that is writable for use as a container
244
+// file system.
245
+func (d *Driver) CreateReadWrite(id, parent, mountLabel string, storageOpt map[string]string) error {
246
+	return d.Create(id, parent, mountLabel, storageOpt)
247
+}
248
+
243 249
 // Create prepares the dataset and filesystem for the ZFS driver for the given id under the parent.
244 250
 func (d *Driver) Create(id string, parent string, mountLabel string, storageOpt map[string]string) error {
245 251
 	if len(storageOpt) != 0 {
... ...
@@ -67,6 +67,7 @@ func (s *DockerExternalGraphdriverSuite) SetUpSuite(c *check.C) {
67 67
 		ID         string `json:",omitempty"`
68 68
 		Parent     string `json:",omitempty"`
69 69
 		MountLabel string `json:",omitempty"`
70
+		ReadOnly   bool   `json:",omitempty"`
70 71
 	}
71 72
 
72 73
 	type graphDriverResponse struct {
... ...
@@ -115,6 +116,20 @@ func (s *DockerExternalGraphdriverSuite) SetUpSuite(c *check.C) {
115 115
 		respond(w, "{}")
116 116
 	})
117 117
 
118
+	mux.HandleFunc("/GraphDriver.CreateReadWrite", func(w http.ResponseWriter, r *http.Request) {
119
+		s.ec.creations++
120
+
121
+		var req graphDriverRequest
122
+		if err := decReq(r.Body, &req, w); err != nil {
123
+			return
124
+		}
125
+		if err := driver.CreateReadWrite(req.ID, req.Parent, "", nil); err != nil {
126
+			respond(w, err)
127
+			return
128
+		}
129
+		respond(w, "{}")
130
+	})
131
+
118 132
 	mux.HandleFunc("/GraphDriver.Create", func(w http.ResponseWriter, r *http.Request) {
119 133
 		s.ec.creations++
120 134
 
... ...
@@ -461,7 +461,7 @@ func (ls *layerStore) CreateRWLayer(name string, parent ChainID, mountLabel stri
461 461
 		m.initID = pid
462 462
 	}
463 463
 
464
-	if err = ls.driver.Create(m.mountID, pid, "", storageOpt); err != nil {
464
+	if err = ls.driver.CreateReadWrite(m.mountID, pid, "", storageOpt); err != nil {
465 465
 		return nil, err
466 466
 	}
467 467