github.com/brahmaroutu/docker@v1.2.1-0.20160809185609-eb28dde01f16/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 ensures there's no race between creating a volume and then storing a reference.
   216  func (s *VolumeStore) CreateWithRef(name, driverName, ref string, opts, labels map[string]string) (volume.Volume, error) {
   217  	name = normaliseVolumeName(name)
   218  	s.locks.Lock(name)
   219  	defer s.locks.Unlock(name)
   220  
   221  	v, err := s.create(name, driverName, opts, labels)
   222  	if err != nil {
   223  		return nil, &OpErr{Err: err, Name: name, Op: "create"}
   224  	}
   225  
   226  	s.setNamed(v, ref)
   227  	return v, nil
   228  }
   229  
   230  // Create creates a volume with the given name and driver.
   231  // This is just like CreateWithRef() except we don't store a reference while holding the lock.
   232  func (s *VolumeStore) Create(name, driverName string, opts, labels map[string]string) (volume.Volume, error) {
   233  	return s.CreateWithRef(name, driverName, "", opts, labels)
   234  }
   235  
   236  // create asks the given driver to create a volume with the name/opts.
   237  // If a volume with the name is already known, it will ask the stored driver for the volume.
   238  // If the passed in driver name does not match the driver name which is stored for the given volume name, an error is returned.
   239  // It is expected that callers of this function hold any necessary locks.
   240  func (s *VolumeStore) create(name, driverName string, opts, labels map[string]string) (volume.Volume, error) {
   241  	// Validate the name in a platform-specific manner
   242  	valid, err := volume.IsVolumeNameValid(name)
   243  	if err != nil {
   244  		return nil, err
   245  	}
   246  	if !valid {
   247  		return nil, &OpErr{Err: errInvalidName, Name: name, Op: "create"}
   248  	}
   249  
   250  	if v, exists := s.getNamed(name); exists {
   251  		if v.DriverName() != driverName && driverName != "" && driverName != volume.DefaultDriverName {
   252  			return nil, errNameConflict
   253  		}
   254  		return v, nil
   255  	}
   256  
   257  	// Since there isn't a specified driver name, let's see if any of the existing drivers have this volume name
   258  	if driverName == "" {
   259  		v, _ := s.getVolume(name)
   260  		if v != nil {
   261  			return v, nil
   262  		}
   263  	}
   264  
   265  	vd, err := volumedrivers.GetDriver(driverName)
   266  
   267  	if err != nil {
   268  		return nil, &OpErr{Op: "create", Name: name, Err: err}
   269  	}
   270  
   271  	logrus.Debugf("Registering new volume reference: driver %q, name %q", vd.Name(), name)
   272  
   273  	if v, _ := vd.Get(name); v != nil {
   274  		return v, nil
   275  	}
   276  	v, err := vd.Create(name, opts)
   277  	if err != nil {
   278  		return nil, err
   279  	}
   280  	s.globalLock.Lock()
   281  	s.labels[name] = labels
   282  	s.globalLock.Unlock()
   283  
   284  	if s.db != nil {
   285  		metadata := &volumeMetadata{
   286  			Name:   name,
   287  			Labels: labels,
   288  		}
   289  
   290  		volData, err := json.Marshal(metadata)
   291  		if err != nil {
   292  			return nil, err
   293  		}
   294  
   295  		if err := s.db.Update(func(tx *bolt.Tx) error {
   296  			b := tx.Bucket([]byte(volumeBucketName))
   297  			err := b.Put([]byte(name), volData)
   298  			return err
   299  		}); err != nil {
   300  			return nil, err
   301  		}
   302  	}
   303  
   304  	return volumeWrapper{v, labels, vd.Scope()}, nil
   305  }
   306  
   307  // GetWithRef gets a volume with the given name from the passed in driver and stores the ref
   308  // This is just like Get(), but we store the reference while holding the lock.
   309  // This makes sure there are no races between checking for the existence of a volume and adding a reference for it
   310  func (s *VolumeStore) GetWithRef(name, driverName, ref string) (volume.Volume, error) {
   311  	name = normaliseVolumeName(name)
   312  	s.locks.Lock(name)
   313  	defer s.locks.Unlock(name)
   314  
   315  	vd, err := volumedrivers.GetDriver(driverName)
   316  	if err != nil {
   317  		return nil, &OpErr{Err: err, Name: name, Op: "get"}
   318  	}
   319  
   320  	v, err := vd.Get(name)
   321  	if err != nil {
   322  		return nil, &OpErr{Err: err, Name: name, Op: "get"}
   323  	}
   324  
   325  	s.setNamed(v, ref)
   326  
   327  	return volumeWrapper{v, s.labels[name], vd.Scope()}, nil
   328  }
   329  
   330  // Get looks if a volume with the given name exists and returns it if so
   331  func (s *VolumeStore) Get(name string) (volume.Volume, error) {
   332  	name = normaliseVolumeName(name)
   333  	s.locks.Lock(name)
   334  	defer s.locks.Unlock(name)
   335  
   336  	v, err := s.getVolume(name)
   337  	if err != nil {
   338  		return nil, &OpErr{Err: err, Name: name, Op: "get"}
   339  	}
   340  	s.setNamed(v, "")
   341  	return v, nil
   342  }
   343  
   344  // getVolume requests the volume, if the driver info is stored it just accesses that driver,
   345  // if the driver is unknown it probes all drivers until it finds the first volume with that name.
   346  // it is expected that callers of this function hold any necessary locks
   347  func (s *VolumeStore) getVolume(name string) (volume.Volume, error) {
   348  	labels := map[string]string{}
   349  
   350  	if s.db != nil {
   351  		// get meta
   352  		if err := s.db.Update(func(tx *bolt.Tx) error {
   353  			b := tx.Bucket([]byte(volumeBucketName))
   354  			data := b.Get([]byte(name))
   355  
   356  			if string(data) == "" {
   357  				return nil
   358  			}
   359  
   360  			var meta volumeMetadata
   361  			buf := bytes.NewBuffer(data)
   362  
   363  			if err := json.NewDecoder(buf).Decode(&meta); err != nil {
   364  				return err
   365  			}
   366  			labels = meta.Labels
   367  
   368  			return nil
   369  		}); err != nil {
   370  			return nil, err
   371  		}
   372  	}
   373  
   374  	logrus.Debugf("Getting volume reference for name: %s", name)
   375  	s.globalLock.Lock()
   376  	v, exists := s.names[name]
   377  	s.globalLock.Unlock()
   378  	if exists {
   379  		vd, err := volumedrivers.GetDriver(v.DriverName())
   380  		if err != nil {
   381  			return nil, err
   382  		}
   383  		vol, err := vd.Get(name)
   384  		if err != nil {
   385  			return nil, err
   386  		}
   387  		return volumeWrapper{vol, labels, vd.Scope()}, nil
   388  	}
   389  
   390  	logrus.Debugf("Probing all drivers for volume with name: %s", name)
   391  	drivers, err := volumedrivers.GetAllDrivers()
   392  	if err != nil {
   393  		return nil, err
   394  	}
   395  
   396  	for _, d := range drivers {
   397  		v, err := d.Get(name)
   398  		if err != nil {
   399  			continue
   400  		}
   401  
   402  		return volumeWrapper{v, labels, d.Scope()}, nil
   403  	}
   404  	return nil, errNoSuchVolume
   405  }
   406  
   407  // Remove removes the requested volume. A volume is not removed if it has any refs
   408  func (s *VolumeStore) Remove(v volume.Volume) error {
   409  	name := normaliseVolumeName(v.Name())
   410  	s.locks.Lock(name)
   411  	defer s.locks.Unlock(name)
   412  
   413  	if refs, exists := s.refs[name]; exists && len(refs) > 0 {
   414  		return &OpErr{Err: errVolumeInUse, Name: v.Name(), Op: "remove", Refs: refs}
   415  	}
   416  
   417  	vd, err := volumedrivers.GetDriver(v.DriverName())
   418  	if err != nil {
   419  		return &OpErr{Err: err, Name: vd.Name(), Op: "remove"}
   420  	}
   421  
   422  	logrus.Debugf("Removing volume reference: driver %s, name %s", v.DriverName(), name)
   423  	vol := unwrapVolume(v)
   424  	if err := vd.Remove(vol); err != nil {
   425  		return &OpErr{Err: err, Name: name, Op: "remove"}
   426  	}
   427  
   428  	s.purge(name)
   429  	return nil
   430  }
   431  
   432  // Dereference removes the specified reference to the volume
   433  func (s *VolumeStore) Dereference(v volume.Volume, ref string) {
   434  	s.locks.Lock(v.Name())
   435  	defer s.locks.Unlock(v.Name())
   436  
   437  	s.globalLock.Lock()
   438  	defer s.globalLock.Unlock()
   439  	var refs []string
   440  
   441  	for _, r := range s.refs[v.Name()] {
   442  		if r != ref {
   443  			refs = append(refs, r)
   444  		}
   445  	}
   446  	s.refs[v.Name()] = refs
   447  }
   448  
   449  // Refs gets the current list of refs for the given volume
   450  func (s *VolumeStore) Refs(v volume.Volume) []string {
   451  	s.locks.Lock(v.Name())
   452  	defer s.locks.Unlock(v.Name())
   453  
   454  	s.globalLock.Lock()
   455  	defer s.globalLock.Unlock()
   456  	refs, exists := s.refs[v.Name()]
   457  	if !exists {
   458  		return nil
   459  	}
   460  
   461  	refsOut := make([]string, len(refs))
   462  	copy(refsOut, refs)
   463  	return refsOut
   464  }
   465  
   466  // FilterByDriver returns the available volumes filtered by driver name
   467  func (s *VolumeStore) FilterByDriver(name string) ([]volume.Volume, error) {
   468  	vd, err := volumedrivers.GetDriver(name)
   469  	if err != nil {
   470  		return nil, &OpErr{Err: err, Name: name, Op: "list"}
   471  	}
   472  	ls, err := vd.List()
   473  	if err != nil {
   474  		return nil, &OpErr{Err: err, Name: name, Op: "list"}
   475  	}
   476  	for i, v := range ls {
   477  		ls[i] = volumeWrapper{v, s.labels[v.Name()], vd.Scope()}
   478  	}
   479  	return ls, nil
   480  }
   481  
   482  // FilterByUsed returns the available volumes filtered by if they are in use or not.
   483  // `used=true` returns only volumes that are being used, while `used=false` returns
   484  // only volumes that are not being used.
   485  func (s *VolumeStore) FilterByUsed(vols []volume.Volume, used bool) []volume.Volume {
   486  	return s.filter(vols, func(v volume.Volume) bool {
   487  		s.locks.Lock(v.Name())
   488  		l := len(s.refs[v.Name()])
   489  		s.locks.Unlock(v.Name())
   490  		if (used && l > 0) || (!used && l == 0) {
   491  			return true
   492  		}
   493  		return false
   494  	})
   495  }
   496  
   497  // filterFunc defines a function to allow filter volumes in the store
   498  type filterFunc func(vol volume.Volume) bool
   499  
   500  // filter returns the available volumes filtered by a filterFunc function
   501  func (s *VolumeStore) filter(vols []volume.Volume, f filterFunc) []volume.Volume {
   502  	var ls []volume.Volume
   503  	for _, v := range vols {
   504  		if f(v) {
   505  			ls = append(ls, v)
   506  		}
   507  	}
   508  	return ls
   509  }
   510  
   511  func unwrapVolume(v volume.Volume) volume.Volume {
   512  	if vol, ok := v.(volumeWrapper); ok {
   513  		return vol.Volume
   514  	}
   515  
   516  	return v
   517  }