github.com/mheon/docker@v0.11.2-0.20150922122814-44f47903a831/daemon/daemon.go (about)

     1  // Package daemon exposes the functions that occur on the host server
     2  // that the Docker daemon is running.
     3  //
     4  // In implementing the various functions of the daemon, there is often
     5  // a method-specific struct for configuring the runtime behavior.
     6  package daemon
     7  
     8  import (
     9  	"errors"
    10  	"fmt"
    11  	"io"
    12  	"io/ioutil"
    13  	"os"
    14  	"path/filepath"
    15  	"regexp"
    16  	"runtime"
    17  	"strings"
    18  	"sync"
    19  	"time"
    20  
    21  	"github.com/Sirupsen/logrus"
    22  	"github.com/docker/docker/api"
    23  	"github.com/docker/docker/daemon/events"
    24  	"github.com/docker/docker/daemon/execdriver"
    25  	"github.com/docker/docker/daemon/execdriver/execdrivers"
    26  	"github.com/docker/docker/daemon/graphdriver"
    27  	derr "github.com/docker/docker/errors"
    28  	// register vfs
    29  	_ "github.com/docker/docker/daemon/graphdriver/vfs"
    30  	"github.com/docker/docker/daemon/logger"
    31  	"github.com/docker/docker/daemon/network"
    32  	"github.com/docker/docker/graph"
    33  	"github.com/docker/docker/image"
    34  	"github.com/docker/docker/pkg/archive"
    35  	"github.com/docker/docker/pkg/broadcastwriter"
    36  	"github.com/docker/docker/pkg/fileutils"
    37  	"github.com/docker/docker/pkg/graphdb"
    38  	"github.com/docker/docker/pkg/ioutils"
    39  	"github.com/docker/docker/pkg/namesgenerator"
    40  	"github.com/docker/docker/pkg/nat"
    41  	"github.com/docker/docker/pkg/signal"
    42  	"github.com/docker/docker/pkg/stringid"
    43  	"github.com/docker/docker/pkg/stringutils"
    44  	"github.com/docker/docker/pkg/sysinfo"
    45  	"github.com/docker/docker/pkg/system"
    46  	"github.com/docker/docker/pkg/truncindex"
    47  	"github.com/docker/docker/registry"
    48  	"github.com/docker/docker/runconfig"
    49  	"github.com/docker/docker/trust"
    50  	volumedrivers "github.com/docker/docker/volume/drivers"
    51  	"github.com/docker/docker/volume/local"
    52  	"github.com/docker/docker/volume/store"
    53  	"github.com/docker/libnetwork"
    54  	"github.com/opencontainers/runc/libcontainer/netlink"
    55  )
    56  
    57  var (
    58  	validContainerNameChars   = `[a-zA-Z0-9][a-zA-Z0-9_.-]`
    59  	validContainerNamePattern = regexp.MustCompile(`^/?` + validContainerNameChars + `+$`)
    60  
    61  	errSystemNotSupported = errors.New("The Docker daemon is not supported on this platform.")
    62  )
    63  
    64  type contStore struct {
    65  	s map[string]*Container
    66  	sync.Mutex
    67  }
    68  
    69  func (c *contStore) Add(id string, cont *Container) {
    70  	c.Lock()
    71  	c.s[id] = cont
    72  	c.Unlock()
    73  }
    74  
    75  func (c *contStore) Get(id string) *Container {
    76  	c.Lock()
    77  	res := c.s[id]
    78  	c.Unlock()
    79  	return res
    80  }
    81  
    82  func (c *contStore) Delete(id string) {
    83  	c.Lock()
    84  	delete(c.s, id)
    85  	c.Unlock()
    86  }
    87  
    88  func (c *contStore) List() []*Container {
    89  	containers := new(History)
    90  	c.Lock()
    91  	for _, cont := range c.s {
    92  		containers.Add(cont)
    93  	}
    94  	c.Unlock()
    95  	containers.sort()
    96  	return *containers
    97  }
    98  
    99  // Daemon holds information about the Docker daemon.
   100  type Daemon struct {
   101  	ID               string
   102  	repository       string
   103  	sysInitPath      string
   104  	containers       *contStore
   105  	execCommands     *execStore
   106  	graph            *graph.Graph
   107  	repositories     *graph.TagStore
   108  	idIndex          *truncindex.TruncIndex
   109  	configStore      *Config
   110  	containerGraphDB *graphdb.Database
   111  	driver           graphdriver.Driver
   112  	execDriver       execdriver.Driver
   113  	statsCollector   *statsCollector
   114  	defaultLogConfig runconfig.LogConfig
   115  	RegistryService  *registry.Service
   116  	EventsService    *events.Events
   117  	netController    libnetwork.NetworkController
   118  	volumes          *store.VolumeStore
   119  	root             string
   120  	shutdown         bool
   121  }
   122  
   123  // Get looks for a container using the provided information, which could be
   124  // one of the following inputs from the caller:
   125  //  - A full container ID, which will exact match a container in daemon's list
   126  //  - A container name, which will only exact match via the GetByName() function
   127  //  - A partial container ID prefix (e.g. short ID) of any length that is
   128  //    unique enough to only return a single container object
   129  //  If none of these searches succeed, an error is returned
   130  func (daemon *Daemon) Get(prefixOrName string) (*Container, error) {
   131  	if containerByID := daemon.containers.Get(prefixOrName); containerByID != nil {
   132  		// prefix is an exact match to a full container ID
   133  		return containerByID, nil
   134  	}
   135  
   136  	// GetByName will match only an exact name provided; we ignore errors
   137  	if containerByName, _ := daemon.GetByName(prefixOrName); containerByName != nil {
   138  		// prefix is an exact match to a full container Name
   139  		return containerByName, nil
   140  	}
   141  
   142  	containerID, indexError := daemon.idIndex.Get(prefixOrName)
   143  	if indexError != nil {
   144  		// When truncindex defines an error type, use that instead
   145  		if strings.Contains(indexError.Error(), "no such id") {
   146  			return nil, derr.ErrorCodeNoSuchContainer.WithArgs(prefixOrName)
   147  		}
   148  		return nil, indexError
   149  	}
   150  	return daemon.containers.Get(containerID), nil
   151  }
   152  
   153  // Exists returns a true if a container of the specified ID or name exists,
   154  // false otherwise.
   155  func (daemon *Daemon) Exists(id string) bool {
   156  	c, _ := daemon.Get(id)
   157  	return c != nil
   158  }
   159  
   160  func (daemon *Daemon) containerRoot(id string) string {
   161  	return filepath.Join(daemon.repository, id)
   162  }
   163  
   164  // Load reads the contents of a container from disk
   165  // This is typically done at startup.
   166  func (daemon *Daemon) load(id string) (*Container, error) {
   167  	container := daemon.newBaseContainer(id)
   168  
   169  	if err := container.fromDisk(); err != nil {
   170  		return nil, err
   171  	}
   172  
   173  	if container.ID != id {
   174  		return &container, fmt.Errorf("Container %s is stored at %s", container.ID, id)
   175  	}
   176  
   177  	return &container, nil
   178  }
   179  
   180  // Register makes a container object usable by the daemon as <container.ID>
   181  func (daemon *Daemon) Register(container *Container) error {
   182  	if container.daemon != nil || daemon.Exists(container.ID) {
   183  		return fmt.Errorf("Container is already loaded")
   184  	}
   185  	if err := validateID(container.ID); err != nil {
   186  		return err
   187  	}
   188  	if err := daemon.ensureName(container); err != nil {
   189  		return err
   190  	}
   191  
   192  	container.daemon = daemon
   193  
   194  	// Attach to stdout and stderr
   195  	container.stderr = broadcastwriter.New()
   196  	container.stdout = broadcastwriter.New()
   197  	// Attach to stdin
   198  	if container.Config.OpenStdin {
   199  		container.stdin, container.stdinPipe = io.Pipe()
   200  	} else {
   201  		container.stdinPipe = ioutils.NopWriteCloser(ioutil.Discard) // Silently drop stdin
   202  	}
   203  	// done
   204  	daemon.containers.Add(container.ID, container)
   205  
   206  	// don't update the Suffixarray if we're starting up
   207  	// we'll waste time if we update it for every container
   208  	daemon.idIndex.Add(container.ID)
   209  
   210  	if container.IsRunning() {
   211  		logrus.Debugf("killing old running container %s", container.ID)
   212  		// Set exit code to 128 + SIGKILL (9) to properly represent unsuccessful exit
   213  		container.setStoppedLocking(&execdriver.ExitStatus{ExitCode: 137})
   214  		// use the current driver and ensure that the container is dead x.x
   215  		cmd := &execdriver.Command{
   216  			ID: container.ID,
   217  		}
   218  		daemon.execDriver.Terminate(cmd)
   219  
   220  		if err := container.Unmount(); err != nil {
   221  			logrus.Debugf("unmount error %s", err)
   222  		}
   223  		if err := container.toDiskLocking(); err != nil {
   224  			logrus.Errorf("Error saving stopped state to disk: %v", err)
   225  		}
   226  	}
   227  
   228  	if err := daemon.verifyVolumesInfo(container); err != nil {
   229  		return err
   230  	}
   231  
   232  	if err := container.prepareMountPoints(); err != nil {
   233  		return err
   234  	}
   235  
   236  	return nil
   237  }
   238  
   239  func (daemon *Daemon) ensureName(container *Container) error {
   240  	if container.Name == "" {
   241  		name, err := daemon.generateNewName(container.ID)
   242  		if err != nil {
   243  			return err
   244  		}
   245  		container.Name = name
   246  
   247  		if err := container.toDiskLocking(); err != nil {
   248  			logrus.Errorf("Error saving container name to disk: %v", err)
   249  		}
   250  	}
   251  	return nil
   252  }
   253  
   254  func (daemon *Daemon) restore() error {
   255  	type cr struct {
   256  		container  *Container
   257  		registered bool
   258  	}
   259  
   260  	var (
   261  		debug         = os.Getenv("DEBUG") != ""
   262  		currentDriver = daemon.driver.String()
   263  		containers    = make(map[string]*cr)
   264  	)
   265  
   266  	if !debug {
   267  		logrus.Info("Loading containers: start.")
   268  	}
   269  	dir, err := ioutil.ReadDir(daemon.repository)
   270  	if err != nil {
   271  		return err
   272  	}
   273  
   274  	for _, v := range dir {
   275  		id := v.Name()
   276  		container, err := daemon.load(id)
   277  		if !debug && logrus.GetLevel() == logrus.InfoLevel {
   278  			fmt.Print(".")
   279  		}
   280  		if err != nil {
   281  			logrus.Errorf("Failed to load container %v: %v", id, err)
   282  			continue
   283  		}
   284  
   285  		// Ignore the container if it does not support the current driver being used by the graph
   286  		if (container.Driver == "" && currentDriver == "aufs") || container.Driver == currentDriver {
   287  			logrus.Debugf("Loaded container %v", container.ID)
   288  
   289  			containers[container.ID] = &cr{container: container}
   290  		} else {
   291  			logrus.Debugf("Cannot load container %s because it was created with another graph driver.", container.ID)
   292  		}
   293  	}
   294  
   295  	if entities := daemon.containerGraphDB.List("/", -1); entities != nil {
   296  		for _, p := range entities.Paths() {
   297  			if !debug && logrus.GetLevel() == logrus.InfoLevel {
   298  				fmt.Print(".")
   299  			}
   300  
   301  			e := entities[p]
   302  
   303  			if c, ok := containers[e.ID()]; ok {
   304  				c.registered = true
   305  			}
   306  		}
   307  	}
   308  
   309  	group := sync.WaitGroup{}
   310  	for _, c := range containers {
   311  		group.Add(1)
   312  
   313  		go func(container *Container, registered bool) {
   314  			defer group.Done()
   315  
   316  			if !registered {
   317  				// Try to set the default name for a container if it exists prior to links
   318  				container.Name, err = daemon.generateNewName(container.ID)
   319  				if err != nil {
   320  					logrus.Debugf("Setting default id - %s", err)
   321  				}
   322  			}
   323  
   324  			if err := daemon.Register(container); err != nil {
   325  				logrus.Errorf("Failed to register container %s: %s", container.ID, err)
   326  				// The container register failed should not be started.
   327  				return
   328  			}
   329  
   330  			// check the restart policy on the containers and restart any container with
   331  			// the restart policy of "always"
   332  			if daemon.configStore.AutoRestart && container.shouldRestart() {
   333  				logrus.Debugf("Starting container %s", container.ID)
   334  
   335  				if err := container.Start(); err != nil {
   336  					logrus.Errorf("Failed to start container %s: %s", container.ID, err)
   337  				}
   338  			}
   339  		}(c.container, c.registered)
   340  	}
   341  	group.Wait()
   342  
   343  	if !debug {
   344  		if logrus.GetLevel() == logrus.InfoLevel {
   345  			fmt.Println()
   346  		}
   347  		logrus.Info("Loading containers: done.")
   348  	}
   349  
   350  	return nil
   351  }
   352  
   353  func (daemon *Daemon) mergeAndVerifyConfig(config *runconfig.Config, img *image.Image) error {
   354  	if img != nil && img.Config != nil {
   355  		if err := runconfig.Merge(config, img.Config); err != nil {
   356  			return err
   357  		}
   358  	}
   359  	if config.Entrypoint.Len() == 0 && config.Cmd.Len() == 0 {
   360  		return fmt.Errorf("No command specified")
   361  	}
   362  	return nil
   363  }
   364  
   365  func (daemon *Daemon) generateIDAndName(name string) (string, string, error) {
   366  	var (
   367  		err error
   368  		id  = stringid.GenerateNonCryptoID()
   369  	)
   370  
   371  	if name == "" {
   372  		if name, err = daemon.generateNewName(id); err != nil {
   373  			return "", "", err
   374  		}
   375  		return id, name, nil
   376  	}
   377  
   378  	if name, err = daemon.reserveName(id, name); err != nil {
   379  		return "", "", err
   380  	}
   381  
   382  	return id, name, nil
   383  }
   384  
   385  func (daemon *Daemon) reserveName(id, name string) (string, error) {
   386  	if !validContainerNamePattern.MatchString(name) {
   387  		return "", fmt.Errorf("Invalid container name (%s), only %s are allowed", name, validContainerNameChars)
   388  	}
   389  
   390  	if name[0] != '/' {
   391  		name = "/" + name
   392  	}
   393  
   394  	if _, err := daemon.containerGraphDB.Set(name, id); err != nil {
   395  		if !graphdb.IsNonUniqueNameError(err) {
   396  			return "", err
   397  		}
   398  
   399  		conflictingContainer, err := daemon.GetByName(name)
   400  		if err != nil {
   401  			if strings.Contains(err.Error(), "Could not find entity") {
   402  				return "", err
   403  			}
   404  
   405  			// Remove name and continue starting the container
   406  			if err := daemon.containerGraphDB.Delete(name); err != nil {
   407  				return "", err
   408  			}
   409  		} else {
   410  			nameAsKnownByUser := strings.TrimPrefix(name, "/")
   411  			return "", fmt.Errorf(
   412  				"Conflict. The name %q is already in use by container %s. You have to remove (or rename) that container to be able to reuse that name.", nameAsKnownByUser,
   413  				stringid.TruncateID(conflictingContainer.ID))
   414  		}
   415  	}
   416  	return name, nil
   417  }
   418  
   419  func (daemon *Daemon) generateNewName(id string) (string, error) {
   420  	var name string
   421  	for i := 0; i < 6; i++ {
   422  		name = namesgenerator.GetRandomName(i)
   423  		if name[0] != '/' {
   424  			name = "/" + name
   425  		}
   426  
   427  		if _, err := daemon.containerGraphDB.Set(name, id); err != nil {
   428  			if !graphdb.IsNonUniqueNameError(err) {
   429  				return "", err
   430  			}
   431  			continue
   432  		}
   433  		return name, nil
   434  	}
   435  
   436  	name = "/" + stringid.TruncateID(id)
   437  	if _, err := daemon.containerGraphDB.Set(name, id); err != nil {
   438  		return "", err
   439  	}
   440  	return name, nil
   441  }
   442  
   443  func (daemon *Daemon) generateHostname(id string, config *runconfig.Config) {
   444  	// Generate default hostname
   445  	// FIXME: the lxc template no longer needs to set a default hostname
   446  	if config.Hostname == "" {
   447  		config.Hostname = id[:12]
   448  	}
   449  }
   450  
   451  func (daemon *Daemon) getEntrypointAndArgs(configEntrypoint *stringutils.StrSlice, configCmd *stringutils.StrSlice) (string, []string) {
   452  	var (
   453  		entrypoint string
   454  		args       []string
   455  	)
   456  
   457  	cmdSlice := configCmd.Slice()
   458  	if configEntrypoint.Len() != 0 {
   459  		eSlice := configEntrypoint.Slice()
   460  		entrypoint = eSlice[0]
   461  		args = append(eSlice[1:], cmdSlice...)
   462  	} else {
   463  		entrypoint = cmdSlice[0]
   464  		args = cmdSlice[1:]
   465  	}
   466  	return entrypoint, args
   467  }
   468  
   469  func (daemon *Daemon) newContainer(name string, config *runconfig.Config, imgID string) (*Container, error) {
   470  	var (
   471  		id  string
   472  		err error
   473  	)
   474  	id, name, err = daemon.generateIDAndName(name)
   475  	if err != nil {
   476  		return nil, err
   477  	}
   478  
   479  	daemon.generateHostname(id, config)
   480  	entrypoint, args := daemon.getEntrypointAndArgs(config.Entrypoint, config.Cmd)
   481  
   482  	base := daemon.newBaseContainer(id)
   483  	base.Created = time.Now().UTC()
   484  	base.Path = entrypoint
   485  	base.Args = args //FIXME: de-duplicate from config
   486  	base.Config = config
   487  	base.hostConfig = &runconfig.HostConfig{}
   488  	base.ImageID = imgID
   489  	base.NetworkSettings = &network.Settings{}
   490  	base.Name = name
   491  	base.Driver = daemon.driver.String()
   492  	base.ExecDriver = daemon.execDriver.Name()
   493  
   494  	return &base, err
   495  }
   496  
   497  // GetFullContainerName returns a constructed container name. I think
   498  // it has to do with the fact that a container is a file on disk and
   499  // this is sort of just creating a file name.
   500  func GetFullContainerName(name string) (string, error) {
   501  	if name == "" {
   502  		return "", fmt.Errorf("Container name cannot be empty")
   503  	}
   504  	if name[0] != '/' {
   505  		name = "/" + name
   506  	}
   507  	return name, nil
   508  }
   509  
   510  // GetByName returns a container given a name.
   511  func (daemon *Daemon) GetByName(name string) (*Container, error) {
   512  	fullName, err := GetFullContainerName(name)
   513  	if err != nil {
   514  		return nil, err
   515  	}
   516  	entity := daemon.containerGraphDB.Get(fullName)
   517  	if entity == nil {
   518  		return nil, fmt.Errorf("Could not find entity for %s", name)
   519  	}
   520  	e := daemon.containers.Get(entity.ID())
   521  	if e == nil {
   522  		return nil, fmt.Errorf("Could not find container for entity id %s", entity.ID())
   523  	}
   524  	return e, nil
   525  }
   526  
   527  // children returns all child containers of the container with the
   528  // given name. The containers are returned as a map from the container
   529  // name to a pointer to Container.
   530  func (daemon *Daemon) children(name string) (map[string]*Container, error) {
   531  	name, err := GetFullContainerName(name)
   532  	if err != nil {
   533  		return nil, err
   534  	}
   535  	children := make(map[string]*Container)
   536  
   537  	err = daemon.containerGraphDB.Walk(name, func(p string, e *graphdb.Entity) error {
   538  		c, err := daemon.Get(e.ID())
   539  		if err != nil {
   540  			return err
   541  		}
   542  		children[p] = c
   543  		return nil
   544  	}, 0)
   545  
   546  	if err != nil {
   547  		return nil, err
   548  	}
   549  	return children, nil
   550  }
   551  
   552  // parents returns the names of the parent containers of the container
   553  // with the given name.
   554  func (daemon *Daemon) parents(name string) ([]string, error) {
   555  	name, err := GetFullContainerName(name)
   556  	if err != nil {
   557  		return nil, err
   558  	}
   559  
   560  	return daemon.containerGraphDB.Parents(name)
   561  }
   562  
   563  func (daemon *Daemon) registerLink(parent, child *Container, alias string) error {
   564  	fullName := filepath.Join(parent.Name, alias)
   565  	if !daemon.containerGraphDB.Exists(fullName) {
   566  		_, err := daemon.containerGraphDB.Set(fullName, child.ID)
   567  		return err
   568  	}
   569  	return nil
   570  }
   571  
   572  // NewDaemon sets up everything for the daemon to be able to service
   573  // requests from the webserver.
   574  func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemon, err error) {
   575  	setDefaultMtu(config)
   576  
   577  	// Ensure we have compatible configuration options
   578  	if err := checkConfigOptions(config); err != nil {
   579  		return nil, err
   580  	}
   581  
   582  	// Do we have a disabled network?
   583  	config.DisableBridge = isBridgeNetworkDisabled(config)
   584  
   585  	// Verify the platform is supported as a daemon
   586  	if !platformSupported {
   587  		return nil, errSystemNotSupported
   588  	}
   589  
   590  	// Validate platform-specific requirements
   591  	if err := checkSystem(); err != nil {
   592  		return nil, err
   593  	}
   594  
   595  	// set up SIGUSR1 handler on Unix-like systems, or a Win32 global event
   596  	// on Windows to dump Go routine stacks
   597  	setupDumpStackTrap()
   598  
   599  	// get the canonical path to the Docker root directory
   600  	var realRoot string
   601  	if _, err := os.Stat(config.Root); err != nil && os.IsNotExist(err) {
   602  		realRoot = config.Root
   603  	} else {
   604  		realRoot, err = fileutils.ReadSymlinkedDirectory(config.Root)
   605  		if err != nil {
   606  			return nil, fmt.Errorf("Unable to get the full path to root (%s): %s", config.Root, err)
   607  		}
   608  	}
   609  	config.Root = realRoot
   610  	// Create the root directory if it doesn't exists
   611  	if err := system.MkdirAll(config.Root, 0700); err != nil {
   612  		return nil, err
   613  	}
   614  
   615  	// set up the tmpDir to use a canonical path
   616  	tmp, err := tempDir(config.Root)
   617  	if err != nil {
   618  		return nil, fmt.Errorf("Unable to get the TempDir under %s: %s", config.Root, err)
   619  	}
   620  	realTmp, err := fileutils.ReadSymlinkedDirectory(tmp)
   621  	if err != nil {
   622  		return nil, fmt.Errorf("Unable to get the full path to the TempDir (%s): %s", tmp, err)
   623  	}
   624  	os.Setenv("TMPDIR", realTmp)
   625  
   626  	// Set the default driver
   627  	graphdriver.DefaultDriver = config.GraphDriver
   628  
   629  	// Load storage driver
   630  	driver, err := graphdriver.New(config.Root, config.GraphOptions)
   631  	if err != nil {
   632  		return nil, fmt.Errorf("error initializing graphdriver: %v", err)
   633  	}
   634  	logrus.Debugf("Using graph driver %s", driver)
   635  
   636  	d := &Daemon{}
   637  	d.driver = driver
   638  
   639  	// Ensure the graph driver is shutdown at a later point
   640  	defer func() {
   641  		if err != nil {
   642  			if err := d.Shutdown(); err != nil {
   643  				logrus.Error(err)
   644  			}
   645  		}
   646  	}()
   647  
   648  	// Verify logging driver type
   649  	if config.LogConfig.Type != "none" {
   650  		if _, err := logger.GetLogDriver(config.LogConfig.Type); err != nil {
   651  			return nil, fmt.Errorf("error finding the logging driver: %v", err)
   652  		}
   653  	}
   654  	logrus.Debugf("Using default logging driver %s", config.LogConfig.Type)
   655  
   656  	// Configure and validate the kernels security support
   657  	if err := configureKernelSecuritySupport(config, d.driver.String()); err != nil {
   658  		return nil, err
   659  	}
   660  
   661  	daemonRepo := filepath.Join(config.Root, "containers")
   662  
   663  	if err := system.MkdirAll(daemonRepo, 0700); err != nil {
   664  		return nil, err
   665  	}
   666  
   667  	// Migrate the container if it is aufs and aufs is enabled
   668  	if err := migrateIfDownlevel(d.driver, config.Root); err != nil {
   669  		return nil, err
   670  	}
   671  
   672  	logrus.Debug("Creating images graph")
   673  	g, err := graph.NewGraph(filepath.Join(config.Root, "graph"), d.driver)
   674  	if err != nil {
   675  		return nil, err
   676  	}
   677  
   678  	// Configure the volumes driver
   679  	volStore, err := configureVolumes(config)
   680  	if err != nil {
   681  		return nil, err
   682  	}
   683  
   684  	trustKey, err := api.LoadOrCreateTrustKey(config.TrustKeyPath)
   685  	if err != nil {
   686  		return nil, err
   687  	}
   688  
   689  	trustDir := filepath.Join(config.Root, "trust")
   690  
   691  	if err := system.MkdirAll(trustDir, 0700); err != nil {
   692  		return nil, err
   693  	}
   694  	trustService, err := trust.NewStore(trustDir)
   695  	if err != nil {
   696  		return nil, fmt.Errorf("could not create trust store: %s", err)
   697  	}
   698  
   699  	eventsService := events.New()
   700  	logrus.Debug("Creating repository list")
   701  	tagCfg := &graph.TagStoreConfig{
   702  		Graph:    g,
   703  		Key:      trustKey,
   704  		Registry: registryService,
   705  		Events:   eventsService,
   706  		Trust:    trustService,
   707  	}
   708  	repositories, err := graph.NewTagStore(filepath.Join(config.Root, "repositories-"+d.driver.String()), tagCfg)
   709  	if err != nil {
   710  		return nil, fmt.Errorf("Couldn't create Tag store repositories-%s: %s", d.driver.String(), err)
   711  	}
   712  
   713  	if restorer, ok := d.driver.(graphdriver.ImageRestorer); ok {
   714  		if _, err := restorer.RestoreCustomImages(repositories, g); err != nil {
   715  			return nil, fmt.Errorf("Couldn't restore custom images: %s", err)
   716  		}
   717  	}
   718  
   719  	d.netController, err = initNetworkController(config)
   720  	if err != nil {
   721  		return nil, fmt.Errorf("Error initializing network controller: %v", err)
   722  	}
   723  
   724  	graphdbPath := filepath.Join(config.Root, "linkgraph.db")
   725  	graph, err := graphdb.NewSqliteConn(graphdbPath)
   726  	if err != nil {
   727  		return nil, err
   728  	}
   729  
   730  	d.containerGraphDB = graph
   731  
   732  	var sysInitPath string
   733  	if config.ExecDriver == "lxc" {
   734  		initPath, err := configureSysInit(config)
   735  		if err != nil {
   736  			return nil, err
   737  		}
   738  		sysInitPath = initPath
   739  	}
   740  
   741  	sysInfo := sysinfo.New(false)
   742  	// Check if Devices cgroup is mounted, it is hard requirement for container security,
   743  	// on Linux/FreeBSD.
   744  	if runtime.GOOS != "windows" && !sysInfo.CgroupDevicesEnabled {
   745  		return nil, fmt.Errorf("Devices cgroup isn't mounted")
   746  	}
   747  
   748  	ed, err := execdrivers.NewDriver(config.ExecDriver, config.ExecOptions, config.ExecRoot, config.Root, sysInitPath, sysInfo)
   749  	if err != nil {
   750  		return nil, err
   751  	}
   752  
   753  	d.ID = trustKey.PublicKey().KeyID()
   754  	d.repository = daemonRepo
   755  	d.containers = &contStore{s: make(map[string]*Container)}
   756  	d.execCommands = newExecStore()
   757  	d.graph = g
   758  	d.repositories = repositories
   759  	d.idIndex = truncindex.NewTruncIndex([]string{})
   760  	d.configStore = config
   761  	d.sysInitPath = sysInitPath
   762  	d.execDriver = ed
   763  	d.statsCollector = newStatsCollector(1 * time.Second)
   764  	d.defaultLogConfig = config.LogConfig
   765  	d.RegistryService = registryService
   766  	d.EventsService = eventsService
   767  	d.volumes = volStore
   768  	d.root = config.Root
   769  	go d.execCommandGC()
   770  
   771  	if err := d.restore(); err != nil {
   772  		return nil, err
   773  	}
   774  
   775  	return d, nil
   776  }
   777  
   778  // Shutdown stops the daemon.
   779  func (daemon *Daemon) Shutdown() error {
   780  	daemon.shutdown = true
   781  	if daemon.containers != nil {
   782  		group := sync.WaitGroup{}
   783  		logrus.Debug("starting clean shutdown of all containers...")
   784  		for _, container := range daemon.List() {
   785  			c := container
   786  			if c.IsRunning() {
   787  				logrus.Debugf("stopping %s", c.ID)
   788  				group.Add(1)
   789  
   790  				go func() {
   791  					defer group.Done()
   792  					// TODO(windows): Handle docker restart with paused containers
   793  					if c.isPaused() {
   794  						// To terminate a process in freezer cgroup, we should send
   795  						// SIGTERM to this process then unfreeze it, and the process will
   796  						// force to terminate immediately.
   797  						logrus.Debugf("Found container %s is paused, sending SIGTERM before unpause it", c.ID)
   798  						sig, ok := signal.SignalMap["TERM"]
   799  						if !ok {
   800  							logrus.Warnf("System does not support SIGTERM")
   801  							return
   802  						}
   803  						if err := daemon.kill(c, int(sig)); err != nil {
   804  							logrus.Debugf("sending SIGTERM to container %s with error: %v", c.ID, err)
   805  							return
   806  						}
   807  						if err := c.unpause(); err != nil {
   808  							logrus.Debugf("Failed to unpause container %s with error: %v", c.ID, err)
   809  							return
   810  						}
   811  						if _, err := c.WaitStop(10 * time.Second); err != nil {
   812  							logrus.Debugf("container %s failed to exit in 10 second of SIGTERM, sending SIGKILL to force", c.ID)
   813  							sig, ok := signal.SignalMap["KILL"]
   814  							if !ok {
   815  								logrus.Warnf("System does not support SIGKILL")
   816  								return
   817  							}
   818  							daemon.kill(c, int(sig))
   819  						}
   820  					} else {
   821  						// If container failed to exit in 10 seconds of SIGTERM, then using the force
   822  						if err := c.Stop(10); err != nil {
   823  							logrus.Errorf("Stop container %s with error: %v", c.ID, err)
   824  						}
   825  					}
   826  					c.WaitStop(-1 * time.Second)
   827  					logrus.Debugf("container stopped %s", c.ID)
   828  				}()
   829  			}
   830  		}
   831  		group.Wait()
   832  
   833  		// trigger libnetwork Stop only if it's initialized
   834  		if daemon.netController != nil {
   835  			daemon.netController.Stop()
   836  		}
   837  	}
   838  
   839  	if daemon.containerGraphDB != nil {
   840  		if err := daemon.containerGraphDB.Close(); err != nil {
   841  			logrus.Errorf("Error during container graph.Close(): %v", err)
   842  		}
   843  	}
   844  
   845  	if daemon.driver != nil {
   846  		if err := daemon.driver.Cleanup(); err != nil {
   847  			logrus.Errorf("Error during graph storage driver.Cleanup(): %v", err)
   848  		}
   849  	}
   850  
   851  	return nil
   852  }
   853  
   854  // Mount sets container.basefs
   855  // (is it not set coming in? why is it unset?)
   856  func (daemon *Daemon) Mount(container *Container) error {
   857  	dir, err := daemon.driver.Get(container.ID, container.getMountLabel())
   858  	if err != nil {
   859  		return fmt.Errorf("Error getting container %s from driver %s: %s", container.ID, daemon.driver, err)
   860  	}
   861  
   862  	if container.basefs != dir {
   863  		// The mount path reported by the graph driver should always be trusted on Windows, since the
   864  		// volume path for a given mounted layer may change over time.  This should only be an error
   865  		// on non-Windows operating systems.
   866  		if container.basefs != "" && runtime.GOOS != "windows" {
   867  			daemon.driver.Put(container.ID)
   868  			return fmt.Errorf("Error: driver %s is returning inconsistent paths for container %s ('%s' then '%s')",
   869  				daemon.driver, container.ID, container.basefs, dir)
   870  		}
   871  	}
   872  	container.basefs = dir
   873  	return nil
   874  }
   875  
   876  func (daemon *Daemon) unmount(container *Container) error {
   877  	daemon.driver.Put(container.ID)
   878  	return nil
   879  }
   880  
   881  func (daemon *Daemon) run(c *Container, pipes *execdriver.Pipes, startCallback execdriver.DriverCallback) (execdriver.ExitStatus, error) {
   882  	hooks := execdriver.Hooks{
   883  		Start: startCallback,
   884  	}
   885  	hooks.PreStart = append(hooks.PreStart, func(processConfig *execdriver.ProcessConfig, pid int) error {
   886  		return c.setNetworkNamespaceKey(pid)
   887  	})
   888  	return daemon.execDriver.Run(c.command, pipes, hooks)
   889  }
   890  
   891  func (daemon *Daemon) kill(c *Container, sig int) error {
   892  	return daemon.execDriver.Kill(c.command, sig)
   893  }
   894  
   895  func (daemon *Daemon) stats(c *Container) (*execdriver.ResourceStats, error) {
   896  	return daemon.execDriver.Stats(c.ID)
   897  }
   898  
   899  func (daemon *Daemon) subscribeToContainerStats(c *Container) (chan interface{}, error) {
   900  	ch := daemon.statsCollector.collect(c)
   901  	return ch, nil
   902  }
   903  
   904  func (daemon *Daemon) unsubscribeToContainerStats(c *Container, ch chan interface{}) error {
   905  	daemon.statsCollector.unsubscribe(c, ch)
   906  	return nil
   907  }
   908  
   909  func (daemon *Daemon) changes(container *Container) ([]archive.Change, error) {
   910  	initID := fmt.Sprintf("%s-init", container.ID)
   911  	return daemon.driver.Changes(container.ID, initID)
   912  }
   913  
   914  func (daemon *Daemon) diff(container *Container) (archive.Archive, error) {
   915  	initID := fmt.Sprintf("%s-init", container.ID)
   916  	return daemon.driver.Diff(container.ID, initID)
   917  }
   918  
   919  func (daemon *Daemon) createRootfs(container *Container) error {
   920  	// Step 1: create the container directory.
   921  	// This doubles as a barrier to avoid race conditions.
   922  	if err := os.Mkdir(container.root, 0700); err != nil {
   923  		return err
   924  	}
   925  	initID := fmt.Sprintf("%s-init", container.ID)
   926  	if err := daemon.driver.Create(initID, container.ImageID); err != nil {
   927  		return err
   928  	}
   929  	initPath, err := daemon.driver.Get(initID, "")
   930  	if err != nil {
   931  		return err
   932  	}
   933  
   934  	if err := setupInitLayer(initPath); err != nil {
   935  		daemon.driver.Put(initID)
   936  		return err
   937  	}
   938  
   939  	// We want to unmount init layer before we take snapshot of it
   940  	// for the actual container.
   941  	daemon.driver.Put(initID)
   942  
   943  	if err := daemon.driver.Create(container.ID, initID); err != nil {
   944  		return err
   945  	}
   946  	return nil
   947  }
   948  
   949  // Graph needs to be removed.
   950  //
   951  // FIXME: this is a convenience function for integration tests
   952  // which need direct access to daemon.graph.
   953  // Once the tests switch to using engine and jobs, this method
   954  // can go away.
   955  func (daemon *Daemon) Graph() *graph.Graph {
   956  	return daemon.graph
   957  }
   958  
   959  // Repositories returns all repositories.
   960  func (daemon *Daemon) Repositories() *graph.TagStore {
   961  	return daemon.repositories
   962  }
   963  
   964  func (daemon *Daemon) config() *Config {
   965  	return daemon.configStore
   966  }
   967  
   968  func (daemon *Daemon) systemInitPath() string {
   969  	return daemon.sysInitPath
   970  }
   971  
   972  // GraphDriver returns the currently used driver for processing
   973  // container layers.
   974  func (daemon *Daemon) GraphDriver() graphdriver.Driver {
   975  	return daemon.driver
   976  }
   977  
   978  // ExecutionDriver returns the currently used driver for creating and
   979  // starting execs in a container.
   980  func (daemon *Daemon) ExecutionDriver() execdriver.Driver {
   981  	return daemon.execDriver
   982  }
   983  
   984  func (daemon *Daemon) containerGraph() *graphdb.Database {
   985  	return daemon.containerGraphDB
   986  }
   987  
   988  // ImageGetCached returns the earliest created image that is a child
   989  // of the image with imgID, that had the same config when it was
   990  // created. nil is returned if a child cannot be found. An error is
   991  // returned if the parent image cannot be found.
   992  func (daemon *Daemon) ImageGetCached(imgID string, config *runconfig.Config) (*image.Image, error) {
   993  	// Retrieve all images
   994  	images := daemon.Graph().Map()
   995  
   996  	// Store the tree in a map of map (map[parentId][childId])
   997  	imageMap := make(map[string]map[string]struct{})
   998  	for _, img := range images {
   999  		if _, exists := imageMap[img.Parent]; !exists {
  1000  			imageMap[img.Parent] = make(map[string]struct{})
  1001  		}
  1002  		imageMap[img.Parent][img.ID] = struct{}{}
  1003  	}
  1004  
  1005  	// Loop on the children of the given image and check the config
  1006  	var match *image.Image
  1007  	for elem := range imageMap[imgID] {
  1008  		img, ok := images[elem]
  1009  		if !ok {
  1010  			return nil, fmt.Errorf("unable to find image %q", elem)
  1011  		}
  1012  		if runconfig.Compare(&img.ContainerConfig, config) {
  1013  			if match == nil || match.Created.Before(img.Created) {
  1014  				match = img
  1015  			}
  1016  		}
  1017  	}
  1018  	return match, nil
  1019  }
  1020  
  1021  // tempDir returns the default directory to use for temporary files.
  1022  func tempDir(rootDir string) (string, error) {
  1023  	var tmpDir string
  1024  	if tmpDir = os.Getenv("DOCKER_TMPDIR"); tmpDir == "" {
  1025  		tmpDir = filepath.Join(rootDir, "tmp")
  1026  	}
  1027  	return tmpDir, system.MkdirAll(tmpDir, 0700)
  1028  }
  1029  
  1030  func (daemon *Daemon) setHostConfig(container *Container, hostConfig *runconfig.HostConfig) error {
  1031  	container.Lock()
  1032  	if err := parseSecurityOpt(container, hostConfig); err != nil {
  1033  		container.Unlock()
  1034  		return err
  1035  	}
  1036  	container.Unlock()
  1037  
  1038  	// Do not lock while creating volumes since this could be calling out to external plugins
  1039  	// Don't want to block other actions, like `docker ps` because we're waiting on an external plugin
  1040  	if err := daemon.registerMountPoints(container, hostConfig); err != nil {
  1041  		return err
  1042  	}
  1043  
  1044  	container.Lock()
  1045  	defer container.Unlock()
  1046  	// Register any links from the host config before starting the container
  1047  	if err := daemon.registerLinks(container, hostConfig); err != nil {
  1048  		return err
  1049  	}
  1050  
  1051  	container.hostConfig = hostConfig
  1052  	container.toDisk()
  1053  	return nil
  1054  }
  1055  
  1056  func setDefaultMtu(config *Config) {
  1057  	// do nothing if the config does not have the default 0 value.
  1058  	if config.Mtu != 0 {
  1059  		return
  1060  	}
  1061  	config.Mtu = defaultNetworkMtu
  1062  	if routeMtu, err := getDefaultRouteMtu(); err == nil {
  1063  		config.Mtu = routeMtu
  1064  	}
  1065  }
  1066  
  1067  var errNoDefaultRoute = errors.New("no default route was found")
  1068  
  1069  // getDefaultRouteMtu returns the MTU for the default route's interface.
  1070  func getDefaultRouteMtu() (int, error) {
  1071  	routes, err := netlink.NetworkGetRoutes()
  1072  	if err != nil {
  1073  		return 0, err
  1074  	}
  1075  	for _, r := range routes {
  1076  		if r.Default && r.Iface != nil {
  1077  			return r.Iface.MTU, nil
  1078  		}
  1079  	}
  1080  	return 0, errNoDefaultRoute
  1081  }
  1082  
  1083  // verifyContainerSettings performs validation of the hostconfig and config
  1084  // structures.
  1085  func (daemon *Daemon) verifyContainerSettings(hostConfig *runconfig.HostConfig, config *runconfig.Config) ([]string, error) {
  1086  
  1087  	// First perform verification of settings common across all platforms.
  1088  	if config != nil {
  1089  		if config.WorkingDir != "" {
  1090  			config.WorkingDir = filepath.FromSlash(config.WorkingDir) // Ensure in platform semantics
  1091  			if !system.IsAbs(config.WorkingDir) {
  1092  				return nil, fmt.Errorf("The working directory '%s' is invalid. It needs to be an absolute path.", config.WorkingDir)
  1093  			}
  1094  		}
  1095  
  1096  		if len(config.StopSignal) > 0 {
  1097  			_, err := signal.ParseSignal(config.StopSignal)
  1098  			if err != nil {
  1099  				return nil, err
  1100  			}
  1101  		}
  1102  	}
  1103  
  1104  	if hostConfig == nil {
  1105  		return nil, nil
  1106  	}
  1107  
  1108  	for port := range hostConfig.PortBindings {
  1109  		_, portStr := nat.SplitProtoPort(string(port))
  1110  		if _, err := nat.ParsePort(portStr); err != nil {
  1111  			return nil, fmt.Errorf("Invalid port specification: %q", portStr)
  1112  		}
  1113  		for _, pb := range hostConfig.PortBindings[port] {
  1114  			_, err := nat.NewPort(nat.SplitProtoPort(pb.HostPort))
  1115  			if err != nil {
  1116  				return nil, fmt.Errorf("Invalid port specification: %q", pb.HostPort)
  1117  			}
  1118  		}
  1119  	}
  1120  
  1121  	// Now do platform-specific verification
  1122  	return verifyPlatformContainerSettings(daemon, hostConfig, config)
  1123  }
  1124  
  1125  func configureVolumes(config *Config) (*store.VolumeStore, error) {
  1126  	volumesDriver, err := local.New(config.Root)
  1127  	if err != nil {
  1128  		return nil, err
  1129  	}
  1130  
  1131  	volumedrivers.Register(volumesDriver, volumesDriver.Name())
  1132  	s := store.New()
  1133  	s.AddAll(volumesDriver.List())
  1134  
  1135  	return s, nil
  1136  }