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  }