github.com/nullne/docker@v1.13.0-rc1/volume/store/store.go (about)

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