Browse code

Windows: Refactor daemon

Signed-off-by: John Howard <jhoward@microsoft.com>

John Howard authored on 2015/05/16 08:34:26
Showing 6 changed files
... ...
@@ -1,12 +1,11 @@
1 1
 package daemon
2 2
 
3 3
 import (
4
+	"errors"
4 5
 	"fmt"
5 6
 	"io"
6 7
 	"io/ioutil"
7
-	"net"
8 8
 	"os"
9
-	"path"
10 9
 	"path/filepath"
11 10
 	"regexp"
12 11
 	"runtime"
... ...
@@ -14,45 +13,38 @@ import (
14 14
 	"sync"
15 15
 	"time"
16 16
 
17
-	"github.com/docker/libcontainer/label"
18
-	"github.com/docker/libnetwork"
19
-	"github.com/docker/libnetwork/netlabel"
20
-	"github.com/docker/libnetwork/options"
21
-
22 17
 	"github.com/Sirupsen/logrus"
23 18
 	"github.com/docker/docker/api"
24
-	"github.com/docker/docker/autogen/dockerversion"
25 19
 	"github.com/docker/docker/daemon/events"
26 20
 	"github.com/docker/docker/daemon/execdriver"
27 21
 	"github.com/docker/docker/daemon/execdriver/execdrivers"
28 22
 	"github.com/docker/docker/daemon/graphdriver"
29
-	_ "github.com/docker/docker/daemon/graphdriver/vfs"
30 23
 	"github.com/docker/docker/daemon/logger"
31 24
 	"github.com/docker/docker/daemon/network"
32 25
 	"github.com/docker/docker/graph"
33 26
 	"github.com/docker/docker/image"
34
-	"github.com/docker/docker/pkg/archive"
35 27
 	"github.com/docker/docker/pkg/broadcastwriter"
36 28
 	"github.com/docker/docker/pkg/fileutils"
37 29
 	"github.com/docker/docker/pkg/graphdb"
38 30
 	"github.com/docker/docker/pkg/ioutils"
39 31
 	"github.com/docker/docker/pkg/namesgenerator"
40 32
 	"github.com/docker/docker/pkg/parsers"
41
-	"github.com/docker/docker/pkg/parsers/kernel"
42 33
 	"github.com/docker/docker/pkg/stringid"
43 34
 	"github.com/docker/docker/pkg/sysinfo"
35
+	"github.com/docker/docker/pkg/system"
44 36
 	"github.com/docker/docker/pkg/truncindex"
45 37
 	"github.com/docker/docker/registry"
46 38
 	"github.com/docker/docker/runconfig"
47 39
 	"github.com/docker/docker/trust"
48
-	"github.com/docker/docker/utils"
49
-	volumedrivers "github.com/docker/docker/volume/drivers"
50
-	"github.com/docker/docker/volume/local"
40
+	"github.com/docker/libnetwork"
51 41
 )
52 42
 
53 43
 var (
54 44
 	validContainerNameChars   = `[a-zA-Z0-9][a-zA-Z0-9_.-]`
55 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")
56 49
 )
57 50
 
58 51
 type contStore struct {
... ...
@@ -146,7 +138,7 @@ func (daemon *Daemon) Exists(id string) bool {
146 146
 }
147 147
 
148 148
 func (daemon *Daemon) containerRoot(id string) string {
149
-	return path.Join(daemon.repository, id)
149
+	return filepath.Join(daemon.repository, id)
150 150
 }
151 151
 
152 152
 // Load reads the contents of a container from disk
... ...
@@ -461,31 +453,6 @@ func (daemon *Daemon) getEntrypointAndArgs(configEntrypoint *runconfig.Entrypoin
461 461
 	return entrypoint, args
462 462
 }
463 463
 
464
-func parseSecurityOpt(container *Container, config *runconfig.HostConfig) error {
465
-	var (
466
-		labelOpts []string
467
-		err       error
468
-	)
469
-
470
-	for _, opt := range config.SecurityOpt {
471
-		con := strings.SplitN(opt, ":", 2)
472
-		if len(con) == 1 {
473
-			return fmt.Errorf("Invalid --security-opt: %q", opt)
474
-		}
475
-		switch con[0] {
476
-		case "label":
477
-			labelOpts = append(labelOpts, con[1])
478
-		case "apparmor":
479
-			container.AppArmorProfile = con[1]
480
-		default:
481
-			return fmt.Errorf("Invalid --security-opt: %q", opt)
482
-		}
483
-	}
484
-
485
-	container.ProcessLabel, container.MountLabel, err = label.InitLabels(labelOpts)
486
-	return err
487
-}
488
-
489 464
 func (daemon *Daemon) newContainer(name string, config *runconfig.Config, imgID string) (*Container, error) {
490 465
 	var (
491 466
 		id  string
... ...
@@ -518,32 +485,6 @@ func (daemon *Daemon) newContainer(name string, config *runconfig.Config, imgID
518 518
 	return container, err
519 519
 }
520 520
 
521
-func (daemon *Daemon) createRootfs(container *Container) error {
522
-	// Step 1: create the container directory.
523
-	// This doubles as a barrier to avoid race conditions.
524
-	if err := os.Mkdir(container.root, 0700); err != nil {
525
-		return err
526
-	}
527
-	initID := fmt.Sprintf("%s-init", container.ID)
528
-	if err := daemon.driver.Create(initID, container.ImageID); err != nil {
529
-		return err
530
-	}
531
-	initPath, err := daemon.driver.Get(initID, "")
532
-	if err != nil {
533
-		return err
534
-	}
535
-	defer daemon.driver.Put(initID)
536
-
537
-	if err := graph.SetupInitLayer(initPath); err != nil {
538
-		return err
539
-	}
540
-
541
-	if err := daemon.driver.Create(container.ID, initID); err != nil {
542
-		return err
543
-	}
544
-	return nil
545
-}
546
-
547 521
 func GetFullContainerName(name string) (string, error) {
548 522
 	if name == "" {
549 523
 		return "", fmt.Errorf("Container name cannot be empty")
... ...
@@ -602,7 +543,7 @@ func (daemon *Daemon) Parents(name string) ([]string, error) {
602 602
 }
603 603
 
604 604
 func (daemon *Daemon) RegisterLink(parent, child *Container, alias string) error {
605
-	fullName := path.Join(parent.Name, alias)
605
+	fullName := filepath.Join(parent.Name, alias)
606 606
 	if !daemon.containerGraph.Exists(fullName) {
607 607
 		_, err := daemon.containerGraph.Set(fullName, child.ID)
608 608
 		return err
... ...
@@ -648,26 +589,16 @@ func (daemon *Daemon) RegisterLinks(container *Container, hostConfig *runconfig.
648 648
 }
649 649
 
650 650
 func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemon, err error) {
651
-	// Check for mutually incompatible config options
652
-	if config.Bridge.Iface != "" && config.Bridge.IP != "" {
653
-		return nil, fmt.Errorf("You specified -b & --bip, mutually exclusive options. Please specify only one.")
654
-	}
655
-	if !config.Bridge.EnableIPTables && !config.Bridge.InterContainerCommunication {
656
-		return nil, fmt.Errorf("You specified --iptables=false with --icc=false. ICC uses iptables to function. Please set --icc or --iptables to true.")
657
-	}
658
-	if !config.Bridge.EnableIPTables && config.Bridge.EnableIPMasq {
659
-		config.Bridge.EnableIPMasq = false
651
+	// Ensure we have compatible configuration options
652
+	if err := checkConfigOptions(config); err != nil {
653
+		return nil, err
660 654
 	}
661
-	config.DisableNetwork = config.Bridge.Iface == disableNetworkBridge
655
+
656
+	// Do we have a disabled network?
657
+	config.DisableNetwork = isNetworkDisabled(config)
662 658
 
663 659
 	// Check that the system is supported and we have sufficient privileges
664
-	if runtime.GOOS != "linux" {
665
-		return nil, fmt.Errorf("The Docker daemon is only supported on linux")
666
-	}
667
-	if os.Geteuid() != 0 {
668
-		return nil, fmt.Errorf("The Docker daemon needs to be run as root")
669
-	}
670
-	if err := checkKernel(); err != nil {
660
+	if err := checkSystem(); err != nil {
671 661
 		return nil, err
672 662
 	}
673 663
 
... ...
@@ -697,7 +628,7 @@ func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemo
697 697
 	}
698 698
 	config.Root = realRoot
699 699
 	// Create the root directory if it doesn't exists
700
-	if err := os.MkdirAll(config.Root, 0700); err != nil && !os.IsExist(err) {
700
+	if err := system.MkdirAll(config.Root, 0700); err != nil && !os.IsExist(err) {
701 701
 		return nil, err
702 702
 	}
703 703
 
... ...
@@ -714,6 +645,7 @@ func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemo
714 714
 	d := &Daemon{}
715 715
 	d.driver = driver
716 716
 
717
+	// Ensure the graph driver is shutdown at a later point
717 718
 	defer func() {
718 719
 		if err != nil {
719 720
 			if err := d.Shutdown(); err != nil {
... ...
@@ -730,50 +662,41 @@ func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemo
730 730
 	}
731 731
 	logrus.Debugf("Using default logging driver %s", config.LogConfig.Type)
732 732
 
733
-	if config.EnableSelinuxSupport {
734
-		if selinuxEnabled() {
735
-			// As Docker on btrfs and SELinux are incompatible at present, error on both being enabled
736
-			if d.driver.String() == "btrfs" {
737
-				return nil, fmt.Errorf("SELinux is not supported with the BTRFS graph driver")
738
-			}
739
-			logrus.Debug("SELinux enabled successfully")
740
-		} else {
741
-			logrus.Warn("Docker could not enable SELinux on the host system")
742
-		}
743
-	} else {
744
-		selinuxSetDisabled()
733
+	// Configure and validate the kernels security support
734
+	if err := configureKernelSecuritySupport(config, d.driver.String()); err != nil {
735
+		return nil, err
745 736
 	}
746 737
 
747
-	daemonRepo := path.Join(config.Root, "containers")
738
+	daemonRepo := filepath.Join(config.Root, "containers")
748 739
 
749
-	if err := os.MkdirAll(daemonRepo, 0700); err != nil && !os.IsExist(err) {
740
+	if err := system.MkdirAll(daemonRepo, 0700); err != nil && !os.IsExist(err) {
750 741
 		return nil, err
751 742
 	}
752 743
 
753 744
 	// Migrate the container if it is aufs and aufs is enabled
754
-	if err := migrateIfAufs(d.driver, config.Root); err != nil {
745
+	if err := migrateIfDownlevel(d.driver, config.Root); err != nil {
755 746
 		return nil, err
756 747
 	}
757 748
 
758 749
 	logrus.Debug("Creating images graph")
759
-	g, err := graph.NewGraph(path.Join(config.Root, "graph"), d.driver)
750
+	g, err := graph.NewGraph(filepath.Join(config.Root, "graph"), d.driver)
760 751
 	if err != nil {
761 752
 		return nil, err
762 753
 	}
763 754
 
764
-	volumesDriver, err := local.New(config.Root)
765
-	if err != nil {
755
+	// Configure the volumes driver
756
+	if err := configureVolumes(config); err != nil {
766 757
 		return nil, err
767 758
 	}
768
-	volumedrivers.Register(volumesDriver, volumesDriver.Name())
769 759
 
770 760
 	trustKey, err := api.LoadOrCreateTrustKey(config.TrustKeyPath)
771 761
 	if err != nil {
772 762
 		return nil, err
773 763
 	}
774 764
 
775
-	trustDir := path.Join(config.Root, "trust")
776
-	if err := os.MkdirAll(trustDir, 0700); err != nil && !os.IsExist(err) {
765
+	trustDir := filepath.Join(config.Root, "trust")
766
+
767
+	if err := system.MkdirAll(trustDir, 0700); err != nil && !os.IsExist(err) {
777 768
 		return nil, err
778 769
 	}
779 770
 	trustService, err := trust.NewTrustStore(trustDir)
... ...
@@ -790,7 +713,7 @@ func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemo
790 790
 		Events:   eventsService,
791 791
 		Trust:    trustService,
792 792
 	}
793
-	repositories, err := graph.NewTagStore(path.Join(config.Root, "repositories-"+d.driver.String()), tagCfg)
793
+	repositories, err := graph.NewTagStore(filepath.Join(config.Root, "repositories-"+d.driver.String()), tagCfg)
794 794
 	if err != nil {
795 795
 		return nil, fmt.Errorf("Couldn't create Tag store: %s", err)
796 796
 	}
... ...
@@ -802,7 +725,7 @@ func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemo
802 802
 		}
803 803
 	}
804 804
 
805
-	graphdbPath := path.Join(config.Root, "linkgraph.db")
805
+	graphdbPath := filepath.Join(config.Root, "linkgraph.db")
806 806
 	graph, err := graphdb.NewSqliteConn(graphdbPath)
807 807
 	if err != nil {
808 808
 		return nil, err
... ...
@@ -810,24 +733,9 @@ func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemo
810 810
 
811 811
 	d.containerGraph = graph
812 812
 
813
-	localCopy := path.Join(config.Root, "init", fmt.Sprintf("dockerinit-%s", dockerversion.VERSION))
814
-	sysInitPath := utils.DockerInitPath(localCopy)
815
-	if sysInitPath == "" {
816
-		return nil, fmt.Errorf("Could not locate dockerinit: This usually means docker was built incorrectly. See https://docs.docker.com/contributing/devenvironment for official build instructions.")
817
-	}
818
-
819
-	if sysInitPath != localCopy {
820
-		// When we find a suitable dockerinit binary (even if it's our local binary), we copy it into config.Root at localCopy for future use (so that the original can go away without that being a problem, for example during a package upgrade).
821
-		if err := os.Mkdir(path.Dir(localCopy), 0700); err != nil && !os.IsExist(err) {
822
-			return nil, err
823
-		}
824
-		if _, err := fileutils.CopyFile(sysInitPath, localCopy); err != nil {
825
-			return nil, err
826
-		}
827
-		if err := os.Chmod(localCopy, 0700); err != nil {
828
-			return nil, err
829
-		}
830
-		sysInitPath = localCopy
813
+	sysInitPath, err := configureSysInit(config)
814
+	if err != nil {
815
+		return nil, err
831 816
 	}
832 817
 
833 818
 	sysInfo := sysinfo.New(false)
... ...
@@ -860,104 +768,6 @@ func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemo
860 860
 	return d, nil
861 861
 }
862 862
 
863
-func initNetworkController(config *Config) (libnetwork.NetworkController, error) {
864
-	controller, err := libnetwork.New()
865
-	if err != nil {
866
-		return nil, fmt.Errorf("error obtaining controller instance: %v", err)
867
-	}
868
-
869
-	// Initialize default driver "null"
870
-
871
-	if err := controller.ConfigureNetworkDriver("null", options.Generic{}); err != nil {
872
-		return nil, fmt.Errorf("Error initializing null driver: %v", err)
873
-	}
874
-
875
-	// Initialize default network on "null"
876
-	if _, err := controller.NewNetwork("null", "none"); err != nil {
877
-		return nil, fmt.Errorf("Error creating default \"null\" network: %v", err)
878
-	}
879
-
880
-	// Initialize default driver "host"
881
-	if err := controller.ConfigureNetworkDriver("host", options.Generic{}); err != nil {
882
-		return nil, fmt.Errorf("Error initializing host driver: %v", err)
883
-	}
884
-
885
-	// Initialize default network on "host"
886
-	if _, err := controller.NewNetwork("host", "host"); err != nil {
887
-		return nil, fmt.Errorf("Error creating default \"host\" network: %v", err)
888
-	}
889
-
890
-	// Initialize default driver "bridge"
891
-	option := options.Generic{
892
-		"EnableIPForwarding": config.Bridge.EnableIPForward}
893
-
894
-	if err := controller.ConfigureNetworkDriver("bridge", options.Generic{netlabel.GenericData: option}); err != nil {
895
-		return nil, fmt.Errorf("Error initializing bridge driver: %v", err)
896
-	}
897
-
898
-	netOption := options.Generic{
899
-		"BridgeName":          config.Bridge.Iface,
900
-		"Mtu":                 config.Mtu,
901
-		"EnableIPTables":      config.Bridge.EnableIPTables,
902
-		"EnableIPMasquerade":  config.Bridge.EnableIPMasq,
903
-		"EnableICC":           config.Bridge.InterContainerCommunication,
904
-		"EnableUserlandProxy": config.Bridge.EnableUserlandProxy,
905
-	}
906
-
907
-	if config.Bridge.IP != "" {
908
-		ip, bipNet, err := net.ParseCIDR(config.Bridge.IP)
909
-		if err != nil {
910
-			return nil, err
911
-		}
912
-
913
-		bipNet.IP = ip
914
-		netOption["AddressIPv4"] = bipNet
915
-	}
916
-
917
-	if config.Bridge.FixedCIDR != "" {
918
-		_, fCIDR, err := net.ParseCIDR(config.Bridge.FixedCIDR)
919
-		if err != nil {
920
-			return nil, err
921
-		}
922
-
923
-		netOption["FixedCIDR"] = fCIDR
924
-	}
925
-
926
-	if config.Bridge.FixedCIDRv6 != "" {
927
-		_, fCIDRv6, err := net.ParseCIDR(config.Bridge.FixedCIDRv6)
928
-		if err != nil {
929
-			return nil, err
930
-		}
931
-
932
-		netOption["FixedCIDRv6"] = fCIDRv6
933
-	}
934
-
935
-	if config.Bridge.DefaultGatewayIPv4 != nil {
936
-		netOption["DefaultGatewayIPv4"] = config.Bridge.DefaultGatewayIPv4
937
-	}
938
-
939
-	if config.Bridge.DefaultGatewayIPv6 != nil {
940
-		netOption["DefaultGatewayIPv6"] = config.Bridge.DefaultGatewayIPv6
941
-	}
942
-
943
-	// --ip processing
944
-	if config.Bridge.DefaultIP != nil {
945
-		netOption["DefaultBindingIP"] = config.Bridge.DefaultIP
946
-	}
947
-
948
-	// Initialize default network on "bridge" with the same name
949
-	_, err = controller.NewNetwork("bridge", "bridge",
950
-		libnetwork.NetworkOptionGeneric(options.Generic{
951
-			netlabel.GenericData: netOption,
952
-			netlabel.EnableIPv6:  config.Bridge.EnableIPv6,
953
-		}))
954
-	if err != nil {
955
-		return nil, fmt.Errorf("Error creating default \"bridge\" network: %v", err)
956
-	}
957
-
958
-	return controller, nil
959
-}
960
-
961 863
 func (daemon *Daemon) Shutdown() error {
962 864
 	if daemon.containerGraph != nil {
963 865
 		if err := daemon.containerGraph.Close(); err != nil {
... ...
@@ -1005,13 +815,18 @@ func (daemon *Daemon) Mount(container *Container) error {
1005 1005
 	if err != nil {
1006 1006
 		return fmt.Errorf("Error getting container %s from driver %s: %s", container.ID, daemon.driver, err)
1007 1007
 	}
1008
-	if container.basefs == "" {
1009
-		container.basefs = dir
1010
-	} else if container.basefs != dir {
1011
-		daemon.driver.Put(container.ID)
1012
-		return fmt.Errorf("Error: driver %s is returning inconsistent paths for container %s ('%s' then '%s')",
1013
-			daemon.driver, container.ID, container.basefs, dir)
1008
+
1009
+	if container.basefs != dir {
1010
+		// The mount path reported by the graph driver should always be trusted on Windows, since the
1011
+		// volume path for a given mounted layer may change over time.  This should only be an error
1012
+		// on non-Windows operating systems.
1013
+		if container.basefs != "" && runtime.GOOS != "windows" {
1014
+			daemon.driver.Put(container.ID)
1015
+			return fmt.Errorf("Error: driver %s is returning inconsistent paths for container %s ('%s' then '%s')",
1016
+				daemon.driver, container.ID, container.basefs, dir)
1017
+		}
1014 1018
 	}
1019
+	container.basefs = dir
1015 1020
 	return nil
1016 1021
 }
1017 1022
 
... ...
@@ -1020,16 +835,6 @@ func (daemon *Daemon) Unmount(container *Container) error {
1020 1020
 	return nil
1021 1021
 }
1022 1022
 
1023
-func (daemon *Daemon) Changes(container *Container) ([]archive.Change, error) {
1024
-	initID := fmt.Sprintf("%s-init", container.ID)
1025
-	return daemon.driver.Changes(container.ID, initID)
1026
-}
1027
-
1028
-func (daemon *Daemon) Diff(container *Container) (archive.Archive, error) {
1029
-	initID := fmt.Sprintf("%s-init", container.ID)
1030
-	return daemon.driver.Diff(container.ID, initID)
1031
-}
1032
-
1033 1023
 func (daemon *Daemon) Run(c *Container, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (execdriver.ExitStatus, error) {
1034 1024
 	return daemon.execDriver.Run(c.command, pipes, startCallback)
1035 1025
 }
... ...
@@ -1134,80 +939,7 @@ func tempDir(rootDir string) (string, error) {
1134 1134
 	if tmpDir = os.Getenv("DOCKER_TMPDIR"); tmpDir == "" {
1135 1135
 		tmpDir = filepath.Join(rootDir, "tmp")
1136 1136
 	}
1137
-	return tmpDir, os.MkdirAll(tmpDir, 0700)
1138
-}
1139
-
1140
-func checkKernel() error {
1141
-	// Check for unsupported kernel versions
1142
-	// FIXME: it would be cleaner to not test for specific versions, but rather
1143
-	// test for specific functionalities.
1144
-	// Unfortunately we can't test for the feature "does not cause a kernel panic"
1145
-	// without actually causing a kernel panic, so we need this workaround until
1146
-	// the circumstances of pre-3.10 crashes are clearer.
1147
-	// For details see https://github.com/docker/docker/issues/407
1148
-	if k, err := kernel.GetKernelVersion(); err != nil {
1149
-		logrus.Warnf("%s", err)
1150
-	} else {
1151
-		if kernel.CompareKernelVersion(k, &kernel.KernelVersionInfo{Kernel: 3, Major: 10, Minor: 0}) < 0 {
1152
-			if os.Getenv("DOCKER_NOWARN_KERNEL_VERSION") == "" {
1153
-				logrus.Warnf("You are running linux kernel version %s, which might be unstable running docker. Please upgrade your kernel to 3.10.0.", k.String())
1154
-			}
1155
-		}
1156
-	}
1157
-	return nil
1158
-}
1159
-
1160
-func (daemon *Daemon) verifyContainerSettings(hostConfig *runconfig.HostConfig) ([]string, error) {
1161
-	var warnings []string
1162
-
1163
-	if hostConfig == nil {
1164
-		return warnings, nil
1165
-	}
1166
-
1167
-	if hostConfig.LxcConf.Len() > 0 && !strings.Contains(daemon.ExecutionDriver().Name(), "lxc") {
1168
-		return warnings, fmt.Errorf("Cannot use --lxc-conf with execdriver: %s", daemon.ExecutionDriver().Name())
1169
-	}
1170
-	if hostConfig.Memory != 0 && hostConfig.Memory < 4194304 {
1171
-		return warnings, fmt.Errorf("Minimum memory limit allowed is 4MB")
1172
-	}
1173
-	if hostConfig.Memory > 0 && !daemon.SystemConfig().MemoryLimit {
1174
-		warnings = append(warnings, "Your kernel does not support memory limit capabilities. Limitation discarded.")
1175
-		logrus.Warnf("Your kernel does not support memory limit capabilities. Limitation discarded.")
1176
-		hostConfig.Memory = 0
1177
-	}
1178
-	if hostConfig.Memory > 0 && hostConfig.MemorySwap != -1 && !daemon.SystemConfig().SwapLimit {
1179
-		warnings = append(warnings, "Your kernel does not support swap limit capabilities, memory limited without swap.")
1180
-		logrus.Warnf("Your kernel does not support swap limit capabilities, memory limited without swap.")
1181
-		hostConfig.MemorySwap = -1
1182
-	}
1183
-	if hostConfig.Memory > 0 && hostConfig.MemorySwap > 0 && hostConfig.MemorySwap < hostConfig.Memory {
1184
-		return warnings, fmt.Errorf("Minimum memoryswap limit should be larger than memory limit, see usage.")
1185
-	}
1186
-	if hostConfig.Memory == 0 && hostConfig.MemorySwap > 0 {
1187
-		return warnings, fmt.Errorf("You should always set the Memory limit when using Memoryswap limit, see usage.")
1188
-	}
1189
-	if hostConfig.CpuPeriod > 0 && !daemon.SystemConfig().CpuCfsPeriod {
1190
-		warnings = append(warnings, "Your kernel does not support CPU cfs period. Period discarded.")
1191
-		logrus.Warnf("Your kernel does not support CPU cfs period. Period discarded.")
1192
-		hostConfig.CpuPeriod = 0
1193
-	}
1194
-	if hostConfig.CpuQuota > 0 && !daemon.SystemConfig().CpuCfsQuota {
1195
-		warnings = append(warnings, "Your kernel does not support CPU cfs quota. Quota discarded.")
1196
-		logrus.Warnf("Your kernel does not support CPU cfs quota. Quota discarded.")
1197
-		hostConfig.CpuQuota = 0
1198
-	}
1199
-	if hostConfig.BlkioWeight > 0 && (hostConfig.BlkioWeight < 10 || hostConfig.BlkioWeight > 1000) {
1200
-		return warnings, fmt.Errorf("Range of blkio weight is from 10 to 1000.")
1201
-	}
1202
-	if hostConfig.OomKillDisable && !daemon.SystemConfig().OomKillDisable {
1203
-		hostConfig.OomKillDisable = false
1204
-		return warnings, fmt.Errorf("Your kernel does not support oom kill disable.")
1205
-	}
1206
-	if daemon.SystemConfig().IPv4ForwardingDisabled {
1207
-		warnings = append(warnings, "IPv4 forwarding is disabled. Networking will not work.")
1208
-		logrus.Warnf("IPv4 forwarding is disabled. Networking will not work")
1209
-	}
1210
-	return warnings, nil
1137
+	return tmpDir, system.MkdirAll(tmpDir, 0700)
1211 1138
 }
1212 1139
 
1213 1140
 func (daemon *Daemon) setHostConfig(container *Container, hostConfig *runconfig.HostConfig) error {
1214 1141
new file mode 100644
... ...
@@ -0,0 +1,354 @@
0
+// +build !windows
1
+
2
+package daemon
3
+
4
+import (
5
+	"fmt"
6
+	"net"
7
+	"os"
8
+	"path/filepath"
9
+	"runtime"
10
+	"strings"
11
+
12
+	"github.com/Sirupsen/logrus"
13
+	"github.com/docker/docker/autogen/dockerversion"
14
+	"github.com/docker/docker/daemon/graphdriver"
15
+	_ "github.com/docker/docker/daemon/graphdriver/vfs"
16
+	"github.com/docker/docker/graph"
17
+	"github.com/docker/docker/pkg/archive"
18
+	"github.com/docker/docker/pkg/fileutils"
19
+	"github.com/docker/docker/pkg/parsers/kernel"
20
+	"github.com/docker/docker/runconfig"
21
+	"github.com/docker/docker/utils"
22
+	volumedrivers "github.com/docker/docker/volume/drivers"
23
+	"github.com/docker/docker/volume/local"
24
+	"github.com/docker/libcontainer/label"
25
+	"github.com/docker/libnetwork"
26
+	"github.com/docker/libnetwork/netlabel"
27
+	"github.com/docker/libnetwork/options"
28
+)
29
+
30
+const runDir = "/var/run/docker"
31
+const defaultVolumesPathName = "volumes"
32
+
33
+func (daemon *Daemon) Changes(container *Container) ([]archive.Change, error) {
34
+	initID := fmt.Sprintf("%s-init", container.ID)
35
+	return daemon.driver.Changes(container.ID, initID)
36
+}
37
+
38
+func (daemon *Daemon) Diff(container *Container) (archive.Archive, error) {
39
+	initID := fmt.Sprintf("%s-init", container.ID)
40
+	return daemon.driver.Diff(container.ID, initID)
41
+}
42
+
43
+func parseSecurityOpt(container *Container, config *runconfig.HostConfig) error {
44
+	var (
45
+		labelOpts []string
46
+		err       error
47
+	)
48
+
49
+	for _, opt := range config.SecurityOpt {
50
+		con := strings.SplitN(opt, ":", 2)
51
+		if len(con) == 1 {
52
+			return fmt.Errorf("Invalid --security-opt: %q", opt)
53
+		}
54
+		switch con[0] {
55
+		case "label":
56
+			labelOpts = append(labelOpts, con[1])
57
+		case "apparmor":
58
+			container.AppArmorProfile = con[1]
59
+		default:
60
+			return fmt.Errorf("Invalid --security-opt: %q", opt)
61
+		}
62
+	}
63
+
64
+	container.ProcessLabel, container.MountLabel, err = label.InitLabels(labelOpts)
65
+	return err
66
+}
67
+
68
+func (daemon *Daemon) createRootfs(container *Container) error {
69
+	// Step 1: create the container directory.
70
+	// This doubles as a barrier to avoid race conditions.
71
+	if err := os.Mkdir(container.root, 0700); err != nil {
72
+		return err
73
+	}
74
+	initID := fmt.Sprintf("%s-init", container.ID)
75
+	if err := daemon.driver.Create(initID, container.ImageID); err != nil {
76
+		return err
77
+	}
78
+	initPath, err := daemon.driver.Get(initID, "")
79
+	if err != nil {
80
+		return err
81
+	}
82
+	defer daemon.driver.Put(initID)
83
+
84
+	if err := graph.SetupInitLayer(initPath); err != nil {
85
+		return err
86
+	}
87
+
88
+	if err := daemon.driver.Create(container.ID, initID); err != nil {
89
+		return err
90
+	}
91
+	return nil
92
+}
93
+
94
+func checkKernel() error {
95
+	// Check for unsupported kernel versions
96
+	// FIXME: it would be cleaner to not test for specific versions, but rather
97
+	// test for specific functionalities.
98
+	// Unfortunately we can't test for the feature "does not cause a kernel panic"
99
+	// without actually causing a kernel panic, so we need this workaround until
100
+	// the circumstances of pre-3.10 crashes are clearer.
101
+	// For details see https://github.com/docker/docker/issues/407
102
+	if k, err := kernel.GetKernelVersion(); err != nil {
103
+		logrus.Warnf("%s", err)
104
+	} else {
105
+		if kernel.CompareKernelVersion(k, &kernel.KernelVersionInfo{Kernel: 3, Major: 10, Minor: 0}) < 0 {
106
+			if os.Getenv("DOCKER_NOWARN_KERNEL_VERSION") == "" {
107
+				logrus.Warnf("You are running linux kernel version %s, which might be unstable running docker. Please upgrade your kernel to 3.10.0.", k.String())
108
+			}
109
+		}
110
+	}
111
+	return nil
112
+}
113
+
114
+func (daemon *Daemon) verifyContainerSettings(hostConfig *runconfig.HostConfig) ([]string, error) {
115
+	var warnings []string
116
+
117
+	if hostConfig == nil {
118
+		return warnings, nil
119
+	}
120
+
121
+	if hostConfig.LxcConf.Len() > 0 && !strings.Contains(daemon.ExecutionDriver().Name(), "lxc") {
122
+		return warnings, fmt.Errorf("Cannot use --lxc-conf with execdriver: %s", daemon.ExecutionDriver().Name())
123
+	}
124
+	if hostConfig.Memory != 0 && hostConfig.Memory < 4194304 {
125
+		return warnings, fmt.Errorf("Minimum memory limit allowed is 4MB")
126
+	}
127
+	if hostConfig.Memory > 0 && !daemon.SystemConfig().MemoryLimit {
128
+		warnings = append(warnings, "Your kernel does not support memory limit capabilities. Limitation discarded.")
129
+		logrus.Warnf("Your kernel does not support memory limit capabilities. Limitation discarded.")
130
+		hostConfig.Memory = 0
131
+	}
132
+	if hostConfig.Memory > 0 && hostConfig.MemorySwap != -1 && !daemon.SystemConfig().SwapLimit {
133
+		warnings = append(warnings, "Your kernel does not support swap limit capabilities, memory limited without swap.")
134
+		logrus.Warnf("Your kernel does not support swap limit capabilities, memory limited without swap.")
135
+		hostConfig.MemorySwap = -1
136
+	}
137
+	if hostConfig.Memory > 0 && hostConfig.MemorySwap > 0 && hostConfig.MemorySwap < hostConfig.Memory {
138
+		return warnings, fmt.Errorf("Minimum memoryswap limit should be larger than memory limit, see usage.")
139
+	}
140
+	if hostConfig.Memory == 0 && hostConfig.MemorySwap > 0 {
141
+		return warnings, fmt.Errorf("You should always set the Memory limit when using Memoryswap limit, see usage.")
142
+	}
143
+	if hostConfig.CpuPeriod > 0 && !daemon.SystemConfig().CpuCfsPeriod {
144
+		warnings = append(warnings, "Your kernel does not support CPU cfs period. Period discarded.")
145
+		logrus.Warnf("Your kernel does not support CPU cfs period. Period discarded.")
146
+		hostConfig.CpuPeriod = 0
147
+	}
148
+	if hostConfig.CpuQuota > 0 && !daemon.SystemConfig().CpuCfsQuota {
149
+		warnings = append(warnings, "Your kernel does not support CPU cfs quota. Quota discarded.")
150
+		logrus.Warnf("Your kernel does not support CPU cfs quota. Quota discarded.")
151
+		hostConfig.CpuQuota = 0
152
+	}
153
+	if hostConfig.BlkioWeight > 0 && (hostConfig.BlkioWeight < 10 || hostConfig.BlkioWeight > 1000) {
154
+		return warnings, fmt.Errorf("Range of blkio weight is from 10 to 1000.")
155
+	}
156
+	if hostConfig.OomKillDisable && !daemon.SystemConfig().OomKillDisable {
157
+		hostConfig.OomKillDisable = false
158
+		return warnings, fmt.Errorf("Your kernel does not support oom kill disable.")
159
+	}
160
+	if daemon.SystemConfig().IPv4ForwardingDisabled {
161
+		warnings = append(warnings, "IPv4 forwarding is disabled. Networking will not work.")
162
+		logrus.Warnf("IPv4 forwarding is disabled. Networking will not work")
163
+	}
164
+	return warnings, nil
165
+}
166
+
167
+// checkConfigOptions checks for mutually incompatible config options
168
+func checkConfigOptions(config *Config) error {
169
+	// Check for mutually incompatible config options
170
+	if config.Bridge.Iface != "" && config.Bridge.IP != "" {
171
+		return fmt.Errorf("You specified -b & --bip, mutually exclusive options. Please specify only one.")
172
+	}
173
+	if !config.Bridge.EnableIPTables && !config.Bridge.InterContainerCommunication {
174
+		return fmt.Errorf("You specified --iptables=false with --icc=false. ICC uses iptables to function. Please set --icc or --iptables to true.")
175
+	}
176
+	if !config.Bridge.EnableIPTables && config.Bridge.EnableIPMasq {
177
+		config.Bridge.EnableIPMasq = false
178
+	}
179
+	return nil
180
+}
181
+
182
+// checkSystem validates the system is supported and we have sufficient privileges
183
+func checkSystem() error {
184
+	// TODO Windows. Once daemon is running on Windows, move this code back to
185
+	// NewDaemon() in daemon.go, and extend the check to support Windows.
186
+	if runtime.GOOS != "linux" {
187
+		return ErrSystemNotSupported
188
+	}
189
+	if os.Geteuid() != 0 {
190
+		return fmt.Errorf("The Docker daemon needs to be run as root")
191
+	}
192
+	if err := checkKernel(); err != nil {
193
+		return err
194
+	}
195
+	return nil
196
+}
197
+
198
+// configureKernelSecuritySupport configures and validate security support for the kernel
199
+func configureKernelSecuritySupport(config *Config, driverName string) error {
200
+	if config.EnableSelinuxSupport {
201
+		if selinuxEnabled() {
202
+			// As Docker on btrfs and SELinux are incompatible at present, error on both being enabled
203
+			if driverName == "btrfs" {
204
+				return fmt.Errorf("SELinux is not supported with the BTRFS graph driver")
205
+			}
206
+			logrus.Debug("SELinux enabled successfully")
207
+		} else {
208
+			logrus.Warn("Docker could not enable SELinux on the host system")
209
+		}
210
+	} else {
211
+		selinuxSetDisabled()
212
+	}
213
+	return nil
214
+}
215
+
216
+// MigrateIfDownlevel is a wrapper for AUFS migration for downlevel
217
+func migrateIfDownlevel(driver graphdriver.Driver, root string) error {
218
+	return migrateIfAufs(driver, root)
219
+}
220
+
221
+func configureVolumes(config *Config) error {
222
+	volumesDriver, err := local.New(config.Root)
223
+	if err != nil {
224
+		return err
225
+	}
226
+	volumedrivers.Register(volumesDriver, volumesDriver.Name())
227
+	return nil
228
+}
229
+
230
+func configureSysInit(config *Config) (string, error) {
231
+	localCopy := filepath.Join(config.Root, "init", fmt.Sprintf("dockerinit-%s", dockerversion.VERSION))
232
+	sysInitPath := utils.DockerInitPath(localCopy)
233
+	if sysInitPath == "" {
234
+		return "", fmt.Errorf("Could not locate dockerinit: This usually means docker was built incorrectly. See https://docs.docker.com/contributing/devenvironment for official build instructions.")
235
+	}
236
+
237
+	if sysInitPath != localCopy {
238
+		// When we find a suitable dockerinit binary (even if it's our local binary), we copy it into config.Root at localCopy for future use (so that the original can go away without that being a problem, for example during a package upgrade).
239
+		if err := os.Mkdir(filepath.Dir(localCopy), 0700); err != nil && !os.IsExist(err) {
240
+			return "", err
241
+		}
242
+		if _, err := fileutils.CopyFile(sysInitPath, localCopy); err != nil {
243
+			return "", err
244
+		}
245
+		if err := os.Chmod(localCopy, 0700); err != nil {
246
+			return "", err
247
+		}
248
+		sysInitPath = localCopy
249
+	}
250
+	return sysInitPath, nil
251
+}
252
+
253
+func isNetworkDisabled(config *Config) bool {
254
+	return config.Bridge.Iface == disableNetworkBridge
255
+}
256
+
257
+func initNetworkController(config *Config) (libnetwork.NetworkController, error) {
258
+	controller, err := libnetwork.New()
259
+	if err != nil {
260
+		return nil, fmt.Errorf("error obtaining controller instance: %v", err)
261
+	}
262
+
263
+	// Initialize default driver "null"
264
+
265
+	if err := controller.ConfigureNetworkDriver("null", options.Generic{}); err != nil {
266
+		return nil, fmt.Errorf("Error initializing null driver: %v", err)
267
+	}
268
+
269
+	// Initialize default network on "null"
270
+	if _, err := controller.NewNetwork("null", "none"); err != nil {
271
+		return nil, fmt.Errorf("Error creating default \"null\" network: %v", err)
272
+	}
273
+
274
+	// Initialize default driver "host"
275
+	if err := controller.ConfigureNetworkDriver("host", options.Generic{}); err != nil {
276
+		return nil, fmt.Errorf("Error initializing host driver: %v", err)
277
+	}
278
+
279
+	// Initialize default network on "host"
280
+	if _, err := controller.NewNetwork("host", "host"); err != nil {
281
+		return nil, fmt.Errorf("Error creating default \"host\" network: %v", err)
282
+	}
283
+
284
+	// Initialize default driver "bridge"
285
+	option := options.Generic{
286
+		"EnableIPForwarding": config.Bridge.EnableIPForward}
287
+
288
+	if err := controller.ConfigureNetworkDriver("bridge", options.Generic{netlabel.GenericData: option}); err != nil {
289
+		return nil, fmt.Errorf("Error initializing bridge driver: %v", err)
290
+	}
291
+
292
+	netOption := options.Generic{
293
+		"BridgeName":          config.Bridge.Iface,
294
+		"Mtu":                 config.Mtu,
295
+		"EnableIPTables":      config.Bridge.EnableIPTables,
296
+		"EnableIPMasquerade":  config.Bridge.EnableIPMasq,
297
+		"EnableICC":           config.Bridge.InterContainerCommunication,
298
+		"EnableUserlandProxy": config.Bridge.EnableUserlandProxy,
299
+	}
300
+
301
+	if config.Bridge.IP != "" {
302
+		ip, bipNet, err := net.ParseCIDR(config.Bridge.IP)
303
+		if err != nil {
304
+			return nil, err
305
+		}
306
+
307
+		bipNet.IP = ip
308
+		netOption["AddressIPv4"] = bipNet
309
+	}
310
+
311
+	if config.Bridge.FixedCIDR != "" {
312
+		_, fCIDR, err := net.ParseCIDR(config.Bridge.FixedCIDR)
313
+		if err != nil {
314
+			return nil, err
315
+		}
316
+
317
+		netOption["FixedCIDR"] = fCIDR
318
+	}
319
+
320
+	if config.Bridge.FixedCIDRv6 != "" {
321
+		_, fCIDRv6, err := net.ParseCIDR(config.Bridge.FixedCIDRv6)
322
+		if err != nil {
323
+			return nil, err
324
+		}
325
+
326
+		netOption["FixedCIDRv6"] = fCIDRv6
327
+	}
328
+
329
+	if config.Bridge.DefaultGatewayIPv4 != nil {
330
+		netOption["DefaultGatewayIPv4"] = config.Bridge.DefaultGatewayIPv4
331
+	}
332
+
333
+	if config.Bridge.DefaultGatewayIPv6 != nil {
334
+		netOption["DefaultGatewayIPv6"] = config.Bridge.DefaultGatewayIPv6
335
+	}
336
+
337
+	// --ip processing
338
+	if config.Bridge.DefaultIP != nil {
339
+		netOption["DefaultBindingIP"] = config.Bridge.DefaultIP
340
+	}
341
+
342
+	// Initialize default network on "bridge" with the same name
343
+	_, err = controller.NewNetwork("bridge", "bridge",
344
+		libnetwork.NetworkOptionGeneric(options.Generic{
345
+			netlabel.GenericData: netOption,
346
+			netlabel.EnableIPv6:  config.Bridge.EnableIPv6,
347
+		}))
348
+	if err != nil {
349
+		return nil, fmt.Errorf("Error creating default \"bridge\" network: %v", err)
350
+	}
351
+
352
+	return controller, nil
353
+}
0 354
new file mode 100644
... ...
@@ -0,0 +1,107 @@
0
+package daemon
1
+
2
+import (
3
+	"fmt"
4
+	"os"
5
+	"runtime"
6
+	"syscall"
7
+
8
+	"github.com/docker/docker/daemon/graphdriver"
9
+	"github.com/docker/docker/pkg/archive"
10
+	"github.com/docker/docker/runconfig"
11
+	"github.com/docker/libnetwork"
12
+)
13
+
14
+var runDir = os.Getenv("TEMP")
15
+
16
+func (daemon *Daemon) Changes(container *Container) ([]archive.Change, error) {
17
+	return daemon.driver.Changes(container.ID, container.ImageID)
18
+}
19
+
20
+func (daemon *Daemon) Diff(container *Container) (archive.Archive, error) {
21
+	return daemon.driver.Diff(container.ID, container.ImageID)
22
+}
23
+
24
+func parseSecurityOpt(container *Container, config *runconfig.HostConfig) error {
25
+	return nil
26
+}
27
+
28
+func (daemon *Daemon) createRootfs(container *Container) error {
29
+	// Step 1: create the container directory.
30
+	// This doubles as a barrier to avoid race conditions.
31
+	if err := os.Mkdir(container.root, 0700); err != nil {
32
+		return err
33
+	}
34
+	if err := daemon.driver.Create(container.ID, container.ImageID); err != nil {
35
+		return err
36
+	}
37
+	return nil
38
+}
39
+
40
+func checkKernel() error {
41
+	return nil
42
+}
43
+
44
+func (daemon *Daemon) verifyContainerSettings(hostConfig *runconfig.HostConfig) ([]string, error) {
45
+	// TODO Windows. Verifications TBC
46
+	return nil, nil
47
+}
48
+
49
+// checkConfigOptions checks for mutually incompatible config options
50
+func checkConfigOptions(config *Config) error {
51
+	return nil
52
+}
53
+
54
+// checkSystem validates the system is supported and we have sufficient privileges
55
+func checkSystem() error {
56
+	var dwVersion uint32
57
+
58
+	// TODO Windows. Once daemon is running on Windows, move this code back to
59
+	// NewDaemon() in daemon.go, and extend the check to support Windows.
60
+	if runtime.GOOS != "linux" && runtime.GOOS != "windows" {
61
+		return ErrSystemNotSupported
62
+	}
63
+
64
+	// TODO Windows. May need at some point to ensure have elevation and
65
+	// possibly LocalSystem.
66
+
67
+	// Validate the OS version. Note that docker.exe must be manifested for this
68
+	// call to return the correct version.
69
+	dwVersion, err := syscall.GetVersion()
70
+	if err != nil {
71
+		return fmt.Errorf("Failed to call GetVersion()")
72
+	}
73
+	if int(dwVersion&0xFF) < 10 {
74
+		return fmt.Errorf("This version of Windows does not support the docker daemon")
75
+	}
76
+
77
+	return nil
78
+}
79
+
80
+// configureKernelSecuritySupport configures and validate security support for the kernel
81
+func configureKernelSecuritySupport(config *Config, driverName string) error {
82
+	return nil
83
+}
84
+
85
+func migrateIfDownlevel(driver graphdriver.Driver, root string) error {
86
+	return nil
87
+}
88
+
89
+func configureVolumes(config *Config) error {
90
+	// Windows does not support volumes at this time
91
+	return nil
92
+}
93
+
94
+func configureSysInit(config *Config) (string, error) {
95
+	// TODO Windows.
96
+	return os.Getenv("TEMP"), nil
97
+}
98
+
99
+func isNetworkDisabled(config *Config) bool {
100
+	return false
101
+}
102
+
103
+func initNetworkController(config *Config) (libnetwork.NetworkController, error) {
104
+	// TODO Windows
105
+	return nil, nil
106
+}
... ...
@@ -14,13 +14,10 @@ import (
14 14
 	apiserver "github.com/docker/docker/api/server"
15 15
 	"github.com/docker/docker/autogen/dockerversion"
16 16
 	"github.com/docker/docker/daemon"
17
-	_ "github.com/docker/docker/daemon/execdriver/lxc"
18
-	_ "github.com/docker/docker/daemon/execdriver/native"
19 17
 	"github.com/docker/docker/pkg/homedir"
20 18
 	flag "github.com/docker/docker/pkg/mflag"
21 19
 	"github.com/docker/docker/pkg/pidfile"
22 20
 	"github.com/docker/docker/pkg/signal"
23
-	"github.com/docker/docker/pkg/system"
24 21
 	"github.com/docker/docker/pkg/timeutils"
25 22
 	"github.com/docker/docker/pkg/tlsconfig"
26 23
 	"github.com/docker/docker/registry"
... ...
@@ -113,8 +110,8 @@ func mainDaemon() {
113 113
 		EnableCors:  daemonCfg.EnableCors,
114 114
 		CorsHeaders: daemonCfg.CorsHeaders,
115 115
 		Version:     dockerversion.VERSION,
116
-		SocketGroup: daemonCfg.SocketGroup,
117 116
 	}
117
+	serverConfig = setPlatformServerConfig(serverConfig, daemonCfg)
118 118
 
119 119
 	if *flTls {
120 120
 		if *flTlsVerify {
... ...
@@ -212,14 +209,3 @@ func shutdownDaemon(d *daemon.Daemon, timeout time.Duration) {
212 212
 		logrus.Error("Force shutdown daemon")
213 213
 	}
214 214
 }
215
-
216
-// currentUserIsOwner checks whether the current user is the owner of the given
217
-// file.
218
-func currentUserIsOwner(f string) bool {
219
-	if fileInfo, err := system.Stat(f); err == nil && fileInfo != nil {
220
-		if int(fileInfo.Uid()) == os.Getuid() {
221
-			return true
222
-		}
223
-	}
224
-	return false
225
-}
226 215
new file mode 100644
... ...
@@ -0,0 +1,30 @@
0
+// +build daemon,!windows
1
+
2
+package main
3
+
4
+import (
5
+	"os"
6
+
7
+	apiserver "github.com/docker/docker/api/server"
8
+	"github.com/docker/docker/daemon"
9
+	"github.com/docker/docker/pkg/system"
10
+
11
+	_ "github.com/docker/docker/daemon/execdriver/lxc"
12
+	_ "github.com/docker/docker/daemon/execdriver/native"
13
+)
14
+
15
+func setPlatformServerConfig(serverConfig *apiserver.ServerConfig, daemonCfg *daemon.Config) *apiserver.ServerConfig {
16
+	serverConfig.SocketGroup = daemonCfg.SocketGroup
17
+	return serverConfig
18
+}
19
+
20
+// currentUserIsOwner checks whether the current user is the owner of the given
21
+// file.
22
+func currentUserIsOwner(f string) bool {
23
+	if fileInfo, err := system.Stat(f); err == nil && fileInfo != nil {
24
+		if int(fileInfo.Uid()) == os.Getuid() {
25
+			return true
26
+		}
27
+	}
28
+	return false
29
+}
0 30
new file mode 100644
... ...
@@ -0,0 +1,18 @@
0
+// +build daemon
1
+
2
+package main
3
+
4
+import (
5
+	apiserver "github.com/docker/docker/api/server"
6
+	"github.com/docker/docker/daemon"
7
+)
8
+
9
+func setPlatformServerConfig(serverConfig *apiserver.ServerConfig, daemonCfg *daemon.Config) *apiserver.ServerConfig {
10
+	return serverConfig
11
+}
12
+
13
+// currentUserIsOwner checks whether the current user is the owner of the given
14
+// file.
15
+func currentUserIsOwner(f string) bool {
16
+	return false
17
+}