github.com/MaximeAubanel/moby@v1.13.1/volume/store/store.go (about)

     1  package store
     2  
     3  import (
     4  	"net"
     5  	"os"
     6  	"path/filepath"
     7  	"sync"
     8  	"time"
     9  
    10  	"github.com/pkg/errors"
    11  
    12  	"github.com/Sirupsen/logrus"
    13  	"github.com/boltdb/bolt"
    14  	"github.com/docker/docker/pkg/locker"
    15  	"github.com/docker/docker/volume"
    16  	"github.com/docker/docker/volume/drivers"
    17  )
    18  
    19  const (
    20  	volumeDataDir = "volumes"
    21  )
    22  
    23  type volumeWrapper struct {
    24  	volume.Volume
    25  	labels  map[string]string
    26  	scope   string
    27  	options map[string]string
    28  }
    29  
    30  func (v volumeWrapper) Options() map[string]string {
    31  	options := map[string]string{}
    32  	for key, value := range v.options {
    33  		options[key] = value
    34  	}
    35  	return options
    36  }
    37  
    38  func (v volumeWrapper) Labels() map[string]string {
    39  	return v.labels
    40  }
    41  
    42  func (v volumeWrapper) Scope() string {
    43  	return v.scope
    44  }
    45  
    46  func (v volumeWrapper) CachedPath() string {
    47  	if vv, ok := v.Volume.(interface {
    48  		CachedPath() string
    49  	}); ok {
    50  		return vv.CachedPath()
    51  	}
    52  	return v.Volume.Path()
    53  }
    54  
    55  // New initializes a VolumeStore to keep
    56  // reference counting of volumes in the system.
    57  func New(rootPath string) (*VolumeStore, error) {
    58  	vs := &VolumeStore{
    59  		locks:   &locker.Locker{},
    60  		names:   make(map[string]volume.Volume),
    61  		refs:    make(map[string][]string),
    62  		labels:  make(map[string]map[string]string),
    63  		options: make(map[string]map[string]string),
    64  	}
    65  
    66  	if rootPath != "" {
    67  		// initialize metadata store
    68  		volPath := filepath.Join(rootPath, volumeDataDir)
    69  		if err := os.MkdirAll(volPath, 750); err != nil {
    70  			return nil, err
    71  		}
    72  
    73  		dbPath := filepath.Join(volPath, "metadata.db")
    74  
    75  		var err error
    76  		vs.db, err = bolt.Open(dbPath, 0600, &bolt.Options{Timeout: 1 * time.Second})
    77  		if err != nil {
    78  			return nil, errors.Wrap(err, "error while opening volume store metadata database")
    79  		}
    80  
    81  		// initialize volumes bucket
    82  		if err := vs.db.Update(func(tx *bolt.Tx) error {
    83  			if _, err := tx.CreateBucketIfNotExists(volumeBucketName); err != nil {
    84  				return errors.Wrap(err, "error while setting up volume store metadata database")
    85  			}
    86  			return nil
    87  		}); err != nil {
    88  			return nil, err
    89  		}
    90  	}
    91  
    92  	vs.restore()
    93  
    94  	return vs, nil
    95  }
    96  
    97  func (s *VolumeStore) getNamed(name string) (volume.Volume, bool) {
    98  	s.globalLock.RLock()
    99  	v, exists := s.names[name]
   100  	s.globalLock.RUnlock()
   101  	return v, exists
   102  }
   103  
   104  func (s *VolumeStore) setNamed(v volume.Volume, ref string) {
   105  	s.globalLock.Lock()
   106  	s.names[v.Name()] = v
   107  	if len(ref) > 0 {
   108  		s.refs[v.Name()] = append(s.refs[v.Name()], ref)
   109  	}
   110  	s.globalLock.Unlock()
   111  }
   112  
   113  // getRefs gets the list of refs for a given name
   114  // Callers of this function are expected to hold the name lock.
   115  func (s *VolumeStore) getRefs(name string) []string {
   116  	s.globalLock.RLock()
   117  	refs := s.refs[name]
   118  	s.globalLock.RUnlock()
   119  	return refs
   120  }
   121  
   122  // Purge allows the cleanup of internal data on docker in case
   123  // the internal data is out of sync with volumes driver plugins.
   124  func (s *VolumeStore) Purge(name string) {
   125  	s.globalLock.Lock()
   126  	v, exists := s.names[name]
   127  	if exists {
   128  		if _, err := volumedrivers.RemoveDriver(v.DriverName()); err != nil {
   129  			logrus.Error("Error dereferencing volume driver: %v", err)
   130  		}
   131  	}
   132  	if err := s.removeMeta(name); err != nil {
   133  		logrus.Errorf("Error removing volume metadata for volume %q: %v", name, err)
   134  	}
   135  	delete(s.names, name)
   136  	delete(s.refs, name)
   137  	delete(s.labels, name)
   138  	delete(s.options, name)
   139  	s.globalLock.Unlock()
   140  }
   141  
   142  // VolumeStore is a struct that stores the list of volumes available and keeps track of their usage counts
   143  type VolumeStore struct {
   144  	// locks ensures that only one action is being performed on a particular volume at a time without locking the entire store
   145  	// since actions on volumes can be quite slow, this ensures the store is free to handle requests for other volumes.
   146  	locks *locker.Locker
   147  	// globalLock is used to protect access to mutable structures used by the store object
   148  	globalLock sync.RWMutex
   149  	// names stores the volume name -> volume relationship.
   150  	// This is used for making lookups faster so we don't have to probe all drivers
   151  	names map[string]volume.Volume
   152  	// refs stores the volume name and the list of things referencing it
   153  	refs map[string][]string
   154  	// labels stores volume labels for each volume
   155  	labels map[string]map[string]string
   156  	// options stores volume options for each volume
   157  	options map[string]map[string]string
   158  	db      *bolt.DB
   159  }
   160  
   161  // List proxies to all registered volume drivers to get the full list of volumes
   162  // If a driver returns a volume that has name which conflicts with another volume from a different driver,
   163  // the first volume is chosen and the conflicting volume is dropped.
   164  func (s *VolumeStore) List() ([]volume.Volume, []string, error) {
   165  	vols, warnings, err := s.list()
   166  	if err != nil {
   167  		return nil, nil, &OpErr{Err: err, Op: "list"}
   168  	}
   169  	var out []volume.Volume
   170  
   171  	for _, v := range vols {
   172  		name := normaliseVolumeName(v.Name())
   173  
   174  		s.locks.Lock(name)
   175  		storedV, exists := s.getNamed(name)
   176  		// Note: it's not safe to populate the cache here because the volume may have been
   177  		// deleted before we acquire a lock on its name
   178  		if exists && storedV.DriverName() != v.DriverName() {
   179  			logrus.Warnf("Volume name %s already exists for driver %s, not including volume returned by %s", v.Name(), storedV.DriverName(), v.DriverName())
   180  			s.locks.Unlock(v.Name())
   181  			continue
   182  		}
   183  
   184  		out = append(out, v)
   185  		s.locks.Unlock(v.Name())
   186  	}
   187  	return out, warnings, nil
   188  }
   189  
   190  // list goes through each volume driver and asks for its list of volumes.
   191  func (s *VolumeStore) list() ([]volume.Volume, []string, error) {
   192  	var (
   193  		ls       []volume.Volume
   194  		warnings []string
   195  	)
   196  
   197  	drivers, err := volumedrivers.GetAllDrivers()
   198  	if err != nil {
   199  		return nil, nil, err
   200  	}
   201  
   202  	type vols struct {
   203  		vols       []volume.Volume
   204  		err        error
   205  		driverName string
   206  	}
   207  	chVols := make(chan vols, len(drivers))
   208  
   209  	for _, vd := range drivers {
   210  		go func(d volume.Driver) {
   211  			vs, err := d.List()
   212  			if err != nil {
   213  				chVols <- vols{driverName: d.Name(), err: &OpErr{Err: err, Name: d.Name(), Op: "list"}}
   214  				return
   215  			}
   216  			for i, v := range vs {
   217  				s.globalLock.RLock()
   218  				vs[i] = volumeWrapper{v, s.labels[v.Name()], d.Scope(), s.options[v.Name()]}
   219  				s.globalLock.RUnlock()
   220  			}
   221  
   222  			chVols <- vols{vols: vs}
   223  		}(vd)
   224  	}
   225  
   226  	badDrivers := make(map[string]struct{})
   227  	for i := 0; i < len(drivers); i++ {
   228  		vs := <-chVols
   229  
   230  		if vs.err != nil {
   231  			warnings = append(warnings, vs.err.Error())
   232  			badDrivers[vs.driverName] = struct{}{}
   233  			logrus.Warn(vs.err)
   234  		}
   235  		ls = append(ls, vs.vols...)
   236  	}
   237  
   238  	if len(badDrivers) > 0 {
   239  		s.globalLock.RLock()
   240  		for _, v := range s.names {
   241  			if _, exists := badDrivers[v.DriverName()]; exists {
   242  				ls = append(ls, v)
   243  			}
   244  		}
   245  		s.globalLock.RUnlock()
   246  	}
   247  	return ls, warnings, nil
   248  }
   249  
   250  // CreateWithRef creates a volume with the given name and driver and stores the ref
   251  // This ensures there's no race between creating a volume and then storing a reference.
   252  func (s *VolumeStore) CreateWithRef(name, driverName, ref string, opts, labels map[string]string) (volume.Volume, error) {
   253  	name = normaliseVolumeName(name)
   254  	s.locks.Lock(name)
   255  	defer s.locks.Unlock(name)
   256  
   257  	v, err := s.create(name, driverName, opts, labels)
   258  	if err != nil {
   259  		return nil, &OpErr{Err: err, Name: name, Op: "create"}
   260  	}
   261  
   262  	s.setNamed(v, ref)
   263  	return v, nil
   264  }
   265  
   266  // Create creates a volume with the given name and driver.
   267  // This is just like CreateWithRef() except we don't store a reference while holding the lock.
   268  func (s *VolumeStore) Create(name, driverName string, opts, labels map[string]string) (volume.Volume, error) {
   269  	return s.CreateWithRef(name, driverName, "", opts, labels)
   270  }
   271  
   272  // checkConflict checks the local cache for name collisions with the passed in name,
   273  // for existing volumes with the same name but in a different driver.
   274  // This is used by `Create` as a best effort to prevent name collisions for volumes.
   275  // If a matching volume is found that is not a conflict that is returned so the caller
   276  // does not need to perform an additional lookup.
   277  // When no matching volume is found, both returns will be nil
   278  //
   279  // Note: This does not probe all the drivers for name collisions because v1 plugins
   280  // are very slow, particularly if the plugin is down, and cause other issues,
   281  // particularly around locking the store.
   282  // TODO(cpuguy83): With v2 plugins this shouldn't be a problem. Could also potentially
   283  // use a connect timeout for this kind of check to ensure we aren't blocking for a
   284  // long time.
   285  func (s *VolumeStore) checkConflict(name, driverName string) (volume.Volume, error) {
   286  	// check the local cache
   287  	v, _ := s.getNamed(name)
   288  	if v == nil {
   289  		return nil, nil
   290  	}
   291  
   292  	vDriverName := v.DriverName()
   293  	var conflict bool
   294  	if driverName != "" {
   295  		// Retrieve canonical driver name to avoid inconsistencies (for example
   296  		// "plugin" vs. "plugin:latest")
   297  		vd, err := volumedrivers.GetDriver(driverName)
   298  		if err != nil {
   299  			return nil, err
   300  		}
   301  
   302  		if vDriverName != vd.Name() {
   303  			conflict = true
   304  		}
   305  	}
   306  
   307  	// let's check if the found volume ref
   308  	// is stale by checking with the driver if it still exists
   309  	exists, err := volumeExists(v)
   310  	if err != nil {
   311  		return nil, errors.Wrapf(errNameConflict, "found reference to volume '%s' in driver '%s', but got an error while checking the driver: %v", name, vDriverName, err)
   312  	}
   313  
   314  	if exists {
   315  		if conflict {
   316  			return nil, errors.Wrapf(errNameConflict, "driver '%s' already has volume '%s'", vDriverName, name)
   317  		}
   318  		return v, nil
   319  	}
   320  
   321  	if len(s.getRefs(v.Name())) > 0 {
   322  		// Containers are referencing this volume but it doesn't seem to exist anywhere.
   323  		// Return a conflict error here, the user can fix this with `docker volume rm -f`
   324  		return nil, errors.Wrapf(errNameConflict, "found references to volume '%s' in driver '%s' but the volume was not found in the driver -- you may need to remove containers referencing this volume or force remove the volume to re-create it", name, vDriverName)
   325  	}
   326  
   327  	// doesn't exist, so purge it from the cache
   328  	s.Purge(name)
   329  	return nil, nil
   330  }
   331  
   332  // volumeExists returns if the volume is still present in the driver.
   333  // An error is returned if there was an issue communicating with the driver.
   334  func volumeExists(v volume.Volume) (bool, error) {
   335  	exists, err := lookupVolume(v.DriverName(), v.Name())
   336  	if err != nil {
   337  		return false, err
   338  	}
   339  	return exists != nil, nil
   340  }
   341  
   342  // create asks the given driver to create a volume with the name/opts.
   343  // If a volume with the name is already known, it will ask the stored driver for the volume.
   344  // If the passed in driver name does not match the driver name which is stored
   345  //  for the given volume name, an error is returned after checking if the reference is stale.
   346  // If the reference is stale, it will be purged and this create can continue.
   347  // It is expected that callers of this function hold any necessary locks.
   348  func (s *VolumeStore) create(name, driverName string, opts, labels map[string]string) (volume.Volume, error) {
   349  	// Validate the name in a platform-specific manner
   350  	valid, err := volume.IsVolumeNameValid(name)
   351  	if err != nil {
   352  		return nil, err
   353  	}
   354  	if !valid {
   355  		return nil, &OpErr{Err: errInvalidName, Name: name, Op: "create"}
   356  	}
   357  
   358  	v, err := s.checkConflict(name, driverName)
   359  	if err != nil {
   360  		return nil, err
   361  	}
   362  
   363  	if v != nil {
   364  		return v, nil
   365  	}
   366  
   367  	// Since there isn't a specified driver name, let's see if any of the existing drivers have this volume name
   368  	if driverName == "" {
   369  		v, _ := s.getVolume(name)
   370  		if v != nil {
   371  			return v, nil
   372  		}
   373  	}
   374  
   375  	vd, err := volumedrivers.CreateDriver(driverName)
   376  
   377  	if err != nil {
   378  		return nil, &OpErr{Op: "create", Name: name, Err: err}
   379  	}
   380  
   381  	logrus.Debugf("Registering new volume reference: driver %q, name %q", vd.Name(), name)
   382  
   383  	if v, _ := vd.Get(name); v != nil {
   384  		return v, nil
   385  	}
   386  	v, err = vd.Create(name, opts)
   387  	if err != nil {
   388  		return nil, err
   389  	}
   390  	s.globalLock.Lock()
   391  	s.labels[name] = labels
   392  	s.options[name] = opts
   393  	s.globalLock.Unlock()
   394  
   395  	metadata := volumeMetadata{
   396  		Name:    name,
   397  		Driver:  vd.Name(),
   398  		Labels:  labels,
   399  		Options: opts,
   400  	}
   401  
   402  	if err := s.setMeta(name, metadata); err != nil {
   403  		return nil, err
   404  	}
   405  	return volumeWrapper{v, labels, vd.Scope(), opts}, nil
   406  }
   407  
   408  // GetWithRef gets a volume with the given name from the passed in driver and stores the ref
   409  // This is just like Get(), but we store the reference while holding the lock.
   410  // This makes sure there are no races between checking for the existence of a volume and adding a reference for it
   411  func (s *VolumeStore) GetWithRef(name, driverName, ref string) (volume.Volume, error) {
   412  	name = normaliseVolumeName(name)
   413  	s.locks.Lock(name)
   414  	defer s.locks.Unlock(name)
   415  
   416  	vd, err := volumedrivers.GetDriver(driverName)
   417  	if err != nil {
   418  		return nil, &OpErr{Err: err, Name: name, Op: "get"}
   419  	}
   420  
   421  	v, err := vd.Get(name)
   422  	if err != nil {
   423  		return nil, &OpErr{Err: err, Name: name, Op: "get"}
   424  	}
   425  
   426  	s.setNamed(v, ref)
   427  
   428  	s.globalLock.RLock()
   429  	defer s.globalLock.RUnlock()
   430  	return volumeWrapper{v, s.labels[name], vd.Scope(), s.options[name]}, nil
   431  }
   432  
   433  // Get looks if a volume with the given name exists and returns it if so
   434  func (s *VolumeStore) Get(name string) (volume.Volume, error) {
   435  	name = normaliseVolumeName(name)
   436  	s.locks.Lock(name)
   437  	defer s.locks.Unlock(name)
   438  
   439  	v, err := s.getVolume(name)
   440  	if err != nil {
   441  		return nil, &OpErr{Err: err, Name: name, Op: "get"}
   442  	}
   443  	s.setNamed(v, "")
   444  	return v, nil
   445  }
   446  
   447  // getVolume requests the volume, if the driver info is stored it just accesses that driver,
   448  // if the driver is unknown it probes all drivers until it finds the first volume with that name.
   449  // it is expected that callers of this function hold any necessary locks
   450  func (s *VolumeStore) getVolume(name string) (volume.Volume, error) {
   451  	var meta volumeMetadata
   452  	meta, err := s.getMeta(name)
   453  	if err != nil {
   454  		return nil, err
   455  	}
   456  
   457  	driverName := meta.Driver
   458  	if driverName == "" {
   459  		s.globalLock.RLock()
   460  		v, exists := s.names[name]
   461  		s.globalLock.RUnlock()
   462  		if exists {
   463  			meta.Driver = v.DriverName()
   464  			if err := s.setMeta(name, meta); err != nil {
   465  				return nil, err
   466  			}
   467  		}
   468  	}
   469  
   470  	if meta.Driver != "" {
   471  		vol, err := lookupVolume(meta.Driver, name)
   472  		if err != nil {
   473  			return nil, err
   474  		}
   475  		if vol == nil {
   476  			s.Purge(name)
   477  			return nil, errNoSuchVolume
   478  		}
   479  
   480  		var scope string
   481  		vd, err := volumedrivers.GetDriver(meta.Driver)
   482  		if err == nil {
   483  			scope = vd.Scope()
   484  		}
   485  		return volumeWrapper{vol, meta.Labels, scope, meta.Options}, nil
   486  	}
   487  
   488  	logrus.Debugf("Probing all drivers for volume with name: %s", name)
   489  	drivers, err := volumedrivers.GetAllDrivers()
   490  	if err != nil {
   491  		return nil, err
   492  	}
   493  
   494  	for _, d := range drivers {
   495  		v, err := d.Get(name)
   496  		if err != nil || v == nil {
   497  			continue
   498  		}
   499  		meta.Driver = v.DriverName()
   500  		if err := s.setMeta(name, meta); err != nil {
   501  			return nil, err
   502  		}
   503  		return volumeWrapper{v, meta.Labels, d.Scope(), meta.Options}, nil
   504  	}
   505  	return nil, errNoSuchVolume
   506  }
   507  
   508  // lookupVolume gets the specified volume from the specified driver.
   509  // This will only return errors related to communications with the driver.
   510  // If the driver returns an error that is not communication related the
   511  //   error is logged but not returned.
   512  // If the volume is not found it will return `nil, nil``
   513  func lookupVolume(driverName, volumeName string) (volume.Volume, error) {
   514  	vd, err := volumedrivers.GetDriver(driverName)
   515  	if err != nil {
   516  		return nil, errors.Wrapf(err, "error while checking if volume %q exists in driver %q", volumeName, driverName)
   517  	}
   518  	v, err := vd.Get(volumeName)
   519  	if err != nil {
   520  		err = errors.Cause(err)
   521  		if _, ok := err.(net.Error); ok {
   522  			return nil, errors.Wrapf(err, "error while checking if volume %q exists in driver %q", v.Name(), v.DriverName())
   523  		}
   524  
   525  		// At this point, the error could be anything from the driver, such as "no such volume"
   526  		// Let's not check an error here, and instead check if the driver returned a volume
   527  		logrus.WithError(err).WithField("driver", driverName).WithField("volume", volumeName).Warnf("Error while looking up volume")
   528  	}
   529  	return v, nil
   530  }
   531  
   532  // Remove removes the requested volume. A volume is not removed if it has any refs
   533  func (s *VolumeStore) Remove(v volume.Volume) error {
   534  	name := normaliseVolumeName(v.Name())
   535  	s.locks.Lock(name)
   536  	defer s.locks.Unlock(name)
   537  
   538  	refs := s.getRefs(name)
   539  	if len(refs) > 0 {
   540  		return &OpErr{Err: errVolumeInUse, Name: v.Name(), Op: "remove", Refs: refs}
   541  	}
   542  
   543  	vd, err := volumedrivers.GetDriver(v.DriverName())
   544  	if err != nil {
   545  		return &OpErr{Err: err, Name: vd.Name(), Op: "remove"}
   546  	}
   547  
   548  	logrus.Debugf("Removing volume reference: driver %s, name %s", v.DriverName(), name)
   549  	vol := unwrapVolume(v)
   550  	if err := vd.Remove(vol); err != nil {
   551  		return &OpErr{Err: err, Name: name, Op: "remove"}
   552  	}
   553  
   554  	s.Purge(name)
   555  	return nil
   556  }
   557  
   558  // Dereference removes the specified reference to the volume
   559  func (s *VolumeStore) Dereference(v volume.Volume, ref string) {
   560  	s.locks.Lock(v.Name())
   561  	defer s.locks.Unlock(v.Name())
   562  
   563  	s.globalLock.Lock()
   564  	defer s.globalLock.Unlock()
   565  	var refs []string
   566  
   567  	for _, r := range s.refs[v.Name()] {
   568  		if r != ref {
   569  			refs = append(refs, r)
   570  		}
   571  	}
   572  	s.refs[v.Name()] = refs
   573  }
   574  
   575  // Refs gets the current list of refs for the given volume
   576  func (s *VolumeStore) Refs(v volume.Volume) []string {
   577  	s.locks.Lock(v.Name())
   578  	defer s.locks.Unlock(v.Name())
   579  
   580  	refs := s.getRefs(v.Name())
   581  	refsOut := make([]string, len(refs))
   582  	copy(refsOut, refs)
   583  	return refsOut
   584  }
   585  
   586  // FilterByDriver returns the available volumes filtered by driver name
   587  func (s *VolumeStore) FilterByDriver(name string) ([]volume.Volume, error) {
   588  	vd, err := volumedrivers.GetDriver(name)
   589  	if err != nil {
   590  		return nil, &OpErr{Err: err, Name: name, Op: "list"}
   591  	}
   592  	ls, err := vd.List()
   593  	if err != nil {
   594  		return nil, &OpErr{Err: err, Name: name, Op: "list"}
   595  	}
   596  	for i, v := range ls {
   597  		options := map[string]string{}
   598  		s.globalLock.RLock()
   599  		for key, value := range s.options[v.Name()] {
   600  			options[key] = value
   601  		}
   602  		ls[i] = volumeWrapper{v, s.labels[v.Name()], vd.Scope(), options}
   603  		s.globalLock.RUnlock()
   604  	}
   605  	return ls, nil
   606  }
   607  
   608  // FilterByUsed returns the available volumes filtered by if they are in use or not.
   609  // `used=true` returns only volumes that are being used, while `used=false` returns
   610  // only volumes that are not being used.
   611  func (s *VolumeStore) FilterByUsed(vols []volume.Volume, used bool) []volume.Volume {
   612  	return s.filter(vols, func(v volume.Volume) bool {
   613  		s.locks.Lock(v.Name())
   614  		l := len(s.getRefs(v.Name()))
   615  		s.locks.Unlock(v.Name())
   616  		if (used && l > 0) || (!used && l == 0) {
   617  			return true
   618  		}
   619  		return false
   620  	})
   621  }
   622  
   623  // filterFunc defines a function to allow filter volumes in the store
   624  type filterFunc func(vol volume.Volume) bool
   625  
   626  // filter returns the available volumes filtered by a filterFunc function
   627  func (s *VolumeStore) filter(vols []volume.Volume, f filterFunc) []volume.Volume {
   628  	var ls []volume.Volume
   629  	for _, v := range vols {
   630  		if f(v) {
   631  			ls = append(ls, v)
   632  		}
   633  	}
   634  	return ls
   635  }
   636  
   637  func unwrapVolume(v volume.Volume) volume.Volume {
   638  	if vol, ok := v.(volumeWrapper); ok {
   639  		return vol.Volume
   640  	}
   641  
   642  	return v
   643  }
   644  
   645  // Shutdown releases all resources used by the volume store
   646  // It does not make any changes to volumes, drivers, etc.
   647  func (s *VolumeStore) Shutdown() error {
   648  	return s.db.Close()
   649  }