package service // import "github.com/docker/docker/volume/service"

import (
	"context"
	"fmt"
	"net"
	"os"
	"path/filepath"
	"runtime"
	"sync"
	"time"

	"github.com/pkg/errors"

	"github.com/boltdb/bolt"
	"github.com/docker/docker/errdefs"
	"github.com/docker/docker/pkg/locker"
	"github.com/docker/docker/volume"
	"github.com/docker/docker/volume/drivers"
	volumemounts "github.com/docker/docker/volume/mounts"
	"github.com/docker/docker/volume/service/opts"
	"github.com/sirupsen/logrus"
)

const (
	volumeDataDir = "volumes"
)

type volumeWrapper struct {
	volume.Volume
	labels  map[string]string
	scope   string
	options map[string]string
}

func (v volumeWrapper) Options() map[string]string {
	if v.options == nil {
		return nil
	}
	options := make(map[string]string, len(v.options))
	for key, value := range v.options {
		options[key] = value
	}
	return options
}

func (v volumeWrapper) Labels() map[string]string {
	if v.labels == nil {
		return nil
	}

	labels := make(map[string]string, len(v.labels))
	for key, value := range v.labels {
		labels[key] = value
	}
	return labels
}

func (v volumeWrapper) Scope() string {
	return v.scope
}

func (v volumeWrapper) CachedPath() string {
	if vv, ok := v.Volume.(interface {
		CachedPath() string
	}); ok {
		return vv.CachedPath()
	}
	return v.Volume.Path()
}

// NewStore creates a new volume store at the given path
func NewStore(rootPath string, drivers *drivers.Store) (*VolumeStore, error) {
	vs := &VolumeStore{
		locks:   &locker.Locker{},
		names:   make(map[string]volume.Volume),
		refs:    make(map[string]map[string]struct{}),
		labels:  make(map[string]map[string]string),
		options: make(map[string]map[string]string),
		drivers: drivers,
	}

	if rootPath != "" {
		// initialize metadata store
		volPath := filepath.Join(rootPath, volumeDataDir)
		if err := os.MkdirAll(volPath, 0750); err != nil {
			return nil, err
		}

		var err error
		vs.db, err = bolt.Open(filepath.Join(volPath, "metadata.db"), 0600, &bolt.Options{Timeout: 1 * time.Second})
		if err != nil {
			return nil, errors.Wrap(err, "error while opening volume store metadata database")
		}

		// initialize volumes bucket
		if err := vs.db.Update(func(tx *bolt.Tx) error {
			if _, err := tx.CreateBucketIfNotExists(volumeBucketName); err != nil {
				return errors.Wrap(err, "error while setting up volume store metadata database")
			}
			return nil
		}); err != nil {
			return nil, err
		}
	}

	vs.restore()

	return vs, nil
}

func (s *VolumeStore) getNamed(name string) (volume.Volume, bool) {
	s.globalLock.RLock()
	v, exists := s.names[name]
	s.globalLock.RUnlock()
	return v, exists
}

func (s *VolumeStore) setNamed(v volume.Volume, ref string) {
	name := v.Name()

	s.globalLock.Lock()
	s.names[name] = v
	if len(ref) > 0 {
		if s.refs[name] == nil {
			s.refs[name] = make(map[string]struct{})
		}
		s.refs[name][ref] = struct{}{}
	}
	s.globalLock.Unlock()
}

// hasRef returns true if the given name has at least one ref.
// Callers of this function are expected to hold the name lock.
func (s *VolumeStore) hasRef(name string) bool {
	s.globalLock.RLock()
	l := len(s.refs[name])
	s.globalLock.RUnlock()
	return l > 0
}

// getRefs gets the list of refs for a given name
// Callers of this function are expected to hold the name lock.
func (s *VolumeStore) getRefs(name string) []string {
	s.globalLock.RLock()
	defer s.globalLock.RUnlock()

	refs := make([]string, 0, len(s.refs[name]))
	for r := range s.refs[name] {
		refs = append(refs, r)
	}

	return refs
}

// purge allows the cleanup of internal data on docker in case
// the internal data is out of sync with volumes driver plugins.
func (s *VolumeStore) purge(ctx context.Context, name string) error {
	s.globalLock.Lock()
	defer s.globalLock.Unlock()

	select {
	case <-ctx.Done():
		return ctx.Err()
	default:
	}

	v, exists := s.names[name]
	if exists {
		driverName := v.DriverName()
		if _, err := s.drivers.ReleaseDriver(driverName); err != nil {
			logrus.WithError(err).WithField("driver", driverName).Error("Error releasing reference to volume driver")
		}
	}
	if err := s.removeMeta(name); err != nil {
		logrus.Errorf("Error removing volume metadata for volume %q: %v", name, err)
	}
	delete(s.names, name)
	delete(s.refs, name)
	delete(s.labels, name)
	delete(s.options, name)
	return nil
}

// VolumeStore is a struct that stores the list of volumes available and keeps track of their usage counts
type VolumeStore struct {
	// locks ensures that only one action is being performed on a particular volume at a time without locking the entire store
	// since actions on volumes can be quite slow, this ensures the store is free to handle requests for other volumes.
	locks   *locker.Locker
	drivers *drivers.Store
	// globalLock is used to protect access to mutable structures used by the store object
	globalLock sync.RWMutex
	// names stores the volume name -> volume relationship.
	// This is used for making lookups faster so we don't have to probe all drivers
	names map[string]volume.Volume
	// refs stores the volume name and the list of things referencing it
	refs map[string]map[string]struct{}
	// labels stores volume labels for each volume
	labels map[string]map[string]string
	// options stores volume options for each volume
	options map[string]map[string]string
	db      *bolt.DB
}

func filterByDriver(names []string) filterFunc {
	return func(v volume.Volume) bool {
		for _, name := range names {
			if name == v.DriverName() {
				return true
			}
		}
		return false
	}
}

func (s *VolumeStore) byReferenced(referenced bool) filterFunc {
	return func(v volume.Volume) bool {
		return s.hasRef(v.Name()) == referenced
	}
}

func (s *VolumeStore) filter(ctx context.Context, vols *[]volume.Volume, by By) (warnings []string, err error) {
	// note that this specifically does not support the `FromList` By type.
	switch f := by.(type) {
	case nil:
		if *vols == nil {
			var ls []volume.Volume
			ls, warnings, err = s.list(ctx)
			if err != nil {
				return warnings, err
			}
			*vols = ls
		}
	case byDriver:
		if *vols != nil {
			filter(vols, filterByDriver([]string(f)))
			return nil, nil
		}
		var ls []volume.Volume
		ls, warnings, err = s.list(ctx, []string(f)...)
		if err != nil {
			return nil, err
		}
		*vols = ls
	case ByReferenced:
		// TODO(@cpuguy83): It would be nice to optimize this by looking at the list
		// of referenced volumes, however the locking strategy makes this difficult
		// without either providing inconsistent data or deadlocks.
		if *vols == nil {
			var ls []volume.Volume
			ls, warnings, err = s.list(ctx)
			if err != nil {
				return nil, err
			}
			*vols = ls
		}
		filter(vols, s.byReferenced(bool(f)))
	case andCombinator:
		for _, by := range f {
			w, err := s.filter(ctx, vols, by)
			if err != nil {
				return warnings, err
			}
			warnings = append(warnings, w...)
		}
	case orCombinator:
		for _, by := range f {
			switch by.(type) {
			case byDriver:
				var ls []volume.Volume
				w, err := s.filter(ctx, &ls, by)
				if err != nil {
					return warnings, err
				}
				warnings = append(warnings, w...)
			default:
				ls, w, err := s.list(ctx)
				if err != nil {
					return warnings, err
				}
				warnings = append(warnings, w...)
				w, err = s.filter(ctx, &ls, by)
				if err != nil {
					return warnings, err
				}
				warnings = append(warnings, w...)
				*vols = append(*vols, ls...)
			}
		}
		unique(vols)
	case CustomFilter:
		if *vols == nil {
			var ls []volume.Volume
			ls, warnings, err = s.list(ctx)
			if err != nil {
				return nil, err
			}
			*vols = ls
		}
		filter(vols, filterFunc(f))
	default:
		return nil, errdefs.InvalidParameter(errors.Errorf("unsupported filter: %T", f))
	}
	return warnings, nil
}

func unique(ls *[]volume.Volume) {
	names := make(map[string]bool, len(*ls))
	filter(ls, func(v volume.Volume) bool {
		if names[v.Name()] {
			return false
		}
		names[v.Name()] = true
		return true
	})
}

// Find lists volumes filtered by the past in filter.
// If a driver returns a volume that has name which conflicts with another volume from a different driver,
// the first volume is chosen and the conflicting volume is dropped.
func (s *VolumeStore) Find(ctx context.Context, by By) (vols []volume.Volume, warnings []string, err error) {
	logrus.WithField("ByType", fmt.Sprintf("%T", by)).WithField("ByValue", fmt.Sprintf("%+v", by)).Debug("VolumeStore.Find")
	switch f := by.(type) {
	case nil, orCombinator, andCombinator, byDriver, ByReferenced, CustomFilter:
		warnings, err = s.filter(ctx, &vols, by)
	case fromList:
		warnings, err = s.filter(ctx, f.ls, f.by)
	default:
		// Really shouldn't be possible, but makes sure that any new By's are added to this check.
		err = errdefs.InvalidParameter(errors.Errorf("unsupported filter type: %T", f))
	}
	if err != nil {
		return nil, nil, &OpErr{Err: err, Op: "list"}
	}

	var out []volume.Volume

	for _, v := range vols {
		name := normalizeVolumeName(v.Name())

		s.locks.Lock(name)
		storedV, exists := s.getNamed(name)
		// Note: it's not safe to populate the cache here because the volume may have been
		// deleted before we acquire a lock on its name
		if exists && storedV.DriverName() != v.DriverName() {
			logrus.Warnf("Volume name %s already exists for driver %s, not including volume returned by %s", v.Name(), storedV.DriverName(), v.DriverName())
			s.locks.Unlock(v.Name())
			continue
		}

		out = append(out, v)
		s.locks.Unlock(v.Name())
	}
	return out, warnings, nil
}

type filterFunc func(volume.Volume) bool

func filter(vols *[]volume.Volume, fn filterFunc) {
	var evict []int
	for i, v := range *vols {
		if !fn(v) {
			evict = append(evict, i)
		}
	}

	for n, i := range evict {
		copy((*vols)[i-n:], (*vols)[i-n+1:])
		(*vols)[len(*vols)-1] = nil
		*vols = (*vols)[:len(*vols)-1]
	}
}

// list goes through each volume driver and asks for its list of volumes.
// TODO(@cpuguy83): plumb context through
func (s *VolumeStore) list(ctx context.Context, driverNames ...string) ([]volume.Volume, []string, error) {
	var (
		ls       = []volume.Volume{} // do not return a nil value as this affects filtering
		warnings []string
	)

	var dls []volume.Driver

	all, err := s.drivers.GetAllDrivers()
	if err != nil {
		return nil, nil, err
	}
	if len(driverNames) == 0 {
		dls = all
	} else {
		idx := make(map[string]bool, len(driverNames))
		for _, name := range driverNames {
			idx[name] = true
		}
		for _, d := range all {
			if idx[d.Name()] {
				dls = append(dls, d)
			}
		}
	}

	type vols struct {
		vols       []volume.Volume
		err        error
		driverName string
	}
	chVols := make(chan vols, len(dls))

	for _, vd := range dls {
		go func(d volume.Driver) {
			vs, err := d.List()
			if err != nil {
				chVols <- vols{driverName: d.Name(), err: &OpErr{Err: err, Name: d.Name(), Op: "list"}}
				return
			}
			for i, v := range vs {
				s.globalLock.RLock()
				vs[i] = volumeWrapper{v, s.labels[v.Name()], d.Scope(), s.options[v.Name()]}
				s.globalLock.RUnlock()
			}

			chVols <- vols{vols: vs}
		}(vd)
	}

	badDrivers := make(map[string]struct{})
	for i := 0; i < len(dls); i++ {
		vs := <-chVols

		if vs.err != nil {
			warnings = append(warnings, vs.err.Error())
			badDrivers[vs.driverName] = struct{}{}
		}
		ls = append(ls, vs.vols...)
	}

	if len(badDrivers) > 0 {
		s.globalLock.RLock()
		for _, v := range s.names {
			if _, exists := badDrivers[v.DriverName()]; exists {
				ls = append(ls, v)
			}
		}
		s.globalLock.RUnlock()
	}
	return ls, warnings, nil
}

// Create creates a volume with the given name and driver
// If the volume needs to be created with a reference to prevent race conditions
// with volume cleanup, make sure to use the `CreateWithReference` option.
func (s *VolumeStore) Create(ctx context.Context, name, driverName string, createOpts ...opts.CreateOption) (volume.Volume, error) {
	var cfg opts.CreateConfig
	for _, o := range createOpts {
		o(&cfg)
	}

	name = normalizeVolumeName(name)
	s.locks.Lock(name)
	defer s.locks.Unlock(name)

	select {
	case <-ctx.Done():
		return nil, ctx.Err()
	default:
	}

	v, err := s.create(ctx, name, driverName, cfg.Options, cfg.Labels)
	if err != nil {
		if _, ok := err.(*OpErr); ok {
			return nil, err
		}
		return nil, &OpErr{Err: err, Name: name, Op: "create"}
	}

	s.setNamed(v, cfg.Reference)
	return v, nil
}

// checkConflict checks the local cache for name collisions with the passed in name,
// for existing volumes with the same name but in a different driver.
// This is used by `Create` as a best effort to prevent name collisions for volumes.
// If a matching volume is found that is not a conflict that is returned so the caller
// does not need to perform an additional lookup.
// When no matching volume is found, both returns will be nil
//
// Note: This does not probe all the drivers for name collisions because v1 plugins
// are very slow, particularly if the plugin is down, and cause other issues,
// particularly around locking the store.
// TODO(cpuguy83): With v2 plugins this shouldn't be a problem. Could also potentially
// use a connect timeout for this kind of check to ensure we aren't blocking for a
// long time.
func (s *VolumeStore) checkConflict(ctx context.Context, name, driverName string) (volume.Volume, error) {
	// check the local cache
	v, _ := s.getNamed(name)
	if v == nil {
		return nil, nil
	}

	vDriverName := v.DriverName()
	var conflict bool
	if driverName != "" {
		// Retrieve canonical driver name to avoid inconsistencies (for example
		// "plugin" vs. "plugin:latest")
		vd, err := s.drivers.GetDriver(driverName)
		if err != nil {
			return nil, err
		}

		if vDriverName != vd.Name() {
			conflict = true
		}
	}

	// let's check if the found volume ref
	// is stale by checking with the driver if it still exists
	exists, err := volumeExists(ctx, s.drivers, v)
	if err != nil {
		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)
	}

	if exists {
		if conflict {
			return nil, errors.Wrapf(errNameConflict, "driver '%s' already has volume '%s'", vDriverName, name)
		}
		return v, nil
	}

	if s.hasRef(v.Name()) {
		// Containers are referencing this volume but it doesn't seem to exist anywhere.
		// Return a conflict error here, the user can fix this with `docker volume rm -f`
		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)
	}

	// doesn't exist, so purge it from the cache
	s.purge(ctx, name)
	return nil, nil
}

// volumeExists returns if the volume is still present in the driver.
// An error is returned if there was an issue communicating with the driver.
func volumeExists(ctx context.Context, store *drivers.Store, v volume.Volume) (bool, error) {
	exists, err := lookupVolume(ctx, store, v.DriverName(), v.Name())
	if err != nil {
		return false, err
	}
	return exists != nil, nil
}

// create asks the given driver to create a volume with the name/opts.
// If a volume with the name is already known, it will ask the stored driver for the volume.
// If the passed in driver name does not match the driver name which is stored
//  for the given volume name, an error is returned after checking if the reference is stale.
// If the reference is stale, it will be purged and this create can continue.
// It is expected that callers of this function hold any necessary locks.
func (s *VolumeStore) create(ctx context.Context, name, driverName string, opts, labels map[string]string) (volume.Volume, error) {
	// Validate the name in a platform-specific manner

	// volume name validation is specific to the host os and not on container image
	// windows/lcow should have an equivalent volumename validation logic so we create a parser for current host OS
	parser := volumemounts.NewParser(runtime.GOOS)
	err := parser.ValidateVolumeName(name)
	if err != nil {
		return nil, err
	}

	v, err := s.checkConflict(ctx, name, driverName)
	if err != nil {
		return nil, err
	}

	if v != nil {
		// there is an existing volume, if we already have this stored locally, return it.
		// TODO: there could be some inconsistent details such as labels here
		if vv, _ := s.getNamed(v.Name()); vv != nil {
			return vv, nil
		}
	}

	// Since there isn't a specified driver name, let's see if any of the existing drivers have this volume name
	if driverName == "" {
		v, _ = s.getVolume(ctx, name, "")
		if v != nil {
			return v, nil
		}
	}

	if driverName == "" {
		driverName = volume.DefaultDriverName
	}
	vd, err := s.drivers.CreateDriver(driverName)
	if err != nil {
		return nil, &OpErr{Op: "create", Name: name, Err: err}
	}

	logrus.Debugf("Registering new volume reference: driver %q, name %q", vd.Name(), name)
	if v, _ = vd.Get(name); v == nil {
		v, err = vd.Create(name, opts)
		if err != nil {
			if _, err := s.drivers.ReleaseDriver(driverName); err != nil {
				logrus.WithError(err).WithField("driver", driverName).Error("Error releasing reference to volume driver")
			}
			return nil, err
		}
	}

	s.globalLock.Lock()
	s.labels[name] = labels
	s.options[name] = opts
	s.refs[name] = make(map[string]struct{})
	s.globalLock.Unlock()

	metadata := volumeMetadata{
		Name:    name,
		Driver:  vd.Name(),
		Labels:  labels,
		Options: opts,
	}

	if err := s.setMeta(name, metadata); err != nil {
		return nil, err
	}
	return volumeWrapper{v, labels, vd.Scope(), opts}, nil
}

// Get looks if a volume with the given name exists and returns it if so
func (s *VolumeStore) Get(ctx context.Context, name string, getOptions ...opts.GetOption) (volume.Volume, error) {
	var cfg opts.GetConfig
	for _, o := range getOptions {
		o(&cfg)
	}
	name = normalizeVolumeName(name)
	s.locks.Lock(name)
	defer s.locks.Unlock(name)

	v, err := s.getVolume(ctx, name, cfg.Driver)
	if err != nil {
		return nil, &OpErr{Err: err, Name: name, Op: "get"}
	}
	if cfg.Driver != "" && v.DriverName() != cfg.Driver {
		return nil, &OpErr{Name: name, Op: "get", Err: errdefs.Conflict(errors.New("found volume driver does not match passed in driver"))}
	}
	s.setNamed(v, cfg.Reference)
	return v, nil
}

// getVolume requests the volume, if the driver info is stored it just accesses that driver,
// if the driver is unknown it probes all drivers until it finds the first volume with that name.
// it is expected that callers of this function hold any necessary locks
func (s *VolumeStore) getVolume(ctx context.Context, name, driverName string) (volume.Volume, error) {
	var meta volumeMetadata
	meta, err := s.getMeta(name)
	if err != nil {
		return nil, err
	}

	if driverName != "" {
		if meta.Driver == "" {
			meta.Driver = driverName
		}
		if driverName != meta.Driver {
			return nil, errdefs.Conflict(errors.New("provided volume driver does not match stored driver"))
		}
	}

	if driverName == "" {
		driverName = meta.Driver
	}
	if driverName == "" {
		s.globalLock.RLock()
		select {
		case <-ctx.Done():
			s.globalLock.RUnlock()
			return nil, ctx.Err()
		default:
		}
		v, exists := s.names[name]
		s.globalLock.RUnlock()
		if exists {
			meta.Driver = v.DriverName()
			if err := s.setMeta(name, meta); err != nil {
				return nil, err
			}
		}
	}

	if meta.Driver != "" {
		vol, err := lookupVolume(ctx, s.drivers, meta.Driver, name)
		if err != nil {
			return nil, err
		}
		if vol == nil {
			s.purge(ctx, name)
			return nil, errNoSuchVolume
		}

		var scope string
		vd, err := s.drivers.GetDriver(meta.Driver)
		if err == nil {
			scope = vd.Scope()
		}
		return volumeWrapper{vol, meta.Labels, scope, meta.Options}, nil
	}

	logrus.Debugf("Probing all drivers for volume with name: %s", name)
	drivers, err := s.drivers.GetAllDrivers()
	if err != nil {
		return nil, err
	}

	for _, d := range drivers {
		select {
		case <-ctx.Done():
			return nil, ctx.Err()
		default:
		}
		v, err := d.Get(name)
		if err != nil || v == nil {
			continue
		}
		meta.Driver = v.DriverName()
		if err := s.setMeta(name, meta); err != nil {
			return nil, err
		}
		return volumeWrapper{v, meta.Labels, d.Scope(), meta.Options}, nil
	}
	return nil, errNoSuchVolume
}

// lookupVolume gets the specified volume from the specified driver.
// This will only return errors related to communications with the driver.
// If the driver returns an error that is not communication related the
//   error is logged but not returned.
// If the volume is not found it will return `nil, nil``
// TODO(@cpuguy83): plumb through the context to lower level components
func lookupVolume(ctx context.Context, store *drivers.Store, driverName, volumeName string) (volume.Volume, error) {
	if driverName == "" {
		driverName = volume.DefaultDriverName
	}
	vd, err := store.GetDriver(driverName)
	if err != nil {
		return nil, errors.Wrapf(err, "error while checking if volume %q exists in driver %q", volumeName, driverName)
	}
	v, err := vd.Get(volumeName)
	if err != nil {
		err = errors.Cause(err)
		if _, ok := err.(net.Error); ok {
			if v != nil {
				volumeName = v.Name()
				driverName = v.DriverName()
			}
			return nil, errors.Wrapf(err, "error while checking if volume %q exists in driver %q", volumeName, driverName)
		}

		// At this point, the error could be anything from the driver, such as "no such volume"
		// Let's not check an error here, and instead check if the driver returned a volume
		logrus.WithError(err).WithField("driver", driverName).WithField("volume", volumeName).Debug("Error while looking up volume")
	}
	return v, nil
}

// Remove removes the requested volume. A volume is not removed if it has any refs
func (s *VolumeStore) Remove(ctx context.Context, v volume.Volume, rmOpts ...opts.RemoveOption) error {
	var cfg opts.RemoveConfig
	for _, o := range rmOpts {
		o(&cfg)
	}

	name := v.Name()
	s.locks.Lock(name)
	defer s.locks.Unlock(name)

	select {
	case <-ctx.Done():
		return ctx.Err()
	default:
	}

	if s.hasRef(name) {
		return &OpErr{Err: errVolumeInUse, Name: name, Op: "remove", Refs: s.getRefs(name)}
	}

	v, err := s.getVolume(ctx, name, v.DriverName())
	if err != nil {
		return err
	}

	vd, err := s.drivers.GetDriver(v.DriverName())
	if err != nil {
		return &OpErr{Err: err, Name: v.DriverName(), Op: "remove"}
	}

	logrus.Debugf("Removing volume reference: driver %s, name %s", v.DriverName(), name)
	vol := unwrapVolume(v)

	err = vd.Remove(vol)
	if err != nil {
		err = &OpErr{Err: err, Name: name, Op: "remove"}
	}

	if err == nil || cfg.PurgeOnError {
		if e := s.purge(ctx, name); e != nil && err == nil {
			err = e
		}
	}
	return err
}

// Release releases the specified reference to the volume
func (s *VolumeStore) Release(ctx context.Context, name string, ref string) error {
	s.locks.Lock(name)
	defer s.locks.Unlock(name)
	select {
	case <-ctx.Done():
		return ctx.Err()
	default:
	}

	s.globalLock.Lock()
	defer s.globalLock.Unlock()

	select {
	case <-ctx.Done():
		return ctx.Err()
	default:
	}

	if s.refs[name] != nil {
		delete(s.refs[name], ref)
	}
	return nil
}

// CountReferences gives a count of all references for a given volume.
func (s *VolumeStore) CountReferences(v volume.Volume) int {
	name := normalizeVolumeName(v.Name())

	s.locks.Lock(name)
	defer s.locks.Unlock(name)
	s.globalLock.Lock()
	defer s.globalLock.Unlock()

	return len(s.refs[name])
}

func unwrapVolume(v volume.Volume) volume.Volume {
	if vol, ok := v.(volumeWrapper); ok {
		return vol.Volume
	}

	return v
}

// Shutdown releases all resources used by the volume store
// It does not make any changes to volumes, drivers, etc.
func (s *VolumeStore) Shutdown() error {
	return s.db.Close()
}
