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  }