mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Adding readOnly parameter to graphdriver Create method
Since the layer store was introduced, the level above the graphdriver now differentiates between read/write and read-only layers. This distinction is useful for graphdrivers that need to take special steps when creating a layer based on whether it is read-only or not. Adding this parameter allows the graphdrivers to differentiate, which in the case of the Windows graphdriver, removes our dependence on parsing the id of the parent for "-init" in order to infer this information. This will also set the stage for unblocking some of the layer store unit tests in the next preview build of Windows. Signed-off-by: Stefan J. Wernli <swernli@microsoft.com>
This commit is contained in:
parent
fc9912fd00
commit
ef5bfad321
14 changed files with 104 additions and 21 deletions
|
@ -194,6 +194,12 @@ func (a *Driver) Exists(id string) bool {
|
||||||
return true
|
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
|
// Create three folders for each id
|
||||||
// mnt, layers, and diff
|
// mnt, layers, and diff
|
||||||
func (a *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) error {
|
func (a *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) error {
|
||||||
|
|
|
@ -320,7 +320,7 @@ func TestGetDiff(t *testing.T) {
|
||||||
d := newDriver(t)
|
d := newDriver(t)
|
||||||
defer os.RemoveAll(tmp)
|
defer os.RemoveAll(tmp)
|
||||||
|
|
||||||
if err := d.Create("1", "", "", nil); err != nil {
|
if err := d.CreateReadWrite("1", "", "", nil); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,7 +357,7 @@ func TestChanges(t *testing.T) {
|
||||||
if err := d.Create("1", "", "", nil); err != nil {
|
if err := d.Create("1", "", "", nil); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := d.Create("2", "1", "", nil); err != nil {
|
if err := d.CreateReadWrite("2", "1", "", nil); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,7 +403,7 @@ func TestChanges(t *testing.T) {
|
||||||
t.Fatalf("Change kind should be ChangeAdd got %s", change.Kind)
|
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)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
mntPoint, err = d.Get("3", "")
|
mntPoint, err = d.Get("3", "")
|
||||||
|
@ -448,7 +448,7 @@ func TestDiffSize(t *testing.T) {
|
||||||
d := newDriver(t)
|
d := newDriver(t)
|
||||||
defer os.RemoveAll(tmp)
|
defer os.RemoveAll(tmp)
|
||||||
|
|
||||||
if err := d.Create("1", "", "", nil); err != nil {
|
if err := d.CreateReadWrite("1", "", "", nil); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -490,7 +490,7 @@ func TestChildDiffSize(t *testing.T) {
|
||||||
defer os.RemoveAll(tmp)
|
defer os.RemoveAll(tmp)
|
||||||
defer d.Cleanup()
|
defer d.Cleanup()
|
||||||
|
|
||||||
if err := d.Create("1", "", "", nil); err != nil {
|
if err := d.CreateReadWrite("1", "", "", nil); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -592,7 +592,7 @@ func TestApplyDiff(t *testing.T) {
|
||||||
defer os.RemoveAll(tmp)
|
defer os.RemoveAll(tmp)
|
||||||
defer d.Cleanup()
|
defer d.Cleanup()
|
||||||
|
|
||||||
if err := d.Create("1", "", "", nil); err != nil {
|
if err := d.CreateReadWrite("1", "", "", nil); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -671,7 +671,7 @@ func testMountMoreThan42Layers(t *testing.T, mountPath string) {
|
||||||
}
|
}
|
||||||
current = hash(current)
|
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.Logf("Current layer %d", i)
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,6 +241,12 @@ func (d *Driver) subvolumesDirID(id string) string {
|
||||||
return path.Join(d.subvolumesDir(), id)
|
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.
|
// Create the filesystem with given id.
|
||||||
func (d *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) error {
|
func (d *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) error {
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ func TestBtrfsCreateSnap(t *testing.T) {
|
||||||
|
|
||||||
func TestBtrfsSubvolDelete(t *testing.T) {
|
func TestBtrfsSubvolDelete(t *testing.T) {
|
||||||
d := graphtest.GetDriver(t, "btrfs")
|
d := graphtest.GetDriver(t, "btrfs")
|
||||||
if err := d.Create("test", "", "", nil); err != nil {
|
if err := d.CreateReadWrite("test", "", "", nil); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer graphtest.PutDriver(t)
|
defer graphtest.PutDriver(t)
|
||||||
|
|
|
@ -117,6 +117,12 @@ func (d *Driver) Cleanup() error {
|
||||||
return err
|
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.
|
// Create adds a device with a given id and the parent.
|
||||||
func (d *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) error {
|
func (d *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) error {
|
||||||
if err := d.DeviceSet.AddDevice(id, parent, storageOpt); err != nil {
|
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
|
||||||
type ProtoDriver interface {
|
type ProtoDriver interface {
|
||||||
// String returns a string representation of this driver.
|
// String returns a string representation of this driver.
|
||||||
String() string
|
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
|
// Create creates a new, empty, filesystem layer with the
|
||||||
// specified id and parent and mountLabel. Parent and mountLabel may be "".
|
// specified id and parent and mountLabel. Parent and mountLabel may be "".
|
||||||
Create(id, parent, mountLabel string, storageOpt map[string]string) error
|
Create(id, parent, mountLabel string, storageOpt map[string]string) error
|
||||||
|
|
|
@ -215,7 +215,7 @@ func createBase(t *testing.T, driver graphdriver.Driver, name string) {
|
||||||
oldmask := syscall.Umask(0)
|
oldmask := syscall.Umask(0)
|
||||||
defer syscall.Umask(oldmask)
|
defer syscall.Umask(oldmask)
|
||||||
|
|
||||||
if err := driver.Create(name, "", "", nil); err != nil {
|
if err := driver.CreateReadWrite(name, "", "", nil); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -220,6 +220,12 @@ func (d *Driver) Cleanup() error {
|
||||||
return nil
|
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.
|
// 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.
|
// 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) {
|
func (d *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) (retErr error) {
|
||||||
|
|
|
@ -54,6 +54,22 @@ func (d *graphDriverProxy) String() string {
|
||||||
return d.name
|
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 {
|
func (d *graphDriverProxy) Create(id, parent, mountLabel string, storageOpt map[string]string) error {
|
||||||
args := &graphDriverRequest{
|
args := &graphDriverRequest{
|
||||||
ID: id,
|
ID: id,
|
||||||
|
|
|
@ -68,6 +68,12 @@ func (d *Driver) Cleanup() error {
|
||||||
return nil
|
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.
|
// 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 {
|
func (d *Driver) Create(id, parent, mountLabel string, storageOpt map[string]string) error {
|
||||||
if len(storageOpt) != 0 {
|
if len(storageOpt) != 0 {
|
||||||
|
|
|
@ -106,8 +106,18 @@ func (d *Driver) Exists(id string) bool {
|
||||||
return result
|
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 {
|
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 {
|
if len(storageOpt) != 0 {
|
||||||
return fmt.Errorf("--storage-opt is not supported for windows")
|
return fmt.Errorf("--storage-opt is not supported for windows")
|
||||||
}
|
}
|
||||||
|
@ -124,27 +134,30 @@ func (d *Driver) Create(id, parent, mountLabel string, storageOpt map[string]str
|
||||||
|
|
||||||
var layerChain []string
|
var layerChain []string
|
||||||
|
|
||||||
parentIsInit := strings.HasSuffix(rPId, "-init")
|
if rPId != "" {
|
||||||
|
|
||||||
if !parentIsInit && rPId != "" {
|
|
||||||
parentPath, err := hcsshim.GetLayerMountPath(d.info, rPId)
|
parentPath, err := hcsshim.GetLayerMountPath(d.info, rPId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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...)
|
layerChain = append(layerChain, parentChain...)
|
||||||
|
|
||||||
if parentIsInit {
|
if readOnly {
|
||||||
if len(layerChain) == 0 {
|
if err := hcsshim.CreateLayer(d.info, id, rPId); err != nil {
|
||||||
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 {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} 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
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -240,6 +240,12 @@ func (d *Driver) mountPath(id string) string {
|
||||||
return path.Join(d.options.mountPath, "graph", getMountpoint(id))
|
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.
|
// 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 {
|
func (d *Driver) Create(id string, parent string, mountLabel string, storageOpt map[string]string) error {
|
||||||
if len(storageOpt) != 0 {
|
if len(storageOpt) != 0 {
|
||||||
|
|
|
@ -67,6 +67,7 @@ func (s *DockerExternalGraphdriverSuite) SetUpSuite(c *check.C) {
|
||||||
ID string `json:",omitempty"`
|
ID string `json:",omitempty"`
|
||||||
Parent string `json:",omitempty"`
|
Parent string `json:",omitempty"`
|
||||||
MountLabel string `json:",omitempty"`
|
MountLabel string `json:",omitempty"`
|
||||||
|
ReadOnly bool `json:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type graphDriverResponse struct {
|
type graphDriverResponse struct {
|
||||||
|
@ -115,6 +116,20 @@ func (s *DockerExternalGraphdriverSuite) SetUpSuite(c *check.C) {
|
||||||
respond(w, "{}")
|
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) {
|
mux.HandleFunc("/GraphDriver.Create", func(w http.ResponseWriter, r *http.Request) {
|
||||||
s.ec.creations++
|
s.ec.creations++
|
||||||
|
|
||||||
|
|
|
@ -461,7 +461,7 @@ func (ls *layerStore) CreateRWLayer(name string, parent ChainID, mountLabel stri
|
||||||
m.initID = pid
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue