github.com/dpiddy/docker@v1.12.2-rc1/volume/store/store.go (about)

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