| package graphdriver // import "github.com/docker/docker/daemon/graphdriver" |
| |
| import ( |
| "errors" |
| "fmt" |
| "io" |
| |
| "github.com/docker/docker/pkg/archive" |
| "github.com/docker/docker/pkg/containerfs" |
| "github.com/docker/docker/pkg/idtools" |
| "github.com/docker/docker/pkg/plugingetter" |
| "github.com/docker/docker/pkg/plugins" |
| ) |
| |
| type graphDriverProxy struct { |
| name string |
| p plugingetter.CompatPlugin |
| caps Capabilities |
| client *plugins.Client |
| } |
| |
| type graphDriverRequest struct { |
| ID string `json:",omitempty"` |
| Parent string `json:",omitempty"` |
| MountLabel string `json:",omitempty"` |
| StorageOpt map[string]string `json:",omitempty"` |
| } |
| |
| type graphDriverResponse struct { |
| Err string `json:",omitempty"` |
| Dir string `json:",omitempty"` |
| Exists bool `json:",omitempty"` |
| Status [][2]string `json:",omitempty"` |
| Changes []archive.Change `json:",omitempty"` |
| Size int64 `json:",omitempty"` |
| Metadata map[string]string `json:",omitempty"` |
| Capabilities Capabilities `json:",omitempty"` |
| } |
| |
| type graphDriverInitRequest struct { |
| Home string |
| Opts []string `json:"Opts"` |
| UIDMaps []idtools.IDMap `json:"UIDMaps"` |
| GIDMaps []idtools.IDMap `json:"GIDMaps"` |
| } |
| |
| func (d *graphDriverProxy) Init(home string, opts []string, uidMaps, gidMaps []idtools.IDMap) error { |
| if !d.p.IsV1() { |
| if cp, ok := d.p.(plugingetter.CountedPlugin); ok { |
| // always acquire here, it will be cleaned up on daemon shutdown |
| cp.Acquire() |
| } |
| } |
| args := &graphDriverInitRequest{ |
| Home: home, |
| Opts: opts, |
| UIDMaps: uidMaps, |
| GIDMaps: gidMaps, |
| } |
| var ret graphDriverResponse |
| if err := d.client.Call("GraphDriver.Init", args, &ret); err != nil { |
| return err |
| } |
| if ret.Err != "" { |
| return errors.New(ret.Err) |
| } |
| caps, err := d.fetchCaps() |
| if err != nil { |
| return err |
| } |
| d.caps = caps |
| return nil |
| } |
| |
| func (d *graphDriverProxy) fetchCaps() (Capabilities, error) { |
| args := &graphDriverRequest{} |
| var ret graphDriverResponse |
| if err := d.client.Call("GraphDriver.Capabilities", args, &ret); err != nil { |
| if !plugins.IsNotFound(err) { |
| return Capabilities{}, err |
| } |
| } |
| return ret.Capabilities, nil |
| } |
| |
| func (d *graphDriverProxy) String() string { |
| return d.name |
| } |
| |
| func (d *graphDriverProxy) Capabilities() Capabilities { |
| return d.caps |
| } |
| |
| func (d *graphDriverProxy) CreateReadWrite(id, parent string, opts *CreateOpts) error { |
| return d.create("GraphDriver.CreateReadWrite", id, parent, opts) |
| } |
| |
| func (d *graphDriverProxy) Create(id, parent string, opts *CreateOpts) error { |
| return d.create("GraphDriver.Create", id, parent, opts) |
| } |
| |
| func (d *graphDriverProxy) create(method, id, parent string, opts *CreateOpts) error { |
| args := &graphDriverRequest{ |
| ID: id, |
| Parent: parent, |
| } |
| if opts != nil { |
| args.MountLabel = opts.MountLabel |
| args.StorageOpt = opts.StorageOpt |
| } |
| var ret graphDriverResponse |
| if err := d.client.Call(method, args, &ret); err != nil { |
| return err |
| } |
| if ret.Err != "" { |
| return errors.New(ret.Err) |
| } |
| return nil |
| } |
| |
| func (d *graphDriverProxy) Remove(id string) error { |
| args := &graphDriverRequest{ID: id} |
| var ret graphDriverResponse |
| if err := d.client.Call("GraphDriver.Remove", args, &ret); err != nil { |
| return err |
| } |
| if ret.Err != "" { |
| return errors.New(ret.Err) |
| } |
| return nil |
| } |
| |
| func (d *graphDriverProxy) Get(id, mountLabel string) (containerfs.ContainerFS, error) { |
| args := &graphDriverRequest{ |
| ID: id, |
| MountLabel: mountLabel, |
| } |
| var ret graphDriverResponse |
| if err := d.client.Call("GraphDriver.Get", args, &ret); err != nil { |
| return nil, err |
| } |
| var err error |
| if ret.Err != "" { |
| err = errors.New(ret.Err) |
| } |
| return containerfs.NewLocalContainerFS(d.p.ScopedPath(ret.Dir)), err |
| } |
| |
| func (d *graphDriverProxy) Put(id string) error { |
| args := &graphDriverRequest{ID: id} |
| var ret graphDriverResponse |
| if err := d.client.Call("GraphDriver.Put", args, &ret); err != nil { |
| return err |
| } |
| if ret.Err != "" { |
| return errors.New(ret.Err) |
| } |
| return nil |
| } |
| |
| func (d *graphDriverProxy) Exists(id string) bool { |
| args := &graphDriverRequest{ID: id} |
| var ret graphDriverResponse |
| if err := d.client.Call("GraphDriver.Exists", args, &ret); err != nil { |
| return false |
| } |
| return ret.Exists |
| } |
| |
| func (d *graphDriverProxy) Status() [][2]string { |
| args := &graphDriverRequest{} |
| var ret graphDriverResponse |
| if err := d.client.Call("GraphDriver.Status", args, &ret); err != nil { |
| return nil |
| } |
| return ret.Status |
| } |
| |
| func (d *graphDriverProxy) GetMetadata(id string) (map[string]string, error) { |
| args := &graphDriverRequest{ |
| ID: id, |
| } |
| var ret graphDriverResponse |
| if err := d.client.Call("GraphDriver.GetMetadata", args, &ret); err != nil { |
| return nil, err |
| } |
| if ret.Err != "" { |
| return nil, errors.New(ret.Err) |
| } |
| return ret.Metadata, nil |
| } |
| |
| func (d *graphDriverProxy) Cleanup() error { |
| if !d.p.IsV1() { |
| if cp, ok := d.p.(plugingetter.CountedPlugin); ok { |
| // always release |
| defer cp.Release() |
| } |
| } |
| |
| args := &graphDriverRequest{} |
| var ret graphDriverResponse |
| if err := d.client.Call("GraphDriver.Cleanup", args, &ret); err != nil { |
| return nil |
| } |
| if ret.Err != "" { |
| return errors.New(ret.Err) |
| } |
| return nil |
| } |
| |
| func (d *graphDriverProxy) Diff(id, parent string) (io.ReadCloser, error) { |
| args := &graphDriverRequest{ |
| ID: id, |
| Parent: parent, |
| } |
| body, err := d.client.Stream("GraphDriver.Diff", args) |
| if err != nil { |
| return nil, err |
| } |
| return body, nil |
| } |
| |
| func (d *graphDriverProxy) Changes(id, parent string) ([]archive.Change, error) { |
| args := &graphDriverRequest{ |
| ID: id, |
| Parent: parent, |
| } |
| var ret graphDriverResponse |
| if err := d.client.Call("GraphDriver.Changes", args, &ret); err != nil { |
| return nil, err |
| } |
| if ret.Err != "" { |
| return nil, errors.New(ret.Err) |
| } |
| |
| return ret.Changes, nil |
| } |
| |
| func (d *graphDriverProxy) ApplyDiff(id, parent string, diff io.Reader) (int64, error) { |
| var ret graphDriverResponse |
| if err := d.client.SendFile(fmt.Sprintf("GraphDriver.ApplyDiff?id=%s&parent=%s", id, parent), diff, &ret); err != nil { |
| return -1, err |
| } |
| if ret.Err != "" { |
| return -1, errors.New(ret.Err) |
| } |
| return ret.Size, nil |
| } |
| |
| func (d *graphDriverProxy) DiffSize(id, parent string) (int64, error) { |
| args := &graphDriverRequest{ |
| ID: id, |
| Parent: parent, |
| } |
| var ret graphDriverResponse |
| if err := d.client.Call("GraphDriver.DiffSize", args, &ret); err != nil { |
| return -1, err |
| } |
| if ret.Err != "" { |
| return -1, errors.New(ret.Err) |
| } |
| return ret.Size, nil |
| } |