Browse code

Decouple daemon and container to manage networks.

Signed-off-by: David Calavera <david.calavera@gmail.com>

David Calavera authored on 2015/11/04 03:25:09
Showing 7 changed files
... ...
@@ -77,11 +77,8 @@ func killProcessDirectly(container *Container) error {
77 77
 	return nil
78 78
 }
79 79
 
80
-func (container *Container) setupLinkedContainers() ([]string, error) {
81
-	var (
82
-		env    []string
83
-		daemon = container.daemon
84
-	)
80
+func (daemon *Daemon) setupLinkedContainers(container *Container) ([]string, error) {
81
+	var env []string
85 82
 	children, err := daemon.children(container.Name)
86 83
 	if err != nil {
87 84
 		return nil, err
... ...
@@ -185,17 +182,16 @@ func getDevicesFromPath(deviceMapping runconfig.DeviceMapping) (devs []*configs.
185 185
 	return devs, derr.ErrorCodeDeviceInfo.WithArgs(deviceMapping.PathOnHost, err)
186 186
 }
187 187
 
188
-func populateCommand(c *Container, env []string) error {
188
+func (daemon *Daemon) populateCommand(c *Container, env []string) error {
189 189
 	var en *execdriver.Network
190 190
 	if !c.Config.NetworkDisabled {
191 191
 		en = &execdriver.Network{}
192
-		if !c.daemon.execDriver.SupportsHooks() || c.hostConfig.NetworkMode.IsHost() {
192
+		if !daemon.execDriver.SupportsHooks() || c.hostConfig.NetworkMode.IsHost() {
193 193
 			en.NamespacePath = c.NetworkSettings.SandboxKey
194 194
 		}
195 195
 
196
-		parts := strings.SplitN(string(c.hostConfig.NetworkMode), ":", 2)
197
-		if parts[0] == "container" {
198
-			nc, err := c.getNetworkedContainer()
196
+		if c.hostConfig.NetworkMode.IsContainer() {
197
+			nc, err := daemon.getNetworkedContainer(c.ID, c.hostConfig.NetworkMode.ConnectedContainer())
199 198
 			if err != nil {
200 199
 				return err
201 200
 			}
... ...
@@ -216,7 +212,7 @@ func populateCommand(c *Container, env []string) error {
216 216
 	}
217 217
 
218 218
 	if c.hostConfig.IpcMode.IsContainer() {
219
-		ic, err := c.getIpcContainer()
219
+		ic, err := daemon.getIpcContainer(c)
220 220
 		if err != nil {
221 221
 			return err
222 222
 		}
... ...
@@ -273,7 +269,7 @@ func populateCommand(c *Container, env []string) error {
273 273
 	for _, ul := range ulimits {
274 274
 		ulIdx[ul.Name] = ul
275 275
 	}
276
-	for name, ul := range c.daemon.configStore.Ulimits {
276
+	for name, ul := range daemon.configStore.Ulimits {
277 277
 		if _, exists := ulIdx[name]; !exists {
278 278
 			ulimits = append(ulimits, ul)
279 279
 		}
... ...
@@ -321,12 +317,12 @@ func populateCommand(c *Container, env []string) error {
321 321
 	processConfig.Env = env
322 322
 
323 323
 	remappedRoot := &execdriver.User{}
324
-	rootUID, rootGID := c.daemon.GetRemappedUIDGID()
324
+	rootUID, rootGID := daemon.GetRemappedUIDGID()
325 325
 	if rootUID != 0 {
326 326
 		remappedRoot.UID = rootUID
327 327
 		remappedRoot.GID = rootGID
328 328
 	}
329
-	uidMap, gidMap := c.daemon.GetUIDGIDMaps()
329
+	uidMap, gidMap := daemon.GetUIDGIDMaps()
330 330
 
331 331
 	c.command = &execdriver.Command{
332 332
 		CommonCommand: execdriver.CommonCommand{
... ...
@@ -442,7 +438,7 @@ func (container *Container) buildHostnameFile() error {
442 442
 	return ioutil.WriteFile(container.HostnamePath, []byte(container.Config.Hostname+"\n"), 0644)
443 443
 }
444 444
 
445
-func (container *Container) buildSandboxOptions(n libnetwork.Network) ([]libnetwork.SandboxOption, error) {
445
+func (daemon *Daemon) buildSandboxOptions(container *Container, n libnetwork.Network) ([]libnetwork.SandboxOption, error) {
446 446
 	var (
447 447
 		sboxOptions []libnetwork.SandboxOption
448 448
 		err         error
... ...
@@ -458,7 +454,7 @@ func (container *Container) buildSandboxOptions(n libnetwork.Network) ([]libnetw
458 458
 		sboxOptions = append(sboxOptions, libnetwork.OptionUseDefaultSandbox())
459 459
 		sboxOptions = append(sboxOptions, libnetwork.OptionOriginHostsPath("/etc/hosts"))
460 460
 		sboxOptions = append(sboxOptions, libnetwork.OptionOriginResolvConfPath("/etc/resolv.conf"))
461
-	} else if container.daemon.execDriver.SupportsHooks() {
461
+	} else if daemon.execDriver.SupportsHooks() {
462 462
 		// OptionUseExternalKey is mandatory for userns support.
463 463
 		// But optional for non-userns support
464 464
 		sboxOptions = append(sboxOptions, libnetwork.OptionUseExternalKey())
... ...
@@ -478,8 +474,8 @@ func (container *Container) buildSandboxOptions(n libnetwork.Network) ([]libnetw
478 478
 
479 479
 	if len(container.hostConfig.DNS) > 0 {
480 480
 		dns = container.hostConfig.DNS
481
-	} else if len(container.daemon.configStore.DNS) > 0 {
482
-		dns = container.daemon.configStore.DNS
481
+	} else if len(daemon.configStore.DNS) > 0 {
482
+		dns = daemon.configStore.DNS
483 483
 	}
484 484
 
485 485
 	for _, d := range dns {
... ...
@@ -488,8 +484,8 @@ func (container *Container) buildSandboxOptions(n libnetwork.Network) ([]libnetw
488 488
 
489 489
 	if len(container.hostConfig.DNSSearch) > 0 {
490 490
 		dnsSearch = container.hostConfig.DNSSearch
491
-	} else if len(container.daemon.configStore.DNSSearch) > 0 {
492
-		dnsSearch = container.daemon.configStore.DNSSearch
491
+	} else if len(daemon.configStore.DNSSearch) > 0 {
492
+		dnsSearch = daemon.configStore.DNSSearch
493 493
 	}
494 494
 
495 495
 	for _, ds := range dnsSearch {
... ...
@@ -498,8 +494,8 @@ func (container *Container) buildSandboxOptions(n libnetwork.Network) ([]libnetw
498 498
 
499 499
 	if len(container.hostConfig.DNSOptions) > 0 {
500 500
 		dnsOptions = container.hostConfig.DNSOptions
501
-	} else if len(container.daemon.configStore.DNSOptions) > 0 {
502
-		dnsOptions = container.daemon.configStore.DNSOptions
501
+	} else if len(daemon.configStore.DNSOptions) > 0 {
502
+		dnsOptions = daemon.configStore.DNSOptions
503 503
 	}
504 504
 
505 505
 	for _, ds := range dnsOptions {
... ...
@@ -536,7 +532,7 @@ func (container *Container) buildSandboxOptions(n libnetwork.Network) ([]libnetw
536 536
 
537 537
 	var childEndpoints, parentEndpoints []string
538 538
 
539
-	children, err := container.daemon.children(container.Name)
539
+	children, err := daemon.children(container.Name)
540 540
 	if err != nil {
541 541
 		return nil, err
542 542
 	}
... ...
@@ -560,18 +556,18 @@ func (container *Container) buildSandboxOptions(n libnetwork.Network) ([]libnetw
560 560
 	}
561 561
 
562 562
 	bridgeSettings := container.NetworkSettings.Networks["bridge"]
563
-	refs := container.daemon.containerGraph().RefPaths(container.ID)
563
+	refs := daemon.containerGraph().RefPaths(container.ID)
564 564
 	for _, ref := range refs {
565 565
 		if ref.ParentID == "0" {
566 566
 			continue
567 567
 		}
568 568
 
569
-		c, err := container.daemon.Get(ref.ParentID)
569
+		c, err := daemon.Get(ref.ParentID)
570 570
 		if err != nil {
571 571
 			logrus.Error(err)
572 572
 		}
573 573
 
574
-		if c != nil && !container.daemon.configStore.DisableBridge && container.hostConfig.NetworkMode.IsPrivate() {
574
+		if c != nil && !daemon.configStore.DisableBridge && container.hostConfig.NetworkMode.IsPrivate() {
575 575
 			logrus.Debugf("Update /etc/hosts of %s for alias %s with ip %s", c.ID, ref.Name, bridgeSettings.IPAddress)
576 576
 			sboxOptions = append(sboxOptions, libnetwork.OptionParentUpdate(c.ID, ref.Name, bridgeSettings.IPAddress))
577 577
 			if ep.ID() != "" {
... ...
@@ -719,13 +715,13 @@ func (container *Container) updateJoinInfo(n libnetwork.Network, ep libnetwork.E
719 719
 	return nil
720 720
 }
721 721
 
722
-func (container *Container) updateNetworkSettings(n libnetwork.Network) error {
722
+func (daemon *Daemon) updateNetworkSettings(container *Container, n libnetwork.Network) error {
723 723
 	if container.NetworkSettings == nil {
724 724
 		container.NetworkSettings = &network.Settings{Networks: make(map[string]*network.EndpointSettings)}
725 725
 	}
726 726
 
727 727
 	for s := range container.NetworkSettings.Networks {
728
-		sn, err := container.daemon.FindNetwork(s)
728
+		sn, err := daemon.FindNetwork(s)
729 729
 		if err != nil {
730 730
 			continue
731 731
 		}
... ...
@@ -769,8 +765,8 @@ func (container *Container) updateSandboxNetworkSettings(sb libnetwork.Sandbox)
769 769
 
770 770
 // UpdateNetwork is used to update the container's network (e.g. when linked containers
771 771
 // get removed/unlinked).
772
-func (container *Container) updateNetwork() error {
773
-	ctrl := container.daemon.netController
772
+func (daemon *Daemon) updateNetwork(container *Container) error {
773
+	ctrl := daemon.netController
774 774
 	sid := container.NetworkSettings.SandboxID
775 775
 
776 776
 	sb, err := ctrl.SandboxByID(sid)
... ...
@@ -781,7 +777,7 @@ func (container *Container) updateNetwork() error {
781 781
 	// Find if container is connected to the default bridge network
782 782
 	var n libnetwork.Network
783 783
 	for name := range container.NetworkSettings.Networks {
784
-		sn, err := container.daemon.FindNetwork(name)
784
+		sn, err := daemon.FindNetwork(name)
785 785
 		if err != nil {
786 786
 			continue
787 787
 		}
... ...
@@ -796,7 +792,7 @@ func (container *Container) updateNetwork() error {
796 796
 		return nil
797 797
 	}
798 798
 
799
-	options, err := container.buildSandboxOptions(n)
799
+	options, err := daemon.buildSandboxOptions(container, n)
800 800
 	if err != nil {
801 801
 		return derr.ErrorCodeNetworkUpdate.WithArgs(err)
802 802
 	}
... ...
@@ -893,8 +889,8 @@ func (container *Container) buildCreateEndpointOptions(n libnetwork.Network) ([]
893 893
 	return createOptions, nil
894 894
 }
895 895
 
896
-func (container *Container) allocateNetwork() error {
897
-	controller := container.daemon.netController
896
+func (daemon *Daemon) allocateNetwork(container *Container) error {
897
+	controller := daemon.netController
898 898
 
899 899
 	// Cleanup any stale sandbox left over due to ungraceful daemon shutdown
900 900
 	if err := controller.SandboxDestroy(container.ID); err != nil {
... ...
@@ -913,7 +909,7 @@ func (container *Container) allocateNetwork() error {
913 913
 			networkName = controller.Config().Daemon.DefaultNetwork
914 914
 		}
915 915
 		if mode.IsUserDefined() {
916
-			n, err := container.daemon.FindNetwork(networkName)
916
+			n, err := daemon.FindNetwork(networkName)
917 917
 			if err != nil {
918 918
 				return err
919 919
 			}
... ...
@@ -925,7 +921,7 @@ func (container *Container) allocateNetwork() error {
925 925
 	}
926 926
 
927 927
 	for n := range container.NetworkSettings.Networks {
928
-		if err := container.connectToNetwork(n, updateSettings); err != nil {
928
+		if err := daemon.connectToNetwork(container, n, updateSettings); err != nil {
929 929
 			return err
930 930
 		}
931 931
 	}
... ...
@@ -933,9 +929,9 @@ func (container *Container) allocateNetwork() error {
933 933
 	return container.writeHostConfig()
934 934
 }
935 935
 
936
-func (container *Container) getNetworkSandbox() libnetwork.Sandbox {
936
+func (daemon *Daemon) getNetworkSandbox(container *Container) libnetwork.Sandbox {
937 937
 	var sb libnetwork.Sandbox
938
-	container.daemon.netController.WalkSandboxes(func(s libnetwork.Sandbox) bool {
938
+	daemon.netController.WalkSandboxes(func(s libnetwork.Sandbox) bool {
939 939
 		if s.ContainerID() == container.ID {
940 940
 			sb = s
941 941
 			return true
... ...
@@ -946,11 +942,11 @@ func (container *Container) getNetworkSandbox() libnetwork.Sandbox {
946 946
 }
947 947
 
948 948
 // ConnectToNetwork connects a container to a netork
949
-func (container *Container) ConnectToNetwork(idOrName string) error {
949
+func (daemon *Daemon) ConnectToNetwork(container *Container, idOrName string) error {
950 950
 	if !container.Running {
951 951
 		return derr.ErrorCodeNotRunning.WithArgs(container.ID)
952 952
 	}
953
-	if err := container.connectToNetwork(idOrName, true); err != nil {
953
+	if err := daemon.connectToNetwork(container, idOrName, true); err != nil {
954 954
 		return err
955 955
 	}
956 956
 	if err := container.toDiskLocking(); err != nil {
... ...
@@ -959,26 +955,26 @@ func (container *Container) ConnectToNetwork(idOrName string) error {
959 959
 	return nil
960 960
 }
961 961
 
962
-func (container *Container) connectToNetwork(idOrName string, updateSettings bool) (err error) {
962
+func (daemon *Daemon) connectToNetwork(container *Container, idOrName string, updateSettings bool) (err error) {
963 963
 	if container.hostConfig.NetworkMode.IsContainer() {
964 964
 		return runconfig.ErrConflictSharedNetwork
965 965
 	}
966 966
 
967 967
 	if runconfig.NetworkMode(idOrName).IsBridge() &&
968
-		container.daemon.configStore.DisableBridge {
968
+		daemon.configStore.DisableBridge {
969 969
 		container.Config.NetworkDisabled = true
970 970
 		return nil
971 971
 	}
972 972
 
973
-	controller := container.daemon.netController
973
+	controller := daemon.netController
974 974
 
975
-	n, err := container.daemon.FindNetwork(idOrName)
975
+	n, err := daemon.FindNetwork(idOrName)
976 976
 	if err != nil {
977 977
 		return err
978 978
 	}
979 979
 
980 980
 	if updateSettings {
981
-		if err := container.updateNetworkSettings(n); err != nil {
981
+		if err := daemon.updateNetworkSettings(container, n); err != nil {
982 982
 			return err
983 983
 		}
984 984
 	}
... ...
@@ -1014,9 +1010,9 @@ func (container *Container) connectToNetwork(idOrName string, updateSettings boo
1014 1014
 		return err
1015 1015
 	}
1016 1016
 
1017
-	sb := container.getNetworkSandbox()
1017
+	sb := daemon.getNetworkSandbox(container)
1018 1018
 	if sb == nil {
1019
-		options, err := container.buildSandboxOptions(n)
1019
+		options, err := daemon.buildSandboxOptions(container, n)
1020 1020
 		if err != nil {
1021 1021
 			return err
1022 1022
 		}
... ...
@@ -1039,12 +1035,12 @@ func (container *Container) connectToNetwork(idOrName string, updateSettings boo
1039 1039
 	return nil
1040 1040
 }
1041 1041
 
1042
-func (container *Container) initializeNetworking() error {
1042
+func (daemon *Daemon) initializeNetworking(container *Container) error {
1043 1043
 	var err error
1044 1044
 
1045 1045
 	if container.hostConfig.NetworkMode.IsContainer() {
1046 1046
 		// we need to get the hosts files from the container to join
1047
-		nc, err := container.getNetworkedContainer()
1047
+		nc, err := daemon.getNetworkedContainer(container.ID, container.hostConfig.NetworkMode.ConnectedContainer())
1048 1048
 		if err != nil {
1049 1049
 			return err
1050 1050
 		}
... ...
@@ -1070,7 +1066,7 @@ func (container *Container) initializeNetworking() error {
1070 1070
 
1071 1071
 	}
1072 1072
 
1073
-	if err := container.allocateNetwork(); err != nil {
1073
+	if err := daemon.allocateNetwork(container); err != nil {
1074 1074
 		return err
1075 1075
 	}
1076 1076
 
... ...
@@ -1079,21 +1075,21 @@ func (container *Container) initializeNetworking() error {
1079 1079
 
1080 1080
 // called from the libcontainer pre-start hook to set the network
1081 1081
 // namespace configuration linkage to the libnetwork "sandbox" entity
1082
-func (container *Container) setNetworkNamespaceKey(pid int) error {
1082
+func (daemon *Daemon) setNetworkNamespaceKey(containerId string, pid int) error {
1083 1083
 	path := fmt.Sprintf("/proc/%d/ns/net", pid)
1084 1084
 	var sandbox libnetwork.Sandbox
1085
-	search := libnetwork.SandboxContainerWalker(&sandbox, container.ID)
1086
-	container.daemon.netController.WalkSandboxes(search)
1085
+	search := libnetwork.SandboxContainerWalker(&sandbox, containerId)
1086
+	daemon.netController.WalkSandboxes(search)
1087 1087
 	if sandbox == nil {
1088
-		return derr.ErrorCodeNoSandbox.WithArgs(container.ID)
1088
+		return derr.ErrorCodeNoSandbox.WithArgs(containerId)
1089 1089
 	}
1090 1090
 
1091 1091
 	return sandbox.SetKey(path)
1092 1092
 }
1093 1093
 
1094
-func (container *Container) getIpcContainer() (*Container, error) {
1094
+func (daemon *Daemon) getIpcContainer(container *Container) (*Container, error) {
1095 1095
 	containerID := container.hostConfig.IpcMode.Container()
1096
-	c, err := container.daemon.Get(containerID)
1096
+	c, err := daemon.Get(containerID)
1097 1097
 	if err != nil {
1098 1098
 		return nil, err
1099 1099
 	}
... ...
@@ -1130,27 +1126,18 @@ func (container *Container) setupWorkingDirectory() error {
1130 1130
 	return nil
1131 1131
 }
1132 1132
 
1133
-func (container *Container) getNetworkedContainer() (*Container, error) {
1134
-	parts := strings.SplitN(string(container.hostConfig.NetworkMode), ":", 2)
1135
-	switch parts[0] {
1136
-	case "container":
1137
-		if len(parts) != 2 {
1138
-			return nil, derr.ErrorCodeParseContainer
1139
-		}
1140
-		nc, err := container.daemon.Get(parts[1])
1141
-		if err != nil {
1142
-			return nil, err
1143
-		}
1144
-		if container == nc {
1145
-			return nil, derr.ErrorCodeJoinSelf
1146
-		}
1147
-		if !nc.IsRunning() {
1148
-			return nil, derr.ErrorCodeJoinRunning.WithArgs(parts[1])
1149
-		}
1150
-		return nc, nil
1151
-	default:
1152
-		return nil, derr.ErrorCodeModeNotContainer
1133
+func (daemon *Daemon) getNetworkedContainer(containerId, connectedContainerId string) (*Container, error) {
1134
+	nc, err := daemon.Get(connectedContainerId)
1135
+	if err != nil {
1136
+		return nil, err
1137
+	}
1138
+	if containerId == nc.ID {
1139
+		return nil, derr.ErrorCodeJoinSelf
1140
+	}
1141
+	if !nc.IsRunning() {
1142
+		return nil, derr.ErrorCodeJoinRunning.WithArgs(connectedContainerId)
1153 1143
 	}
1144
+	return nc, nil
1154 1145
 }
1155 1146
 
1156 1147
 func (daemon *Daemon) releaseNetwork(container *Container) {
... ...
@@ -1337,8 +1324,8 @@ func (container *Container) hasMountFor(path string) bool {
1337 1337
 	return exists
1338 1338
 }
1339 1339
 
1340
-func (container *Container) setupIpcDirs() error {
1341
-	rootUID, rootGID := container.daemon.GetRemappedUIDGID()
1340
+func (daemon *Daemon) setupIpcDirs(container *Container) error {
1341
+	rootUID, rootGID := daemon.GetRemappedUIDGID()
1342 1342
 	if !container.hasMountFor("/dev/shm") {
1343 1343
 		shmPath, err := container.shmPath()
1344 1344
 		if err != nil {
... ...
@@ -27,7 +27,7 @@ func killProcessDirectly(container *Container) error {
27 27
 	return nil
28 28
 }
29 29
 
30
-func (container *Container) setupLinkedContainers() ([]string, error) {
30
+func (daemon *Daemon) setupLinkedContainers(container *Container) ([]string, error) {
31 31
 	return nil, nil
32 32
 }
33 33
 
... ...
@@ -36,12 +36,12 @@ func (container *Container) createDaemonEnvironment(linkedEnv []string) []string
36 36
 	return container.Config.Env
37 37
 }
38 38
 
39
-func (container *Container) initializeNetworking() error {
39
+func (daemon *Daemon) initializeNetworking(container *Container) error {
40 40
 	return nil
41 41
 }
42 42
 
43 43
 // ConnectToNetwork connects a container to the network
44
-func (container *Container) ConnectToNetwork(idOrName string) error {
44
+func (daemon *Daemon) ConnectToNetwork(container *Container, idOrName string) error {
45 45
 	return nil
46 46
 }
47 47
 
... ...
@@ -54,7 +54,7 @@ func (container *Container) setupWorkingDirectory() error {
54 54
 	return nil
55 55
 }
56 56
 
57
-func populateCommand(c *Container, env []string) error {
57
+func (daemon *Daemon) populateCommand(c *Container, env []string) error {
58 58
 	en := &execdriver.Network{
59 59
 		Interface: nil,
60 60
 	}
... ...
@@ -66,7 +66,7 @@ func populateCommand(c *Container, env []string) error {
66 66
 		if !c.Config.NetworkDisabled {
67 67
 			en.Interface = &execdriver.NetworkInterface{
68 68
 				MacAddress:   c.Config.MacAddress,
69
-				Bridge:       c.daemon.configStore.Bridge.VirtualSwitchName,
69
+				Bridge:       daemon.configStore.Bridge.VirtualSwitchName,
70 70
 				PortBindings: c.hostConfig.PortBindings,
71 71
 
72 72
 				// TODO Windows. Include IPAddress. There already is a
... ...
@@ -99,22 +99,22 @@ func populateCommand(c *Container, env []string) error {
99 99
 	processConfig.Env = env
100 100
 
101 101
 	var layerPaths []string
102
-	img, err := c.daemon.graph.Get(c.ImageID)
102
+	img, err := daemon.graph.Get(c.ImageID)
103 103
 	if err != nil {
104 104
 		return derr.ErrorCodeGetGraph.WithArgs(c.ImageID, err)
105 105
 	}
106
-	for i := img; i != nil && err == nil; i, err = c.daemon.graph.GetParent(i) {
107
-		lp, err := c.daemon.driver.Get(i.ID, "")
106
+	for i := img; i != nil && err == nil; i, err = daemon.graph.GetParent(i) {
107
+		lp, err := daemon.driver.Get(i.ID, "")
108 108
 		if err != nil {
109
-			return derr.ErrorCodeGetLayer.WithArgs(c.daemon.driver.String(), i.ID, err)
109
+			return derr.ErrorCodeGetLayer.WithArgs(daemon.driver.String(), i.ID, err)
110 110
 		}
111 111
 		layerPaths = append(layerPaths, lp)
112
-		err = c.daemon.driver.Put(i.ID)
112
+		err = daemon.driver.Put(i.ID)
113 113
 		if err != nil {
114
-			return derr.ErrorCodePutLayer.WithArgs(c.daemon.driver.String(), i.ID, err)
114
+			return derr.ErrorCodePutLayer.WithArgs(daemon.driver.String(), i.ID, err)
115 115
 		}
116 116
 	}
117
-	m, err := c.daemon.driver.GetMetadata(c.ID)
117
+	m, err := daemon.driver.GetMetadata(c.ID)
118 118
 	if err != nil {
119 119
 		return derr.ErrorCodeGetLayerMetadata.WithArgs(err)
120 120
 	}
... ...
@@ -149,16 +149,16 @@ func (daemon *Daemon) getSize(container *Container) (int64, int64) {
149 149
 }
150 150
 
151 151
 // setNetworkNamespaceKey is a no-op on Windows.
152
-func (container *Container) setNetworkNamespaceKey(pid int) error {
152
+func (daemon *Daemon) setNetworkNamespaceKey(containerId string, pid int) error {
153 153
 	return nil
154 154
 }
155 155
 
156 156
 // allocateNetwork is a no-op on Windows.
157
-func (container *Container) allocateNetwork() error {
157
+func (daemon *Daemon) allocateNetwork(container *Container) error {
158 158
 	return nil
159 159
 }
160 160
 
161
-func (container *Container) updateNetwork() error {
161
+func (daemon *Daemon) updateNetwork(container *Container) error {
162 162
 	return nil
163 163
 }
164 164
 
... ...
@@ -172,7 +172,7 @@ func appendNetworkMounts(container *Container, volumeMounts []volume.MountPoint)
172 172
 	return volumeMounts, nil
173 173
 }
174 174
 
175
-func (container *Container) setupIpcDirs() error {
175
+func (daemon *Daemon) setupIpcDirs(container *Container) error {
176 176
 	return nil
177 177
 }
178 178
 
... ...
@@ -957,7 +957,7 @@ func (daemon *Daemon) run(c *Container, pipes *execdriver.Pipes, startCallback e
957 957
 		Start: startCallback,
958 958
 	}
959 959
 	hooks.PreStart = append(hooks.PreStart, func(processConfig *execdriver.ProcessConfig, pid int, chOOM <-chan struct{}) error {
960
-		return c.setNetworkNamespaceKey(pid)
960
+		return daemon.setNetworkNamespaceKey(c.ID, pid)
961 961
 	})
962 962
 	return daemon.execDriver.Run(c.command, pipes, hooks)
963 963
 }
... ...
@@ -45,7 +45,7 @@ func (daemon *Daemon) ContainerRm(name string, config *ContainerRmConfig) error
45 45
 
46 46
 		parentContainer, _ := daemon.Get(pe.ID())
47 47
 		if parentContainer != nil {
48
-			if err := parentContainer.updateNetwork(); err != nil {
48
+			if err := daemon.updateNetwork(parentContainer); err != nil {
49 49
 				logrus.Debugf("Could not update network to remove link %s: %v", n, err)
50 50
 			}
51 51
 		}
... ...
@@ -134,7 +134,7 @@ func (daemon *Daemon) ConnectContainerToNetwork(containerName, networkName strin
134 134
 	if err != nil {
135 135
 		return err
136 136
 	}
137
-	return container.ConnectToNetwork(networkName)
137
+	return daemon.ConnectToNetwork(container, networkName)
138 138
 }
139 139
 
140 140
 // DisconnectContainerFromNetwork disconnects the given container from
... ...
@@ -97,10 +97,10 @@ func (daemon *Daemon) containerStart(container *Container) (err error) {
97 97
 	// backwards API compatibility.
98 98
 	container.hostConfig = runconfig.SetDefaultNetModeIfBlank(container.hostConfig)
99 99
 
100
-	if err := container.initializeNetworking(); err != nil {
100
+	if err := daemon.initializeNetworking(container); err != nil {
101 101
 		return err
102 102
 	}
103
-	linkedEnv, err := container.setupLinkedContainers()
103
+	linkedEnv, err := daemon.setupLinkedContainers(container)
104 104
 	if err != nil {
105 105
 		return err
106 106
 	}
... ...
@@ -108,12 +108,12 @@ func (daemon *Daemon) containerStart(container *Container) (err error) {
108 108
 		return err
109 109
 	}
110 110
 	env := container.createDaemonEnvironment(linkedEnv)
111
-	if err := populateCommand(container, env); err != nil {
111
+	if err := daemon.populateCommand(container, env); err != nil {
112 112
 		return err
113 113
 	}
114 114
 
115 115
 	if !container.hostConfig.IpcMode.IsContainer() && !container.hostConfig.IpcMode.IsHost() {
116
-		if err := container.setupIpcDirs(); err != nil {
116
+		if err := daemon.setupIpcDirs(container); err != nil {
117 117
 			return err
118 118
 		}
119 119
 	}
... ...
@@ -66,6 +66,15 @@ func (n NetworkMode) IsNone() bool {
66 66
 	return n == "none"
67 67
 }
68 68
 
69
+// ConnectedContainer is the id of the container which network this container is connected to.
70
+func (n NetworkMode) ConnectedContainer() string {
71
+	parts := strings.SplitN(string(n), ":", 2)
72
+	if len(parts) > 1 {
73
+		return parts[1]
74
+	}
75
+	return ""
76
+}
77
+
69 78
 // IsUserDefined indicates user-created network
70 79
 func (n NetworkMode) IsUserDefined() bool {
71 80
 	return !n.IsDefault() && !n.IsBridge() && !n.IsHost() && !n.IsNone() && !n.IsContainer()