github.com/jiasir/docker@v1.3.3-0.20170609024000-252e610103e7/volume/drivers/extpoint.go (about) 1 //go:generate pluginrpc-gen -i $GOFILE -o proxy.go -type volumeDriver -name VolumeDriver 2 3 package volumedrivers 4 5 import ( 6 "fmt" 7 "sort" 8 "sync" 9 10 "github.com/docker/docker/pkg/locker" 11 getter "github.com/docker/docker/pkg/plugingetter" 12 "github.com/docker/docker/volume" 13 ) 14 15 // currently created by hand. generation tool would generate this like: 16 // $ extpoint-gen Driver > volume/extpoint.go 17 18 var drivers = &driverExtpoint{ 19 extensions: make(map[string]volume.Driver), 20 driverLock: &locker.Locker{}, 21 } 22 23 const extName = "VolumeDriver" 24 25 // NewVolumeDriver returns a driver has the given name mapped on the given client. 26 func NewVolumeDriver(name string, baseHostPath string, c client) volume.Driver { 27 proxy := &volumeDriverProxy{c} 28 return &volumeDriverAdapter{name: name, baseHostPath: baseHostPath, proxy: proxy} 29 } 30 31 // volumeDriver defines the available functions that volume plugins must implement. 32 // This interface is only defined to generate the proxy objects. 33 // It's not intended to be public or reused. 34 type volumeDriver interface { 35 // Create a volume with the given name 36 Create(name string, opts map[string]string) (err error) 37 // Remove the volume with the given name 38 Remove(name string) (err error) 39 // Get the mountpoint of the given volume 40 Path(name string) (mountpoint string, err error) 41 // Mount the given volume and return the mountpoint 42 Mount(name, id string) (mountpoint string, err error) 43 // Unmount the given volume 44 Unmount(name, id string) (err error) 45 // List lists all the volumes known to the driver 46 List() (volumes []*proxyVolume, err error) 47 // Get retrieves the volume with the requested name 48 Get(name string) (volume *proxyVolume, err error) 49 // Capabilities gets the list of capabilities of the driver 50 Capabilities() (capabilities volume.Capability, err error) 51 } 52 53 type driverExtpoint struct { 54 extensions map[string]volume.Driver 55 sync.Mutex 56 driverLock *locker.Locker 57 plugingetter getter.PluginGetter 58 } 59 60 // RegisterPluginGetter sets the plugingetter 61 func RegisterPluginGetter(plugingetter getter.PluginGetter) { 62 drivers.plugingetter = plugingetter 63 } 64 65 // Register associates the given driver to the given name, checking if 66 // the name is already associated 67 func Register(extension volume.Driver, name string) bool { 68 if name == "" { 69 return false 70 } 71 72 drivers.Lock() 73 defer drivers.Unlock() 74 75 _, exists := drivers.extensions[name] 76 if exists { 77 return false 78 } 79 80 if err := validateDriver(extension); err != nil { 81 return false 82 } 83 84 drivers.extensions[name] = extension 85 86 return true 87 } 88 89 // Unregister dissociates the name from its driver, if the association exists. 90 func Unregister(name string) bool { 91 drivers.Lock() 92 defer drivers.Unlock() 93 94 _, exists := drivers.extensions[name] 95 if !exists { 96 return false 97 } 98 delete(drivers.extensions, name) 99 return true 100 } 101 102 // lookup returns the driver associated with the given name. If a 103 // driver with the given name has not been registered it checks if 104 // there is a VolumeDriver plugin available with the given name. 105 func lookup(name string, mode int) (volume.Driver, error) { 106 drivers.driverLock.Lock(name) 107 defer drivers.driverLock.Unlock(name) 108 109 drivers.Lock() 110 ext, ok := drivers.extensions[name] 111 drivers.Unlock() 112 if ok { 113 return ext, nil 114 } 115 if drivers.plugingetter != nil { 116 p, err := drivers.plugingetter.Get(name, extName, mode) 117 if err != nil { 118 return nil, fmt.Errorf("Error looking up volume plugin %s: %v", name, err) 119 } 120 121 d := NewVolumeDriver(p.Name(), p.BasePath(), p.Client()) 122 if err := validateDriver(d); err != nil { 123 return nil, err 124 } 125 126 if p.IsV1() { 127 drivers.Lock() 128 drivers.extensions[name] = d 129 drivers.Unlock() 130 } 131 return d, nil 132 } 133 return nil, fmt.Errorf("Error looking up volume plugin %s", name) 134 } 135 136 func validateDriver(vd volume.Driver) error { 137 scope := vd.Scope() 138 if scope != volume.LocalScope && scope != volume.GlobalScope { 139 return fmt.Errorf("Driver %q provided an invalid capability scope: %s", vd.Name(), scope) 140 } 141 return nil 142 } 143 144 // GetDriver returns a volume driver by its name. 145 // If the driver is empty, it looks for the local driver. 146 func GetDriver(name string) (volume.Driver, error) { 147 if name == "" { 148 name = volume.DefaultDriverName 149 } 150 return lookup(name, getter.Lookup) 151 } 152 153 // CreateDriver returns a volume driver by its name and increments RefCount. 154 // If the driver is empty, it looks for the local driver. 155 func CreateDriver(name string) (volume.Driver, error) { 156 if name == "" { 157 name = volume.DefaultDriverName 158 } 159 return lookup(name, getter.Acquire) 160 } 161 162 // RemoveDriver returns a volume driver by its name and decrements RefCount.. 163 // If the driver is empty, it looks for the local driver. 164 func RemoveDriver(name string) (volume.Driver, error) { 165 if name == "" { 166 name = volume.DefaultDriverName 167 } 168 return lookup(name, getter.Release) 169 } 170 171 // GetDriverList returns list of volume drivers registered. 172 // If no driver is registered, empty string list will be returned. 173 func GetDriverList() []string { 174 var driverList []string 175 drivers.Lock() 176 for driverName := range drivers.extensions { 177 driverList = append(driverList, driverName) 178 } 179 drivers.Unlock() 180 sort.Strings(driverList) 181 return driverList 182 } 183 184 // GetAllDrivers lists all the registered drivers 185 func GetAllDrivers() ([]volume.Driver, error) { 186 var plugins []getter.CompatPlugin 187 if drivers.plugingetter != nil { 188 var err error 189 plugins, err = drivers.plugingetter.GetAllByCap(extName) 190 if err != nil { 191 return nil, fmt.Errorf("error listing plugins: %v", err) 192 } 193 } 194 var ds []volume.Driver 195 196 drivers.Lock() 197 defer drivers.Unlock() 198 199 for _, d := range drivers.extensions { 200 ds = append(ds, d) 201 } 202 203 for _, p := range plugins { 204 name := p.Name() 205 206 if _, ok := drivers.extensions[name]; ok { 207 continue 208 } 209 210 ext := NewVolumeDriver(name, p.BasePath(), p.Client()) 211 if p.IsV1() { 212 drivers.extensions[name] = ext 213 } 214 ds = append(ds, ext) 215 } 216 return ds, nil 217 }