github.com/sirupsen/docker@v0.10.1-0.20150325003727-22dba32b4dab/daemon/daemon.go (about)

     1  package daemon
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  	"io/ioutil"
     8  	"os"
     9  	"path"
    10  	"path/filepath"
    11  	"regexp"
    12  	"runtime"
    13  	"strings"
    14  	"sync"
    15  	"time"
    16  
    17  	"github.com/docker/libcontainer/label"
    18  
    19  	log "github.com/Sirupsen/logrus"
    20  	"github.com/docker/docker/api"
    21  	"github.com/docker/docker/autogen/dockerversion"
    22  	"github.com/docker/docker/daemon/execdriver"
    23  	"github.com/docker/docker/daemon/execdriver/execdrivers"
    24  	"github.com/docker/docker/daemon/execdriver/lxc"
    25  	"github.com/docker/docker/daemon/graphdriver"
    26  	_ "github.com/docker/docker/daemon/graphdriver/vfs"
    27  	_ "github.com/docker/docker/daemon/networkdriver/bridge"
    28  	"github.com/docker/docker/daemon/networkdriver/portallocator"
    29  	"github.com/docker/docker/engine"
    30  	"github.com/docker/docker/graph"
    31  	"github.com/docker/docker/image"
    32  	"github.com/docker/docker/pkg/archive"
    33  	"github.com/docker/docker/pkg/broadcastwriter"
    34  	"github.com/docker/docker/pkg/graphdb"
    35  	"github.com/docker/docker/pkg/ioutils"
    36  	"github.com/docker/docker/pkg/namesgenerator"
    37  	"github.com/docker/docker/pkg/parsers"
    38  	"github.com/docker/docker/pkg/parsers/kernel"
    39  	"github.com/docker/docker/pkg/pidfile"
    40  	"github.com/docker/docker/pkg/resolvconf"
    41  	"github.com/docker/docker/pkg/stringid"
    42  	"github.com/docker/docker/pkg/sysinfo"
    43  	"github.com/docker/docker/pkg/truncindex"
    44  	"github.com/docker/docker/runconfig"
    45  	"github.com/docker/docker/trust"
    46  	"github.com/docker/docker/utils"
    47  	"github.com/docker/docker/volumes"
    48  
    49  	"github.com/go-fsnotify/fsnotify"
    50  )
    51  
    52  var (
    53  	validContainerNameChars   = `[a-zA-Z0-9][a-zA-Z0-9_.-]`
    54  	validContainerNamePattern = regexp.MustCompile(`^/?` + validContainerNameChars + `+$`)
    55  )
    56  
    57  type contStore struct {
    58  	s map[string]*Container
    59  	sync.Mutex
    60  }
    61  
    62  func (c *contStore) Add(id string, cont *Container) {
    63  	c.Lock()
    64  	c.s[id] = cont
    65  	c.Unlock()
    66  }
    67  
    68  func (c *contStore) Get(id string) *Container {
    69  	c.Lock()
    70  	res := c.s[id]
    71  	c.Unlock()
    72  	return res
    73  }
    74  
    75  func (c *contStore) Delete(id string) {
    76  	c.Lock()
    77  	delete(c.s, id)
    78  	c.Unlock()
    79  }
    80  
    81  func (c *contStore) List() []*Container {
    82  	containers := new(History)
    83  	c.Lock()
    84  	for _, cont := range c.s {
    85  		containers.Add(cont)
    86  	}
    87  	c.Unlock()
    88  	containers.Sort()
    89  	return *containers
    90  }
    91  
    92  type Daemon struct {
    93  	ID               string
    94  	repository       string
    95  	sysInitPath      string
    96  	containers       *contStore
    97  	execCommands     *execStore
    98  	graph            *graph.Graph
    99  	repositories     *graph.TagStore
   100  	idIndex          *truncindex.TruncIndex
   101  	sysInfo          *sysinfo.SysInfo
   102  	volumes          *volumes.Repository
   103  	eng              *engine.Engine
   104  	config           *Config
   105  	containerGraph   *graphdb.Database
   106  	driver           graphdriver.Driver
   107  	execDriver       execdriver.Driver
   108  	trustStore       *trust.TrustStore
   109  	statsCollector   *statsCollector
   110  	defaultLogConfig runconfig.LogConfig
   111  }
   112  
   113  // Install installs daemon capabilities to eng.
   114  func (daemon *Daemon) Install(eng *engine.Engine) error {
   115  	// FIXME: remove ImageDelete's dependency on Daemon, then move to graph/
   116  	for name, method := range map[string]engine.Handler{
   117  		"attach":            daemon.ContainerAttach,
   118  		"commit":            daemon.ContainerCommit,
   119  		"container_changes": daemon.ContainerChanges,
   120  		"container_copy":    daemon.ContainerCopy,
   121  		"container_rename":  daemon.ContainerRename,
   122  		"container_inspect": daemon.ContainerInspect,
   123  		"container_stats":   daemon.ContainerStats,
   124  		"containers":        daemon.Containers,
   125  		"create":            daemon.ContainerCreate,
   126  		"rm":                daemon.ContainerRm,
   127  		"export":            daemon.ContainerExport,
   128  		"info":              daemon.CmdInfo,
   129  		"kill":              daemon.ContainerKill,
   130  		"logs":              daemon.ContainerLogs,
   131  		"pause":             daemon.ContainerPause,
   132  		"resize":            daemon.ContainerResize,
   133  		"restart":           daemon.ContainerRestart,
   134  		"start":             daemon.ContainerStart,
   135  		"stop":              daemon.ContainerStop,
   136  		"top":               daemon.ContainerTop,
   137  		"unpause":           daemon.ContainerUnpause,
   138  		"wait":              daemon.ContainerWait,
   139  		"image_delete":      daemon.ImageDelete, // FIXME: see above
   140  		"execCreate":        daemon.ContainerExecCreate,
   141  		"execStart":         daemon.ContainerExecStart,
   142  		"execResize":        daemon.ContainerExecResize,
   143  		"execInspect":       daemon.ContainerExecInspect,
   144  	} {
   145  		if err := eng.Register(name, method); err != nil {
   146  			return err
   147  		}
   148  	}
   149  	if err := daemon.Repositories().Install(eng); err != nil {
   150  		return err
   151  	}
   152  	if err := daemon.trustStore.Install(eng); err != nil {
   153  		return err
   154  	}
   155  	// FIXME: this hack is necessary for legacy integration tests to access
   156  	// the daemon object.
   157  	eng.Hack_SetGlobalVar("httpapi.daemon", daemon)
   158  	return nil
   159  }
   160  
   161  // Get looks for a container using the provided information, which could be
   162  // one of the following inputs from the caller:
   163  //  - A full container ID, which will exact match a container in daemon's list
   164  //  - A container name, which will only exact match via the GetByName() function
   165  //  - A partial container ID prefix (e.g. short ID) of any length that is
   166  //    unique enough to only return a single container object
   167  //  If none of these searches succeed, an error is returned
   168  func (daemon *Daemon) Get(prefixOrName string) (*Container, error) {
   169  	if containerByID := daemon.containers.Get(prefixOrName); containerByID != nil {
   170  		// prefix is an exact match to a full container ID
   171  		return containerByID, nil
   172  	}
   173  
   174  	// GetByName will match only an exact name provided; we ignore errors
   175  	containerByName, _ := daemon.GetByName(prefixOrName)
   176  	containerId, indexError := daemon.idIndex.Get(prefixOrName)
   177  
   178  	if containerByName != nil {
   179  		// prefix is an exact match to a full container Name
   180  		return containerByName, nil
   181  	}
   182  
   183  	if containerId != "" {
   184  		// prefix is a fuzzy match to a container ID
   185  		return daemon.containers.Get(containerId), nil
   186  	}
   187  	return nil, indexError
   188  }
   189  
   190  // Exists returns a true if a container of the specified ID or name exists,
   191  // false otherwise.
   192  func (daemon *Daemon) Exists(id string) bool {
   193  	c, _ := daemon.Get(id)
   194  	return c != nil
   195  }
   196  
   197  func (daemon *Daemon) containerRoot(id string) string {
   198  	return path.Join(daemon.repository, id)
   199  }
   200  
   201  // Load reads the contents of a container from disk
   202  // This is typically done at startup.
   203  func (daemon *Daemon) load(id string) (*Container, error) {
   204  	container := &Container{
   205  		root:         daemon.containerRoot(id),
   206  		State:        NewState(),
   207  		execCommands: newExecStore(),
   208  	}
   209  	if err := container.FromDisk(); err != nil {
   210  		return nil, err
   211  	}
   212  
   213  	if container.ID != id {
   214  		return container, fmt.Errorf("Container %s is stored at %s", container.ID, id)
   215  	}
   216  
   217  	container.readHostConfig()
   218  
   219  	return container, nil
   220  }
   221  
   222  // Register makes a container object usable by the daemon as <container.ID>
   223  // This is a wrapper for register
   224  func (daemon *Daemon) Register(container *Container) error {
   225  	return daemon.register(container, true)
   226  }
   227  
   228  // register makes a container object usable by the daemon as <container.ID>
   229  func (daemon *Daemon) register(container *Container, updateSuffixarray bool) error {
   230  	if container.daemon != nil || daemon.Exists(container.ID) {
   231  		return fmt.Errorf("Container is already loaded")
   232  	}
   233  	if err := validateID(container.ID); err != nil {
   234  		return err
   235  	}
   236  	if err := daemon.ensureName(container); err != nil {
   237  		return err
   238  	}
   239  
   240  	container.daemon = daemon
   241  
   242  	// Attach to stdout and stderr
   243  	container.stderr = broadcastwriter.New()
   244  	container.stdout = broadcastwriter.New()
   245  	// Attach to stdin
   246  	if container.Config.OpenStdin {
   247  		container.stdin, container.stdinPipe = io.Pipe()
   248  	} else {
   249  		container.stdinPipe = ioutils.NopWriteCloser(ioutil.Discard) // Silently drop stdin
   250  	}
   251  	// done
   252  	daemon.containers.Add(container.ID, container)
   253  
   254  	// don't update the Suffixarray if we're starting up
   255  	// we'll waste time if we update it for every container
   256  	daemon.idIndex.Add(container.ID)
   257  
   258  	container.registerVolumes()
   259  
   260  	// FIXME: if the container is supposed to be running but is not, auto restart it?
   261  	//        if so, then we need to restart monitor and init a new lock
   262  	// If the container is supposed to be running, make sure of it
   263  	if container.IsRunning() {
   264  		log.Debugf("killing old running container %s", container.ID)
   265  
   266  		existingPid := container.Pid
   267  		container.SetStopped(&execdriver.ExitStatus{ExitCode: 0})
   268  
   269  		// We only have to handle this for lxc because the other drivers will ensure that
   270  		// no processes are left when docker dies
   271  		if container.ExecDriver == "" || strings.Contains(container.ExecDriver, "lxc") {
   272  			lxc.KillLxc(container.ID, 9)
   273  		} else {
   274  			// use the current driver and ensure that the container is dead x.x
   275  			cmd := &execdriver.Command{
   276  				ID: container.ID,
   277  			}
   278  			var err error
   279  			cmd.ProcessConfig.Process, err = os.FindProcess(existingPid)
   280  			if err != nil {
   281  				log.Debugf("cannot find existing process for %d", existingPid)
   282  			}
   283  			daemon.execDriver.Terminate(cmd)
   284  		}
   285  
   286  		if err := container.Unmount(); err != nil {
   287  			log.Debugf("unmount error %s", err)
   288  		}
   289  		if err := container.ToDisk(); err != nil {
   290  			log.Debugf("saving stopped state to disk %s", err)
   291  		}
   292  
   293  		info := daemon.execDriver.Info(container.ID)
   294  		if !info.IsRunning() {
   295  			log.Debugf("Container %s was supposed to be running but is not.", container.ID)
   296  
   297  			log.Debugf("Marking as stopped")
   298  
   299  			container.SetStopped(&execdriver.ExitStatus{ExitCode: -127})
   300  			if err := container.ToDisk(); err != nil {
   301  				return err
   302  			}
   303  		}
   304  	}
   305  	return nil
   306  }
   307  
   308  func (daemon *Daemon) ensureName(container *Container) error {
   309  	if container.Name == "" {
   310  		name, err := daemon.generateNewName(container.ID)
   311  		if err != nil {
   312  			return err
   313  		}
   314  		container.Name = name
   315  
   316  		if err := container.ToDisk(); err != nil {
   317  			log.Debugf("Error saving container name %s", err)
   318  		}
   319  	}
   320  	return nil
   321  }
   322  
   323  func (daemon *Daemon) LogToDisk(src *broadcastwriter.BroadcastWriter, dst, stream string) error {
   324  	log, err := os.OpenFile(dst, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0600)
   325  	if err != nil {
   326  		return err
   327  	}
   328  	src.AddWriter(log, stream)
   329  	return nil
   330  }
   331  
   332  func (daemon *Daemon) restore() error {
   333  	var (
   334  		debug         = (os.Getenv("DEBUG") != "" || os.Getenv("TEST") != "")
   335  		containers    = make(map[string]*Container)
   336  		currentDriver = daemon.driver.String()
   337  	)
   338  
   339  	if !debug {
   340  		log.Infof("Loading containers: start.")
   341  	}
   342  	dir, err := ioutil.ReadDir(daemon.repository)
   343  	if err != nil {
   344  		return err
   345  	}
   346  
   347  	for _, v := range dir {
   348  		id := v.Name()
   349  		container, err := daemon.load(id)
   350  		if !debug && log.GetLevel() == log.InfoLevel {
   351  			fmt.Print(".")
   352  		}
   353  		if err != nil {
   354  			log.Errorf("Failed to load container %v: %v", id, err)
   355  			continue
   356  		}
   357  
   358  		// Ignore the container if it does not support the current driver being used by the graph
   359  		if (container.Driver == "" && currentDriver == "aufs") || container.Driver == currentDriver {
   360  			log.Debugf("Loaded container %v", container.ID)
   361  
   362  			containers[container.ID] = container
   363  		} else {
   364  			log.Debugf("Cannot load container %s because it was created with another graph driver.", container.ID)
   365  		}
   366  	}
   367  
   368  	registeredContainers := []*Container{}
   369  
   370  	if entities := daemon.containerGraph.List("/", -1); entities != nil {
   371  		for _, p := range entities.Paths() {
   372  			if !debug && log.GetLevel() == log.InfoLevel {
   373  				fmt.Print(".")
   374  			}
   375  
   376  			e := entities[p]
   377  
   378  			if container, ok := containers[e.ID()]; ok {
   379  				if err := daemon.register(container, false); err != nil {
   380  					log.Debugf("Failed to register container %s: %s", container.ID, err)
   381  				}
   382  
   383  				registeredContainers = append(registeredContainers, container)
   384  
   385  				// delete from the map so that a new name is not automatically generated
   386  				delete(containers, e.ID())
   387  			}
   388  		}
   389  	}
   390  
   391  	// Any containers that are left over do not exist in the graph
   392  	for _, container := range containers {
   393  		// Try to set the default name for a container if it exists prior to links
   394  		container.Name, err = daemon.generateNewName(container.ID)
   395  		if err != nil {
   396  			log.Debugf("Setting default id - %s", err)
   397  		}
   398  
   399  		if err := daemon.register(container, false); err != nil {
   400  			log.Debugf("Failed to register container %s: %s", container.ID, err)
   401  		}
   402  
   403  		registeredContainers = append(registeredContainers, container)
   404  	}
   405  
   406  	// check the restart policy on the containers and restart any container with
   407  	// the restart policy of "always"
   408  	if daemon.config.AutoRestart {
   409  		log.Debugf("Restarting containers...")
   410  
   411  		for _, container := range registeredContainers {
   412  			if container.hostConfig.RestartPolicy.Name == "always" ||
   413  				(container.hostConfig.RestartPolicy.Name == "on-failure" && container.ExitCode != 0) {
   414  				log.Debugf("Starting container %s", container.ID)
   415  
   416  				if err := container.Start(); err != nil {
   417  					log.Debugf("Failed to start container %s: %s", container.ID, err)
   418  				}
   419  			}
   420  		}
   421  	}
   422  
   423  	if !debug {
   424  		if log.GetLevel() == log.InfoLevel {
   425  			fmt.Println()
   426  		}
   427  		log.Infof("Loading containers: done.")
   428  	}
   429  
   430  	return nil
   431  }
   432  
   433  // set up the watch on the host's /etc/resolv.conf so that we can update container's
   434  // live resolv.conf when the network changes on the host
   435  func (daemon *Daemon) setupResolvconfWatcher() error {
   436  
   437  	watcher, err := fsnotify.NewWatcher()
   438  	if err != nil {
   439  		return err
   440  	}
   441  
   442  	//this goroutine listens for the events on the watch we add
   443  	//on the resolv.conf file on the host
   444  	go func() {
   445  		for {
   446  			select {
   447  			case event := <-watcher.Events:
   448  				if event.Name == "/etc/resolv.conf" &&
   449  					(event.Op&fsnotify.Write == fsnotify.Write ||
   450  						event.Op&fsnotify.Create == fsnotify.Create) {
   451  					// verify a real change happened before we go further--a file write may have happened
   452  					// without an actual change to the file
   453  					updatedResolvConf, newResolvConfHash, err := resolvconf.GetIfChanged()
   454  					if err != nil {
   455  						log.Debugf("Error retrieving updated host resolv.conf: %v", err)
   456  					} else if updatedResolvConf != nil {
   457  						// because the new host resolv.conf might have localhost nameservers..
   458  						updatedResolvConf, modified := resolvconf.FilterResolvDns(updatedResolvConf, daemon.config.EnableIPv6)
   459  						if modified {
   460  							// changes have occurred during localhost cleanup: generate an updated hash
   461  							newHash, err := utils.HashData(bytes.NewReader(updatedResolvConf))
   462  							if err != nil {
   463  								log.Debugf("Error generating hash of new resolv.conf: %v", err)
   464  							} else {
   465  								newResolvConfHash = newHash
   466  							}
   467  						}
   468  						log.Debugf("host network resolv.conf changed--walking container list for updates")
   469  						contList := daemon.containers.List()
   470  						for _, container := range contList {
   471  							if err := container.updateResolvConf(updatedResolvConf, newResolvConfHash); err != nil {
   472  								log.Debugf("Error on resolv.conf update check for container ID: %s: %v", container.ID, err)
   473  							}
   474  						}
   475  					}
   476  				}
   477  			case err := <-watcher.Errors:
   478  				log.Debugf("host resolv.conf notify error: %v", err)
   479  			}
   480  		}
   481  	}()
   482  
   483  	if err := watcher.Add("/etc"); err != nil {
   484  		return err
   485  	}
   486  	return nil
   487  }
   488  
   489  func (daemon *Daemon) checkDeprecatedExpose(config *runconfig.Config) bool {
   490  	if config != nil {
   491  		if config.PortSpecs != nil {
   492  			for _, p := range config.PortSpecs {
   493  				if strings.Contains(p, ":") {
   494  					return true
   495  				}
   496  			}
   497  		}
   498  	}
   499  	return false
   500  }
   501  
   502  func (daemon *Daemon) mergeAndVerifyConfig(config *runconfig.Config, img *image.Image) ([]string, error) {
   503  	warnings := []string{}
   504  	if (img != nil && daemon.checkDeprecatedExpose(img.Config)) || daemon.checkDeprecatedExpose(config) {
   505  		warnings = append(warnings, "The mapping to public ports on your host via Dockerfile EXPOSE (host:port:port) has been deprecated. Use -p to publish the ports.")
   506  	}
   507  	if img != nil && img.Config != nil {
   508  		if err := runconfig.Merge(config, img.Config); err != nil {
   509  			return nil, err
   510  		}
   511  	}
   512  	if len(config.Entrypoint) == 0 && len(config.Cmd) == 0 {
   513  		return nil, fmt.Errorf("No command specified")
   514  	}
   515  	return warnings, nil
   516  }
   517  
   518  func (daemon *Daemon) generateIdAndName(name string) (string, string, error) {
   519  	var (
   520  		err error
   521  		id  = stringid.GenerateRandomID()
   522  	)
   523  
   524  	if name == "" {
   525  		if name, err = daemon.generateNewName(id); err != nil {
   526  			return "", "", err
   527  		}
   528  		return id, name, nil
   529  	}
   530  
   531  	if name, err = daemon.reserveName(id, name); err != nil {
   532  		return "", "", err
   533  	}
   534  
   535  	return id, name, nil
   536  }
   537  
   538  func (daemon *Daemon) reserveName(id, name string) (string, error) {
   539  	if !validContainerNamePattern.MatchString(name) {
   540  		return "", fmt.Errorf("Invalid container name (%s), only %s are allowed", name, validContainerNameChars)
   541  	}
   542  
   543  	if name[0] != '/' {
   544  		name = "/" + name
   545  	}
   546  
   547  	if _, err := daemon.containerGraph.Set(name, id); err != nil {
   548  		if !graphdb.IsNonUniqueNameError(err) {
   549  			return "", err
   550  		}
   551  
   552  		conflictingContainer, err := daemon.GetByName(name)
   553  		if err != nil {
   554  			if strings.Contains(err.Error(), "Could not find entity") {
   555  				return "", err
   556  			}
   557  
   558  			// Remove name and continue starting the container
   559  			if err := daemon.containerGraph.Delete(name); err != nil {
   560  				return "", err
   561  			}
   562  		} else {
   563  			nameAsKnownByUser := strings.TrimPrefix(name, "/")
   564  			return "", fmt.Errorf(
   565  				"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,
   566  				stringid.TruncateID(conflictingContainer.ID))
   567  		}
   568  	}
   569  	return name, nil
   570  }
   571  
   572  func (daemon *Daemon) generateNewName(id string) (string, error) {
   573  	var name string
   574  	for i := 0; i < 6; i++ {
   575  		name = namesgenerator.GetRandomName(i)
   576  		if name[0] != '/' {
   577  			name = "/" + name
   578  		}
   579  
   580  		if _, err := daemon.containerGraph.Set(name, id); err != nil {
   581  			if !graphdb.IsNonUniqueNameError(err) {
   582  				return "", err
   583  			}
   584  			continue
   585  		}
   586  		return name, nil
   587  	}
   588  
   589  	name = "/" + stringid.TruncateID(id)
   590  	if _, err := daemon.containerGraph.Set(name, id); err != nil {
   591  		return "", err
   592  	}
   593  	return name, nil
   594  }
   595  
   596  func (daemon *Daemon) generateHostname(id string, config *runconfig.Config) {
   597  	// Generate default hostname
   598  	// FIXME: the lxc template no longer needs to set a default hostname
   599  	if config.Hostname == "" {
   600  		config.Hostname = id[:12]
   601  	}
   602  }
   603  
   604  func (daemon *Daemon) getEntrypointAndArgs(configEntrypoint, configCmd []string) (string, []string) {
   605  	var (
   606  		entrypoint string
   607  		args       []string
   608  	)
   609  	if len(configEntrypoint) != 0 {
   610  		entrypoint = configEntrypoint[0]
   611  		args = append(configEntrypoint[1:], configCmd...)
   612  	} else {
   613  		entrypoint = configCmd[0]
   614  		args = configCmd[1:]
   615  	}
   616  	return entrypoint, args
   617  }
   618  
   619  func parseSecurityOpt(container *Container, config *runconfig.HostConfig) error {
   620  	var (
   621  		labelOpts []string
   622  		err       error
   623  	)
   624  
   625  	for _, opt := range config.SecurityOpt {
   626  		con := strings.SplitN(opt, ":", 2)
   627  		if len(con) == 1 {
   628  			return fmt.Errorf("Invalid --security-opt: %q", opt)
   629  		}
   630  		switch con[0] {
   631  		case "label":
   632  			labelOpts = append(labelOpts, con[1])
   633  		case "apparmor":
   634  			container.AppArmorProfile = con[1]
   635  		default:
   636  			return fmt.Errorf("Invalid --security-opt: %q", opt)
   637  		}
   638  	}
   639  
   640  	container.ProcessLabel, container.MountLabel, err = label.InitLabels(labelOpts)
   641  	return err
   642  }
   643  
   644  func (daemon *Daemon) newContainer(name string, config *runconfig.Config, imgID string) (*Container, error) {
   645  	var (
   646  		id  string
   647  		err error
   648  	)
   649  	id, name, err = daemon.generateIdAndName(name)
   650  	if err != nil {
   651  		return nil, err
   652  	}
   653  
   654  	daemon.generateHostname(id, config)
   655  	entrypoint, args := daemon.getEntrypointAndArgs(config.Entrypoint, config.Cmd)
   656  
   657  	container := &Container{
   658  		// FIXME: we should generate the ID here instead of receiving it as an argument
   659  		ID:              id,
   660  		Created:         time.Now().UTC(),
   661  		Path:            entrypoint,
   662  		Args:            args, //FIXME: de-duplicate from config
   663  		Config:          config,
   664  		hostConfig:      &runconfig.HostConfig{},
   665  		ImageID:         imgID,
   666  		NetworkSettings: &NetworkSettings{},
   667  		Name:            name,
   668  		Driver:          daemon.driver.String(),
   669  		ExecDriver:      daemon.execDriver.Name(),
   670  		State:           NewState(),
   671  		execCommands:    newExecStore(),
   672  	}
   673  	container.root = daemon.containerRoot(container.ID)
   674  	return container, err
   675  }
   676  
   677  func (daemon *Daemon) createRootfs(container *Container) error {
   678  	// Step 1: create the container directory.
   679  	// This doubles as a barrier to avoid race conditions.
   680  	if err := os.Mkdir(container.root, 0700); err != nil {
   681  		return err
   682  	}
   683  	initID := fmt.Sprintf("%s-init", container.ID)
   684  	if err := daemon.driver.Create(initID, container.ImageID); err != nil {
   685  		return err
   686  	}
   687  	initPath, err := daemon.driver.Get(initID, "")
   688  	if err != nil {
   689  		return err
   690  	}
   691  	defer daemon.driver.Put(initID)
   692  
   693  	if err := graph.SetupInitLayer(initPath); err != nil {
   694  		return err
   695  	}
   696  
   697  	if err := daemon.driver.Create(container.ID, initID); err != nil {
   698  		return err
   699  	}
   700  	return nil
   701  }
   702  
   703  func GetFullContainerName(name string) (string, error) {
   704  	if name == "" {
   705  		return "", fmt.Errorf("Container name cannot be empty")
   706  	}
   707  	if name[0] != '/' {
   708  		name = "/" + name
   709  	}
   710  	return name, nil
   711  }
   712  
   713  func (daemon *Daemon) GetByName(name string) (*Container, error) {
   714  	fullName, err := GetFullContainerName(name)
   715  	if err != nil {
   716  		return nil, err
   717  	}
   718  	entity := daemon.containerGraph.Get(fullName)
   719  	if entity == nil {
   720  		return nil, fmt.Errorf("Could not find entity for %s", name)
   721  	}
   722  	e := daemon.containers.Get(entity.ID())
   723  	if e == nil {
   724  		return nil, fmt.Errorf("Could not find container for entity id %s", entity.ID())
   725  	}
   726  	return e, nil
   727  }
   728  
   729  func (daemon *Daemon) Children(name string) (map[string]*Container, error) {
   730  	name, err := GetFullContainerName(name)
   731  	if err != nil {
   732  		return nil, err
   733  	}
   734  	children := make(map[string]*Container)
   735  
   736  	err = daemon.containerGraph.Walk(name, func(p string, e *graphdb.Entity) error {
   737  		c, err := daemon.Get(e.ID())
   738  		if err != nil {
   739  			return err
   740  		}
   741  		children[p] = c
   742  		return nil
   743  	}, 0)
   744  
   745  	if err != nil {
   746  		return nil, err
   747  	}
   748  	return children, nil
   749  }
   750  
   751  func (daemon *Daemon) Parents(name string) ([]string, error) {
   752  	name, err := GetFullContainerName(name)
   753  	if err != nil {
   754  		return nil, err
   755  	}
   756  
   757  	return daemon.containerGraph.Parents(name)
   758  }
   759  
   760  func (daemon *Daemon) RegisterLink(parent, child *Container, alias string) error {
   761  	fullName := path.Join(parent.Name, alias)
   762  	if !daemon.containerGraph.Exists(fullName) {
   763  		_, err := daemon.containerGraph.Set(fullName, child.ID)
   764  		return err
   765  	}
   766  	return nil
   767  }
   768  
   769  func (daemon *Daemon) RegisterLinks(container *Container, hostConfig *runconfig.HostConfig) error {
   770  	if hostConfig != nil && hostConfig.Links != nil {
   771  		for _, l := range hostConfig.Links {
   772  			parts, err := parsers.PartParser("name:alias", l)
   773  			if err != nil {
   774  				return err
   775  			}
   776  			child, err := daemon.Get(parts["name"])
   777  			if err != nil {
   778  				//An error from daemon.Get() means this name could not be found
   779  				return fmt.Errorf("Could not get container for %s", parts["name"])
   780  			}
   781  			for child.hostConfig.NetworkMode.IsContainer() {
   782  				parts := strings.SplitN(string(child.hostConfig.NetworkMode), ":", 2)
   783  				child, err = daemon.Get(parts[1])
   784  				if err != nil {
   785  					return fmt.Errorf("Could not get container for %s", parts[1])
   786  				}
   787  			}
   788  			if child.hostConfig.NetworkMode.IsHost() {
   789  				return runconfig.ErrConflictHostNetworkAndLinks
   790  			}
   791  			if err := daemon.RegisterLink(container, child, parts["alias"]); err != nil {
   792  				return err
   793  			}
   794  		}
   795  
   796  		// After we load all the links into the daemon
   797  		// set them to nil on the hostconfig
   798  		hostConfig.Links = nil
   799  		if err := container.WriteHostConfig(); err != nil {
   800  			return err
   801  		}
   802  	}
   803  	return nil
   804  }
   805  
   806  // FIXME: harmonize with NewGraph()
   807  func NewDaemon(config *Config, eng *engine.Engine) (*Daemon, error) {
   808  	daemon, err := NewDaemonFromDirectory(config, eng)
   809  	if err != nil {
   810  		return nil, err
   811  	}
   812  	return daemon, nil
   813  }
   814  
   815  func NewDaemonFromDirectory(config *Config, eng *engine.Engine) (*Daemon, error) {
   816  	if config.Mtu == 0 {
   817  		config.Mtu = getDefaultNetworkMtu()
   818  	}
   819  	// Check for mutually incompatible config options
   820  	if config.BridgeIface != "" && config.BridgeIP != "" {
   821  		return nil, fmt.Errorf("You specified -b & --bip, mutually exclusive options. Please specify only one.")
   822  	}
   823  	if !config.EnableIptables && !config.InterContainerCommunication {
   824  		return nil, fmt.Errorf("You specified --iptables=false with --icc=false. ICC uses iptables to function. Please set --icc or --iptables to true.")
   825  	}
   826  	if !config.EnableIptables && config.EnableIpMasq {
   827  		config.EnableIpMasq = false
   828  	}
   829  	config.DisableNetwork = config.BridgeIface == disableNetworkBridge
   830  
   831  	// register portallocator release on shutdown
   832  	eng.OnShutdown(func() {
   833  		if err := portallocator.ReleaseAll(); err != nil {
   834  			log.Errorf("portallocator.ReleaseAll(): %s", err)
   835  		}
   836  	})
   837  	// Claim the pidfile first, to avoid any and all unexpected race conditions.
   838  	// Some of the init doesn't need a pidfile lock - but let's not try to be smart.
   839  	if config.Pidfile != "" {
   840  		file, err := pidfile.New(config.Pidfile)
   841  		if err != nil {
   842  			return nil, err
   843  		}
   844  		eng.OnShutdown(func() {
   845  			// Always release the pidfile last, just in case
   846  			file.Remove()
   847  		})
   848  	}
   849  
   850  	// Check that the system is supported and we have sufficient privileges
   851  	if runtime.GOOS != "linux" {
   852  		return nil, fmt.Errorf("The Docker daemon is only supported on linux")
   853  	}
   854  	if os.Geteuid() != 0 {
   855  		return nil, fmt.Errorf("The Docker daemon needs to be run as root")
   856  	}
   857  	if err := checkKernel(); err != nil {
   858  		return nil, err
   859  	}
   860  
   861  	// set up the TempDir to use a canonical path
   862  	tmp, err := utils.TempDir(config.Root)
   863  	if err != nil {
   864  		return nil, fmt.Errorf("Unable to get the TempDir under %s: %s", config.Root, err)
   865  	}
   866  	realTmp, err := utils.ReadSymlinkedDirectory(tmp)
   867  	if err != nil {
   868  		return nil, fmt.Errorf("Unable to get the full path to the TempDir (%s): %s", tmp, err)
   869  	}
   870  	os.Setenv("TMPDIR", realTmp)
   871  
   872  	// get the canonical path to the Docker root directory
   873  	var realRoot string
   874  	if _, err := os.Stat(config.Root); err != nil && os.IsNotExist(err) {
   875  		realRoot = config.Root
   876  	} else {
   877  		realRoot, err = utils.ReadSymlinkedDirectory(config.Root)
   878  		if err != nil {
   879  			return nil, fmt.Errorf("Unable to get the full path to root (%s): %s", config.Root, err)
   880  		}
   881  	}
   882  	config.Root = realRoot
   883  	// Create the root directory if it doesn't exists
   884  	if err := os.MkdirAll(config.Root, 0700); err != nil && !os.IsExist(err) {
   885  		return nil, err
   886  	}
   887  
   888  	// Set the default driver
   889  	graphdriver.DefaultDriver = config.GraphDriver
   890  
   891  	// Load storage driver
   892  	driver, err := graphdriver.New(config.Root, config.GraphOptions)
   893  	if err != nil {
   894  		return nil, fmt.Errorf("error intializing graphdriver: %v", err)
   895  	}
   896  	log.Debugf("Using graph driver %s", driver)
   897  	// register cleanup for graph driver
   898  	eng.OnShutdown(func() {
   899  		if err := driver.Cleanup(); err != nil {
   900  			log.Errorf("Error during graph storage driver.Cleanup(): %v", err)
   901  		}
   902  	})
   903  
   904  	if config.EnableSelinuxSupport {
   905  		if selinuxEnabled() {
   906  			// As Docker on btrfs and SELinux are incompatible at present, error on both being enabled
   907  			if driver.String() == "btrfs" {
   908  				return nil, fmt.Errorf("SELinux is not supported with the BTRFS graph driver")
   909  			}
   910  			log.Debug("SELinux enabled successfully")
   911  		} else {
   912  			log.Warn("Docker could not enable SELinux on the host system")
   913  		}
   914  	} else {
   915  		selinuxSetDisabled()
   916  	}
   917  
   918  	daemonRepo := path.Join(config.Root, "containers")
   919  
   920  	if err := os.MkdirAll(daemonRepo, 0700); err != nil && !os.IsExist(err) {
   921  		return nil, err
   922  	}
   923  
   924  	// Migrate the container if it is aufs and aufs is enabled
   925  	if err = migrateIfAufs(driver, config.Root); err != nil {
   926  		return nil, err
   927  	}
   928  
   929  	log.Debugf("Creating images graph")
   930  	g, err := graph.NewGraph(path.Join(config.Root, "graph"), driver)
   931  	if err != nil {
   932  		return nil, err
   933  	}
   934  
   935  	volumesDriver, err := graphdriver.GetDriver("vfs", config.Root, config.GraphOptions)
   936  	if err != nil {
   937  		return nil, err
   938  	}
   939  
   940  	volumes, err := volumes.NewRepository(filepath.Join(config.Root, "volumes"), volumesDriver)
   941  	if err != nil {
   942  		return nil, err
   943  	}
   944  
   945  	trustKey, err := api.LoadOrCreateTrustKey(config.TrustKeyPath)
   946  	if err != nil {
   947  		return nil, err
   948  	}
   949  
   950  	log.Debugf("Creating repository list")
   951  	repositories, err := graph.NewTagStore(path.Join(config.Root, "repositories-"+driver.String()), g, trustKey)
   952  	if err != nil {
   953  		return nil, fmt.Errorf("Couldn't create Tag store: %s", err)
   954  	}
   955  
   956  	trustDir := path.Join(config.Root, "trust")
   957  	if err := os.MkdirAll(trustDir, 0700); err != nil && !os.IsExist(err) {
   958  		return nil, err
   959  	}
   960  	t, err := trust.NewTrustStore(trustDir)
   961  	if err != nil {
   962  		return nil, fmt.Errorf("could not create trust store: %s", err)
   963  	}
   964  
   965  	if !config.DisableNetwork {
   966  		job := eng.Job("init_networkdriver")
   967  
   968  		job.SetenvBool("EnableIptables", config.EnableIptables)
   969  		job.SetenvBool("InterContainerCommunication", config.InterContainerCommunication)
   970  		job.SetenvBool("EnableIpForward", config.EnableIpForward)
   971  		job.SetenvBool("EnableIpMasq", config.EnableIpMasq)
   972  		job.SetenvBool("EnableIPv6", config.EnableIPv6)
   973  		job.Setenv("BridgeIface", config.BridgeIface)
   974  		job.Setenv("BridgeIP", config.BridgeIP)
   975  		job.Setenv("FixedCIDR", config.FixedCIDR)
   976  		job.Setenv("FixedCIDRv6", config.FixedCIDRv6)
   977  		job.Setenv("DefaultBindingIP", config.DefaultIp.String())
   978  
   979  		if err := job.Run(); err != nil {
   980  			return nil, err
   981  		}
   982  	}
   983  
   984  	graphdbPath := path.Join(config.Root, "linkgraph.db")
   985  	graph, err := graphdb.NewSqliteConn(graphdbPath)
   986  	if err != nil {
   987  		return nil, err
   988  	}
   989  	// register graph close on shutdown
   990  	eng.OnShutdown(func() {
   991  		if err := graph.Close(); err != nil {
   992  			log.Errorf("Error during container graph.Close(): %v", err)
   993  		}
   994  	})
   995  
   996  	localCopy := path.Join(config.Root, "init", fmt.Sprintf("dockerinit-%s", dockerversion.VERSION))
   997  	sysInitPath := utils.DockerInitPath(localCopy)
   998  	if sysInitPath == "" {
   999  		return nil, fmt.Errorf("Could not locate dockerinit: This usually means docker was built incorrectly. See http://docs.docker.com/contributing/devenvironment for official build instructions.")
  1000  	}
  1001  
  1002  	if sysInitPath != localCopy {
  1003  		// When we find a suitable dockerinit binary (even if it's our local binary), we copy it into config.Root at localCopy for future use (so that the original can go away without that being a problem, for example during a package upgrade).
  1004  		if err := os.Mkdir(path.Dir(localCopy), 0700); err != nil && !os.IsExist(err) {
  1005  			return nil, err
  1006  		}
  1007  		if _, err := utils.CopyFile(sysInitPath, localCopy); err != nil {
  1008  			return nil, err
  1009  		}
  1010  		if err := os.Chmod(localCopy, 0700); err != nil {
  1011  			return nil, err
  1012  		}
  1013  		sysInitPath = localCopy
  1014  	}
  1015  
  1016  	sysInfo := sysinfo.New(false)
  1017  	const runDir = "/var/run/docker"
  1018  	ed, err := execdrivers.NewDriver(config.ExecDriver, runDir, sysInitPath, sysInfo)
  1019  	if err != nil {
  1020  		return nil, err
  1021  	}
  1022  
  1023  	daemon := &Daemon{
  1024  		ID:               trustKey.PublicKey().KeyID(),
  1025  		repository:       daemonRepo,
  1026  		containers:       &contStore{s: make(map[string]*Container)},
  1027  		execCommands:     newExecStore(),
  1028  		graph:            g,
  1029  		repositories:     repositories,
  1030  		idIndex:          truncindex.NewTruncIndex([]string{}),
  1031  		sysInfo:          sysInfo,
  1032  		volumes:          volumes,
  1033  		config:           config,
  1034  		containerGraph:   graph,
  1035  		driver:           driver,
  1036  		sysInitPath:      sysInitPath,
  1037  		execDriver:       ed,
  1038  		eng:              eng,
  1039  		trustStore:       t,
  1040  		statsCollector:   newStatsCollector(1 * time.Second),
  1041  		defaultLogConfig: config.LogConfig,
  1042  	}
  1043  
  1044  	eng.OnShutdown(func() {
  1045  		if err := daemon.shutdown(); err != nil {
  1046  			log.Errorf("Error during daemon.shutdown(): %v", err)
  1047  		}
  1048  	})
  1049  
  1050  	if err := daemon.restore(); err != nil {
  1051  		return nil, err
  1052  	}
  1053  
  1054  	// set up filesystem watch on resolv.conf for network changes
  1055  	if err := daemon.setupResolvconfWatcher(); err != nil {
  1056  		return nil, err
  1057  	}
  1058  
  1059  	return daemon, nil
  1060  }
  1061  
  1062  func (daemon *Daemon) shutdown() error {
  1063  	group := sync.WaitGroup{}
  1064  	log.Debugf("starting clean shutdown of all containers...")
  1065  	for _, container := range daemon.List() {
  1066  		c := container
  1067  		if c.IsRunning() {
  1068  			log.Debugf("stopping %s", c.ID)
  1069  			group.Add(1)
  1070  
  1071  			go func() {
  1072  				defer group.Done()
  1073  				if err := c.KillSig(15); err != nil {
  1074  					log.Debugf("kill 15 error for %s - %s", c.ID, err)
  1075  				}
  1076  				c.WaitStop(-1 * time.Second)
  1077  				log.Debugf("container stopped %s", c.ID)
  1078  			}()
  1079  		}
  1080  	}
  1081  	group.Wait()
  1082  
  1083  	return nil
  1084  }
  1085  
  1086  func (daemon *Daemon) Mount(container *Container) error {
  1087  	dir, err := daemon.driver.Get(container.ID, container.GetMountLabel())
  1088  	if err != nil {
  1089  		return fmt.Errorf("Error getting container %s from driver %s: %s", container.ID, daemon.driver, err)
  1090  	}
  1091  	if container.basefs == "" {
  1092  		container.basefs = dir
  1093  	} else if container.basefs != dir {
  1094  		daemon.driver.Put(container.ID)
  1095  		return fmt.Errorf("Error: driver %s is returning inconsistent paths for container %s ('%s' then '%s')",
  1096  			daemon.driver, container.ID, container.basefs, dir)
  1097  	}
  1098  	return nil
  1099  }
  1100  
  1101  func (daemon *Daemon) Unmount(container *Container) error {
  1102  	daemon.driver.Put(container.ID)
  1103  	return nil
  1104  }
  1105  
  1106  func (daemon *Daemon) Changes(container *Container) ([]archive.Change, error) {
  1107  	initID := fmt.Sprintf("%s-init", container.ID)
  1108  	return daemon.driver.Changes(container.ID, initID)
  1109  }
  1110  
  1111  func (daemon *Daemon) Diff(container *Container) (archive.Archive, error) {
  1112  	initID := fmt.Sprintf("%s-init", container.ID)
  1113  	return daemon.driver.Diff(container.ID, initID)
  1114  }
  1115  
  1116  func (daemon *Daemon) Run(c *Container, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (execdriver.ExitStatus, error) {
  1117  	return daemon.execDriver.Run(c.command, pipes, startCallback)
  1118  }
  1119  
  1120  func (daemon *Daemon) Pause(c *Container) error {
  1121  	if err := daemon.execDriver.Pause(c.command); err != nil {
  1122  		return err
  1123  	}
  1124  	c.SetPaused()
  1125  	return nil
  1126  }
  1127  
  1128  func (daemon *Daemon) Unpause(c *Container) error {
  1129  	if err := daemon.execDriver.Unpause(c.command); err != nil {
  1130  		return err
  1131  	}
  1132  	c.SetUnpaused()
  1133  	return nil
  1134  }
  1135  
  1136  func (daemon *Daemon) Kill(c *Container, sig int) error {
  1137  	return daemon.execDriver.Kill(c.command, sig)
  1138  }
  1139  
  1140  func (daemon *Daemon) Stats(c *Container) (*execdriver.ResourceStats, error) {
  1141  	return daemon.execDriver.Stats(c.ID)
  1142  }
  1143  
  1144  func (daemon *Daemon) SubscribeToContainerStats(name string) (chan interface{}, error) {
  1145  	c, err := daemon.Get(name)
  1146  	if err != nil {
  1147  		return nil, err
  1148  	}
  1149  	ch := daemon.statsCollector.collect(c)
  1150  	return ch, nil
  1151  }
  1152  
  1153  func (daemon *Daemon) UnsubscribeToContainerStats(name string, ch chan interface{}) error {
  1154  	c, err := daemon.Get(name)
  1155  	if err != nil {
  1156  		return err
  1157  	}
  1158  	daemon.statsCollector.unsubscribe(c, ch)
  1159  	return nil
  1160  }
  1161  
  1162  // Nuke kills all containers then removes all content
  1163  // from the content root, including images, volumes and
  1164  // container filesystems.
  1165  // Again: this will remove your entire docker daemon!
  1166  // FIXME: this is deprecated, and only used in legacy
  1167  // tests. Please remove.
  1168  func (daemon *Daemon) Nuke() error {
  1169  	var wg sync.WaitGroup
  1170  	for _, container := range daemon.List() {
  1171  		wg.Add(1)
  1172  		go func(c *Container) {
  1173  			c.Kill()
  1174  			wg.Done()
  1175  		}(container)
  1176  	}
  1177  	wg.Wait()
  1178  
  1179  	return os.RemoveAll(daemon.config.Root)
  1180  }
  1181  
  1182  // FIXME: this is a convenience function for integration tests
  1183  // which need direct access to daemon.graph.
  1184  // Once the tests switch to using engine and jobs, this method
  1185  // can go away.
  1186  func (daemon *Daemon) Graph() *graph.Graph {
  1187  	return daemon.graph
  1188  }
  1189  
  1190  func (daemon *Daemon) Repositories() *graph.TagStore {
  1191  	return daemon.repositories
  1192  }
  1193  
  1194  func (daemon *Daemon) Config() *Config {
  1195  	return daemon.config
  1196  }
  1197  
  1198  func (daemon *Daemon) SystemConfig() *sysinfo.SysInfo {
  1199  	return daemon.sysInfo
  1200  }
  1201  
  1202  func (daemon *Daemon) SystemInitPath() string {
  1203  	return daemon.sysInitPath
  1204  }
  1205  
  1206  func (daemon *Daemon) GraphDriver() graphdriver.Driver {
  1207  	return daemon.driver
  1208  }
  1209  
  1210  func (daemon *Daemon) ExecutionDriver() execdriver.Driver {
  1211  	return daemon.execDriver
  1212  }
  1213  
  1214  func (daemon *Daemon) ContainerGraph() *graphdb.Database {
  1215  	return daemon.containerGraph
  1216  }
  1217  
  1218  func (daemon *Daemon) ImageGetCached(imgID string, config *runconfig.Config) (*image.Image, error) {
  1219  	// Retrieve all images
  1220  	images, err := daemon.Graph().Map()
  1221  	if err != nil {
  1222  		return nil, err
  1223  	}
  1224  
  1225  	// Store the tree in a map of map (map[parentId][childId])
  1226  	imageMap := make(map[string]map[string]struct{})
  1227  	for _, img := range images {
  1228  		if _, exists := imageMap[img.Parent]; !exists {
  1229  			imageMap[img.Parent] = make(map[string]struct{})
  1230  		}
  1231  		imageMap[img.Parent][img.ID] = struct{}{}
  1232  	}
  1233  
  1234  	// Loop on the children of the given image and check the config
  1235  	var match *image.Image
  1236  	for elem := range imageMap[imgID] {
  1237  		img, ok := images[elem]
  1238  		if !ok {
  1239  			return nil, fmt.Errorf("unable to find image %q", elem)
  1240  		}
  1241  		if runconfig.Compare(&img.ContainerConfig, config) {
  1242  			if match == nil || match.Created.Before(img.Created) {
  1243  				match = img
  1244  			}
  1245  		}
  1246  	}
  1247  	return match, nil
  1248  }
  1249  
  1250  func checkKernel() error {
  1251  	// Check for unsupported kernel versions
  1252  	// FIXME: it would be cleaner to not test for specific versions, but rather
  1253  	// test for specific functionalities.
  1254  	// Unfortunately we can't test for the feature "does not cause a kernel panic"
  1255  	// without actually causing a kernel panic, so we need this workaround until
  1256  	// the circumstances of pre-3.8 crashes are clearer.
  1257  	// For details see http://github.com/docker/docker/issues/407
  1258  	if k, err := kernel.GetKernelVersion(); err != nil {
  1259  		log.Warnf("%s", err)
  1260  	} else {
  1261  		if kernel.CompareKernelVersion(k, &kernel.KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0}) < 0 {
  1262  			if os.Getenv("DOCKER_NOWARN_KERNEL_VERSION") == "" {
  1263  				log.Warnf("You are running linux kernel version %s, which might be unstable running docker. Please upgrade your kernel to 3.8.0.", k.String())
  1264  			}
  1265  		}
  1266  	}
  1267  	return nil
  1268  }