Quellcode durchsuchen

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

Adding readOnly parameter to graphdriver Create method
John Howard vor 9 Jahren
Ursprung
Commit
fec6cd2eb9

+ 6 - 0
daemon/graphdriver/aufs/aufs.go

@@ -194,6 +194,12 @@ func (a *Driver) Exists(id string) bool {
 	return true
 }
 
+// CreateReadWrite creates a layer that is writable for use as a container
+// file system.
+func (a *Driver) CreateReadWrite(id, parent, mountLabel string, storageOpt map[string]string) error {
+	return a.Create(id, parent, mountLabel, storageOpt)
+}
+
 // Create three folders for each id
 // mnt, layers, and diff
 func (a *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) error {

+ 7 - 7
daemon/graphdriver/aufs/aufs_test.go

@@ -320,7 +320,7 @@ func TestGetDiff(t *testing.T) {
 	d := newDriver(t)
 	defer os.RemoveAll(tmp)
 
-	if err := d.Create("1", "", "", nil); err != nil {
+	if err := d.CreateReadWrite("1", "", "", nil); err != nil {
 		t.Fatal(err)
 	}
 
@@ -357,7 +357,7 @@ func TestChanges(t *testing.T) {
 	if err := d.Create("1", "", "", nil); err != nil {
 		t.Fatal(err)
 	}
-	if err := d.Create("2", "1", "", nil); err != nil {
+	if err := d.CreateReadWrite("2", "1", "", nil); err != nil {
 		t.Fatal(err)
 	}
 
@@ -403,7 +403,7 @@ func TestChanges(t *testing.T) {
 		t.Fatalf("Change kind should be ChangeAdd got %s", change.Kind)
 	}
 
-	if err := d.Create("3", "2", "", nil); err != nil {
+	if err := d.CreateReadWrite("3", "2", "", nil); err != nil {
 		t.Fatal(err)
 	}
 	mntPoint, err = d.Get("3", "")
@@ -448,7 +448,7 @@ func TestDiffSize(t *testing.T) {
 	d := newDriver(t)
 	defer os.RemoveAll(tmp)
 
-	if err := d.Create("1", "", "", nil); err != nil {
+	if err := d.CreateReadWrite("1", "", "", nil); err != nil {
 		t.Fatal(err)
 	}
 
@@ -490,7 +490,7 @@ func TestChildDiffSize(t *testing.T) {
 	defer os.RemoveAll(tmp)
 	defer d.Cleanup()
 
-	if err := d.Create("1", "", "", nil); err != nil {
+	if err := d.CreateReadWrite("1", "", "", nil); err != nil {
 		t.Fatal(err)
 	}
 
@@ -592,7 +592,7 @@ func TestApplyDiff(t *testing.T) {
 	defer os.RemoveAll(tmp)
 	defer d.Cleanup()
 
-	if err := d.Create("1", "", "", nil); err != nil {
+	if err := d.CreateReadWrite("1", "", "", nil); err != nil {
 		t.Fatal(err)
 	}
 
@@ -671,7 +671,7 @@ func testMountMoreThan42Layers(t *testing.T, mountPath string) {
 		}
 		current = hash(current)
 
-		if err := d.Create(current, parent, "", nil); err != nil {
+		if err := d.CreateReadWrite(current, parent, "", nil); err != nil {
 			t.Logf("Current layer %d", i)
 			t.Error(err)
 		}

+ 6 - 0
daemon/graphdriver/btrfs/btrfs.go

@@ -246,6 +246,12 @@ func (d *Driver) subvolumesDirID(id string) string {
 	return path.Join(d.subvolumesDir(), id)
 }
 
+// CreateReadWrite creates a layer that is writable for use as a container
+// file system.
+func (d *Driver) CreateReadWrite(id, parent, mountLabel string, storageOpt map[string]string) error {
+	return d.Create(id, parent, mountLabel, storageOpt)
+}
+
 // Create the filesystem with given id.
 func (d *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) error {
 

+ 1 - 1
daemon/graphdriver/btrfs/btrfs_test.go

@@ -30,7 +30,7 @@ func TestBtrfsCreateSnap(t *testing.T) {
 
 func TestBtrfsSubvolDelete(t *testing.T) {
 	d := graphtest.GetDriver(t, "btrfs")
-	if err := d.Create("test", "", "", nil); err != nil {
+	if err := d.CreateReadWrite("test", "", "", nil); err != nil {
 		t.Fatal(err)
 	}
 	defer graphtest.PutDriver(t)

+ 6 - 0
daemon/graphdriver/devmapper/driver.go

@@ -117,6 +117,12 @@ func (d *Driver) Cleanup() error {
 	return err
 }
 
+// CreateReadWrite creates a layer that is writable for use as a container
+// file system.
+func (d *Driver) CreateReadWrite(id, parent, mountLabel string, storageOpt map[string]string) error {
+	return d.Create(id, parent, mountLabel, storageOpt)
+}
+
 // Create adds a device with a given id and the parent.
 func (d *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) error {
 	if err := d.DeviceSet.AddDevice(id, parent, storageOpt); err != nil {

+ 3 - 0
daemon/graphdriver/driver.go

@@ -46,6 +46,9 @@ type InitFunc func(root string, options []string, uidMaps, gidMaps []idtools.IDM
 type ProtoDriver interface {
 	// String returns a string representation of this driver.
 	String() string
+	// CreateReadWrite creates a new, empty filesystem layer that is ready
+	// to be used as the storage for a container.
+	CreateReadWrite(id, parent, mountLabel string, storageOpt map[string]string) error
 	// Create creates a new, empty, filesystem layer with the
 	// specified id and parent and mountLabel. Parent and mountLabel may be "".
 	Create(id, parent, mountLabel string, storageOpt map[string]string) error

+ 1 - 1
daemon/graphdriver/graphtest/graphtest_unix.go

@@ -215,7 +215,7 @@ func createBase(t *testing.T, driver graphdriver.Driver, name string) {
 	oldmask := syscall.Umask(0)
 	defer syscall.Umask(oldmask)
 
-	if err := driver.Create(name, "", "", nil); err != nil {
+	if err := driver.CreateReadWrite(name, "", "", nil); err != nil {
 		t.Fatal(err)
 	}
 

+ 6 - 0
daemon/graphdriver/overlay/overlay.go

@@ -223,6 +223,12 @@ func (d *Driver) Cleanup() error {
 	return nil
 }
 
+// CreateReadWrite creates a layer that is writable for use as a container
+// file system.
+func (d *Driver) CreateReadWrite(id, parent, mountLabel string, storageOpt map[string]string) error {
+	return d.Create(id, parent, mountLabel, storageOpt)
+}
+
 // Create is used to create the upper, lower, and merge directories required for overlay fs for a given id.
 // The parent filesystem is used to configure these directories for the overlay.
 func (d *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) (retErr error) {

+ 16 - 0
daemon/graphdriver/proxy.go

@@ -54,6 +54,22 @@ func (d *graphDriverProxy) String() string {
 	return d.name
 }
 
+func (d *graphDriverProxy) CreateReadWrite(id, parent, mountLabel string, storageOpt map[string]string) error {
+	args := &graphDriverRequest{
+		ID:         id,
+		Parent:     parent,
+		MountLabel: mountLabel,
+	}
+	var ret graphDriverResponse
+	if err := d.client.Call("GraphDriver.CreateReadWrite", args, &ret); err != nil {
+		return err
+	}
+	if ret.Err != "" {
+		return errors.New(ret.Err)
+	}
+	return nil
+}
+
 func (d *graphDriverProxy) Create(id, parent, mountLabel string, storageOpt map[string]string) error {
 	args := &graphDriverRequest{
 		ID:         id,

+ 6 - 0
daemon/graphdriver/vfs/driver.go

@@ -68,6 +68,12 @@ func (d *Driver) Cleanup() error {
 	return nil
 }
 
+// CreateReadWrite creates a layer that is writable for use as a container
+// file system.
+func (d *Driver) CreateReadWrite(id, parent, mountLabel string, storageOpt map[string]string) error {
+	return d.Create(id, parent, mountLabel, storageOpt)
+}
+
 // Create prepares the filesystem for the VFS driver and copies the directory for the given id under the parent.
 func (d *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) error {
 	if len(storageOpt) != 0 {

+ 24 - 11
daemon/graphdriver/windows/windows.go

@@ -107,8 +107,18 @@ func (d *Driver) Exists(id string) bool {
 	return result
 }
 
-// Create creates a new layer with the given id.
+// CreateReadWrite creates a layer that is writable for use as a container
+// file system.
+func (d *Driver) CreateReadWrite(id, parent, mountLabel string, storageOpt map[string]string) error {
+	return d.create(id, parent, mountLabel, false, storageOpt)
+}
+
+// Create creates a new read-only layer with the given id.
 func (d *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) error {
+	return d.create(id, parent, mountLabel, true, storageOpt)
+}
+
+func (d *Driver) create(id, parent, mountLabel string, readOnly bool, storageOpt map[string]string) error {
 	if len(storageOpt) != 0 {
 		return fmt.Errorf("--storage-opt is not supported for windows")
 	}
@@ -125,27 +135,30 @@ func (d *Driver) Create(id, parent, mountLabel string, storageOpt map[string]str
 
 	var layerChain []string
 
-	parentIsInit := strings.HasSuffix(rPId, "-init")
-
-	if !parentIsInit && rPId != "" {
+	if rPId != "" {
 		parentPath, err := hcsshim.GetLayerMountPath(d.info, rPId)
 		if err != nil {
 			return err
 		}
-		layerChain = []string{parentPath}
+		if _, err := os.Stat(filepath.Join(parentPath, "Files")); err == nil {
+			// This is a legitimate parent layer (not the empty "-init" layer),
+			// so include it in the layer chain.
+			layerChain = []string{parentPath}
+		}
 	}
 
 	layerChain = append(layerChain, parentChain...)
 
-	if parentIsInit {
-		if len(layerChain) == 0 {
-			return fmt.Errorf("Cannot create a read/write layer without a parent layer.")
-		}
-		if err := hcsshim.CreateSandboxLayer(d.info, id, layerChain[0], layerChain); err != nil {
+	if readOnly {
+		if err := hcsshim.CreateLayer(d.info, id, rPId); err != nil {
 			return err
 		}
 	} else {
-		if err := hcsshim.CreateLayer(d.info, id, rPId); err != nil {
+		var parentPath string
+		if len(layerChain) != 0 {
+			parentPath = layerChain[0]
+		}
+		if err := hcsshim.CreateSandboxLayer(d.info, id, parentPath, layerChain); err != nil {
 			return err
 		}
 	}

+ 6 - 0
daemon/graphdriver/zfs/zfs.go

@@ -240,6 +240,12 @@ func (d *Driver) mountPath(id string) string {
 	return path.Join(d.options.mountPath, "graph", getMountpoint(id))
 }
 
+// CreateReadWrite creates a layer that is writable for use as a container
+// file system.
+func (d *Driver) CreateReadWrite(id, parent, mountLabel string, storageOpt map[string]string) error {
+	return d.Create(id, parent, mountLabel, storageOpt)
+}
+
 // Create prepares the dataset and filesystem for the ZFS driver for the given id under the parent.
 func (d *Driver) Create(id string, parent string, mountLabel string, storageOpt map[string]string) error {
 	if len(storageOpt) != 0 {

+ 15 - 0
integration-cli/docker_cli_external_graphdriver_unix_test.go

@@ -67,6 +67,7 @@ func (s *DockerExternalGraphdriverSuite) SetUpSuite(c *check.C) {
 		ID         string `json:",omitempty"`
 		Parent     string `json:",omitempty"`
 		MountLabel string `json:",omitempty"`
+		ReadOnly   bool   `json:",omitempty"`
 	}
 
 	type graphDriverResponse struct {
@@ -115,6 +116,20 @@ func (s *DockerExternalGraphdriverSuite) SetUpSuite(c *check.C) {
 		respond(w, "{}")
 	})
 
+	mux.HandleFunc("/GraphDriver.CreateReadWrite", func(w http.ResponseWriter, r *http.Request) {
+		s.ec.creations++
+
+		var req graphDriverRequest
+		if err := decReq(r.Body, &req, w); err != nil {
+			return
+		}
+		if err := driver.CreateReadWrite(req.ID, req.Parent, "", nil); err != nil {
+			respond(w, err)
+			return
+		}
+		respond(w, "{}")
+	})
+
 	mux.HandleFunc("/GraphDriver.Create", func(w http.ResponseWriter, r *http.Request) {
 		s.ec.creations++
 

+ 1 - 1
layer/layer_store.go

@@ -461,7 +461,7 @@ func (ls *layerStore) CreateRWLayer(name string, parent ChainID, mountLabel stri
 		m.initID = pid
 	}
 
-	if err = ls.driver.Create(m.mountID, pid, "", storageOpt); err != nil {
+	if err = ls.driver.CreateReadWrite(m.mountID, pid, "", storageOpt); err != nil {
 		return nil, err
 	}