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