// Init returns a new BTRFS driver. // An error is returned if BTRFS is not supported. func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { fsMagic, err := graphdriver.GetFSMagic(home) if err != nil { return nil, err } if fsMagic != graphdriver.FsMagicBtrfs { return nil, graphdriver.ErrPrerequisites } rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) if err != nil { return nil, err } if err := idtools.MkdirAllAs(home, 0700, rootUID, rootGID); err != nil { return nil, err } if err := mount.MakePrivate(home); err != nil { return nil, err } driver := &Driver{ home: home, uidMaps: uidMaps, gidMaps: gidMaps, } return graphdriver.NewNaiveDiffDriver(driver, uidMaps, gidMaps), nil }
// Init creates a driver with the given home and the set of options. func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { fsMagic, err := graphdriver.GetFSMagic(home) if err != nil { return nil, err } if fsName, ok := graphdriver.FsNames[fsMagic]; ok { backingFs = fsName } deviceSet, err := NewDeviceSet(home, true, options, uidMaps, gidMaps) if err != nil { return nil, err } if err := mount.MakePrivate(home); err != nil { return nil, err } d := &Driver{ DeviceSet: deviceSet, home: home, uidMaps: uidMaps, gidMaps: gidMaps, } return graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps), nil }
// Init returns a new BTRFS driver. // An error is returned if BTRFS is not supported. func Init(home string, options []string) (graphdriver.Driver, error) { rootdir := path.Dir(home) var buf syscall.Statfs_t if err := syscall.Statfs(rootdir, &buf); err != nil { return nil, err } if graphdriver.FsMagic(buf.Type) != graphdriver.FsMagicBtrfs { return nil, graphdriver.ErrPrerequisites } if err := os.MkdirAll(home, 0700); err != nil { return nil, err } if err := mount.MakePrivate(home); err != nil { return nil, err } driver := &Driver{ home: home, } return graphdriver.NewNaiveDiffDriver(driver), nil }
// Init returns a new BTRFS driver. // An error is returned if BTRFS is not supported. func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { rootdir := path.Dir(home) var buf syscall.Statfs_t if err := syscall.Statfs(rootdir, &buf); err != nil { return nil, err } if graphdriver.FsMagic(buf.Type) != graphdriver.FsMagicBtrfs { return nil, graphdriver.ErrPrerequisites } rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) if err != nil { return nil, err } if err := idtools.MkdirAllAs(home, 0700, rootUID, rootGID); err != nil { return nil, err } if err := mount.MakePrivate(home); err != nil { return nil, err } driver := &Driver{ home: home, uidMaps: uidMaps, gidMaps: gidMaps, } return graphdriver.NewNaiveDiffDriver(driver, uidMaps, gidMaps), nil }
// Init returns a new VFS driver. // This sets the home directory for the driver and returns NaiveDiffDriver. func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { d := &Driver{ home: home, uidMaps: uidMaps, gidMaps: gidMaps, } rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) if err != nil { return nil, err } if err := idtools.MkdirAllAs(home, 0700, rootUID, rootGID); err != nil { return nil, err } return graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps), nil }
// Init returns a new BTRFS driver. // An error is returned if BTRFS is not supported. func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { fsMagic, err := graphdriver.GetFSMagic(home) if err != nil { return nil, err } if fsMagic != graphdriver.FsMagicBtrfs { return nil, graphdriver.ErrPrerequisites } rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) if err != nil { return nil, err } if err := idtools.MkdirAllAs(home, 0700, rootUID, rootGID); err != nil { return nil, err } if err := mount.MakePrivate(home); err != nil { return nil, err } opt, err := parseOptions(options) if err != nil { return nil, err } if userDiskQuota { if err := subvolEnableQuota(home); err != nil { return nil, err } quotaEnabled = true } driver := &Driver{ home: home, uidMaps: uidMaps, gidMaps: gidMaps, options: opt, } return graphdriver.NewNaiveDiffDriver(driver, uidMaps, gidMaps), nil }
// Init creates a driver with the given home and the set of options. func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { deviceSet, err := NewDeviceSet(home, true, options, uidMaps, gidMaps) if err != nil { return nil, err } if err := mount.MakePrivate(home); err != nil { return nil, err } d := &Driver{ DeviceSet: deviceSet, home: home, uidMaps: uidMaps, gidMaps: gidMaps, } return graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps), nil }
func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { if err := os.MkdirAll(home, 0700); err != nil && !os.IsExist(err) { log.Errorf("Rbd create home dir %s failed: %v", err) return nil, err } rbdSet, err := NewRbdSet(home, true, options, uidMaps, gidMaps) if err != nil { return nil, err } if err := mount.MakePrivate(home); err != nil { return nil, err } d := &Driver{ RbdSet: rbdSet, home: home, uidMaps: uidMaps, gidMaps: gidMaps, } return graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps), nil }
// Init returns a new ZFS driver. // It takes base mount path and an array of options which are represented as key value pairs. // Each option is in the for key=value. 'zfs.fsname' is expected to be a valid key in the options. func Init(base string, opt []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { var err error if _, err := exec.LookPath("zfs"); err != nil { logrus.Debugf("[zfs] zfs command is not available: %v", err) return nil, graphdriver.ErrPrerequisites } file, err := os.OpenFile("/dev/zfs", os.O_RDWR, 600) if err != nil { logrus.Debugf("[zfs] cannot open /dev/zfs: %v", err) return nil, graphdriver.ErrPrerequisites } defer file.Close() options, err := parseOptions(opt) if err != nil { return nil, err } options.mountPath = base rootdir := path.Dir(base) if options.fsName == "" { err = checkRootdirFs(rootdir) if err != nil { return nil, err } } if options.fsName == "" { options.fsName, err = lookupZfsDataset(rootdir) if err != nil { return nil, err } } zfs.SetLogger(new(Logger)) filesystems, err := zfs.Filesystems(options.fsName) if err != nil { return nil, fmt.Errorf("Cannot find root filesystem %s: %v", options.fsName, err) } filesystemsCache := make(map[string]bool, len(filesystems)) var rootDataset *zfs.Dataset for _, fs := range filesystems { if fs.Name == options.fsName { rootDataset = fs } filesystemsCache[fs.Name] = true } if rootDataset == nil { return nil, fmt.Errorf("BUG: zfs get all -t filesystem -rHp '%s' should contain '%s'", options.fsName, options.fsName) } rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) if err != nil { return nil, fmt.Errorf("Failed to get root uid/guid: %v", err) } if err := idtools.MkdirAllAs(base, 0700, rootUID, rootGID); err != nil { return nil, fmt.Errorf("Failed to create '%s': %v", base, err) } if err := mount.MakePrivate(base); err != nil { return nil, err } d := &Driver{ dataset: rootDataset, options: options, filesystemsCache: filesystemsCache, uidMaps: uidMaps, gidMaps: gidMaps, ctr: graphdriver.NewRefCounter(graphdriver.NewDefaultChecker()), } return graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps), nil }
// Init returns a new VFS driver. // This sets the home directory for the driver and returns NaiveDiffDriver. func Init(home string, options []string) (graphdriver.Driver, error) { d := &Driver{ home: home, } return graphdriver.NewNaiveDiffDriver(d), nil }
func (s *DockerExternalGraphdriverSuite) SetUpSuite(c *check.C) { mux := http.NewServeMux() s.server = httptest.NewServer(mux) type graphDriverRequest struct { ID string `json:",omitempty"` Parent string `json:",omitempty"` MountLabel string `json:",omitempty"` } type graphDriverResponse struct { Err error `json:",omitempty"` Dir string `json:",omitempty"` Exists bool `json:",omitempty"` Status [][2]string `json:",omitempty"` Metadata map[string]string `json:",omitempty"` Changes []archive.Change `json:",omitempty"` Size int64 `json:",omitempty"` } respond := func(w http.ResponseWriter, data interface{}) { w.Header().Set("Content-Type", "appplication/vnd.docker.plugins.v1+json") switch t := data.(type) { case error: fmt.Fprintln(w, fmt.Sprintf(`{"Err": %q}`, t.Error())) case string: fmt.Fprintln(w, t) default: json.NewEncoder(w).Encode(&data) } } decReq := func(b io.ReadCloser, out interface{}, w http.ResponseWriter) error { defer b.Close() if err := json.NewDecoder(b).Decode(&out); err != nil { http.Error(w, fmt.Sprintf("error decoding json: %s", err.Error()), 500) } return nil } base, err := ioutil.TempDir("", "external-graph-test") c.Assert(err, check.IsNil) vfsProto, err := vfs.Init(base, []string{}, nil, nil) if err != nil { c.Fatalf("error initializing graph driver: %v", err) } driver := graphdriver.NewNaiveDiffDriver(vfsProto, nil, nil) mux.HandleFunc("/Plugin.Activate", func(w http.ResponseWriter, r *http.Request) { s.ec.activations++ respond(w, `{"Implements": ["GraphDriver"]}`) }) mux.HandleFunc("/GraphDriver.Init", func(w http.ResponseWriter, r *http.Request) { s.ec.init++ respond(w, "{}") }) mux.HandleFunc("/GraphDriver.Create", 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.Create(req.ID, req.Parent); err != nil { respond(w, err) return } respond(w, "{}") }) mux.HandleFunc("/GraphDriver.Remove", func(w http.ResponseWriter, r *http.Request) { s.ec.removals++ var req graphDriverRequest if err := decReq(r.Body, &req, w); err != nil { return } if err := driver.Remove(req.ID); err != nil { respond(w, err) return } respond(w, "{}") }) mux.HandleFunc("/GraphDriver.Get", func(w http.ResponseWriter, r *http.Request) { s.ec.gets++ var req graphDriverRequest if err := decReq(r.Body, &req, w); err != nil { return } dir, err := driver.Get(req.ID, req.MountLabel) if err != nil { respond(w, err) return } respond(w, &graphDriverResponse{Dir: dir}) }) mux.HandleFunc("/GraphDriver.Put", func(w http.ResponseWriter, r *http.Request) { s.ec.puts++ var req graphDriverRequest if err := decReq(r.Body, &req, w); err != nil { return } if err := driver.Put(req.ID); err != nil { respond(w, err) return } respond(w, "{}") }) mux.HandleFunc("/GraphDriver.Exists", func(w http.ResponseWriter, r *http.Request) { s.ec.exists++ var req graphDriverRequest if err := decReq(r.Body, &req, w); err != nil { return } respond(w, &graphDriverResponse{Exists: driver.Exists(req.ID)}) }) mux.HandleFunc("/GraphDriver.Status", func(w http.ResponseWriter, r *http.Request) { s.ec.stats++ respond(w, &graphDriverResponse{Status: driver.Status()}) }) mux.HandleFunc("/GraphDriver.Cleanup", func(w http.ResponseWriter, r *http.Request) { s.ec.cleanups++ err := driver.Cleanup() if err != nil { respond(w, err) return } respond(w, `{}`) }) mux.HandleFunc("/GraphDriver.GetMetadata", func(w http.ResponseWriter, r *http.Request) { s.ec.metadata++ var req graphDriverRequest if err := decReq(r.Body, &req, w); err != nil { return } data, err := driver.GetMetadata(req.ID) if err != nil { respond(w, err) return } respond(w, &graphDriverResponse{Metadata: data}) }) mux.HandleFunc("/GraphDriver.Diff", func(w http.ResponseWriter, r *http.Request) { s.ec.diff++ var req graphDriverRequest if err := decReq(r.Body, &req, w); err != nil { return } diff, err := driver.Diff(req.ID, req.Parent) if err != nil { respond(w, err) return } io.Copy(w, diff) }) mux.HandleFunc("/GraphDriver.Changes", func(w http.ResponseWriter, r *http.Request) { s.ec.changes++ var req graphDriverRequest if err := decReq(r.Body, &req, w); err != nil { return } changes, err := driver.Changes(req.ID, req.Parent) if err != nil { respond(w, err) return } respond(w, &graphDriverResponse{Changes: changes}) }) mux.HandleFunc("/GraphDriver.ApplyDiff", func(w http.ResponseWriter, r *http.Request) { s.ec.applydiff++ var diff archive.Reader = r.Body defer r.Body.Close() id := r.URL.Query().Get("id") parent := r.URL.Query().Get("parent") if id == "" { http.Error(w, fmt.Sprintf("missing id"), 409) } size, err := driver.ApplyDiff(id, parent, diff) if err != nil { respond(w, err) return } respond(w, &graphDriverResponse{Size: size}) }) mux.HandleFunc("/GraphDriver.DiffSize", func(w http.ResponseWriter, r *http.Request) { s.ec.diffsize++ var req graphDriverRequest if err := decReq(r.Body, &req, w); err != nil { return } size, err := driver.DiffSize(req.ID, req.Parent) if err != nil { respond(w, err) return } respond(w, &graphDriverResponse{Size: size}) }) if err := os.MkdirAll("/etc/docker/plugins", 0755); err != nil { c.Fatal(err) } if err := ioutil.WriteFile("/etc/docker/plugins/test-external-graph-driver.spec", []byte(s.server.URL), 0644); err != nil { c.Fatal(err) } }
// NaiveDiffDriverWithApply returns a NaiveDiff driver with custom ApplyDiff. func NaiveDiffDriverWithApply(driver ApplyDiffProtoDriver, uidMaps, gidMaps []idtools.IDMap) graphdriver.Driver { return &naiveDiffDriverWithApply{ Driver: graphdriver.NewNaiveDiffDriver(driver, uidMaps, gidMaps), applyDiff: driver, } }
// NaiveDiffDriverWithApply returns a NaiveDiff driver with custom ApplyDiff. func NaiveDiffDriverWithApply(driver ApplyDiffProtoDriver) graphdriver.Driver { return &naiveDiffDriverWithApply{ Driver: graphdriver.NewNaiveDiffDriver(driver), applyDiff: driver, } }
// Init returns a new AUFS driver. // An error is returned if AUFS is not supported. func Init(root string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { // Try to load the aufs kernel module if err := supportsAufs(); err != nil { return nil, graphdriver.ErrNotSupported } fsMagic, err := graphdriver.GetFSMagic(root) if err != nil { return nil, err } if fsName, ok := graphdriver.FsNames[fsMagic]; ok { backingFs = fsName } switch fsMagic { case graphdriver.FsMagicAufs, graphdriver.FsMagicBtrfs, graphdriver.FsMagicEcryptfs: logrus.Errorf("AUFS is not supported over %s", backingFs) return nil, graphdriver.ErrIncompatibleFS } paths := []string{ "mnt", "diff", "layers", } a := &Driver{ root: root, uidMaps: uidMaps, gidMaps: gidMaps, pathCache: make(map[string]string), ctr: graphdriver.NewRefCounter(graphdriver.NewFsChecker(graphdriver.FsMagicAufs)), } rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) if err != nil { return nil, err } // Create the root aufs driver dir and return // if it already exists // If not populate the dir structure if err := idtools.MkdirAllAs(root, 0700, rootUID, rootGID); err != nil { if os.IsExist(err) { return a, nil } return nil, err } if err := mountpk.MakePrivate(root); err != nil { return nil, err } // Populate the dir structure for _, p := range paths { if err := idtools.MkdirAllAs(path.Join(root, p), 0700, rootUID, rootGID); err != nil { return nil, err } } a.naiveDiff = graphdriver.NewNaiveDiffDriver(a, uidMaps, gidMaps) return a, nil }
// Init returns a new ZFS driver. // It takes base mount path and a array of options which are represented as key value pairs. // Each option is in the for key=value. 'zfs.fsname' is expected to be a valid key in the options. func Init(base string, opt []string) (graphdriver.Driver, error) { var err error if _, err := exec.LookPath("zfs"); err != nil { logrus.Debugf("[zfs] zfs command is not available: %v", err) return nil, graphdriver.ErrPrerequisites } file, err := os.OpenFile("/dev/zfs", os.O_RDWR, 600) if err != nil { logrus.Debugf("[zfs] cannot open /dev/zfs: %v", err) return nil, graphdriver.ErrPrerequisites } defer file.Close() options, err := parseOptions(opt) if err != nil { return nil, err } options.mountPath = base rootdir := path.Dir(base) if options.fsName == "" { err = checkRootdirFs(rootdir) if err != nil { return nil, err } } if options.fsName == "" { options.fsName, err = lookupZfsDataset(rootdir) if err != nil { return nil, err } } zfs.SetLogger(new(Logger)) filesystems, err := zfs.Filesystems(options.fsName) if err != nil { return nil, fmt.Errorf("Cannot find root filesystem %s: %v", options.fsName, err) } filesystemsCache := make(map[string]bool, len(filesystems)) var rootDataset *zfs.Dataset for _, fs := range filesystems { if fs.Name == options.fsName { rootDataset = fs } filesystemsCache[fs.Name] = true } if rootDataset == nil { return nil, fmt.Errorf("BUG: zfs get all -t filesystem -rHp '%s' should contain '%s'", options.fsName, options.fsName) } d := &Driver{ dataset: rootDataset, options: options, filesystemsCache: filesystemsCache, } return graphdriver.NewNaiveDiffDriver(d), nil }
// Init returns the a native diff driver for overlay filesystem. // If overlay filesystem is not supported on the host, graphdriver.ErrNotSupported is returned as error. // If an overlay filesystem is not supported over an existing filesystem then error graphdriver.ErrIncompatibleFS is returned. func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { opts, err := parseOptions(options) if err != nil { return nil, err } if err := supportsOverlay(); err != nil { return nil, graphdriver.ErrNotSupported } // require kernel 4.0.0 to ensure multiple lower dirs are supported v, err := kernel.GetKernelVersion() if err != nil { return nil, err } if kernel.CompareKernelVersion(*v, kernel.VersionInfo{Kernel: 4, Major: 0, Minor: 0}) < 0 { if !opts.overrideKernelCheck { return nil, graphdriver.ErrNotSupported } logrus.Warn("Using pre-4.0.0 kernel for overlay2, mount failures may require kernel update") } fsMagic, err := graphdriver.GetFSMagic(home) if err != nil { return nil, err } if fsName, ok := graphdriver.FsNames[fsMagic]; ok { backingFs = fsName } // check if they are running over btrfs, aufs, zfs, overlay, or ecryptfs switch fsMagic { case graphdriver.FsMagicBtrfs, graphdriver.FsMagicAufs, graphdriver.FsMagicZfs, graphdriver.FsMagicOverlay, graphdriver.FsMagicEcryptfs: logrus.Errorf("'overlay2' is not supported over %s", backingFs) return nil, graphdriver.ErrIncompatibleFS } rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) if err != nil { return nil, err } // Create the driver home dir if err := idtools.MkdirAllAs(path.Join(home, linkDir), 0700, rootUID, rootGID); err != nil && !os.IsExist(err) { return nil, err } if err := mount.MakePrivate(home); err != nil { return nil, err } d := &Driver{ home: home, uidMaps: uidMaps, gidMaps: gidMaps, ctr: graphdriver.NewRefCounter(graphdriver.NewFsChecker(graphdriver.FsMagicOverlay)), } d.naiveDiff = graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps) if backingFs == "xfs" { // Try to enable project quota support over xfs. if d.quotaCtl, err = quota.NewControl(home); err == nil { projectQuotaSupported = true } } logrus.Debugf("backingFs=%s, projectQuotaSupported=%v", backingFs, projectQuotaSupported) return d, nil }