github.com/olljanat/moby@v1.13.1/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  	getter "github.com/docker/docker/pkg/plugingetter"
    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, baseHostPath string, c client) volume.Driver {
    26  	proxy := &volumeDriverProxy{c}
    27  	return &volumeDriverAdapter{name: name, baseHostPath: baseHostPath, 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  	if drivers.plugingetter != nil {
   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.BasePath(), 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  	return nil, fmt.Errorf("Error looking up volume plugin %s", name)
   133  }
   134  
   135  func validateDriver(vd volume.Driver) error {
   136  	scope := vd.Scope()
   137  	if scope != volume.LocalScope && scope != volume.GlobalScope {
   138  		return fmt.Errorf("Driver %q provided an invalid capability scope: %s", vd.Name(), scope)
   139  	}
   140  	return nil
   141  }
   142  
   143  // GetDriver returns a volume driver by its name.
   144  // If the driver is empty, it looks for the local driver.
   145  func GetDriver(name string) (volume.Driver, error) {
   146  	if name == "" {
   147  		name = volume.DefaultDriverName
   148  	}
   149  	return lookup(name, getter.LOOKUP)
   150  }
   151  
   152  // CreateDriver returns a volume driver by its name and increments RefCount.
   153  // If the driver is empty, it looks for the local driver.
   154  func CreateDriver(name string) (volume.Driver, error) {
   155  	if name == "" {
   156  		name = volume.DefaultDriverName
   157  	}
   158  	return lookup(name, getter.ACQUIRE)
   159  }
   160  
   161  // RemoveDriver returns a volume driver by its name and decrements RefCount..
   162  // If the driver is empty, it looks for the local driver.
   163  func RemoveDriver(name string) (volume.Driver, error) {
   164  	if name == "" {
   165  		name = volume.DefaultDriverName
   166  	}
   167  	return lookup(name, getter.RELEASE)
   168  }
   169  
   170  // GetDriverList returns list of volume drivers registered.
   171  // If no driver is registered, empty string list will be returned.
   172  func GetDriverList() []string {
   173  	var driverList []string
   174  	drivers.Lock()
   175  	for driverName := range drivers.extensions {
   176  		driverList = append(driverList, driverName)
   177  	}
   178  	drivers.Unlock()
   179  	return driverList
   180  }
   181  
   182  // GetAllDrivers lists all the registered drivers
   183  func GetAllDrivers() ([]volume.Driver, error) {
   184  	var plugins []getter.CompatPlugin
   185  	if drivers.plugingetter != nil {
   186  		var err error
   187  		plugins, err = drivers.plugingetter.GetAllByCap(extName)
   188  		if err != nil {
   189  			return nil, fmt.Errorf("error listing plugins: %v", err)
   190  		}
   191  	}
   192  	var ds []volume.Driver
   193  
   194  	drivers.Lock()
   195  	defer drivers.Unlock()
   196  
   197  	for _, d := range drivers.extensions {
   198  		ds = append(ds, d)
   199  	}
   200  
   201  	for _, p := range plugins {
   202  		name := p.Name()
   203  		ext, ok := drivers.extensions[name]
   204  		if ok {
   205  			continue
   206  		}
   207  
   208  		ext = NewVolumeDriver(name, p.BasePath(), p.Client())
   209  		if p.IsV1() {
   210  			drivers.extensions[name] = ext
   211  		}
   212  		ds = append(ds, ext)
   213  	}
   214  	return ds, nil
   215  }