Move responsibility of ls/inspect to volume driver

Makes `docker volume ls` and `docker volume inspect` ask the volume
drivers rather than only using what is cached locally.

Previously in order to use a volume from an external driver, one would
either have to use `docker volume create` or have a container that is
already using that volume for it to be visible to the other volume
API's.

For keeping uniqueness of volume names in the daemon, names are bound to
a driver on a first come first serve basis. If two drivers have a volume
with the same name, the first one is chosen, and a warning is logged
about the second one.

Adds 2 new methods to the plugin API, `List` and `Get`.
If a plugin does not implement these endpoints, a user will not be able
to find the specified volumes as well requests go through the drivers.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
This commit is contained in:
Brian Goff 2015-09-23 16:29:14 -04:00
parent 5548d51a76
commit 390876ba18
2 changed files with 78 additions and 5 deletions

View file

@ -108,6 +108,15 @@ func (p *Plugin) activateWithLock() error {
return nil
}
func (p *Plugin) implements(kind string) bool {
for _, driver := range p.Manifest.Implements {
if driver == kind {
return true
}
}
return false
}
func load(name string) (*Plugin, error) {
return loadWithRetry(name, true)
}
@ -166,11 +175,9 @@ func Get(name, imp string) (*Plugin, error) {
if err != nil {
return nil, err
}
for _, driver := range pl.Manifest.Implements {
logrus.Debugf("%s implements: %s", name, driver)
if driver == imp {
return pl, nil
}
if pl.implements(imp) {
logrus.Debugf("%s implements: %s", name, imp)
return pl, nil
}
return nil, ErrNotImplements
}
@ -179,3 +186,37 @@ func Get(name, imp string) (*Plugin, error) {
func Handle(iface string, fn func(string, *Client)) {
extpointHandlers[iface] = fn
}
// GetAll returns all the plugins for the specified implementation
func GetAll(imp string) ([]*Plugin, error) {
pluginNames, err := Scan()
if err != nil {
return nil, err
}
type plLoad struct {
pl *Plugin
err error
}
chPl := make(chan plLoad, len(pluginNames))
for _, name := range pluginNames {
go func(name string) {
pl, err := loadWithRetry(name, false)
chPl <- plLoad{pl, err}
}(name)
}
var out []*Plugin
for i := 0; i < len(pluginNames); i++ {
pl := <-chPl
if pl.err != nil {
logrus.Error(err)
continue
}
if pl.pl.implements(imp) {
out = append(out, pl.pl)
}
}
return out, nil
}