2600777469
Before #16032, once links were setup in the sqlite db, hostConfig.Links was cleared out. This means that we need to migrate data back out of the sqlite db and put it back into hostConfig.Links so that links specified on older daemons can be used. Signed-off-by: Brian Goff <cpuguy83@gmail.com>
128 lines
3.8 KiB
Go
128 lines
3.8 KiB
Go
package daemon
|
|
|
|
import (
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/Sirupsen/logrus"
|
|
"github.com/docker/docker/container"
|
|
"github.com/docker/docker/pkg/graphdb"
|
|
)
|
|
|
|
// linkIndex stores link relationships between containers, including their specified alias
|
|
// The alias is the name the parent uses to reference the child
|
|
type linkIndex struct {
|
|
// idx maps a parent->alias->child relationship
|
|
idx map[*container.Container]map[string]*container.Container
|
|
// childIdx maps child->parent->aliases
|
|
childIdx map[*container.Container]map[*container.Container]map[string]struct{}
|
|
mu sync.Mutex
|
|
}
|
|
|
|
func newLinkIndex() *linkIndex {
|
|
return &linkIndex{
|
|
idx: make(map[*container.Container]map[string]*container.Container),
|
|
childIdx: make(map[*container.Container]map[*container.Container]map[string]struct{}),
|
|
}
|
|
}
|
|
|
|
// link adds indexes for the passed in parent/child/alias relationships
|
|
func (l *linkIndex) link(parent, child *container.Container, alias string) {
|
|
l.mu.Lock()
|
|
|
|
if l.idx[parent] == nil {
|
|
l.idx[parent] = make(map[string]*container.Container)
|
|
}
|
|
l.idx[parent][alias] = child
|
|
if l.childIdx[child] == nil {
|
|
l.childIdx[child] = make(map[*container.Container]map[string]struct{})
|
|
}
|
|
if l.childIdx[child][parent] == nil {
|
|
l.childIdx[child][parent] = make(map[string]struct{})
|
|
}
|
|
l.childIdx[child][parent][alias] = struct{}{}
|
|
|
|
l.mu.Unlock()
|
|
}
|
|
|
|
// unlink removes the requested alias for the given parent/child
|
|
func (l *linkIndex) unlink(alias string, child, parent *container.Container) {
|
|
l.mu.Lock()
|
|
delete(l.idx[parent], alias)
|
|
delete(l.childIdx[child], parent)
|
|
l.mu.Unlock()
|
|
}
|
|
|
|
// children maps all the aliases-> children for the passed in parent
|
|
// aliases here are the aliases the parent uses to refer to the child
|
|
func (l *linkIndex) children(parent *container.Container) map[string]*container.Container {
|
|
l.mu.Lock()
|
|
children := l.idx[parent]
|
|
l.mu.Unlock()
|
|
return children
|
|
}
|
|
|
|
// parents maps all the aliases->parent for the passed in child
|
|
// aliases here are the aliases the parents use to refer to the child
|
|
func (l *linkIndex) parents(child *container.Container) map[string]*container.Container {
|
|
l.mu.Lock()
|
|
|
|
parents := make(map[string]*container.Container)
|
|
for parent, aliases := range l.childIdx[child] {
|
|
for alias := range aliases {
|
|
parents[alias] = parent
|
|
}
|
|
}
|
|
|
|
l.mu.Unlock()
|
|
return parents
|
|
}
|
|
|
|
// delete deletes all link relationships referencing this container
|
|
func (l *linkIndex) delete(container *container.Container) {
|
|
l.mu.Lock()
|
|
for _, child := range l.idx[container] {
|
|
delete(l.childIdx[child], container)
|
|
}
|
|
delete(l.idx, container)
|
|
delete(l.childIdx, container)
|
|
l.mu.Unlock()
|
|
}
|
|
|
|
// migrateLegacySqliteLinks migrates sqlite links to use links from HostConfig
|
|
// when sqlite links were used, hostConfig.Links was set to nil
|
|
func (daemon *Daemon) migrateLegacySqliteLinks(db *graphdb.Database, container *container.Container) error {
|
|
// if links is populated (or an empty slice), then this isn't using sqlite links and can be skipped
|
|
if container.HostConfig == nil || container.HostConfig.Links != nil {
|
|
return nil
|
|
}
|
|
|
|
logrus.Debugf("migrating legacy sqlite link info for container: %s", container.ID)
|
|
|
|
fullName := container.Name
|
|
if fullName[0] != '/' {
|
|
fullName = "/" + fullName
|
|
}
|
|
|
|
// don't use a nil slice, this ensures that the check above will skip once the migration has completed
|
|
links := []string{}
|
|
children, err := db.Children(fullName, 0)
|
|
if err != nil {
|
|
if !strings.Contains(err.Error(), "Cannot find child for") {
|
|
return err
|
|
}
|
|
// else continue... it's ok if we didn't find any children, it'll just be nil and we can continue the migration
|
|
}
|
|
|
|
for _, child := range children {
|
|
c, err := daemon.GetContainer(child.Entity.ID())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
links = append(links, c.Name+":"+child.Edge.Name)
|
|
}
|
|
|
|
container.HostConfig.Links = links
|
|
return container.WriteHostConfig()
|
|
}
|