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