daemon/daemon.go
359b7df5
 package daemon
a27b4b8c
 
 import (
8fb0ca2c
 	"errors"
a27b4b8c
 	"fmt"
46e05ed2
 	"io"
 	"io/ioutil"
 	"os"
e744b0dc
 	"path/filepath"
46e05ed2
 	"regexp"
4949e070
 	"runtime"
46e05ed2
 	"strings"
 	"sync"
 	"time"
 
6f4d8470
 	"github.com/Sirupsen/logrus"
9a85f60c
 	"github.com/docker/docker/api"
c9eb37f9
 	"github.com/docker/docker/daemon/events"
b3ee9ac7
 	"github.com/docker/docker/daemon/execdriver"
 	"github.com/docker/docker/daemon/execdriver/execdrivers"
 	"github.com/docker/docker/daemon/graphdriver"
49834e8d
 	_ "github.com/docker/docker/daemon/graphdriver/vfs"
3a8728b4
 	"github.com/docker/docker/daemon/logger"
53582321
 	"github.com/docker/docker/daemon/network"
b3ee9ac7
 	"github.com/docker/docker/graph"
9001ea26
 	"github.com/docker/docker/image"
5ab09f2f
 	"github.com/docker/docker/pkg/broadcastwriter"
c30a55f1
 	"github.com/docker/docker/pkg/fileutils"
b3ee9ac7
 	"github.com/docker/docker/pkg/graphdb"
76212635
 	"github.com/docker/docker/pkg/ioutils"
b3ee9ac7
 	"github.com/docker/docker/pkg/namesgenerator"
b80fae73
 	"github.com/docker/docker/pkg/stringid"
b3ee9ac7
 	"github.com/docker/docker/pkg/sysinfo"
8fb0ca2c
 	"github.com/docker/docker/pkg/system"
b3ee9ac7
 	"github.com/docker/docker/pkg/truncindex"
03d3d79b
 	"github.com/docker/docker/registry"
b3ee9ac7
 	"github.com/docker/docker/runconfig"
7c88e8f1
 	"github.com/docker/docker/trust"
8fb0ca2c
 	"github.com/docker/libnetwork"
c86189d5
 	"github.com/opencontainers/runc/libcontainer/netlink"
a27b4b8c
 )
 
f63cdf02
 var (
aa2af817
 	validContainerNameChars   = `[a-zA-Z0-9][a-zA-Z0-9_.-]`
3ec39ad0
 	validContainerNamePattern = regexp.MustCompile(`^/?` + validContainerNameChars + `+$`)
8fb0ca2c
 
62a75fca
 	ErrSystemNotSupported = errors.New("The Docker daemon is not supported on this platform.")
f63cdf02
 )
24e02043
 
af17b01a
 type contStore struct {
 	s map[string]*Container
 	sync.Mutex
 }
 
 func (c *contStore) Add(id string, cont *Container) {
 	c.Lock()
 	c.s[id] = cont
 	c.Unlock()
 }
 
 func (c *contStore) Get(id string) *Container {
 	c.Lock()
 	res := c.s[id]
 	c.Unlock()
 	return res
 }
 
 func (c *contStore) Delete(id string) {
 	c.Lock()
 	delete(c.s, id)
 	c.Unlock()
 }
 
 func (c *contStore) List() []*Container {
 	containers := new(History)
0b3fe554
 	c.Lock()
af17b01a
 	for _, cont := range c.s {
 		containers.Add(cont)
 	}
0b3fe554
 	c.Unlock()
af17b01a
 	containers.Sort()
 	return *containers
 }
 
359b7df5
 type Daemon struct {
47a6afb9
 	ID               string
 	repository       string
 	sysInitPath      string
 	containers       *contStore
 	execCommands     *execStore
 	graph            *graph.Graph
 	repositories     *graph.TagStore
 	idIndex          *truncindex.TruncIndex
 	sysInfo          *sysinfo.SysInfo
 	config           *Config
 	containerGraph   *graphdb.Database
 	driver           graphdriver.Driver
 	execDriver       execdriver.Driver
 	statsCollector   *statsCollector
 	defaultLogConfig runconfig.LogConfig
03d3d79b
 	RegistryService  *registry.Service
c9eb37f9
 	EventsService    *events.Events
d18919e3
 	netController    libnetwork.NetworkController
81fa9feb
 	root             string
7c57a4cf
 }
 
6217f294
 // Get looks for a container using the provided information, which could be
 // one of the following inputs from the caller:
 //  - A full container ID, which will exact match a container in daemon's list
 //  - A container name, which will only exact match via the GetByName() function
 //  - A partial container ID prefix (e.g. short ID) of any length that is
 //    unique enough to only return a single container object
 //  If none of these searches succeed, an error is returned
 func (daemon *Daemon) Get(prefixOrName string) (*Container, error) {
 	if containerByID := daemon.containers.Get(prefixOrName); containerByID != nil {
d25a6537
 		// prefix is an exact match to a full container ID
 		return containerByID, nil
231e07de
 	}
be27d971
 
6217f294
 	// GetByName will match only an exact name provided; we ignore errors
73bc885b
 	if containerByName, _ := daemon.GetByName(prefixOrName); containerByName != nil {
d25a6537
 		// prefix is an exact match to a full container Name
 		return containerByName, nil
1cbdaeba
 	}
be27d971
 
73bc885b
 	containerId, indexError := daemon.idIndex.Get(prefixOrName)
 	if indexError != nil {
 		return nil, indexError
be27d971
 	}
73bc885b
 	return daemon.containers.Get(containerId), nil
a27b4b8c
 }
 
6a9f4ecf
 // Exists returns a true if a container of the specified ID or name exists,
 // false otherwise.
359b7df5
 func (daemon *Daemon) Exists(id string) bool {
d25a6537
 	c, _ := daemon.Get(id)
 	return c != nil
a27b4b8c
 }
 
359b7df5
 func (daemon *Daemon) containerRoot(id string) string {
8fb0ca2c
 	return filepath.Join(daemon.repository, id)
7c57a4cf
 }
 
1cbdaeba
 // Load reads the contents of a container from disk
6a9f4ecf
 // This is typically done at startup.
359b7df5
 func (daemon *Daemon) load(id string) (*Container, error) {
003afaf1
 	container := &Container{
bd9814f0
 		CommonContainer: daemon.newBaseContainer(id),
003afaf1
 	}
b9e4b957
 
7c57a4cf
 	if err := container.FromDisk(); err != nil {
 		return nil, err
 	}
41870a42
 
fd224ee5
 	if container.ID != id {
 		return container, fmt.Errorf("Container %s is stored at %s", container.ID, id)
7c57a4cf
 	}
41870a42
 
a27b4b8c
 	return container, nil
 }
 
359b7df5
 // Register makes a container object usable by the daemon as <container.ID>
5d5c8939
 // This is a wrapper for register
359b7df5
 func (daemon *Daemon) Register(container *Container) error {
41870a42
 	return daemon.register(container, true)
5d5c8939
 }
 
 // register makes a container object usable by the daemon as <container.ID>
41870a42
 func (daemon *Daemon) register(container *Container, updateSuffixarray bool) error {
359b7df5
 	if container.daemon != nil || daemon.Exists(container.ID) {
7c57a4cf
 		return fmt.Errorf("Container is already loaded")
 	}
fd224ee5
 	if err := validateID(container.ID); err != nil {
7c57a4cf
 		return err
 	}
359b7df5
 	if err := daemon.ensureName(container); err != nil {
a9ed238b
 		return err
 	}
3dcaf20d
 
359b7df5
 	container.daemon = daemon
329f4449
 
7c57a4cf
 	// Attach to stdout and stderr
3a7e0735
 	container.stderr = broadcastwriter.New()
 	container.stdout = broadcastwriter.New()
7c57a4cf
 	// Attach to stdin
 	if container.Config.OpenStdin {
3a7e0735
 		container.stdin, container.stdinPipe = io.Pipe()
7c57a4cf
 	} else {
76212635
 		container.stdinPipe = ioutils.NopWriteCloser(ioutil.Discard) // Silently drop stdin
7c57a4cf
 	}
 	// done
af17b01a
 	daemon.containers.Add(container.ID, container)
5d5c8939
 
 	// don't update the Suffixarray if we're starting up
 	// we'll waste time if we update it for every container
e0dad305
 	daemon.idIndex.Add(container.ID)
82848d41
 
53d9609d
 	if err := daemon.verifyVolumesInfo(container); err != nil {
81fa9feb
 		return err
 	}
 
2653c7c1
 	if err := container.prepareMountPoints(); err != nil {
81fa9feb
 		return err
 	}
e744b0dc
 
e0339d4b
 	if container.IsRunning() {
6f4d8470
 		logrus.Debugf("killing old running container %s", container.ID)
b0b2f979
 		// Set exit code to 128 + SIGKILL (9) to properly represent unsuccessful exit
 		container.SetStopped(&execdriver.ExitStatus{ExitCode: 137})
cf997aa9
 
44cd599e
 		// use the current driver and ensure that the container is dead x.x
 		cmd := &execdriver.Command{
 			ID: container.ID,
cf997aa9
 		}
44cd599e
 		daemon.execDriver.Terminate(cmd)
a091d949
 
cf997aa9
 		if err := container.Unmount(); err != nil {
6f4d8470
 			logrus.Debugf("unmount error %s", err)
cf997aa9
 		}
 		if err := container.ToDisk(); err != nil {
af7f8187
 			logrus.Errorf("Error saving stopped state to disk: %v", err)
772ef99d
 		}
82848d41
 	}
a5f7c4aa
 
7c57a4cf
 	return nil
 }
 
359b7df5
 func (daemon *Daemon) ensureName(container *Container) error {
a9ed238b
 	if container.Name == "" {
6ec86cb6
 		name, err := daemon.generateNewName(container.ID)
a9ed238b
 		if err != nil {
6ec86cb6
 			return err
a9ed238b
 		}
 		container.Name = name
 
 		if err := container.ToDisk(); err != nil {
af7f8187
 			logrus.Errorf("Error saving container name to disk: %v", err)
a9ed238b
 		}
 	}
 	return nil
 }
 
359b7df5
 func (daemon *Daemon) restore() error {
81fa9feb
 	type cr struct {
 		container  *Container
 		registered bool
 	}
 
34bd2d62
 	var (
41870a42
 		debug         = (os.Getenv("DEBUG") != "" || os.Getenv("TEST") != "")
 		currentDriver = daemon.driver.String()
81fa9feb
 		containers    = make(map[string]*cr)
34bd2d62
 	)
0fd0deb7
 
 	if !debug {
6f4d8470
 		logrus.Info("Loading containers: start.")
20b1e196
 	}
359b7df5
 	dir, err := ioutil.ReadDir(daemon.repository)
a27b4b8c
 	if err != nil {
 		return err
 	}
356af154
 
fde909ff
 	for _, v := range dir {
7c57a4cf
 		id := v.Name()
359b7df5
 		container, err := daemon.load(id)
6f4d8470
 		if !debug && logrus.GetLevel() == logrus.InfoLevel {
fde909ff
 			fmt.Print(".")
20b1e196
 		}
a27b4b8c
 		if err != nil {
6f4d8470
 			logrus.Errorf("Failed to load container %v: %v", id, err)
a27b4b8c
 			continue
 		}
4908d7f8
 
 		// Ignore the container if it does not support the current driver being used by the graph
41870a42
 		if (container.Driver == "" && currentDriver == "aufs") || container.Driver == currentDriver {
6f4d8470
 			logrus.Debugf("Loaded container %v", container.ID)
41870a42
 
81fa9feb
 			containers[container.ID] = &cr{container: container}
4908d7f8
 		} else {
6f4d8470
 			logrus.Debugf("Cannot load container %s because it was created with another graph driver.", container.ID)
4908d7f8
 		}
1cbdaeba
 	}
 
359b7df5
 	if entities := daemon.containerGraph.List("/", -1); entities != nil {
356af154
 		for _, p := range entities.Paths() {
6f4d8470
 			if !debug && logrus.GetLevel() == logrus.InfoLevel {
fde909ff
 				fmt.Print(".")
 			}
41870a42
 
356af154
 			e := entities[p]
41870a42
 
81fa9feb
 			if c, ok := containers[e.ID()]; ok {
 				c.registered = true
356af154
 			}
1cbdaeba
 		}
356af154
 	}
2e6b241d
 
81fa9feb
 	group := sync.WaitGroup{}
 	for _, c := range containers {
 		group.Add(1)
41870a42
 
81fa9feb
 		go func(container *Container, registered bool) {
 			defer group.Done()
41870a42
 
81fa9feb
 			if !registered {
 				// Try to set the default name for a container if it exists prior to links
 				container.Name, err = daemon.generateNewName(container.ID)
 				if err != nil {
 					logrus.Debugf("Setting default id - %s", err)
 				}
 			}
356af154
 
81fa9feb
 			if err := daemon.register(container, false); err != nil {
 				logrus.Debugf("Failed to register container %s: %s", container.ID, err)
 			}
41870a42
 
81fa9feb
 			// check the restart policy on the containers and restart any container with
 			// the restart policy of "always"
2653c7c1
 			if daemon.config.AutoRestart && container.shouldRestart() {
6f4d8470
 				logrus.Debugf("Starting container %s", container.ID)
41870a42
 
 				if err := container.Start(); err != nil {
6f4d8470
 					logrus.Debugf("Failed to start container %s: %s", container.ID, err)
41870a42
 				}
 			}
81fa9feb
 		}(c.container, c.registered)
34bd2d62
 	}
81fa9feb
 	group.Wait()
34bd2d62
 
0fd0deb7
 	if !debug {
6f4d8470
 		if logrus.GetLevel() == logrus.InfoLevel {
88dc6cc2
 			fmt.Println()
 		}
6f4d8470
 		logrus.Info("Loading containers: done.")
20b1e196
 	}
1cbdaeba
 
a27b4b8c
 	return nil
 }
 
9001ea26
 func (daemon *Daemon) mergeAndVerifyConfig(config *runconfig.Config, img *image.Image) error {
89367899
 	if img != nil && img.Config != nil {
6393c383
 		if err := runconfig.Merge(config, img.Config); err != nil {
15134a33
 			return err
b2503a72
 		}
 	}
767df67e
 	if config.Entrypoint.Len() == 0 && config.Cmd.Len() == 0 {
15134a33
 		return fmt.Errorf("No command specified")
24e02043
 	}
15134a33
 	return nil
12778854
 }
24e02043
 
359b7df5
 func (daemon *Daemon) generateIdAndName(name string) (string, string, error) {
12778854
 	var (
 		err error
b80fae73
 		id  = stringid.GenerateRandomID()
12778854
 	)
1cbdaeba
 
0d292440
 	if name == "" {
6ec86cb6
 		if name, err = daemon.generateNewName(id); err != nil {
 			return "", "", err
f63cdf02
 		}
6ec86cb6
 		return id, name, nil
 	}
 
 	if name, err = daemon.reserveName(id, name); err != nil {
 		return "", "", err
 	}
 
 	return id, name, nil
 }
 
 func (daemon *Daemon) reserveName(id, name string) (string, error) {
 	if !validContainerNamePattern.MatchString(name) {
 		return "", fmt.Errorf("Invalid container name (%s), only %s are allowed", name, validContainerNameChars)
0d292440
 	}
6ec86cb6
 
0d292440
 	if name[0] != '/' {
 		name = "/" + name
 	}
6ec86cb6
 
359b7df5
 	if _, err := daemon.containerGraph.Set(name, id); err != nil {
e8af7fcf
 		if !graphdb.IsNonUniqueNameError(err) {
6ec86cb6
 			return "", err
7bf3a073
 		}
 
359b7df5
 		conflictingContainer, err := daemon.GetByName(name)
7bf3a073
 		if err != nil {
 			if strings.Contains(err.Error(), "Could not find entity") {
6ec86cb6
 				return "", err
7bf3a073
 			}
 
 			// Remove name and continue starting the container
359b7df5
 			if err := daemon.containerGraph.Delete(name); err != nil {
6ec86cb6
 				return "", err
7bf3a073
 			}
 		} else {
1cb7b9ad
 			nameAsKnownByUser := strings.TrimPrefix(name, "/")
6ec86cb6
 			return "", fmt.Errorf(
78820a63
 				"Conflict. The name %q is already in use by container %s. You have to delete (or rename) that container to be able to reuse that name.", nameAsKnownByUser,
b80fae73
 				stringid.TruncateID(conflictingContainer.ID))
8fa6e2b1
 		}
1cbdaeba
 	}
6ec86cb6
 	return name, nil
 }
 
 func (daemon *Daemon) generateNewName(id string) (string, error) {
 	var name string
e70a5ab0
 	for i := 0; i < 6; i++ {
6ec86cb6
 		name = namesgenerator.GetRandomName(i)
 		if name[0] != '/' {
 			name = "/" + name
 		}
 
 		if _, err := daemon.containerGraph.Set(name, id); err != nil {
 			if !graphdb.IsNonUniqueNameError(err) {
 				return "", err
 			}
 			continue
 		}
 		return name, nil
 	}
 
b80fae73
 	name = "/" + stringid.TruncateID(id)
6ec86cb6
 	if _, err := daemon.containerGraph.Set(name, id); err != nil {
 		return "", err
 	}
 	return name, nil
12778854
 }
1cbdaeba
 
359b7df5
 func (daemon *Daemon) generateHostname(id string, config *runconfig.Config) {
24e02043
 	// Generate default hostname
 	// FIXME: the lxc template no longer needs to set a default hostname
 	if config.Hostname == "" {
 		config.Hostname = id[:12]
 	}
12778854
 }
24e02043
 
767df67e
 func (daemon *Daemon) getEntrypointAndArgs(configEntrypoint *runconfig.Entrypoint, configCmd *runconfig.Command) (string, []string) {
12778854
 	var (
 		entrypoint string
 		args       []string
 	)
767df67e
 
 	cmdSlice := configCmd.Slice()
 	if configEntrypoint.Len() != 0 {
 		eSlice := configEntrypoint.Slice()
 		entrypoint = eSlice[0]
 		args = append(eSlice[1:], cmdSlice...)
24e02043
 	} else {
767df67e
 		entrypoint = cmdSlice[0]
 		args = cmdSlice[1:]
24e02043
 	}
12778854
 	return entrypoint, args
 }
 
89367899
 func (daemon *Daemon) newContainer(name string, config *runconfig.Config, imgID string) (*Container, error) {
08547dff
 	var (
 		id  string
 		err error
12778854
 	)
359b7df5
 	id, name, err = daemon.generateIdAndName(name)
12778854
 	if err != nil {
 		return nil, err
 	}
 
359b7df5
 	daemon.generateHostname(id, config)
5130fe5d
 	entrypoint, args := daemon.getEntrypointAndArgs(config.Entrypoint, config.Cmd)
24e02043
 
bd9814f0
 	base := daemon.newBaseContainer(id)
 	base.Created = time.Now().UTC()
 	base.Path = entrypoint
 	base.Args = args //FIXME: de-duplicate from config
 	base.Config = config
 	base.hostConfig = &runconfig.HostConfig{}
 	base.ImageID = imgID
 	base.NetworkSettings = &network.Settings{}
 	base.Name = name
 	base.Driver = daemon.driver.String()
 	base.ExecDriver = daemon.execDriver.Name()
 
24e02043
 	container := &Container{
bd9814f0
 		CommonContainer: base,
 	}
b9e4b957
 
08547dff
 	return container, err
12778854
 }
 
36c3614f
 func GetFullContainerName(name string) (string, error) {
a9ed238b
 	if name == "" {
 		return "", fmt.Errorf("Container name cannot be empty")
 	}
356af154
 	if name[0] != '/' {
 		name = "/" + name
 	}
a9ed238b
 	return name, nil
356af154
 }
 
359b7df5
 func (daemon *Daemon) GetByName(name string) (*Container, error) {
36c3614f
 	fullName, err := GetFullContainerName(name)
a9ed238b
 	if err != nil {
 		return nil, err
 	}
359b7df5
 	entity := daemon.containerGraph.Get(fullName)
1cbdaeba
 	if entity == nil {
 		return nil, fmt.Errorf("Could not find entity for %s", name)
 	}
af17b01a
 	e := daemon.containers.Get(entity.ID())
1cbdaeba
 	if e == nil {
 		return nil, fmt.Errorf("Could not find container for entity id %s", entity.ID())
 	}
af17b01a
 	return e, nil
1cbdaeba
 }
 
359b7df5
 func (daemon *Daemon) Children(name string) (map[string]*Container, error) {
36c3614f
 	name, err := GetFullContainerName(name)
a9ed238b
 	if err != nil {
 		return nil, err
 	}
1cbdaeba
 	children := make(map[string]*Container)
 
359b7df5
 	err = daemon.containerGraph.Walk(name, func(p string, e *graphdb.Entity) error {
d25a6537
 		c, err := daemon.Get(e.ID())
 		if err != nil {
 			return err
1cbdaeba
 		}
 		children[p] = c
 		return nil
 	}, 0)
 
 	if err != nil {
 		return nil, err
 	}
 	return children, nil
 }
 
450740c8
 func (daemon *Daemon) Parents(name string) ([]string, error) {
 	name, err := GetFullContainerName(name)
 	if err != nil {
 		return nil, err
 	}
 
 	return daemon.containerGraph.Parents(name)
 }
 
359b7df5
 func (daemon *Daemon) RegisterLink(parent, child *Container, alias string) error {
8fb0ca2c
 	fullName := filepath.Join(parent.Name, alias)
359b7df5
 	if !daemon.containerGraph.Exists(fullName) {
 		_, err := daemon.containerGraph.Set(fullName, child.ID)
1cbdaeba
 		return err
 	}
0d292440
 	return nil
1cbdaeba
 }
 
531f4122
 func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemon, err error) {
ff4e58ff
 	setDefaultMtu(config)
 
8fb0ca2c
 	// Ensure we have compatible configuration options
 	if err := checkConfigOptions(config); err != nil {
 		return nil, err
4dc4d56d
 	}
8fb0ca2c
 
 	// Do we have a disabled network?
c9328c6c
 	config.DisableBridge = isBridgeNetworkDisabled(config)
353b7c8e
 
62a75fca
 	// Verify the platform is supported as a daemon
 	if runtime.GOOS != "linux" && runtime.GOOS != "windows" {
 		return nil, ErrSystemNotSupported
 	}
 
 	// Validate platform-specific requirements
8fb0ca2c
 	if err := checkSystem(); err != nil {
23b2c39a
 		return nil, err
4949e070
 	}
 
f4b08c7f
 	// set up SIGUSR1 handler on Unix-like systems, or a Win32 global event
 	// on Windows to dump Go routine stacks
 	setupDumpStackTrap()
95fcf76c
 
e92a9e0b
 	// get the canonical path to the Docker root directory
 	var realRoot string
 	if _, err := os.Stat(config.Root); err != nil && os.IsNotExist(err) {
 		realRoot = config.Root
 	} else {
c30a55f1
 		realRoot, err = fileutils.ReadSymlinkedDirectory(config.Root)
e92a9e0b
 		if err != nil {
23b2c39a
 			return nil, fmt.Errorf("Unable to get the full path to root (%s): %s", config.Root, err)
e92a9e0b
 		}
 	}
 	config.Root = realRoot
b4ccd7cb
 	// Create the root directory if it doesn't exists
8fb0ca2c
 	if err := system.MkdirAll(config.Root, 0700); err != nil && !os.IsExist(err) {
b4ccd7cb
 		return nil, err
 	}
 
41f69883
 	// set up the tmpDir to use a canonical path
 	tmp, err := tempDir(config.Root)
 	if err != nil {
 		return nil, fmt.Errorf("Unable to get the TempDir under %s: %s", config.Root, err)
 	}
 	realTmp, err := fileutils.ReadSymlinkedDirectory(tmp)
 	if err != nil {
 		return nil, fmt.Errorf("Unable to get the full path to the TempDir (%s): %s", tmp, err)
 	}
 	os.Setenv("TMPDIR", realTmp)
 
6dbeed89
 	// Set the default driver
 	graphdriver.DefaultDriver = config.GraphDriver
 
f2bab155
 	// Load storage driver
822ea97f
 	driver, err := graphdriver.New(config.Root, config.GraphOptions)
f2bab155
 	if err != nil {
3941623f
 		return nil, fmt.Errorf("error initializing graphdriver: %v", err)
f2bab155
 	}
6f4d8470
 	logrus.Debugf("Using graph driver %s", driver)
531f4122
 
 	d := &Daemon{}
 	d.driver = driver
 
8fb0ca2c
 	// Ensure the graph driver is shutdown at a later point
531f4122
 	defer func() {
 		if err != nil {
 			if err := d.Shutdown(); err != nil {
 				logrus.Error(err)
 			}
459e58ff
 		}
531f4122
 	}()
f2bab155
 
3a8728b4
 	// Verify logging driver type
 	if config.LogConfig.Type != "none" {
 		if _, err := logger.GetLogDriver(config.LogConfig.Type); err != nil {
 			return nil, fmt.Errorf("error finding the logging driver: %v", err)
 		}
 	}
 	logrus.Debugf("Using default logging driver %s", config.LogConfig.Type)
 
8fb0ca2c
 	// Configure and validate the kernels security support
 	if err := configureKernelSecuritySupport(config, d.driver.String()); err != nil {
 		return nil, err
4318802f
 	}
 
8fb0ca2c
 	daemonRepo := filepath.Join(config.Root, "containers")
06553a75
 
8fb0ca2c
 	if err := system.MkdirAll(daemonRepo, 0700); err != nil && !os.IsExist(err) {
06553a75
 		return nil, err
 	}
 
670ce98c
 	// Migrate the container if it is aufs and aufs is enabled
8fb0ca2c
 	if err := migrateIfDownlevel(d.driver, config.Root); err != nil {
670ce98c
 		return nil, err
a518b847
 	}
 
6f4d8470
 	logrus.Debug("Creating images graph")
8fb0ca2c
 	g, err := graph.NewGraph(filepath.Join(config.Root, "graph"), d.driver)
2ebf3464
 	if err != nil {
 		return nil, err
 	}
10f23a94
 
8fb0ca2c
 	// Configure the volumes driver
 	if err := configureVolumes(config); err != nil {
1df5f409
 		return nil, err
 	}
45407cf0
 
8ceb9d20
 	trustKey, err := api.LoadOrCreateTrustKey(config.TrustKeyPath)
 	if err != nil {
 		return nil, err
 	}
 
8fb0ca2c
 	trustDir := filepath.Join(config.Root, "trust")
 
 	if err := system.MkdirAll(trustDir, 0700); err != nil && !os.IsExist(err) {
7c88e8f1
 		return nil, err
 	}
9e50bf62
 	trustService, err := trust.NewTrustStore(trustDir)
7c88e8f1
 	if err != nil {
 		return nil, fmt.Errorf("could not create trust store: %s", err)
 	}
 
9e50bf62
 	eventsService := events.New()
 	logrus.Debug("Creating repository list")
 	tagCfg := &graph.TagStoreConfig{
 		Graph:    g,
 		Key:      trustKey,
 		Registry: registryService,
 		Events:   eventsService,
 		Trust:    trustService,
 	}
8fb0ca2c
 	repositories, err := graph.NewTagStore(filepath.Join(config.Root, "repositories-"+d.driver.String()), tagCfg)
9e50bf62
 	if err != nil {
4815fdc3
 		return nil, fmt.Errorf("Couldn't create Tag store repositories-%s: %s", d.driver.String(), err)
9e50bf62
 	}
 
c9328c6c
 	d.netController, err = initNetworkController(config)
 	if err != nil {
 		return nil, fmt.Errorf("Error initializing network controller: %v", err)
1b370f9d
 	}
1cbdaeba
 
8fb0ca2c
 	graphdbPath := filepath.Join(config.Root, "linkgraph.db")
329d1542
 	graph, err := graphdb.NewSqliteConn(graphdbPath)
c08f5b2b
 	if err != nil {
 		return nil, err
 	}
531f4122
 
 	d.containerGraph = graph
1cbdaeba
 
96bc377a
 	var sysInitPath string
 	if config.ExecDriver == "lxc" {
 		initPath, err := configureSysInit(config)
 		if err != nil {
 			return nil, err
 		}
 		sysInitPath = initPath
110c4f20
 	}
 
07c35b41
 	sysInfo := sysinfo.New(false)
9d0ed1de
 	// Check if Devices cgroup is mounted, it is hard requirement for container security,
 	// on Linux/FreeBSD.
 	if runtime.GOOS != "windows" && !sysInfo.CgroupDevicesEnabled {
9b05aa6e
 		return nil, fmt.Errorf("Devices cgroup isn't mounted")
 	}
 
8b2c6cb0
 	ed, err := execdrivers.NewDriver(config.ExecDriver, config.ExecOptions, config.ExecRoot, config.Root, sysInitPath, sysInfo)
f2680e5a
 	if err != nil {
 		return nil, err
 	}
 
531f4122
 	d.ID = trustKey.PublicKey().KeyID()
 	d.repository = daemonRepo
 	d.containers = &contStore{s: make(map[string]*Container)}
 	d.execCommands = newExecStore()
 	d.graph = g
 	d.repositories = repositories
 	d.idIndex = truncindex.NewTruncIndex([]string{})
 	d.sysInfo = sysInfo
 	d.config = config
 	d.sysInitPath = sysInitPath
 	d.execDriver = ed
 	d.statsCollector = newStatsCollector(1 * time.Second)
 	d.defaultLogConfig = config.LogConfig
 	d.RegistryService = registryService
 	d.EventsService = eventsService
81fa9feb
 	d.root = config.Root
5f017bba
 	go d.execCommandGC()
531f4122
 
 	if err := d.restore(); err != nil {
0e3f2f2a
 		return nil, err
 	}
 
d18919e3
 	return d, nil
 }
 
531f4122
 func (daemon *Daemon) Shutdown() error {
 	if daemon.containers != nil {
 		group := sync.WaitGroup{}
 		logrus.Debug("starting clean shutdown of all containers...")
 		for _, container := range daemon.List() {
 			c := container
 			if c.IsRunning() {
 				logrus.Debugf("stopping %s", c.ID)
 				group.Add(1)
 
 				go func() {
 					defer group.Done()
bdb77078
 					// If container failed to exit in 10 seconds of SIGTERM, then using the force
 					if err := c.Stop(10); err != nil {
 						logrus.Errorf("Stop container %s with error: %v", c.ID, err)
531f4122
 					}
 					c.WaitStop(-1 * time.Second)
 					logrus.Debugf("container stopped %s", c.ID)
 				}()
 			}
 		}
 		group.Wait()
c68e7f96
 
 		// trigger libnetwork GC only if it's initialized
 		if daemon.netController != nil {
 			daemon.netController.GC()
 		}
531f4122
 	}
f067e263
 
0964a664
 	if daemon.containerGraph != nil {
 		if err := daemon.containerGraph.Close(); err != nil {
 			logrus.Errorf("Error during container graph.Close(): %v", err)
 		}
 	}
 
 	if daemon.driver != nil {
 		if err := daemon.driver.Cleanup(); err != nil {
 			logrus.Errorf("Error during graph storage driver.Cleanup(): %v", err)
 		}
 	}
 
f067e263
 	return nil
 }
 
359b7df5
 func (daemon *Daemon) Mount(container *Container) error {
1a5ffef6
 	dir, err := daemon.driver.Get(container.ID, container.GetMountLabel())
699a1074
 	if err != nil {
359b7df5
 		return fmt.Errorf("Error getting container %s from driver %s: %s", container.ID, daemon.driver, err)
f2bab155
 	}
8fb0ca2c
 
 	if container.basefs != dir {
 		// The mount path reported by the graph driver should always be trusted on Windows, since the
 		// volume path for a given mounted layer may change over time.  This should only be an error
 		// on non-Windows operating systems.
 		if container.basefs != "" && runtime.GOOS != "windows" {
 			daemon.driver.Put(container.ID)
 			return fmt.Errorf("Error: driver %s is returning inconsistent paths for container %s ('%s' then '%s')",
 				daemon.driver, container.ID, container.basefs, dir)
 		}
699a1074
 	}
8fb0ca2c
 	container.basefs = dir
f2bab155
 	return nil
699a1074
 }
 
359b7df5
 func (daemon *Daemon) Unmount(container *Container) error {
 	daemon.driver.Put(container.ID)
f2bab155
 	return nil
699a1074
 }
 
46f29449
 func (daemon *Daemon) Run(c *Container, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (execdriver.ExitStatus, error) {
359b7df5
 	return daemon.execDriver.Run(c.command, pipes, startCallback)
5a3d9bd4
 }
 
359b7df5
 func (daemon *Daemon) Kill(c *Container, sig int) error {
 	return daemon.execDriver.Kill(c.command, sig)
5a3d9bd4
 }
 
65f58e2a
 func (daemon *Daemon) Stats(c *Container) (*execdriver.ResourceStats, error) {
 	return daemon.execDriver.Stats(c.ID)
 }
 
2f46b760
 func (daemon *Daemon) SubscribeToContainerStats(name string) (chan interface{}, error) {
d25a6537
 	c, err := daemon.Get(name)
 	if err != nil {
 		return nil, err
65f58e2a
 	}
 	ch := daemon.statsCollector.collect(c)
 	return ch, nil
 }
 
2f46b760
 func (daemon *Daemon) UnsubscribeToContainerStats(name string, ch chan interface{}) error {
d25a6537
 	c, err := daemon.Get(name)
 	if err != nil {
 		return err
4f174aa7
 	}
 	daemon.statsCollector.unsubscribe(c, ch)
 	return nil
 }
 
359a6f49
 // FIXME: this is a convenience function for integration tests
359b7df5
 // which need direct access to daemon.graph.
359a6f49
 // Once the tests switch to using engine and jobs, this method
 // can go away.
359b7df5
 func (daemon *Daemon) Graph() *graph.Graph {
 	return daemon.graph
359a6f49
 }
 
359b7df5
 func (daemon *Daemon) Repositories() *graph.TagStore {
 	return daemon.repositories
36c3614f
 }
 
a4befff5
 func (daemon *Daemon) Config() *Config {
359b7df5
 	return daemon.config
36c3614f
 }
 
359b7df5
 func (daemon *Daemon) SystemConfig() *sysinfo.SysInfo {
 	return daemon.sysInfo
36c3614f
 }
 
359b7df5
 func (daemon *Daemon) SystemInitPath() string {
 	return daemon.sysInitPath
36c3614f
 }
 
359b7df5
 func (daemon *Daemon) GraphDriver() graphdriver.Driver {
 	return daemon.driver
36c3614f
 }
 
359b7df5
 func (daemon *Daemon) ExecutionDriver() execdriver.Driver {
 	return daemon.execDriver
36c3614f
 }
 
359b7df5
 func (daemon *Daemon) ContainerGraph() *graphdb.Database {
 	return daemon.containerGraph
36c3614f
 }
 
9001ea26
 func (daemon *Daemon) ImageGetCached(imgID string, config *runconfig.Config) (*image.Image, error) {
3a177ccd
 	// Retrieve all images
cc955ae7
 	images := daemon.Graph().Map()
3a177ccd
 
 	// Store the tree in a map of map (map[parentId][childId])
 	imageMap := make(map[string]map[string]struct{})
 	for _, img := range images {
 		if _, exists := imageMap[img.Parent]; !exists {
 			imageMap[img.Parent] = make(map[string]struct{})
 		}
 		imageMap[img.Parent][img.ID] = struct{}{}
 	}
 
 	// Loop on the children of the given image and check the config
9001ea26
 	var match *image.Image
3a177ccd
 	for elem := range imageMap[imgID] {
a2a50aa3
 		img, ok := images[elem]
 		if !ok {
 			return nil, fmt.Errorf("unable to find image %q", elem)
3a177ccd
 		}
 		if runconfig.Compare(&img.ContainerConfig, config) {
 			if match == nil || match.Created.Before(img.Created) {
 				match = img
 			}
 		}
 	}
 	return match, nil
 }
4949e070
 
f1bbc1f3
 // tempDir returns the default directory to use for temporary files.
 func tempDir(rootDir string) (string, error) {
 	var tmpDir string
 	if tmpDir = os.Getenv("DOCKER_TMPDIR"); tmpDir == "" {
 		tmpDir = filepath.Join(rootDir, "tmp")
 	}
8fb0ca2c
 	return tmpDir, system.MkdirAll(tmpDir, 0700)
93cdb007
 }
dde0cc78
 
 func (daemon *Daemon) setHostConfig(container *Container, hostConfig *runconfig.HostConfig) error {
b2a43baf
 	container.Lock()
 	if err := parseSecurityOpt(container, hostConfig); err != nil {
 		container.Unlock()
81fa9feb
 		return err
 	}
b2a43baf
 	container.Unlock()
81fa9feb
 
b2a43baf
 	// Do not lock while creating volumes since this could be calling out to external plugins
 	// Don't want to block other actions, like `docker ps` because we're waiting on an external plugin
 	if err := daemon.registerMountPoints(container, hostConfig); err != nil {
dde0cc78
 		return err
 	}
 
b2a43baf
 	container.Lock()
 	defer container.Unlock()
dde0cc78
 	// Register any links from the host config before starting the container
 	if err := daemon.RegisterLinks(container, hostConfig); err != nil {
 		return err
 	}
 
 	container.hostConfig = hostConfig
 	container.toDisk()
 	return nil
 }
bd9814f0
 
 func (daemon *Daemon) newBaseContainer(id string) CommonContainer {
 	return CommonContainer{
 		ID:           id,
 		State:        NewState(),
 		MountPoints:  make(map[string]*mountPoint),
 		Volumes:      make(map[string]string),
 		VolumesRW:    make(map[string]bool),
 		execCommands: newExecStore(),
 		root:         daemon.containerRoot(id),
 	}
 }
ff4e58ff
 
 func setDefaultMtu(config *Config) {
 	// do nothing if the config does not have the default 0 value.
 	if config.Mtu != 0 {
 		return
 	}
 	config.Mtu = defaultNetworkMtu
 	if routeMtu, err := getDefaultRouteMtu(); err == nil {
 		config.Mtu = routeMtu
 	}
 }
 
 var errNoDefaultRoute = errors.New("no default route was found")
 
 // getDefaultRouteMtu returns the MTU for the default route's interface.
 func getDefaultRouteMtu() (int, error) {
 	routes, err := netlink.NetworkGetRoutes()
 	if err != nil {
 		return 0, err
 	}
 	for _, r := range routes {
 		if r.Default {
 			return r.Iface.MTU, nil
 		}
 	}
 	return 0, errNoDefaultRoute
 }