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