github.com/OpenFlowLabs/moby@v17.12.1-ce-rc2+incompatible/volume/drivers/adapter.go (about) 1 package volumedrivers 2 3 import ( 4 "errors" 5 "path/filepath" 6 "strings" 7 "time" 8 9 "github.com/docker/docker/volume" 10 "github.com/sirupsen/logrus" 11 ) 12 13 var ( 14 errNoSuchVolume = errors.New("no such volume") 15 ) 16 17 type volumeDriverAdapter struct { 18 name string 19 baseHostPath string 20 capabilities *volume.Capability 21 proxy *volumeDriverProxy 22 } 23 24 func (a *volumeDriverAdapter) Name() string { 25 return a.name 26 } 27 28 func (a *volumeDriverAdapter) Create(name string, opts map[string]string) (volume.Volume, error) { 29 if err := a.proxy.Create(name, opts); err != nil { 30 return nil, err 31 } 32 return &volumeAdapter{ 33 proxy: a.proxy, 34 name: name, 35 driverName: a.name, 36 baseHostPath: a.baseHostPath, 37 }, nil 38 } 39 40 func (a *volumeDriverAdapter) Remove(v volume.Volume) error { 41 return a.proxy.Remove(v.Name()) 42 } 43 44 func hostPath(baseHostPath, path string) string { 45 if baseHostPath != "" { 46 path = filepath.Join(baseHostPath, path) 47 } 48 return path 49 } 50 51 func (a *volumeDriverAdapter) List() ([]volume.Volume, error) { 52 ls, err := a.proxy.List() 53 if err != nil { 54 return nil, err 55 } 56 57 var out []volume.Volume 58 for _, vp := range ls { 59 out = append(out, &volumeAdapter{ 60 proxy: a.proxy, 61 name: vp.Name, 62 baseHostPath: a.baseHostPath, 63 driverName: a.name, 64 eMount: hostPath(a.baseHostPath, vp.Mountpoint), 65 }) 66 } 67 return out, nil 68 } 69 70 func (a *volumeDriverAdapter) Get(name string) (volume.Volume, error) { 71 v, err := a.proxy.Get(name) 72 if err != nil { 73 return nil, err 74 } 75 76 // plugin may have returned no volume and no error 77 if v == nil { 78 return nil, errNoSuchVolume 79 } 80 81 return &volumeAdapter{ 82 proxy: a.proxy, 83 name: v.Name, 84 driverName: a.Name(), 85 eMount: v.Mountpoint, 86 createdAt: v.CreatedAt, 87 status: v.Status, 88 baseHostPath: a.baseHostPath, 89 }, nil 90 } 91 92 func (a *volumeDriverAdapter) Scope() string { 93 cap := a.getCapabilities() 94 return cap.Scope 95 } 96 97 func (a *volumeDriverAdapter) getCapabilities() volume.Capability { 98 if a.capabilities != nil { 99 return *a.capabilities 100 } 101 cap, err := a.proxy.Capabilities() 102 if err != nil { 103 // `GetCapabilities` is a not a required endpoint. 104 // On error assume it's a local-only driver 105 logrus.Warnf("Volume driver %s returned an error while trying to query its capabilities, using default capabilities: %v", a.name, err) 106 return volume.Capability{Scope: volume.LocalScope} 107 } 108 109 // don't spam the warn log below just because the plugin didn't provide a scope 110 if len(cap.Scope) == 0 { 111 cap.Scope = volume.LocalScope 112 } 113 114 cap.Scope = strings.ToLower(cap.Scope) 115 if cap.Scope != volume.LocalScope && cap.Scope != volume.GlobalScope { 116 logrus.Warnf("Volume driver %q returned an invalid scope: %q", a.Name(), cap.Scope) 117 cap.Scope = volume.LocalScope 118 } 119 120 a.capabilities = &cap 121 return cap 122 } 123 124 type volumeAdapter struct { 125 proxy *volumeDriverProxy 126 name string 127 baseHostPath string 128 driverName string 129 eMount string // ephemeral host volume path 130 createdAt time.Time // time the directory was created 131 status map[string]interface{} 132 } 133 134 type proxyVolume struct { 135 Name string 136 Mountpoint string 137 CreatedAt time.Time 138 Status map[string]interface{} 139 } 140 141 func (a *volumeAdapter) Name() string { 142 return a.name 143 } 144 145 func (a *volumeAdapter) DriverName() string { 146 return a.driverName 147 } 148 149 func (a *volumeAdapter) Path() string { 150 if len(a.eMount) == 0 { 151 mountpoint, _ := a.proxy.Path(a.name) 152 a.eMount = hostPath(a.baseHostPath, mountpoint) 153 } 154 return a.eMount 155 } 156 157 func (a *volumeAdapter) CachedPath() string { 158 return a.eMount 159 } 160 161 func (a *volumeAdapter) Mount(id string) (string, error) { 162 mountpoint, err := a.proxy.Mount(a.name, id) 163 a.eMount = hostPath(a.baseHostPath, mountpoint) 164 return a.eMount, err 165 } 166 167 func (a *volumeAdapter) Unmount(id string) error { 168 err := a.proxy.Unmount(a.name, id) 169 if err == nil { 170 a.eMount = "" 171 } 172 return err 173 } 174 175 func (a *volumeAdapter) CreatedAt() (time.Time, error) { 176 return a.createdAt, nil 177 } 178 func (a *volumeAdapter) Status() map[string]interface{} { 179 out := make(map[string]interface{}, len(a.status)) 180 for k, v := range a.status { 181 out[k] = v 182 } 183 return out 184 }