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