Browse code

Windows libnetwork integration

Signed-off-by: msabansal <sabansal@microsoft.com>

msabansal authored on 2016/03/10 13:33:21
Showing 15 changed files
... ...
@@ -101,6 +101,11 @@ bundles:
101 101
 
102 102
 cross: build
103 103
 	$(DOCKER_RUN_DOCKER) hack/make.sh dynbinary binary cross
104
+	
105
+	
106
+win: build
107
+	$(DOCKER_RUN_DOCKER) hack/make.sh win
108
+
104 109
 
105 110
 deb: build
106 111
 	$(DOCKER_RUN_DOCKER) hack/make.sh dynbinary build-deb
... ...
@@ -4,8 +4,11 @@ import (
4 4
 	"encoding/json"
5 5
 	"fmt"
6 6
 	"io"
7
+	"net"
7 8
 	"os"
8 9
 	"path/filepath"
10
+	"strconv"
11
+	"strings"
9 12
 	"sync"
10 13
 	"syscall"
11 14
 	"time"
... ...
@@ -23,14 +26,25 @@ import (
23 23
 	"github.com/docker/docker/pkg/signal"
24 24
 	"github.com/docker/docker/pkg/symlink"
25 25
 	"github.com/docker/docker/runconfig"
26
+	runconfigopts "github.com/docker/docker/runconfig/opts"
26 27
 	"github.com/docker/docker/volume"
27 28
 	containertypes "github.com/docker/engine-api/types/container"
29
+	networktypes "github.com/docker/engine-api/types/network"
28 30
 	"github.com/docker/go-connections/nat"
31
+	"github.com/docker/libnetwork"
32
+	"github.com/docker/libnetwork/netlabel"
33
+	"github.com/docker/libnetwork/options"
34
+	"github.com/docker/libnetwork/types"
29 35
 	"github.com/opencontainers/runc/libcontainer/label"
30 36
 )
31 37
 
32 38
 const configFileName = "config.v2.json"
33 39
 
40
+var (
41
+	errInvalidEndpoint = fmt.Errorf("invalid endpoint while building port map info")
42
+	errInvalidNetwork  = fmt.Errorf("invalid network settings while building port map info")
43
+)
44
+
34 45
 // CommonContainer holds the fields for a container which are
35 46
 // applicable across all platforms supported by the daemon.
36 47
 type CommonContainer struct {
... ...
@@ -581,6 +595,293 @@ func (container *Container) InitDNSHostConfig() {
581 581
 	}
582 582
 }
583 583
 
584
+// GetEndpointInNetwork returns the container's endpoint to the provided network.
585
+func (container *Container) GetEndpointInNetwork(n libnetwork.Network) (libnetwork.Endpoint, error) {
586
+	endpointName := strings.TrimPrefix(container.Name, "/")
587
+	return n.EndpointByName(endpointName)
588
+}
589
+
590
+func (container *Container) buildPortMapInfo(ep libnetwork.Endpoint) error {
591
+	if ep == nil {
592
+		return errInvalidEndpoint
593
+	}
594
+
595
+	networkSettings := container.NetworkSettings
596
+	if networkSettings == nil {
597
+		return errInvalidNetwork
598
+	}
599
+
600
+	if len(networkSettings.Ports) == 0 {
601
+		pm, err := getEndpointPortMapInfo(ep)
602
+		if err != nil {
603
+			return err
604
+		}
605
+		networkSettings.Ports = pm
606
+	}
607
+	return nil
608
+}
609
+
610
+func getEndpointPortMapInfo(ep libnetwork.Endpoint) (nat.PortMap, error) {
611
+	pm := nat.PortMap{}
612
+	driverInfo, err := ep.DriverInfo()
613
+	if err != nil {
614
+		return pm, err
615
+	}
616
+
617
+	if driverInfo == nil {
618
+		// It is not an error for epInfo to be nil
619
+		return pm, nil
620
+	}
621
+
622
+	if expData, ok := driverInfo[netlabel.ExposedPorts]; ok {
623
+		if exposedPorts, ok := expData.([]types.TransportPort); ok {
624
+			for _, tp := range exposedPorts {
625
+				natPort, err := nat.NewPort(tp.Proto.String(), strconv.Itoa(int(tp.Port)))
626
+				if err != nil {
627
+					return pm, fmt.Errorf("Error parsing Port value(%v):%v", tp.Port, err)
628
+				}
629
+				pm[natPort] = nil
630
+			}
631
+		}
632
+	}
633
+
634
+	mapData, ok := driverInfo[netlabel.PortMap]
635
+	if !ok {
636
+		return pm, nil
637
+	}
638
+
639
+	if portMapping, ok := mapData.([]types.PortBinding); ok {
640
+		for _, pp := range portMapping {
641
+			natPort, err := nat.NewPort(pp.Proto.String(), strconv.Itoa(int(pp.Port)))
642
+			if err != nil {
643
+				return pm, err
644
+			}
645
+			natBndg := nat.PortBinding{HostIP: pp.HostIP.String(), HostPort: strconv.Itoa(int(pp.HostPort))}
646
+			pm[natPort] = append(pm[natPort], natBndg)
647
+		}
648
+	}
649
+
650
+	return pm, nil
651
+}
652
+
653
+func getSandboxPortMapInfo(sb libnetwork.Sandbox) nat.PortMap {
654
+	pm := nat.PortMap{}
655
+	if sb == nil {
656
+		return pm
657
+	}
658
+
659
+	for _, ep := range sb.Endpoints() {
660
+		pm, _ = getEndpointPortMapInfo(ep)
661
+		if len(pm) > 0 {
662
+			break
663
+		}
664
+	}
665
+	return pm
666
+}
667
+
668
+// BuildEndpointInfo sets endpoint-related fields on container.NetworkSettings based on the provided network and endpoint.
669
+func (container *Container) BuildEndpointInfo(n libnetwork.Network, ep libnetwork.Endpoint) error {
670
+	if ep == nil {
671
+		return errInvalidEndpoint
672
+	}
673
+
674
+	networkSettings := container.NetworkSettings
675
+	if networkSettings == nil {
676
+		return errInvalidNetwork
677
+	}
678
+
679
+	epInfo := ep.Info()
680
+	if epInfo == nil {
681
+		// It is not an error to get an empty endpoint info
682
+		return nil
683
+	}
684
+
685
+	if _, ok := networkSettings.Networks[n.Name()]; !ok {
686
+		networkSettings.Networks[n.Name()] = new(networktypes.EndpointSettings)
687
+	}
688
+	networkSettings.Networks[n.Name()].NetworkID = n.ID()
689
+	networkSettings.Networks[n.Name()].EndpointID = ep.ID()
690
+
691
+	iface := epInfo.Iface()
692
+	if iface == nil {
693
+		return nil
694
+	}
695
+
696
+	if iface.MacAddress() != nil {
697
+		networkSettings.Networks[n.Name()].MacAddress = iface.MacAddress().String()
698
+	}
699
+
700
+	if iface.Address() != nil {
701
+		ones, _ := iface.Address().Mask.Size()
702
+		networkSettings.Networks[n.Name()].IPAddress = iface.Address().IP.String()
703
+		networkSettings.Networks[n.Name()].IPPrefixLen = ones
704
+	}
705
+
706
+	if iface.AddressIPv6() != nil && iface.AddressIPv6().IP.To16() != nil {
707
+		onesv6, _ := iface.AddressIPv6().Mask.Size()
708
+		networkSettings.Networks[n.Name()].GlobalIPv6Address = iface.AddressIPv6().IP.String()
709
+		networkSettings.Networks[n.Name()].GlobalIPv6PrefixLen = onesv6
710
+	}
711
+
712
+	return nil
713
+}
714
+
715
+// UpdateJoinInfo updates network settings when container joins network n with endpoint ep.
716
+func (container *Container) UpdateJoinInfo(n libnetwork.Network, ep libnetwork.Endpoint) error {
717
+	if err := container.buildPortMapInfo(ep); err != nil {
718
+		return err
719
+	}
720
+
721
+	epInfo := ep.Info()
722
+	if epInfo == nil {
723
+		// It is not an error to get an empty endpoint info
724
+		return nil
725
+	}
726
+	if epInfo.Gateway() != nil {
727
+		container.NetworkSettings.Networks[n.Name()].Gateway = epInfo.Gateway().String()
728
+	}
729
+	if epInfo.GatewayIPv6().To16() != nil {
730
+		container.NetworkSettings.Networks[n.Name()].IPv6Gateway = epInfo.GatewayIPv6().String()
731
+	}
732
+
733
+	return nil
734
+}
735
+
736
+// UpdateSandboxNetworkSettings updates the sandbox ID and Key.
737
+func (container *Container) UpdateSandboxNetworkSettings(sb libnetwork.Sandbox) error {
738
+	container.NetworkSettings.SandboxID = sb.ID()
739
+	container.NetworkSettings.SandboxKey = sb.Key()
740
+	return nil
741
+}
742
+
743
+// BuildJoinOptions builds endpoint Join options from a given network.
744
+func (container *Container) BuildJoinOptions(n libnetwork.Network) ([]libnetwork.EndpointOption, error) {
745
+	var joinOptions []libnetwork.EndpointOption
746
+	if epConfig, ok := container.NetworkSettings.Networks[n.Name()]; ok {
747
+		for _, str := range epConfig.Links {
748
+			name, alias, err := runconfigopts.ParseLink(str)
749
+			if err != nil {
750
+				return nil, err
751
+			}
752
+			joinOptions = append(joinOptions, libnetwork.CreateOptionAlias(name, alias))
753
+		}
754
+	}
755
+	return joinOptions, nil
756
+}
757
+
758
+// BuildCreateEndpointOptions builds endpoint options from a given network.
759
+func (container *Container) BuildCreateEndpointOptions(n libnetwork.Network, epConfig *networktypes.EndpointSettings, sb libnetwork.Sandbox) ([]libnetwork.EndpointOption, error) {
760
+	var (
761
+		bindings      = make(nat.PortMap)
762
+		pbList        []types.PortBinding
763
+		exposeList    []types.TransportPort
764
+		createOptions []libnetwork.EndpointOption
765
+	)
766
+
767
+	defaultNetName := runconfig.DefaultDaemonNetworkMode().NetworkName()
768
+
769
+	if n.Name() == defaultNetName || container.NetworkSettings.IsAnonymousEndpoint {
770
+		createOptions = append(createOptions, libnetwork.CreateOptionAnonymous())
771
+	}
772
+
773
+	if epConfig != nil {
774
+		ipam := epConfig.IPAMConfig
775
+		if ipam != nil && (ipam.IPv4Address != "" || ipam.IPv6Address != "") {
776
+			createOptions = append(createOptions,
777
+				libnetwork.CreateOptionIpam(net.ParseIP(ipam.IPv4Address), net.ParseIP(ipam.IPv6Address), nil))
778
+		}
779
+
780
+		for _, alias := range epConfig.Aliases {
781
+			createOptions = append(createOptions, libnetwork.CreateOptionMyAlias(alias))
782
+		}
783
+	}
784
+
785
+	if !containertypes.NetworkMode(n.Name()).IsUserDefined() {
786
+		createOptions = append(createOptions, libnetwork.CreateOptionDisableResolution())
787
+	}
788
+
789
+	// configs that are applicable only for the endpoint in the network
790
+	// to which container was connected to on docker run.
791
+	// Ideally all these network-specific endpoint configurations must be moved under
792
+	// container.NetworkSettings.Networks[n.Name()]
793
+	if n.Name() == container.HostConfig.NetworkMode.NetworkName() ||
794
+		(n.Name() == defaultNetName && container.HostConfig.NetworkMode.IsDefault()) {
795
+		if container.Config.MacAddress != "" {
796
+			mac, err := net.ParseMAC(container.Config.MacAddress)
797
+			if err != nil {
798
+				return nil, err
799
+			}
800
+
801
+			genericOption := options.Generic{
802
+				netlabel.MacAddress: mac,
803
+			}
804
+
805
+			createOptions = append(createOptions, libnetwork.EndpointOptionGeneric(genericOption))
806
+		}
807
+	}
808
+
809
+	// Port-mapping rules belong to the container & applicable only to non-internal networks
810
+	portmaps := getSandboxPortMapInfo(sb)
811
+	if n.Info().Internal() || len(portmaps) > 0 {
812
+		return createOptions, nil
813
+	}
814
+
815
+	if container.HostConfig.PortBindings != nil {
816
+		for p, b := range container.HostConfig.PortBindings {
817
+			bindings[p] = []nat.PortBinding{}
818
+			for _, bb := range b {
819
+				bindings[p] = append(bindings[p], nat.PortBinding{
820
+					HostIP:   bb.HostIP,
821
+					HostPort: bb.HostPort,
822
+				})
823
+			}
824
+		}
825
+	}
826
+
827
+	portSpecs := container.Config.ExposedPorts
828
+	ports := make([]nat.Port, len(portSpecs))
829
+	var i int
830
+	for p := range portSpecs {
831
+		ports[i] = p
832
+		i++
833
+	}
834
+	nat.SortPortMap(ports, bindings)
835
+	for _, port := range ports {
836
+		expose := types.TransportPort{}
837
+		expose.Proto = types.ParseProtocol(port.Proto())
838
+		expose.Port = uint16(port.Int())
839
+		exposeList = append(exposeList, expose)
840
+
841
+		pb := types.PortBinding{Port: expose.Port, Proto: expose.Proto}
842
+		binding := bindings[port]
843
+		for i := 0; i < len(binding); i++ {
844
+			pbCopy := pb.GetCopy()
845
+			newP, err := nat.NewPort(nat.SplitProtoPort(binding[i].HostPort))
846
+			var portStart, portEnd int
847
+			if err == nil {
848
+				portStart, portEnd, err = newP.Range()
849
+			}
850
+			if err != nil {
851
+				return nil, fmt.Errorf("Error parsing HostPort value(%s):%v", binding[i].HostPort, err)
852
+			}
853
+			pbCopy.HostPort = uint16(portStart)
854
+			pbCopy.HostPortEnd = uint16(portEnd)
855
+			pbCopy.HostIP = net.ParseIP(binding[i].HostIP)
856
+			pbList = append(pbList, pbCopy)
857
+		}
858
+
859
+		if container.HostConfig.PublishAllPorts && len(binding) == 0 {
860
+			pbList = append(pbList, pb)
861
+		}
862
+	}
863
+
864
+	createOptions = append(createOptions,
865
+		libnetwork.CreateOptionPortMapping(pbList),
866
+		libnetwork.CreateOptionExposedPorts(exposeList))
867
+
868
+	return createOptions, nil
869
+}
870
+
584 871
 // UpdateMonitor updates monitor configure for running container
585 872
 func (container *Container) UpdateMonitor(restartPolicy containertypes.RestartPolicy) {
586 873
 	monitor := container.monitor
... ...
@@ -5,10 +5,8 @@ package container
5 5
 import (
6 6
 	"fmt"
7 7
 	"io/ioutil"
8
-	"net"
9 8
 	"os"
10 9
 	"path/filepath"
11
-	"strconv"
12 10
 	"strings"
13 11
 	"syscall"
14 12
 
... ...
@@ -17,27 +15,15 @@ import (
17 17
 	"github.com/docker/docker/pkg/chrootarchive"
18 18
 	"github.com/docker/docker/pkg/symlink"
19 19
 	"github.com/docker/docker/pkg/system"
20
-	runconfigopts "github.com/docker/docker/runconfig/opts"
21 20
 	"github.com/docker/docker/utils"
22 21
 	"github.com/docker/docker/volume"
23 22
 	containertypes "github.com/docker/engine-api/types/container"
24
-	"github.com/docker/engine-api/types/network"
25
-	"github.com/docker/go-connections/nat"
26
-	"github.com/docker/libnetwork"
27
-	"github.com/docker/libnetwork/netlabel"
28
-	"github.com/docker/libnetwork/options"
29
-	"github.com/docker/libnetwork/types"
30 23
 	"github.com/opencontainers/runc/libcontainer/label"
31 24
 )
32 25
 
33 26
 // DefaultSHMSize is the default size (64MB) of the SHM which will be mounted in the container
34 27
 const DefaultSHMSize int64 = 67108864
35 28
 
36
-var (
37
-	errInvalidEndpoint = fmt.Errorf("invalid endpoint while building port map info")
38
-	errInvalidNetwork  = fmt.Errorf("invalid network settings while building port map info")
39
-)
40
-
41 29
 // Container holds the fields specific to unixen implementations.
42 30
 // See CommonContainer for standard fields common to all containers.
43 31
 type Container struct {
... ...
@@ -113,291 +99,6 @@ func (container *Container) BuildHostnameFile() error {
113 113
 	return ioutil.WriteFile(container.HostnamePath, []byte(container.Config.Hostname+"\n"), 0644)
114 114
 }
115 115
 
116
-// GetEndpointInNetwork returns the container's endpoint to the provided network.
117
-func (container *Container) GetEndpointInNetwork(n libnetwork.Network) (libnetwork.Endpoint, error) {
118
-	endpointName := strings.TrimPrefix(container.Name, "/")
119
-	return n.EndpointByName(endpointName)
120
-}
121
-
122
-func (container *Container) buildPortMapInfo(ep libnetwork.Endpoint) error {
123
-	if ep == nil {
124
-		return errInvalidEndpoint
125
-	}
126
-
127
-	networkSettings := container.NetworkSettings
128
-	if networkSettings == nil {
129
-		return errInvalidNetwork
130
-	}
131
-
132
-	if len(networkSettings.Ports) == 0 {
133
-		pm, err := getEndpointPortMapInfo(ep)
134
-		if err != nil {
135
-			return err
136
-		}
137
-		networkSettings.Ports = pm
138
-	}
139
-	return nil
140
-}
141
-
142
-func getEndpointPortMapInfo(ep libnetwork.Endpoint) (nat.PortMap, error) {
143
-	pm := nat.PortMap{}
144
-	driverInfo, err := ep.DriverInfo()
145
-	if err != nil {
146
-		return pm, err
147
-	}
148
-
149
-	if driverInfo == nil {
150
-		// It is not an error for epInfo to be nil
151
-		return pm, nil
152
-	}
153
-
154
-	if expData, ok := driverInfo[netlabel.ExposedPorts]; ok {
155
-		if exposedPorts, ok := expData.([]types.TransportPort); ok {
156
-			for _, tp := range exposedPorts {
157
-				natPort, err := nat.NewPort(tp.Proto.String(), strconv.Itoa(int(tp.Port)))
158
-				if err != nil {
159
-					return pm, fmt.Errorf("Error parsing Port value(%v):%v", tp.Port, err)
160
-				}
161
-				pm[natPort] = nil
162
-			}
163
-		}
164
-	}
165
-
166
-	mapData, ok := driverInfo[netlabel.PortMap]
167
-	if !ok {
168
-		return pm, nil
169
-	}
170
-
171
-	if portMapping, ok := mapData.([]types.PortBinding); ok {
172
-		for _, pp := range portMapping {
173
-			natPort, err := nat.NewPort(pp.Proto.String(), strconv.Itoa(int(pp.Port)))
174
-			if err != nil {
175
-				return pm, err
176
-			}
177
-			natBndg := nat.PortBinding{HostIP: pp.HostIP.String(), HostPort: strconv.Itoa(int(pp.HostPort))}
178
-			pm[natPort] = append(pm[natPort], natBndg)
179
-		}
180
-	}
181
-
182
-	return pm, nil
183
-}
184
-
185
-func getSandboxPortMapInfo(sb libnetwork.Sandbox) nat.PortMap {
186
-	pm := nat.PortMap{}
187
-	if sb == nil {
188
-		return pm
189
-	}
190
-
191
-	for _, ep := range sb.Endpoints() {
192
-		pm, _ = getEndpointPortMapInfo(ep)
193
-		if len(pm) > 0 {
194
-			break
195
-		}
196
-	}
197
-	return pm
198
-}
199
-
200
-// BuildEndpointInfo sets endpoint-related fields on container.NetworkSettings based on the provided network and endpoint.
201
-func (container *Container) BuildEndpointInfo(n libnetwork.Network, ep libnetwork.Endpoint) error {
202
-	if ep == nil {
203
-		return errInvalidEndpoint
204
-	}
205
-
206
-	networkSettings := container.NetworkSettings
207
-	if networkSettings == nil {
208
-		return errInvalidNetwork
209
-	}
210
-
211
-	epInfo := ep.Info()
212
-	if epInfo == nil {
213
-		// It is not an error to get an empty endpoint info
214
-		return nil
215
-	}
216
-
217
-	if _, ok := networkSettings.Networks[n.Name()]; !ok {
218
-		networkSettings.Networks[n.Name()] = new(network.EndpointSettings)
219
-	}
220
-	networkSettings.Networks[n.Name()].NetworkID = n.ID()
221
-	networkSettings.Networks[n.Name()].EndpointID = ep.ID()
222
-
223
-	iface := epInfo.Iface()
224
-	if iface == nil {
225
-		return nil
226
-	}
227
-
228
-	if iface.MacAddress() != nil {
229
-		networkSettings.Networks[n.Name()].MacAddress = iface.MacAddress().String()
230
-	}
231
-
232
-	if iface.Address() != nil {
233
-		ones, _ := iface.Address().Mask.Size()
234
-		networkSettings.Networks[n.Name()].IPAddress = iface.Address().IP.String()
235
-		networkSettings.Networks[n.Name()].IPPrefixLen = ones
236
-	}
237
-
238
-	if iface.AddressIPv6() != nil && iface.AddressIPv6().IP.To16() != nil {
239
-		onesv6, _ := iface.AddressIPv6().Mask.Size()
240
-		networkSettings.Networks[n.Name()].GlobalIPv6Address = iface.AddressIPv6().IP.String()
241
-		networkSettings.Networks[n.Name()].GlobalIPv6PrefixLen = onesv6
242
-	}
243
-
244
-	return nil
245
-}
246
-
247
-// UpdateJoinInfo updates network settings when container joins network n with endpoint ep.
248
-func (container *Container) UpdateJoinInfo(n libnetwork.Network, ep libnetwork.Endpoint) error {
249
-	if err := container.buildPortMapInfo(ep); err != nil {
250
-		return err
251
-	}
252
-
253
-	epInfo := ep.Info()
254
-	if epInfo == nil {
255
-		// It is not an error to get an empty endpoint info
256
-		return nil
257
-	}
258
-	if epInfo.Gateway() != nil {
259
-		container.NetworkSettings.Networks[n.Name()].Gateway = epInfo.Gateway().String()
260
-	}
261
-	if epInfo.GatewayIPv6().To16() != nil {
262
-		container.NetworkSettings.Networks[n.Name()].IPv6Gateway = epInfo.GatewayIPv6().String()
263
-	}
264
-
265
-	return nil
266
-}
267
-
268
-// UpdateSandboxNetworkSettings updates the sandbox ID and Key.
269
-func (container *Container) UpdateSandboxNetworkSettings(sb libnetwork.Sandbox) error {
270
-	container.NetworkSettings.SandboxID = sb.ID()
271
-	container.NetworkSettings.SandboxKey = sb.Key()
272
-	return nil
273
-}
274
-
275
-// BuildJoinOptions builds endpoint Join options from a given network.
276
-func (container *Container) BuildJoinOptions(n libnetwork.Network) ([]libnetwork.EndpointOption, error) {
277
-	var joinOptions []libnetwork.EndpointOption
278
-	if epConfig, ok := container.NetworkSettings.Networks[n.Name()]; ok {
279
-		for _, str := range epConfig.Links {
280
-			name, alias, err := runconfigopts.ParseLink(str)
281
-			if err != nil {
282
-				return nil, err
283
-			}
284
-			joinOptions = append(joinOptions, libnetwork.CreateOptionAlias(name, alias))
285
-		}
286
-	}
287
-	return joinOptions, nil
288
-}
289
-
290
-// BuildCreateEndpointOptions builds endpoint options from a given network.
291
-func (container *Container) BuildCreateEndpointOptions(n libnetwork.Network, epConfig *network.EndpointSettings, sb libnetwork.Sandbox) ([]libnetwork.EndpointOption, error) {
292
-	var (
293
-		bindings      = make(nat.PortMap)
294
-		pbList        []types.PortBinding
295
-		exposeList    []types.TransportPort
296
-		createOptions []libnetwork.EndpointOption
297
-	)
298
-
299
-	if n.Name() == "bridge" || container.NetworkSettings.IsAnonymousEndpoint {
300
-		createOptions = append(createOptions, libnetwork.CreateOptionAnonymous())
301
-	}
302
-
303
-	if epConfig != nil {
304
-		ipam := epConfig.IPAMConfig
305
-		if ipam != nil && (ipam.IPv4Address != "" || ipam.IPv6Address != "") {
306
-			createOptions = append(createOptions,
307
-				libnetwork.CreateOptionIpam(net.ParseIP(ipam.IPv4Address), net.ParseIP(ipam.IPv6Address), nil))
308
-		}
309
-
310
-		for _, alias := range epConfig.Aliases {
311
-			createOptions = append(createOptions, libnetwork.CreateOptionMyAlias(alias))
312
-		}
313
-	}
314
-
315
-	if !containertypes.NetworkMode(n.Name()).IsUserDefined() {
316
-		createOptions = append(createOptions, libnetwork.CreateOptionDisableResolution())
317
-	}
318
-
319
-	// configs that are applicable only for the endpoint in the network
320
-	// to which container was connected to on docker run.
321
-	// Ideally all these network-specific endpoint configurations must be moved under
322
-	// container.NetworkSettings.Networks[n.Name()]
323
-	if n.Name() == container.HostConfig.NetworkMode.NetworkName() ||
324
-		(n.Name() == "bridge" && container.HostConfig.NetworkMode.IsDefault()) {
325
-		if container.Config.MacAddress != "" {
326
-			mac, err := net.ParseMAC(container.Config.MacAddress)
327
-			if err != nil {
328
-				return nil, err
329
-			}
330
-
331
-			genericOption := options.Generic{
332
-				netlabel.MacAddress: mac,
333
-			}
334
-
335
-			createOptions = append(createOptions, libnetwork.EndpointOptionGeneric(genericOption))
336
-		}
337
-	}
338
-
339
-	// Port-mapping rules belong to the container & applicable only to non-internal networks
340
-	portmaps := getSandboxPortMapInfo(sb)
341
-	if n.Info().Internal() || len(portmaps) > 0 {
342
-		return createOptions, nil
343
-	}
344
-
345
-	if container.HostConfig.PortBindings != nil {
346
-		for p, b := range container.HostConfig.PortBindings {
347
-			bindings[p] = []nat.PortBinding{}
348
-			for _, bb := range b {
349
-				bindings[p] = append(bindings[p], nat.PortBinding{
350
-					HostIP:   bb.HostIP,
351
-					HostPort: bb.HostPort,
352
-				})
353
-			}
354
-		}
355
-	}
356
-
357
-	portSpecs := container.Config.ExposedPorts
358
-	ports := make([]nat.Port, len(portSpecs))
359
-	var i int
360
-	for p := range portSpecs {
361
-		ports[i] = p
362
-		i++
363
-	}
364
-	nat.SortPortMap(ports, bindings)
365
-	for _, port := range ports {
366
-		expose := types.TransportPort{}
367
-		expose.Proto = types.ParseProtocol(port.Proto())
368
-		expose.Port = uint16(port.Int())
369
-		exposeList = append(exposeList, expose)
370
-
371
-		pb := types.PortBinding{Port: expose.Port, Proto: expose.Proto}
372
-		binding := bindings[port]
373
-		for i := 0; i < len(binding); i++ {
374
-			pbCopy := pb.GetCopy()
375
-			newP, err := nat.NewPort(nat.SplitProtoPort(binding[i].HostPort))
376
-			var portStart, portEnd int
377
-			if err == nil {
378
-				portStart, portEnd, err = newP.Range()
379
-			}
380
-			if err != nil {
381
-				return nil, fmt.Errorf("Error parsing HostPort value(%s):%v", binding[i].HostPort, err)
382
-			}
383
-			pbCopy.HostPort = uint16(portStart)
384
-			pbCopy.HostPortEnd = uint16(portEnd)
385
-			pbCopy.HostIP = net.ParseIP(binding[i].HostIP)
386
-			pbList = append(pbList, pbCopy)
387
-		}
388
-
389
-		if container.HostConfig.PublishAllPorts && len(binding) == 0 {
390
-			pbList = append(pbList, pb)
391
-		}
392
-	}
393
-
394
-	createOptions = append(createOptions,
395
-		libnetwork.CreateOptionPortMapping(pbList),
396
-		libnetwork.CreateOptionExposedPorts(exposeList))
397
-
398
-	return createOptions, nil
399
-}
400
-
401 116
 // appendNetworkMounts appends any network mounts to the array of mount points passed in
402 117
 func appendNetworkMounts(container *Container, volumeMounts []volume.MountPoint) ([]volume.MountPoint, error) {
403 118
 	for _, mnt := range container.NetworkMounts() {
... ...
@@ -17,6 +17,9 @@ import (
17 17
 type Container struct {
18 18
 	CommonContainer
19 19
 
20
+	HostnamePath   string
21
+	HostsPath      string
22
+	ResolvConfPath string
20 23
 	// Fields below here are platform specific.
21 24
 }
22 25
 
... ...
@@ -84,6 +87,11 @@ func cleanResourcePath(path string) string {
84 84
 	return filepath.Join(string(os.PathSeparator), path)
85 85
 }
86 86
 
87
+// BuildHostnameFile writes the container's hostname file.
88
+func (container *Container) BuildHostnameFile() error {
89
+	return nil
90
+}
91
+
87 92
 // canMountFS determines if the file system for the container
88 93
 // can be mounted locally. In the case of Windows, this is not possible
89 94
 // for Hyper-V containers during WORKDIR execution for example.
... ...
@@ -15,7 +15,9 @@ var (
15 15
 // bridgeConfig stores all the bridge driver specific
16 16
 // configuration.
17 17
 type bridgeConfig struct {
18
-	VirtualSwitchName string `json:"bridge,omitempty"`
18
+	FixedCIDR   string
19
+	NetworkMode string
20
+	Iface       string `json:"bridge,omitempty"`
19 21
 }
20 22
 
21 23
 // Config defines the configuration of a docker daemon.
... ...
@@ -37,6 +39,7 @@ func (config *Config) InstallFlags(cmd *flag.FlagSet, usageFn func(string) strin
37 37
 	config.InstallCommonFlags(cmd, usageFn)
38 38
 
39 39
 	// Then platform-specific install flags.
40
-	cmd.StringVar(&config.bridgeConfig.VirtualSwitchName, []string{"b", "-bridge"}, "", "Attach containers to a virtual switch")
40
+	cmd.StringVar(&config.bridgeConfig.FixedCIDR, []string{"-fixed-cidr"}, "", usageFn("IPv4 subnet for fixed IPs"))
41
+	cmd.StringVar(&config.bridgeConfig.Iface, []string{"b", "-bridge"}, "", "Attach containers to a virtual switch")
41 42
 	cmd.StringVar(&config.SocketGroup, []string{"G", "-group"}, "", usageFn("Users or groups that can access the named pipe"))
42 43
 }
... ...
@@ -1,9 +1,745 @@
1 1
 package daemon
2 2
 
3
-import "errors"
3
+import (
4
+	"errors"
5
+	"fmt"
6
+	"net"
7
+	"os"
8
+	"path"
9
+	"strings"
10
+
11
+	"github.com/Sirupsen/logrus"
12
+	"github.com/docker/docker/container"
13
+	"github.com/docker/docker/daemon/network"
14
+	derr "github.com/docker/docker/errors"
15
+	"github.com/docker/docker/runconfig"
16
+	containertypes "github.com/docker/engine-api/types/container"
17
+	networktypes "github.com/docker/engine-api/types/network"
18
+	"github.com/docker/go-connections/nat"
19
+	"github.com/docker/libnetwork"
20
+	"github.com/docker/libnetwork/netlabel"
21
+	"github.com/docker/libnetwork/options"
22
+	"github.com/docker/libnetwork/types"
23
+)
4 24
 
5 25
 var (
6 26
 	// ErrRootFSReadOnly is returned when a container
7 27
 	// rootfs is marked readonly.
8 28
 	ErrRootFSReadOnly = errors.New("container rootfs is marked read-only")
9 29
 )
30
+
31
+func (daemon *Daemon) buildSandboxOptions(container *container.Container, n libnetwork.Network) ([]libnetwork.SandboxOption, error) {
32
+	var (
33
+		sboxOptions []libnetwork.SandboxOption
34
+		err         error
35
+		dns         []string
36
+		dnsSearch   []string
37
+		dnsOptions  []string
38
+		bindings    = make(nat.PortMap)
39
+		pbList      []types.PortBinding
40
+		exposeList  []types.TransportPort
41
+	)
42
+
43
+	defaultNetName := runconfig.DefaultDaemonNetworkMode().NetworkName()
44
+	sboxOptions = append(sboxOptions, libnetwork.OptionHostname(container.Config.Hostname),
45
+		libnetwork.OptionDomainname(container.Config.Domainname))
46
+
47
+	if container.HostConfig.NetworkMode.IsHost() {
48
+		sboxOptions = append(sboxOptions, libnetwork.OptionUseDefaultSandbox())
49
+		sboxOptions = append(sboxOptions, libnetwork.OptionOriginHostsPath("/etc/hosts"))
50
+		sboxOptions = append(sboxOptions, libnetwork.OptionOriginResolvConfPath("/etc/resolv.conf"))
51
+	} else if daemon.execDriver.SupportsHooks() {
52
+		// OptionUseExternalKey is mandatory for userns support.
53
+		// But optional for non-userns support
54
+		sboxOptions = append(sboxOptions, libnetwork.OptionUseExternalKey())
55
+	}
56
+
57
+	container.HostsPath, err = container.GetRootResourcePath("hosts")
58
+	if err != nil {
59
+		return nil, err
60
+	}
61
+	sboxOptions = append(sboxOptions, libnetwork.OptionHostsPath(container.HostsPath))
62
+
63
+	container.ResolvConfPath, err = container.GetRootResourcePath("resolv.conf")
64
+	if err != nil {
65
+		return nil, err
66
+	}
67
+	sboxOptions = append(sboxOptions, libnetwork.OptionResolvConfPath(container.ResolvConfPath))
68
+
69
+	if len(container.HostConfig.DNS) > 0 {
70
+		dns = container.HostConfig.DNS
71
+	} else if len(daemon.configStore.DNS) > 0 {
72
+		dns = daemon.configStore.DNS
73
+	}
74
+
75
+	for _, d := range dns {
76
+		sboxOptions = append(sboxOptions, libnetwork.OptionDNS(d))
77
+	}
78
+
79
+	if len(container.HostConfig.DNSSearch) > 0 {
80
+		dnsSearch = container.HostConfig.DNSSearch
81
+	} else if len(daemon.configStore.DNSSearch) > 0 {
82
+		dnsSearch = daemon.configStore.DNSSearch
83
+	}
84
+
85
+	for _, ds := range dnsSearch {
86
+		sboxOptions = append(sboxOptions, libnetwork.OptionDNSSearch(ds))
87
+	}
88
+
89
+	if len(container.HostConfig.DNSOptions) > 0 {
90
+		dnsOptions = container.HostConfig.DNSOptions
91
+	} else if len(daemon.configStore.DNSOptions) > 0 {
92
+		dnsOptions = daemon.configStore.DNSOptions
93
+	}
94
+
95
+	for _, ds := range dnsOptions {
96
+		sboxOptions = append(sboxOptions, libnetwork.OptionDNSOptions(ds))
97
+	}
98
+
99
+	if container.NetworkSettings.SecondaryIPAddresses != nil {
100
+		name := container.Config.Hostname
101
+		if container.Config.Domainname != "" {
102
+			name = name + "." + container.Config.Domainname
103
+		}
104
+
105
+		for _, a := range container.NetworkSettings.SecondaryIPAddresses {
106
+			sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(name, a.Addr))
107
+		}
108
+	}
109
+
110
+	for _, extraHost := range container.HostConfig.ExtraHosts {
111
+		// allow IPv6 addresses in extra hosts; only split on first ":"
112
+		parts := strings.SplitN(extraHost, ":", 2)
113
+		sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(parts[0], parts[1]))
114
+	}
115
+
116
+	if container.HostConfig.PortBindings != nil {
117
+		for p, b := range container.HostConfig.PortBindings {
118
+			bindings[p] = []nat.PortBinding{}
119
+			for _, bb := range b {
120
+				bindings[p] = append(bindings[p], nat.PortBinding{
121
+					HostIP:   bb.HostIP,
122
+					HostPort: bb.HostPort,
123
+				})
124
+			}
125
+		}
126
+	}
127
+
128
+	portSpecs := container.Config.ExposedPorts
129
+	ports := make([]nat.Port, len(portSpecs))
130
+	var i int
131
+	for p := range portSpecs {
132
+		ports[i] = p
133
+		i++
134
+	}
135
+	nat.SortPortMap(ports, bindings)
136
+	for _, port := range ports {
137
+		expose := types.TransportPort{}
138
+		expose.Proto = types.ParseProtocol(port.Proto())
139
+		expose.Port = uint16(port.Int())
140
+		exposeList = append(exposeList, expose)
141
+
142
+		pb := types.PortBinding{Port: expose.Port, Proto: expose.Proto}
143
+		binding := bindings[port]
144
+		for i := 0; i < len(binding); i++ {
145
+			pbCopy := pb.GetCopy()
146
+			newP, err := nat.NewPort(nat.SplitProtoPort(binding[i].HostPort))
147
+			var portStart, portEnd int
148
+			if err == nil {
149
+				portStart, portEnd, err = newP.Range()
150
+			}
151
+			if err != nil {
152
+				return nil, fmt.Errorf("Error parsing HostPort value(%s):%v", binding[i].HostPort, err)
153
+			}
154
+			pbCopy.HostPort = uint16(portStart)
155
+			pbCopy.HostPortEnd = uint16(portEnd)
156
+			pbCopy.HostIP = net.ParseIP(binding[i].HostIP)
157
+			pbList = append(pbList, pbCopy)
158
+		}
159
+
160
+		if container.HostConfig.PublishAllPorts && len(binding) == 0 {
161
+			pbList = append(pbList, pb)
162
+		}
163
+	}
164
+
165
+	sboxOptions = append(sboxOptions,
166
+		libnetwork.OptionPortMapping(pbList),
167
+		libnetwork.OptionExposedPorts(exposeList))
168
+
169
+	// Link feature is supported only for the default bridge network.
170
+	// return if this call to build join options is not for default bridge network
171
+	if n.Name() != defaultNetName {
172
+		return sboxOptions, nil
173
+	}
174
+
175
+	ep, _ := container.GetEndpointInNetwork(n)
176
+	if ep == nil {
177
+		return sboxOptions, nil
178
+	}
179
+
180
+	var childEndpoints, parentEndpoints []string
181
+
182
+	children := daemon.children(container)
183
+	for linkAlias, child := range children {
184
+		if !isLinkable(child) {
185
+			return nil, fmt.Errorf("Cannot link to %s, as it does not belong to the default network", child.Name)
186
+		}
187
+		_, alias := path.Split(linkAlias)
188
+		// allow access to the linked container via the alias, real name, and container hostname
189
+		aliasList := alias + " " + child.Config.Hostname
190
+		// only add the name if alias isn't equal to the name
191
+		if alias != child.Name[1:] {
192
+			aliasList = aliasList + " " + child.Name[1:]
193
+		}
194
+		sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(aliasList, child.NetworkSettings.Networks[defaultNetName].IPAddress))
195
+		cEndpoint, _ := child.GetEndpointInNetwork(n)
196
+		if cEndpoint != nil && cEndpoint.ID() != "" {
197
+			childEndpoints = append(childEndpoints, cEndpoint.ID())
198
+		}
199
+	}
200
+
201
+	bridgeSettings := container.NetworkSettings.Networks[defaultNetName]
202
+	for alias, parent := range daemon.parents(container) {
203
+		if daemon.configStore.DisableBridge || !container.HostConfig.NetworkMode.IsPrivate() {
204
+			continue
205
+		}
206
+
207
+		_, alias = path.Split(alias)
208
+		logrus.Debugf("Update /etc/hosts of %s for alias %s with ip %s", parent.ID, alias, bridgeSettings.IPAddress)
209
+		sboxOptions = append(sboxOptions, libnetwork.OptionParentUpdate(
210
+			parent.ID,
211
+			alias,
212
+			bridgeSettings.IPAddress,
213
+		))
214
+		if ep.ID() != "" {
215
+			parentEndpoints = append(parentEndpoints, ep.ID())
216
+		}
217
+	}
218
+
219
+	linkOptions := options.Generic{
220
+		netlabel.GenericData: options.Generic{
221
+			"ParentEndpoints": parentEndpoints,
222
+			"ChildEndpoints":  childEndpoints,
223
+		},
224
+	}
225
+
226
+	sboxOptions = append(sboxOptions, libnetwork.OptionGeneric(linkOptions))
227
+	return sboxOptions, nil
228
+}
229
+
230
+func (daemon *Daemon) updateNetworkSettings(container *container.Container, n libnetwork.Network) error {
231
+	if container.NetworkSettings == nil {
232
+		container.NetworkSettings = &network.Settings{Networks: make(map[string]*networktypes.EndpointSettings)}
233
+	}
234
+
235
+	if !container.HostConfig.NetworkMode.IsHost() && containertypes.NetworkMode(n.Type()).IsHost() {
236
+		return runconfig.ErrConflictHostNetwork
237
+	}
238
+
239
+	for s := range container.NetworkSettings.Networks {
240
+		sn, err := daemon.FindNetwork(s)
241
+		if err != nil {
242
+			continue
243
+		}
244
+
245
+		if sn.Name() == n.Name() {
246
+			// Avoid duplicate config
247
+			return nil
248
+		}
249
+		if !containertypes.NetworkMode(sn.Type()).IsPrivate() ||
250
+			!containertypes.NetworkMode(n.Type()).IsPrivate() {
251
+			return runconfig.ErrConflictSharedNetwork
252
+		}
253
+		if containertypes.NetworkMode(sn.Name()).IsNone() ||
254
+			containertypes.NetworkMode(n.Name()).IsNone() {
255
+			return runconfig.ErrConflictNoNetwork
256
+		}
257
+	}
258
+
259
+	if _, ok := container.NetworkSettings.Networks[n.Name()]; !ok {
260
+		container.NetworkSettings.Networks[n.Name()] = new(networktypes.EndpointSettings)
261
+	}
262
+
263
+	return nil
264
+}
265
+
266
+func (daemon *Daemon) updateEndpointNetworkSettings(container *container.Container, n libnetwork.Network, ep libnetwork.Endpoint) error {
267
+	if err := container.BuildEndpointInfo(n, ep); err != nil {
268
+		return err
269
+	}
270
+
271
+	if container.HostConfig.NetworkMode == runconfig.DefaultDaemonNetworkMode() {
272
+		container.NetworkSettings.Bridge = daemon.configStore.bridgeConfig.Iface
273
+	}
274
+
275
+	return nil
276
+}
277
+
278
+// UpdateNetwork is used to update the container's network (e.g. when linked containers
279
+// get removed/unlinked).
280
+func (daemon *Daemon) updateNetwork(container *container.Container) error {
281
+	ctrl := daemon.netController
282
+	sid := container.NetworkSettings.SandboxID
283
+
284
+	sb, err := ctrl.SandboxByID(sid)
285
+	if err != nil {
286
+		return fmt.Errorf("error locating sandbox id %s: %v", sid, err)
287
+	}
288
+
289
+	// Find if container is connected to the default bridge network
290
+	var n libnetwork.Network
291
+	for name := range container.NetworkSettings.Networks {
292
+		sn, err := daemon.FindNetwork(name)
293
+		if err != nil {
294
+			continue
295
+		}
296
+		if sn.Name() == runconfig.DefaultDaemonNetworkMode().NetworkName() {
297
+			n = sn
298
+			break
299
+		}
300
+	}
301
+
302
+	if n == nil {
303
+		// Not connected to the default bridge network; Nothing to do
304
+		return nil
305
+	}
306
+
307
+	options, err := daemon.buildSandboxOptions(container, n)
308
+	if err != nil {
309
+		return fmt.Errorf("Update network failed: %v", err)
310
+	}
311
+
312
+	if err := sb.Refresh(options...); err != nil {
313
+		return fmt.Errorf("Update network failed: Failure in refresh sandbox %s: %v", sid, err)
314
+	}
315
+
316
+	return nil
317
+}
318
+
319
+// updateContainerNetworkSettings update the network settings
320
+func (daemon *Daemon) updateContainerNetworkSettings(container *container.Container, endpointsConfig map[string]*networktypes.EndpointSettings) error {
321
+	var (
322
+		n   libnetwork.Network
323
+		err error
324
+	)
325
+
326
+	// TODO Windows: Remove this once TP4 builds are not supported
327
+	// Windows TP4 build don't support libnetwork and in that case
328
+	// daemon.netController will be nil
329
+	if daemon.netController == nil {
330
+		return nil
331
+	}
332
+
333
+	mode := container.HostConfig.NetworkMode
334
+	if container.Config.NetworkDisabled || mode.IsContainer() {
335
+		return nil
336
+	}
337
+
338
+	networkName := mode.NetworkName()
339
+	if mode.IsDefault() {
340
+		networkName = daemon.netController.Config().Daemon.DefaultNetwork
341
+	}
342
+	if mode.IsUserDefined() {
343
+		n, err = daemon.FindNetwork(networkName)
344
+		if err != nil {
345
+			return err
346
+		}
347
+		networkName = n.Name()
348
+	}
349
+	if container.NetworkSettings == nil {
350
+		container.NetworkSettings = &network.Settings{}
351
+	}
352
+	if len(endpointsConfig) > 0 {
353
+		container.NetworkSettings.Networks = endpointsConfig
354
+	}
355
+	if container.NetworkSettings.Networks == nil {
356
+		container.NetworkSettings.Networks = make(map[string]*networktypes.EndpointSettings)
357
+		container.NetworkSettings.Networks[networkName] = new(networktypes.EndpointSettings)
358
+	}
359
+	if !mode.IsUserDefined() {
360
+		return nil
361
+	}
362
+	// Make sure to internally store the per network endpoint config by network name
363
+	if _, ok := container.NetworkSettings.Networks[networkName]; ok {
364
+		return nil
365
+	}
366
+	if nwConfig, ok := container.NetworkSettings.Networks[n.ID()]; ok {
367
+		container.NetworkSettings.Networks[networkName] = nwConfig
368
+		delete(container.NetworkSettings.Networks, n.ID())
369
+		return nil
370
+	}
371
+
372
+	return nil
373
+}
374
+
375
+func (daemon *Daemon) allocateNetwork(container *container.Container) error {
376
+	controller := daemon.netController
377
+
378
+	if daemon.netController == nil {
379
+		return nil
380
+	}
381
+
382
+	// Cleanup any stale sandbox left over due to ungraceful daemon shutdown
383
+	if err := controller.SandboxDestroy(container.ID); err != nil {
384
+		logrus.Errorf("failed to cleanup up stale network sandbox for container %s", container.ID)
385
+	}
386
+
387
+	updateSettings := false
388
+	if len(container.NetworkSettings.Networks) == 0 {
389
+		if container.Config.NetworkDisabled || container.HostConfig.NetworkMode.IsContainer() {
390
+			return nil
391
+		}
392
+
393
+		err := daemon.updateContainerNetworkSettings(container, nil)
394
+		if err != nil {
395
+			return err
396
+		}
397
+		updateSettings = true
398
+	}
399
+
400
+	for n, nConf := range container.NetworkSettings.Networks {
401
+		if err := daemon.connectToNetwork(container, n, nConf, updateSettings); err != nil {
402
+			return err
403
+		}
404
+	}
405
+
406
+	return container.WriteHostConfig()
407
+}
408
+
409
+func (daemon *Daemon) getNetworkSandbox(container *container.Container) libnetwork.Sandbox {
410
+	var sb libnetwork.Sandbox
411
+	daemon.netController.WalkSandboxes(func(s libnetwork.Sandbox) bool {
412
+		if s.ContainerID() == container.ID {
413
+			sb = s
414
+			return true
415
+		}
416
+		return false
417
+	})
418
+	return sb
419
+}
420
+
421
+// hasUserDefinedIPAddress returns whether the passed endpoint configuration contains IP address configuration
422
+func hasUserDefinedIPAddress(epConfig *networktypes.EndpointSettings) bool {
423
+	return epConfig != nil && epConfig.IPAMConfig != nil && (len(epConfig.IPAMConfig.IPv4Address) > 0 || len(epConfig.IPAMConfig.IPv6Address) > 0)
424
+}
425
+
426
+// User specified ip address is acceptable only for networks with user specified subnets.
427
+func validateNetworkingConfig(n libnetwork.Network, epConfig *networktypes.EndpointSettings) error {
428
+	if n == nil || epConfig == nil {
429
+		return nil
430
+	}
431
+	if !hasUserDefinedIPAddress(epConfig) {
432
+		return nil
433
+	}
434
+	_, _, nwIPv4Configs, nwIPv6Configs := n.Info().IpamConfig()
435
+	for _, s := range []struct {
436
+		ipConfigured  bool
437
+		subnetConfigs []*libnetwork.IpamConf
438
+	}{
439
+		{
440
+			ipConfigured:  len(epConfig.IPAMConfig.IPv4Address) > 0,
441
+			subnetConfigs: nwIPv4Configs,
442
+		},
443
+		{
444
+			ipConfigured:  len(epConfig.IPAMConfig.IPv6Address) > 0,
445
+			subnetConfigs: nwIPv6Configs,
446
+		},
447
+	} {
448
+		if s.ipConfigured {
449
+			foundSubnet := false
450
+			for _, cfg := range s.subnetConfigs {
451
+				if len(cfg.PreferredPool) > 0 {
452
+					foundSubnet = true
453
+					break
454
+				}
455
+			}
456
+			if !foundSubnet {
457
+				return runconfig.ErrUnsupportedNetworkNoSubnetAndIP
458
+			}
459
+		}
460
+	}
461
+
462
+	return nil
463
+}
464
+
465
+// cleanOperationalData resets the operational data from the passed endpoint settings
466
+func cleanOperationalData(es *networktypes.EndpointSettings) {
467
+	es.EndpointID = ""
468
+	es.Gateway = ""
469
+	es.IPAddress = ""
470
+	es.IPPrefixLen = 0
471
+	es.IPv6Gateway = ""
472
+	es.GlobalIPv6Address = ""
473
+	es.GlobalIPv6PrefixLen = 0
474
+	es.MacAddress = ""
475
+}
476
+
477
+func (daemon *Daemon) updateNetworkConfig(container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings, updateSettings bool) (libnetwork.Network, error) {
478
+	if container.HostConfig.NetworkMode.IsContainer() {
479
+		return nil, runconfig.ErrConflictSharedNetwork
480
+	}
481
+
482
+	if containertypes.NetworkMode(idOrName).IsBridge() &&
483
+		daemon.configStore.DisableBridge {
484
+		container.Config.NetworkDisabled = true
485
+		return nil, nil
486
+	}
487
+
488
+	if !containertypes.NetworkMode(idOrName).IsUserDefined() {
489
+		if hasUserDefinedIPAddress(endpointConfig) {
490
+			return nil, runconfig.ErrUnsupportedNetworkAndIP
491
+		}
492
+		if endpointConfig != nil && len(endpointConfig.Aliases) > 0 {
493
+			return nil, runconfig.ErrUnsupportedNetworkAndAlias
494
+		}
495
+	}
496
+
497
+	n, err := daemon.FindNetwork(idOrName)
498
+	if err != nil {
499
+		return nil, err
500
+	}
501
+
502
+	if err := validateNetworkingConfig(n, endpointConfig); err != nil {
503
+		return nil, err
504
+	}
505
+
506
+	if updateSettings {
507
+		if err := daemon.updateNetworkSettings(container, n); err != nil {
508
+			return nil, err
509
+		}
510
+	}
511
+	return n, nil
512
+}
513
+
514
+func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings, updateSettings bool) (err error) {
515
+	// TODO Windows: Remove this once TP4 builds are not supported
516
+	// Windows TP4 build don't support libnetwork and in that case
517
+	// daemon.netController will be nil
518
+	if daemon.netController == nil {
519
+		return nil
520
+	}
521
+
522
+	n, err := daemon.updateNetworkConfig(container, idOrName, endpointConfig, updateSettings)
523
+	if err != nil {
524
+		return err
525
+	}
526
+	if n == nil {
527
+		return nil
528
+	}
529
+
530
+	controller := daemon.netController
531
+
532
+	sb := daemon.getNetworkSandbox(container)
533
+	createOptions, err := container.BuildCreateEndpointOptions(n, endpointConfig, sb)
534
+	if err != nil {
535
+		return err
536
+	}
537
+
538
+	endpointName := strings.TrimPrefix(container.Name, "/")
539
+	ep, err := n.CreateEndpoint(endpointName, createOptions...)
540
+	if err != nil {
541
+		return err
542
+	}
543
+	defer func() {
544
+		if err != nil {
545
+			if e := ep.Delete(false); e != nil {
546
+				logrus.Warnf("Could not rollback container connection to network %s", idOrName)
547
+			}
548
+		}
549
+	}()
550
+
551
+	if endpointConfig != nil {
552
+		container.NetworkSettings.Networks[n.Name()] = endpointConfig
553
+	}
554
+
555
+	if err := daemon.updateEndpointNetworkSettings(container, n, ep); err != nil {
556
+		return err
557
+	}
558
+
559
+	if sb == nil {
560
+		options, err := daemon.buildSandboxOptions(container, n)
561
+		if err != nil {
562
+			return err
563
+		}
564
+		sb, err = controller.NewSandbox(container.ID, options...)
565
+		if err != nil {
566
+			return err
567
+		}
568
+
569
+		container.UpdateSandboxNetworkSettings(sb)
570
+	}
571
+
572
+	joinOptions, err := container.BuildJoinOptions(n)
573
+	if err != nil {
574
+		return err
575
+	}
576
+
577
+	if err := ep.Join(sb, joinOptions...); err != nil {
578
+		return err
579
+	}
580
+
581
+	if err := container.UpdateJoinInfo(n, ep); err != nil {
582
+		return fmt.Errorf("Updating join info failed: %v", err)
583
+	}
584
+
585
+	daemon.LogNetworkEventWithAttributes(n, "connect", map[string]string{"container": container.ID})
586
+	return nil
587
+}
588
+
589
+// ForceEndpointDelete deletes an endpoing from a network forcefully
590
+func (daemon *Daemon) ForceEndpointDelete(name string, n libnetwork.Network) error {
591
+	ep, err := n.EndpointByName(name)
592
+	if err != nil {
593
+		return err
594
+	}
595
+	return ep.Delete(true)
596
+}
597
+
598
+func disconnectFromNetwork(container *container.Container, n libnetwork.Network, force bool) error {
599
+	var (
600
+		ep   libnetwork.Endpoint
601
+		sbox libnetwork.Sandbox
602
+	)
603
+
604
+	s := func(current libnetwork.Endpoint) bool {
605
+		epInfo := current.Info()
606
+		if epInfo == nil {
607
+			return false
608
+		}
609
+		if sb := epInfo.Sandbox(); sb != nil {
610
+			if sb.ContainerID() == container.ID {
611
+				ep = current
612
+				sbox = sb
613
+				return true
614
+			}
615
+		}
616
+		return false
617
+	}
618
+	n.WalkEndpoints(s)
619
+
620
+	if ep == nil && force {
621
+		epName := strings.TrimPrefix(container.Name, "/")
622
+		ep, err := n.EndpointByName(epName)
623
+		if err != nil {
624
+			return err
625
+		}
626
+		return ep.Delete(force)
627
+	}
628
+
629
+	if ep == nil {
630
+		return fmt.Errorf("container %s is not connected to the network", container.ID)
631
+	}
632
+
633
+	if err := ep.Leave(sbox); err != nil {
634
+		return fmt.Errorf("container %s failed to leave network %s: %v", container.ID, n.Name(), err)
635
+	}
636
+
637
+	if err := ep.Delete(false); err != nil {
638
+		return fmt.Errorf("endpoint delete failed for container %s on network %s: %v", container.ID, n.Name(), err)
639
+	}
640
+
641
+	delete(container.NetworkSettings.Networks, n.Name())
642
+	return nil
643
+}
644
+
645
+func (daemon *Daemon) initializeNetworking(container *container.Container) error {
646
+	var err error
647
+
648
+	// TODO Windows: Remove this once TP4 builds are not supported
649
+	// Windows TP4 build don't support libnetwork and in that case
650
+	// daemon.netController will be nil
651
+	if daemon.netController == nil {
652
+		return nil
653
+	}
654
+
655
+	if container.HostConfig.NetworkMode.IsContainer() {
656
+		// we need to get the hosts files from the container to join
657
+		nc, err := daemon.getNetworkedContainer(container.ID, container.HostConfig.NetworkMode.ConnectedContainer())
658
+		if err != nil {
659
+			return err
660
+		}
661
+		container.HostnamePath = nc.HostnamePath
662
+		container.HostsPath = nc.HostsPath
663
+		container.ResolvConfPath = nc.ResolvConfPath
664
+		container.Config.Hostname = nc.Config.Hostname
665
+		container.Config.Domainname = nc.Config.Domainname
666
+		return nil
667
+	}
668
+
669
+	if container.HostConfig.NetworkMode.IsHost() {
670
+		container.Config.Hostname, err = os.Hostname()
671
+		if err != nil {
672
+			return err
673
+		}
674
+
675
+		parts := strings.SplitN(container.Config.Hostname, ".", 2)
676
+		if len(parts) > 1 {
677
+			container.Config.Hostname = parts[0]
678
+			container.Config.Domainname = parts[1]
679
+		}
680
+
681
+	}
682
+
683
+	if err := daemon.allocateNetwork(container); err != nil {
684
+		return err
685
+	}
686
+
687
+	return container.BuildHostnameFile()
688
+}
689
+
690
+func (daemon *Daemon) getNetworkedContainer(containerID, connectedContainerID string) (*container.Container, error) {
691
+	nc, err := daemon.GetContainer(connectedContainerID)
692
+	if err != nil {
693
+		return nil, err
694
+	}
695
+	if containerID == nc.ID {
696
+		return nil, fmt.Errorf("cannot join own network")
697
+	}
698
+	if !nc.IsRunning() {
699
+		err := fmt.Errorf("cannot join network of a non running container: %s", connectedContainerID)
700
+		return nil, derr.NewRequestConflictError(err)
701
+	}
702
+	if nc.IsRestarting() {
703
+		return nil, errContainerIsRestarting(connectedContainerID)
704
+	}
705
+	return nc, nil
706
+}
707
+
708
+func (daemon *Daemon) releaseNetwork(container *container.Container) {
709
+	if container.HostConfig.NetworkMode.IsContainer() || container.Config.NetworkDisabled {
710
+		return
711
+	}
712
+
713
+	sid := container.NetworkSettings.SandboxID
714
+	settings := container.NetworkSettings.Networks
715
+	container.NetworkSettings.Ports = nil
716
+
717
+	if sid == "" || len(settings) == 0 {
718
+		return
719
+	}
720
+
721
+	var networks []libnetwork.Network
722
+	for n, epSettings := range settings {
723
+		if nw, err := daemon.FindNetwork(n); err == nil {
724
+			networks = append(networks, nw)
725
+		}
726
+		cleanOperationalData(epSettings)
727
+	}
728
+
729
+	sb, err := daemon.netController.SandboxByID(sid)
730
+	if err != nil {
731
+		logrus.Errorf("error locating sandbox id %s: %v", sid, err)
732
+		return
733
+	}
734
+
735
+	if err := sb.Delete(); err != nil {
736
+		logrus.Errorf("Error deleting sandbox id %s for container %s: %v", sid, container.ID, err)
737
+	}
738
+
739
+	attributes := map[string]string{
740
+		"container": container.ID,
741
+	}
742
+	for _, nw := range networks {
743
+		daemon.LogNetworkEventWithAttributes(nw, "disconnect", attributes)
744
+	}
745
+}
... ...
@@ -4,9 +4,7 @@ package daemon
4 4
 
5 5
 import (
6 6
 	"fmt"
7
-	"net"
8 7
 	"os"
9
-	"path"
10 8
 	"path/filepath"
11 9
 	"strconv"
12 10
 	"strings"
... ...
@@ -17,8 +15,6 @@ import (
17 17
 	"github.com/docker/docker/container"
18 18
 	"github.com/docker/docker/daemon/execdriver"
19 19
 	"github.com/docker/docker/daemon/links"
20
-	"github.com/docker/docker/daemon/network"
21
-	"github.com/docker/docker/errors"
22 20
 	"github.com/docker/docker/pkg/fileutils"
23 21
 	"github.com/docker/docker/pkg/idtools"
24 22
 	"github.com/docker/docker/pkg/mount"
... ...
@@ -26,12 +22,8 @@ import (
26 26
 	"github.com/docker/docker/runconfig"
27 27
 	containertypes "github.com/docker/engine-api/types/container"
28 28
 	networktypes "github.com/docker/engine-api/types/network"
29
-	"github.com/docker/go-connections/nat"
30 29
 	"github.com/docker/go-units"
31 30
 	"github.com/docker/libnetwork"
32
-	"github.com/docker/libnetwork/netlabel"
33
-	"github.com/docker/libnetwork/options"
34
-	"github.com/docker/libnetwork/types"
35 31
 	"github.com/opencontainers/runc/libcontainer/configs"
36 32
 	"github.com/opencontainers/runc/libcontainer/devices"
37 33
 	"github.com/opencontainers/runc/libcontainer/label"
... ...
@@ -41,7 +33,7 @@ func (daemon *Daemon) setupLinkedContainers(container *container.Container) ([]s
41 41
 	var env []string
42 42
 	children := daemon.children(container)
43 43
 
44
-	bridgeSettings := container.NetworkSettings.Networks["bridge"]
44
+	bridgeSettings := container.NetworkSettings.Networks[runconfig.DefaultDaemonNetworkMode().NetworkName()]
45 45
 	if bridgeSettings == nil {
46 46
 		return nil, nil
47 47
 	}
... ...
@@ -51,7 +43,7 @@ func (daemon *Daemon) setupLinkedContainers(container *container.Container) ([]s
51 51
 			return nil, fmt.Errorf("Cannot link to a non running container: %s AS %s", child.Name, linkAlias)
52 52
 		}
53 53
 
54
-		childBridgeSettings := child.NetworkSettings.Networks["bridge"]
54
+		childBridgeSettings := child.NetworkSettings.Networks[runconfig.DefaultDaemonNetworkMode().NetworkName()]
55 55
 		if childBridgeSettings == nil {
56 56
 			return nil, fmt.Errorf("container %s not attached to default bridge network", child.ID)
57 57
 		}
... ...
@@ -316,477 +308,6 @@ func (daemon *Daemon) getSize(container *container.Container) (int64, int64) {
316 316
 	return sizeRw, sizeRootfs
317 317
 }
318 318
 
319
-func (daemon *Daemon) buildSandboxOptions(container *container.Container, n libnetwork.Network) ([]libnetwork.SandboxOption, error) {
320
-	var (
321
-		sboxOptions []libnetwork.SandboxOption
322
-		err         error
323
-		dns         []string
324
-		dnsSearch   []string
325
-		dnsOptions  []string
326
-		bindings    = make(nat.PortMap)
327
-		pbList      []types.PortBinding
328
-		exposeList  []types.TransportPort
329
-	)
330
-
331
-	sboxOptions = append(sboxOptions, libnetwork.OptionHostname(container.Config.Hostname),
332
-		libnetwork.OptionDomainname(container.Config.Domainname))
333
-
334
-	if container.HostConfig.NetworkMode.IsHost() {
335
-		sboxOptions = append(sboxOptions, libnetwork.OptionUseDefaultSandbox())
336
-		sboxOptions = append(sboxOptions, libnetwork.OptionOriginHostsPath("/etc/hosts"))
337
-		sboxOptions = append(sboxOptions, libnetwork.OptionOriginResolvConfPath("/etc/resolv.conf"))
338
-	} else if daemon.execDriver.SupportsHooks() {
339
-		// OptionUseExternalKey is mandatory for userns support.
340
-		// But optional for non-userns support
341
-		sboxOptions = append(sboxOptions, libnetwork.OptionUseExternalKey())
342
-	}
343
-
344
-	container.HostsPath, err = container.GetRootResourcePath("hosts")
345
-	if err != nil {
346
-		return nil, err
347
-	}
348
-	sboxOptions = append(sboxOptions, libnetwork.OptionHostsPath(container.HostsPath))
349
-
350
-	container.ResolvConfPath, err = container.GetRootResourcePath("resolv.conf")
351
-	if err != nil {
352
-		return nil, err
353
-	}
354
-	sboxOptions = append(sboxOptions, libnetwork.OptionResolvConfPath(container.ResolvConfPath))
355
-
356
-	if len(container.HostConfig.DNS) > 0 {
357
-		dns = container.HostConfig.DNS
358
-	} else if len(daemon.configStore.DNS) > 0 {
359
-		dns = daemon.configStore.DNS
360
-	}
361
-
362
-	for _, d := range dns {
363
-		sboxOptions = append(sboxOptions, libnetwork.OptionDNS(d))
364
-	}
365
-
366
-	if len(container.HostConfig.DNSSearch) > 0 {
367
-		dnsSearch = container.HostConfig.DNSSearch
368
-	} else if len(daemon.configStore.DNSSearch) > 0 {
369
-		dnsSearch = daemon.configStore.DNSSearch
370
-	}
371
-
372
-	for _, ds := range dnsSearch {
373
-		sboxOptions = append(sboxOptions, libnetwork.OptionDNSSearch(ds))
374
-	}
375
-
376
-	if len(container.HostConfig.DNSOptions) > 0 {
377
-		dnsOptions = container.HostConfig.DNSOptions
378
-	} else if len(daemon.configStore.DNSOptions) > 0 {
379
-		dnsOptions = daemon.configStore.DNSOptions
380
-	}
381
-
382
-	for _, ds := range dnsOptions {
383
-		sboxOptions = append(sboxOptions, libnetwork.OptionDNSOptions(ds))
384
-	}
385
-
386
-	if container.NetworkSettings.SecondaryIPAddresses != nil {
387
-		name := container.Config.Hostname
388
-		if container.Config.Domainname != "" {
389
-			name = name + "." + container.Config.Domainname
390
-		}
391
-
392
-		for _, a := range container.NetworkSettings.SecondaryIPAddresses {
393
-			sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(name, a.Addr))
394
-		}
395
-	}
396
-
397
-	for _, extraHost := range container.HostConfig.ExtraHosts {
398
-		// allow IPv6 addresses in extra hosts; only split on first ":"
399
-		parts := strings.SplitN(extraHost, ":", 2)
400
-		sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(parts[0], parts[1]))
401
-	}
402
-
403
-	if container.HostConfig.PortBindings != nil {
404
-		for p, b := range container.HostConfig.PortBindings {
405
-			bindings[p] = []nat.PortBinding{}
406
-			for _, bb := range b {
407
-				bindings[p] = append(bindings[p], nat.PortBinding{
408
-					HostIP:   bb.HostIP,
409
-					HostPort: bb.HostPort,
410
-				})
411
-			}
412
-		}
413
-	}
414
-
415
-	portSpecs := container.Config.ExposedPorts
416
-	ports := make([]nat.Port, len(portSpecs))
417
-	var i int
418
-	for p := range portSpecs {
419
-		ports[i] = p
420
-		i++
421
-	}
422
-	nat.SortPortMap(ports, bindings)
423
-	for _, port := range ports {
424
-		expose := types.TransportPort{}
425
-		expose.Proto = types.ParseProtocol(port.Proto())
426
-		expose.Port = uint16(port.Int())
427
-		exposeList = append(exposeList, expose)
428
-
429
-		pb := types.PortBinding{Port: expose.Port, Proto: expose.Proto}
430
-		binding := bindings[port]
431
-		for i := 0; i < len(binding); i++ {
432
-			pbCopy := pb.GetCopy()
433
-			newP, err := nat.NewPort(nat.SplitProtoPort(binding[i].HostPort))
434
-			var portStart, portEnd int
435
-			if err == nil {
436
-				portStart, portEnd, err = newP.Range()
437
-			}
438
-			if err != nil {
439
-				return nil, fmt.Errorf("Error parsing HostPort value(%s):%v", binding[i].HostPort, err)
440
-			}
441
-			pbCopy.HostPort = uint16(portStart)
442
-			pbCopy.HostPortEnd = uint16(portEnd)
443
-			pbCopy.HostIP = net.ParseIP(binding[i].HostIP)
444
-			pbList = append(pbList, pbCopy)
445
-		}
446
-
447
-		if container.HostConfig.PublishAllPorts && len(binding) == 0 {
448
-			pbList = append(pbList, pb)
449
-		}
450
-	}
451
-
452
-	sboxOptions = append(sboxOptions,
453
-		libnetwork.OptionPortMapping(pbList),
454
-		libnetwork.OptionExposedPorts(exposeList))
455
-
456
-	// Link feature is supported only for the default bridge network.
457
-	// return if this call to build join options is not for default bridge network
458
-	if n.Name() != "bridge" {
459
-		return sboxOptions, nil
460
-	}
461
-
462
-	ep, _ := container.GetEndpointInNetwork(n)
463
-	if ep == nil {
464
-		return sboxOptions, nil
465
-	}
466
-
467
-	var childEndpoints, parentEndpoints []string
468
-
469
-	children := daemon.children(container)
470
-	for linkAlias, child := range children {
471
-		if !isLinkable(child) {
472
-			return nil, fmt.Errorf("Cannot link to %s, as it does not belong to the default network", child.Name)
473
-		}
474
-		_, alias := path.Split(linkAlias)
475
-		// allow access to the linked container via the alias, real name, and container hostname
476
-		aliasList := alias + " " + child.Config.Hostname
477
-		// only add the name if alias isn't equal to the name
478
-		if alias != child.Name[1:] {
479
-			aliasList = aliasList + " " + child.Name[1:]
480
-		}
481
-		sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(aliasList, child.NetworkSettings.Networks["bridge"].IPAddress))
482
-		cEndpoint, _ := child.GetEndpointInNetwork(n)
483
-		if cEndpoint != nil && cEndpoint.ID() != "" {
484
-			childEndpoints = append(childEndpoints, cEndpoint.ID())
485
-		}
486
-	}
487
-
488
-	bridgeSettings := container.NetworkSettings.Networks["bridge"]
489
-	for alias, parent := range daemon.parents(container) {
490
-		if daemon.configStore.DisableBridge || !container.HostConfig.NetworkMode.IsPrivate() {
491
-			continue
492
-		}
493
-
494
-		_, alias = path.Split(alias)
495
-		logrus.Debugf("Update /etc/hosts of %s for alias %s with ip %s", parent.ID, alias, bridgeSettings.IPAddress)
496
-		sboxOptions = append(sboxOptions, libnetwork.OptionParentUpdate(
497
-			parent.ID,
498
-			alias,
499
-			bridgeSettings.IPAddress,
500
-		))
501
-		if ep.ID() != "" {
502
-			parentEndpoints = append(parentEndpoints, ep.ID())
503
-		}
504
-	}
505
-
506
-	linkOptions := options.Generic{
507
-		netlabel.GenericData: options.Generic{
508
-			"ParentEndpoints": parentEndpoints,
509
-			"ChildEndpoints":  childEndpoints,
510
-		},
511
-	}
512
-
513
-	sboxOptions = append(sboxOptions, libnetwork.OptionGeneric(linkOptions))
514
-	return sboxOptions, nil
515
-}
516
-
517
-func (daemon *Daemon) updateNetworkSettings(container *container.Container, n libnetwork.Network) error {
518
-	if container.NetworkSettings == nil {
519
-		container.NetworkSettings = &network.Settings{Networks: make(map[string]*networktypes.EndpointSettings)}
520
-	}
521
-
522
-	if !container.HostConfig.NetworkMode.IsHost() && containertypes.NetworkMode(n.Type()).IsHost() {
523
-		return runconfig.ErrConflictHostNetwork
524
-	}
525
-
526
-	for s := range container.NetworkSettings.Networks {
527
-		sn, err := daemon.FindNetwork(s)
528
-		if err != nil {
529
-			continue
530
-		}
531
-
532
-		if sn.Name() == n.Name() {
533
-			// Avoid duplicate config
534
-			return nil
535
-		}
536
-		if !containertypes.NetworkMode(sn.Type()).IsPrivate() ||
537
-			!containertypes.NetworkMode(n.Type()).IsPrivate() {
538
-			return runconfig.ErrConflictSharedNetwork
539
-		}
540
-		if containertypes.NetworkMode(sn.Name()).IsNone() ||
541
-			containertypes.NetworkMode(n.Name()).IsNone() {
542
-			return runconfig.ErrConflictNoNetwork
543
-		}
544
-	}
545
-
546
-	if _, ok := container.NetworkSettings.Networks[n.Name()]; !ok {
547
-		container.NetworkSettings.Networks[n.Name()] = new(networktypes.EndpointSettings)
548
-	}
549
-
550
-	return nil
551
-}
552
-
553
-func (daemon *Daemon) updateEndpointNetworkSettings(container *container.Container, n libnetwork.Network, ep libnetwork.Endpoint) error {
554
-	if err := container.BuildEndpointInfo(n, ep); err != nil {
555
-		return err
556
-	}
557
-
558
-	if container.HostConfig.NetworkMode == containertypes.NetworkMode("bridge") {
559
-		container.NetworkSettings.Bridge = daemon.configStore.bridgeConfig.Iface
560
-	}
561
-
562
-	return nil
563
-}
564
-
565
-// UpdateNetwork is used to update the container's network (e.g. when linked containers
566
-// get removed/unlinked).
567
-func (daemon *Daemon) updateNetwork(container *container.Container) error {
568
-	ctrl := daemon.netController
569
-	sid := container.NetworkSettings.SandboxID
570
-
571
-	sb, err := ctrl.SandboxByID(sid)
572
-	if err != nil {
573
-		return fmt.Errorf("error locating sandbox id %s: %v", sid, err)
574
-	}
575
-
576
-	// Find if container is connected to the default bridge network
577
-	var n libnetwork.Network
578
-	for name := range container.NetworkSettings.Networks {
579
-		sn, err := daemon.FindNetwork(name)
580
-		if err != nil {
581
-			continue
582
-		}
583
-		if sn.Name() == "bridge" {
584
-			n = sn
585
-			break
586
-		}
587
-	}
588
-
589
-	if n == nil {
590
-		// Not connected to the default bridge network; Nothing to do
591
-		return nil
592
-	}
593
-
594
-	options, err := daemon.buildSandboxOptions(container, n)
595
-	if err != nil {
596
-		return fmt.Errorf("Update network failed: %v", err)
597
-	}
598
-
599
-	if err := sb.Refresh(options...); err != nil {
600
-		return fmt.Errorf("Update network failed: Failure in refresh sandbox %s: %v", sid, err)
601
-	}
602
-
603
-	return nil
604
-}
605
-
606
-// updateContainerNetworkSettings update the network settings
607
-func (daemon *Daemon) updateContainerNetworkSettings(container *container.Container, endpointsConfig map[string]*networktypes.EndpointSettings) error {
608
-	var (
609
-		n   libnetwork.Network
610
-		err error
611
-	)
612
-
613
-	mode := container.HostConfig.NetworkMode
614
-	if container.Config.NetworkDisabled || mode.IsContainer() {
615
-		return nil
616
-	}
617
-
618
-	networkName := mode.NetworkName()
619
-	if mode.IsDefault() {
620
-		networkName = daemon.netController.Config().Daemon.DefaultNetwork
621
-	}
622
-	if mode.IsUserDefined() {
623
-		n, err = daemon.FindNetwork(networkName)
624
-		if err != nil {
625
-			return err
626
-		}
627
-		networkName = n.Name()
628
-	}
629
-	if container.NetworkSettings == nil {
630
-		container.NetworkSettings = &network.Settings{}
631
-	}
632
-	if len(endpointsConfig) > 0 {
633
-		container.NetworkSettings.Networks = endpointsConfig
634
-	}
635
-	if container.NetworkSettings.Networks == nil {
636
-		container.NetworkSettings.Networks = make(map[string]*networktypes.EndpointSettings)
637
-		container.NetworkSettings.Networks[networkName] = new(networktypes.EndpointSettings)
638
-	}
639
-	if !mode.IsUserDefined() {
640
-		return nil
641
-	}
642
-	// Make sure to internally store the per network endpoint config by network name
643
-	if _, ok := container.NetworkSettings.Networks[networkName]; ok {
644
-		return nil
645
-	}
646
-	if nwConfig, ok := container.NetworkSettings.Networks[n.ID()]; ok {
647
-		container.NetworkSettings.Networks[networkName] = nwConfig
648
-		delete(container.NetworkSettings.Networks, n.ID())
649
-		return nil
650
-	}
651
-
652
-	return nil
653
-}
654
-
655
-func (daemon *Daemon) allocateNetwork(container *container.Container) error {
656
-	controller := daemon.netController
657
-
658
-	// Cleanup any stale sandbox left over due to ungraceful daemon shutdown
659
-	if err := controller.SandboxDestroy(container.ID); err != nil {
660
-		logrus.Errorf("failed to cleanup up stale network sandbox for container %s", container.ID)
661
-	}
662
-
663
-	updateSettings := false
664
-	if len(container.NetworkSettings.Networks) == 0 {
665
-		if container.Config.NetworkDisabled || container.HostConfig.NetworkMode.IsContainer() {
666
-			return nil
667
-		}
668
-
669
-		err := daemon.updateContainerNetworkSettings(container, nil)
670
-		if err != nil {
671
-			return err
672
-		}
673
-		updateSettings = true
674
-	}
675
-
676
-	for n, nConf := range container.NetworkSettings.Networks {
677
-		if err := daemon.connectToNetwork(container, n, nConf, updateSettings); err != nil {
678
-			return err
679
-		}
680
-	}
681
-
682
-	return container.WriteHostConfig()
683
-}
684
-
685
-func (daemon *Daemon) getNetworkSandbox(container *container.Container) libnetwork.Sandbox {
686
-	var sb libnetwork.Sandbox
687
-	daemon.netController.WalkSandboxes(func(s libnetwork.Sandbox) bool {
688
-		if s.ContainerID() == container.ID {
689
-			sb = s
690
-			return true
691
-		}
692
-		return false
693
-	})
694
-	return sb
695
-}
696
-
697
-// hasUserDefinedIPAddress returns whether the passed endpoint configuration contains IP address configuration
698
-func hasUserDefinedIPAddress(epConfig *networktypes.EndpointSettings) bool {
699
-	return epConfig != nil && epConfig.IPAMConfig != nil && (len(epConfig.IPAMConfig.IPv4Address) > 0 || len(epConfig.IPAMConfig.IPv6Address) > 0)
700
-}
701
-
702
-// User specified ip address is acceptable only for networks with user specified subnets.
703
-func validateNetworkingConfig(n libnetwork.Network, epConfig *networktypes.EndpointSettings) error {
704
-	if n == nil || epConfig == nil {
705
-		return nil
706
-	}
707
-	if !hasUserDefinedIPAddress(epConfig) {
708
-		return nil
709
-	}
710
-	_, _, nwIPv4Configs, nwIPv6Configs := n.Info().IpamConfig()
711
-	for _, s := range []struct {
712
-		ipConfigured  bool
713
-		subnetConfigs []*libnetwork.IpamConf
714
-	}{
715
-		{
716
-			ipConfigured:  len(epConfig.IPAMConfig.IPv4Address) > 0,
717
-			subnetConfigs: nwIPv4Configs,
718
-		},
719
-		{
720
-			ipConfigured:  len(epConfig.IPAMConfig.IPv6Address) > 0,
721
-			subnetConfigs: nwIPv6Configs,
722
-		},
723
-	} {
724
-		if s.ipConfigured {
725
-			foundSubnet := false
726
-			for _, cfg := range s.subnetConfigs {
727
-				if len(cfg.PreferredPool) > 0 {
728
-					foundSubnet = true
729
-					break
730
-				}
731
-			}
732
-			if !foundSubnet {
733
-				return runconfig.ErrUnsupportedNetworkNoSubnetAndIP
734
-			}
735
-		}
736
-	}
737
-
738
-	return nil
739
-}
740
-
741
-// cleanOperationalData resets the operational data from the passed endpoint settings
742
-func cleanOperationalData(es *networktypes.EndpointSettings) {
743
-	es.EndpointID = ""
744
-	es.Gateway = ""
745
-	es.IPAddress = ""
746
-	es.IPPrefixLen = 0
747
-	es.IPv6Gateway = ""
748
-	es.GlobalIPv6Address = ""
749
-	es.GlobalIPv6PrefixLen = 0
750
-	es.MacAddress = ""
751
-}
752
-
753
-func (daemon *Daemon) updateNetworkConfig(container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings, updateSettings bool) (libnetwork.Network, error) {
754
-	if container.HostConfig.NetworkMode.IsContainer() {
755
-		return nil, runconfig.ErrConflictSharedNetwork
756
-	}
757
-
758
-	if containertypes.NetworkMode(idOrName).IsBridge() &&
759
-		daemon.configStore.DisableBridge {
760
-		container.Config.NetworkDisabled = true
761
-		return nil, nil
762
-	}
763
-
764
-	if !containertypes.NetworkMode(idOrName).IsUserDefined() {
765
-		if hasUserDefinedIPAddress(endpointConfig) {
766
-			return nil, runconfig.ErrUnsupportedNetworkAndIP
767
-		}
768
-		if endpointConfig != nil && len(endpointConfig.Aliases) > 0 {
769
-			return nil, runconfig.ErrUnsupportedNetworkAndAlias
770
-		}
771
-	}
772
-
773
-	n, err := daemon.FindNetwork(idOrName)
774
-	if err != nil {
775
-		return nil, err
776
-	}
777
-
778
-	if err := validateNetworkingConfig(n, endpointConfig); err != nil {
779
-		return nil, err
780
-	}
781
-
782
-	if updateSettings {
783
-		if err := daemon.updateNetworkSettings(container, n); err != nil {
784
-			return nil, err
785
-		}
786
-	}
787
-	return n, nil
788
-}
789
-
790 319
 // ConnectToNetwork connects a container to a network
791 320
 func (daemon *Daemon) ConnectToNetwork(container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings) error {
792 321
 	if !container.Running {
... ...
@@ -810,83 +331,6 @@ func (daemon *Daemon) ConnectToNetwork(container *container.Container, idOrName
810 810
 	return nil
811 811
 }
812 812
 
813
-func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings, updateSettings bool) (err error) {
814
-	n, err := daemon.updateNetworkConfig(container, idOrName, endpointConfig, updateSettings)
815
-	if err != nil {
816
-		return err
817
-	}
818
-	if n == nil {
819
-		return nil
820
-	}
821
-
822
-	controller := daemon.netController
823
-
824
-	sb := daemon.getNetworkSandbox(container)
825
-	createOptions, err := container.BuildCreateEndpointOptions(n, endpointConfig, sb)
826
-	if err != nil {
827
-		return err
828
-	}
829
-
830
-	endpointName := strings.TrimPrefix(container.Name, "/")
831
-	ep, err := n.CreateEndpoint(endpointName, createOptions...)
832
-	if err != nil {
833
-		return err
834
-	}
835
-	defer func() {
836
-		if err != nil {
837
-			if e := ep.Delete(false); e != nil {
838
-				logrus.Warnf("Could not rollback container connection to network %s", idOrName)
839
-			}
840
-		}
841
-	}()
842
-
843
-	if endpointConfig != nil {
844
-		container.NetworkSettings.Networks[n.Name()] = endpointConfig
845
-	}
846
-
847
-	if err := daemon.updateEndpointNetworkSettings(container, n, ep); err != nil {
848
-		return err
849
-	}
850
-
851
-	if sb == nil {
852
-		options, err := daemon.buildSandboxOptions(container, n)
853
-		if err != nil {
854
-			return err
855
-		}
856
-		sb, err = controller.NewSandbox(container.ID, options...)
857
-		if err != nil {
858
-			return err
859
-		}
860
-
861
-		container.UpdateSandboxNetworkSettings(sb)
862
-	}
863
-
864
-	joinOptions, err := container.BuildJoinOptions(n)
865
-	if err != nil {
866
-		return err
867
-	}
868
-
869
-	if err := ep.Join(sb, joinOptions...); err != nil {
870
-		return err
871
-	}
872
-
873
-	if err := container.UpdateJoinInfo(n, ep); err != nil {
874
-		return fmt.Errorf("Updating join info failed: %v", err)
875
-	}
876
-
877
-	daemon.LogNetworkEventWithAttributes(n, "connect", map[string]string{"container": container.ID})
878
-	return nil
879
-}
880
-
881
-// ForceEndpointDelete deletes an endpoing from a network forcefully
882
-func (daemon *Daemon) ForceEndpointDelete(name string, n libnetwork.Network) error {
883
-	ep, err := n.EndpointByName(name)
884
-	if err != nil {
885
-		return err
886
-	}
887
-	return ep.Delete(true)
888
-}
889
-
890 813
 // DisconnectFromNetwork disconnects container from network n.
891 814
 func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, n libnetwork.Network, force bool) error {
892 815
 	if container.HostConfig.NetworkMode.IsHost() && containertypes.NetworkMode(n.Type()).IsHost() {
... ...
@@ -918,91 +362,6 @@ func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, n li
918 918
 	return nil
919 919
 }
920 920
 
921
-func disconnectFromNetwork(container *container.Container, n libnetwork.Network, force bool) error {
922
-	var (
923
-		ep   libnetwork.Endpoint
924
-		sbox libnetwork.Sandbox
925
-	)
926
-
927
-	s := func(current libnetwork.Endpoint) bool {
928
-		epInfo := current.Info()
929
-		if epInfo == nil {
930
-			return false
931
-		}
932
-		if sb := epInfo.Sandbox(); sb != nil {
933
-			if sb.ContainerID() == container.ID {
934
-				ep = current
935
-				sbox = sb
936
-				return true
937
-			}
938
-		}
939
-		return false
940
-	}
941
-	n.WalkEndpoints(s)
942
-
943
-	if ep == nil && force {
944
-		epName := strings.TrimPrefix(container.Name, "/")
945
-		ep, err := n.EndpointByName(epName)
946
-		if err != nil {
947
-			return err
948
-		}
949
-		return ep.Delete(force)
950
-	}
951
-
952
-	if ep == nil {
953
-		return fmt.Errorf("container %s is not connected to the network", container.ID)
954
-	}
955
-
956
-	if err := ep.Leave(sbox); err != nil {
957
-		return fmt.Errorf("container %s failed to leave network %s: %v", container.ID, n.Name(), err)
958
-	}
959
-
960
-	if err := ep.Delete(false); err != nil {
961
-		return fmt.Errorf("endpoint delete failed for container %s on network %s: %v", container.ID, n.Name(), err)
962
-	}
963
-
964
-	delete(container.NetworkSettings.Networks, n.Name())
965
-	return nil
966
-}
967
-
968
-func (daemon *Daemon) initializeNetworking(container *container.Container) error {
969
-	var err error
970
-
971
-	if container.HostConfig.NetworkMode.IsContainer() {
972
-		// we need to get the hosts files from the container to join
973
-		nc, err := daemon.getNetworkedContainer(container.ID, container.HostConfig.NetworkMode.ConnectedContainer())
974
-		if err != nil {
975
-			return err
976
-		}
977
-		container.HostnamePath = nc.HostnamePath
978
-		container.HostsPath = nc.HostsPath
979
-		container.ResolvConfPath = nc.ResolvConfPath
980
-		container.Config.Hostname = nc.Config.Hostname
981
-		container.Config.Domainname = nc.Config.Domainname
982
-		return nil
983
-	}
984
-
985
-	if container.HostConfig.NetworkMode.IsHost() {
986
-		container.Config.Hostname, err = os.Hostname()
987
-		if err != nil {
988
-			return err
989
-		}
990
-
991
-		parts := strings.SplitN(container.Config.Hostname, ".", 2)
992
-		if len(parts) > 1 {
993
-			container.Config.Hostname = parts[0]
994
-			container.Config.Domainname = parts[1]
995
-		}
996
-
997
-	}
998
-
999
-	if err := daemon.allocateNetwork(container); err != nil {
1000
-		return err
1001
-	}
1002
-
1003
-	return container.BuildHostnameFile()
1004
-}
1005
-
1006 921
 // called from the libcontainer pre-start hook to set the network
1007 922
 // namespace configuration linkage to the libnetwork "sandbox" entity
1008 923
 func (daemon *Daemon) setNetworkNamespaceKey(containerID string, pid int) error {
... ...
@@ -1032,63 +391,6 @@ func (daemon *Daemon) getIpcContainer(container *container.Container) (*containe
1032 1032
 	return c, nil
1033 1033
 }
1034 1034
 
1035
-func (daemon *Daemon) getNetworkedContainer(containerID, connectedContainerID string) (*container.Container, error) {
1036
-	nc, err := daemon.GetContainer(connectedContainerID)
1037
-	if err != nil {
1038
-		return nil, err
1039
-	}
1040
-	if containerID == nc.ID {
1041
-		return nil, fmt.Errorf("cannot join own network")
1042
-	}
1043
-	if !nc.IsRunning() {
1044
-		err := fmt.Errorf("cannot join network of a non running container: %s", connectedContainerID)
1045
-		return nil, errors.NewRequestConflictError(err)
1046
-	}
1047
-	if nc.IsRestarting() {
1048
-		return nil, errContainerIsRestarting(connectedContainerID)
1049
-	}
1050
-	return nc, nil
1051
-}
1052
-
1053
-func (daemon *Daemon) releaseNetwork(container *container.Container) {
1054
-	if container.HostConfig.NetworkMode.IsContainer() || container.Config.NetworkDisabled {
1055
-		return
1056
-	}
1057
-
1058
-	sid := container.NetworkSettings.SandboxID
1059
-	settings := container.NetworkSettings.Networks
1060
-	container.NetworkSettings.Ports = nil
1061
-
1062
-	if sid == "" || len(settings) == 0 {
1063
-		return
1064
-	}
1065
-
1066
-	var networks []libnetwork.Network
1067
-	for n, epSettings := range settings {
1068
-		if nw, err := daemon.FindNetwork(n); err == nil {
1069
-			networks = append(networks, nw)
1070
-		}
1071
-		cleanOperationalData(epSettings)
1072
-	}
1073
-
1074
-	sb, err := daemon.netController.SandboxByID(sid)
1075
-	if err != nil {
1076
-		logrus.Errorf("error locating sandbox id %s: %v", sid, err)
1077
-		return
1078
-	}
1079
-
1080
-	if err := sb.Delete(); err != nil {
1081
-		logrus.Errorf("Error deleting sandbox id %s for container %s: %v", sid, container.ID, err)
1082
-	}
1083
-
1084
-	attributes := map[string]string{
1085
-		"container": container.ID,
1086
-	}
1087
-	for _, nw := range networks {
1088
-		daemon.LogNetworkEventWithAttributes(nw, "disconnect", attributes)
1089
-	}
1090
-}
1091
-
1092 1035
 func (daemon *Daemon) setupIpcDirs(c *container.Container) error {
1093 1036
 	rootUID, rootGID := daemon.GetRemappedUIDGID()
1094 1037
 	if !c.HasMountFor("/dev/shm") {
... ...
@@ -1242,7 +544,7 @@ func detachMounted(path string) error {
1242 1242
 
1243 1243
 func isLinkable(child *container.Container) bool {
1244 1244
 	// A container is linkable only if it belongs to the default network
1245
-	_, ok := child.NetworkSettings.Networks["bridge"]
1245
+	_, ok := child.NetworkSettings.Networks[runconfig.DefaultDaemonNetworkMode().NetworkName()]
1246 1246
 	return ok
1247 1247
 }
1248 1248
 
... ...
@@ -6,11 +6,12 @@ import (
6 6
 	"fmt"
7 7
 	"strings"
8 8
 
9
+	networktypes "github.com/docker/engine-api/types/network"
10
+
9 11
 	"github.com/docker/docker/container"
10 12
 	"github.com/docker/docker/daemon/execdriver"
11 13
 	"github.com/docker/docker/daemon/execdriver/windows"
12 14
 	"github.com/docker/docker/layer"
13
-	networktypes "github.com/docker/engine-api/types/network"
14 15
 	"github.com/docker/libnetwork"
15 16
 )
16 17
 
... ...
@@ -18,28 +19,14 @@ func (daemon *Daemon) setupLinkedContainers(container *container.Container) ([]s
18 18
 	return nil, nil
19 19
 }
20 20
 
21
-// updateContainerNetworkSettings update the network settings
22
-func (daemon *Daemon) updateContainerNetworkSettings(container *container.Container, endpointsConfig map[string]*networktypes.EndpointSettings) error {
23
-	return nil
24
-}
25
-
26
-func (daemon *Daemon) initializeNetworking(container *container.Container) error {
27
-	return nil
28
-}
29
-
30
-// ConnectToNetwork connects a container to the network
21
+// ConnectToNetwork connects a container to a network
31 22
 func (daemon *Daemon) ConnectToNetwork(container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings) error {
32
-	return nil
23
+	return fmt.Errorf("Windows does not support connecting a running container to a network")
33 24
 }
34 25
 
35
-// ForceEndpointDelete deletes an endpoing from a network forcefully
36
-func (daemon *Daemon) ForceEndpointDelete(name string, n libnetwork.Network) error {
37
-	return nil
38
-}
39
-
40
-// DisconnectFromNetwork disconnects a container from the network.
26
+// DisconnectFromNetwork disconnects container from a network.
41 27
 func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, n libnetwork.Network, force bool) error {
42
-	return nil
28
+	return fmt.Errorf("Windows does not support disconnecting a running container from a network")
43 29
 }
44 30
 
45 31
 func (daemon *Daemon) populateCommand(c *container.Container, env []string) error {
... ...
@@ -47,24 +34,51 @@ func (daemon *Daemon) populateCommand(c *container.Container, env []string) erro
47 47
 		Interface: nil,
48 48
 	}
49 49
 
50
-	parts := strings.SplitN(string(c.HostConfig.NetworkMode), ":", 2)
51
-	switch parts[0] {
52
-	case "none":
53
-	case "default", "": // empty string to support existing containers
54
-		if !c.Config.NetworkDisabled {
55
-			en.Interface = &execdriver.NetworkInterface{
56
-				MacAddress:   c.Config.MacAddress,
57
-				Bridge:       daemon.configStore.bridgeConfig.VirtualSwitchName,
58
-				PortBindings: c.HostConfig.PortBindings,
59
-
60
-				// TODO Windows. Include IPAddress. There already is a
61
-				// property IPAddress on execDrive.CommonNetworkInterface,
62
-				// but there is no CLI option in docker to pass through
63
-				// an IPAddress on docker run.
50
+	var epList []string
51
+
52
+	// Connect all the libnetwork allocated networks to the container
53
+	if c.NetworkSettings != nil {
54
+		for n := range c.NetworkSettings.Networks {
55
+			sn, err := daemon.FindNetwork(n)
56
+			if err != nil {
57
+				continue
58
+			}
59
+
60
+			ep, err := c.GetEndpointInNetwork(sn)
61
+			if err != nil {
62
+				continue
63
+			}
64
+
65
+			data, err := ep.DriverInfo()
66
+			if err != nil {
67
+				continue
68
+			}
69
+			if data["hnsid"] != nil {
70
+				epList = append(epList, data["hnsid"].(string))
64 71
 			}
65 72
 		}
66
-	default:
67
-		return fmt.Errorf("invalid network mode: %s", c.HostConfig.NetworkMode)
73
+	}
74
+
75
+	if daemon.netController == nil {
76
+		parts := strings.SplitN(string(c.HostConfig.NetworkMode), ":", 2)
77
+		switch parts[0] {
78
+		case "none":
79
+		case "default", "": // empty string to support existing containers
80
+			if !c.Config.NetworkDisabled {
81
+				en.Interface = &execdriver.NetworkInterface{
82
+					MacAddress:   c.Config.MacAddress,
83
+					Bridge:       daemon.configStore.bridgeConfig.Iface,
84
+					PortBindings: c.HostConfig.PortBindings,
85
+
86
+					// TODO Windows. Include IPAddress. There already is a
87
+					// property IPAddress on execDrive.CommonNetworkInterface,
88
+					// but there is no CLI option in docker to pass through
89
+					// an IPAddress on docker run.
90
+				}
91
+			}
92
+		default:
93
+			return fmt.Errorf("invalid network mode: %s", c.HostConfig.NetworkMode)
94
+		}
68 95
 	}
69 96
 
70 97
 	// TODO Windows. More resource controls to be implemented later.
... ...
@@ -138,6 +152,7 @@ func (daemon *Daemon) populateCommand(c *container.Container, env []string) erro
138 138
 		Isolation:   string(c.HostConfig.Isolation),
139 139
 		ArgsEscaped: c.Config.ArgsEscaped,
140 140
 		HvPartition: hvPartition,
141
+		EpList:      epList,
141 142
 	}
142 143
 
143 144
 	return nil
... ...
@@ -154,18 +169,6 @@ func (daemon *Daemon) setNetworkNamespaceKey(containerID string, pid int) error
154 154
 	return nil
155 155
 }
156 156
 
157
-// allocateNetwork is a no-op on Windows.
158
-func (daemon *Daemon) allocateNetwork(container *container.Container) error {
159
-	return nil
160
-}
161
-
162
-func (daemon *Daemon) updateNetwork(container *container.Container) error {
163
-	return nil
164
-}
165
-
166
-func (daemon *Daemon) releaseNetwork(container *container.Container) {
167
-}
168
-
169 157
 func (daemon *Daemon) setupIpcDirs(container *container.Container) error {
170 158
 	return nil
171 159
 }
... ...
@@ -187,3 +190,7 @@ func detachMounted(path string) error {
187 187
 func killProcessDirectly(container *container.Container) error {
188 188
 	return nil
189 189
 }
190
+
191
+func isLinkable(child *container.Container) bool {
192
+	return false
193
+}
... ...
@@ -71,6 +71,7 @@ import (
71 71
 	"github.com/docker/docker/volume/store"
72 72
 	"github.com/docker/go-connections/nat"
73 73
 	"github.com/docker/libnetwork"
74
+	nwconfig "github.com/docker/libnetwork/config"
74 75
 	lntypes "github.com/docker/libnetwork/types"
75 76
 	"github.com/docker/libtrust"
76 77
 	"github.com/opencontainers/runc/libcontainer"
... ...
@@ -1693,3 +1694,45 @@ func validateID(id string) error {
1693 1693
 	}
1694 1694
 	return nil
1695 1695
 }
1696
+
1697
+func isBridgeNetworkDisabled(config *Config) bool {
1698
+	return config.bridgeConfig.Iface == disableNetworkBridge
1699
+}
1700
+
1701
+func (daemon *Daemon) networkOptions(dconfig *Config) ([]nwconfig.Option, error) {
1702
+	options := []nwconfig.Option{}
1703
+	if dconfig == nil {
1704
+		return options, nil
1705
+	}
1706
+
1707
+	options = append(options, nwconfig.OptionDataDir(dconfig.Root))
1708
+
1709
+	dd := runconfig.DefaultDaemonNetworkMode()
1710
+	dn := runconfig.DefaultDaemonNetworkMode().NetworkName()
1711
+	options = append(options, nwconfig.OptionDefaultDriver(string(dd)))
1712
+	options = append(options, nwconfig.OptionDefaultNetwork(dn))
1713
+
1714
+	if strings.TrimSpace(dconfig.ClusterStore) != "" {
1715
+		kv := strings.Split(dconfig.ClusterStore, "://")
1716
+		if len(kv) != 2 {
1717
+			return nil, fmt.Errorf("kv store daemon config must be of the form KV-PROVIDER://KV-URL")
1718
+		}
1719
+		options = append(options, nwconfig.OptionKVProvider(kv[0]))
1720
+		options = append(options, nwconfig.OptionKVProviderURL(kv[1]))
1721
+	}
1722
+	if len(dconfig.ClusterOpts) > 0 {
1723
+		options = append(options, nwconfig.OptionKVOpts(dconfig.ClusterOpts))
1724
+	}
1725
+
1726
+	if daemon.discoveryWatcher != nil {
1727
+		options = append(options, nwconfig.OptionDiscoveryWatcher(daemon.discoveryWatcher))
1728
+	}
1729
+
1730
+	if dconfig.ClusterAdvertise != "" {
1731
+		options = append(options, nwconfig.OptionDiscoveryAddress(dconfig.ClusterAdvertise))
1732
+	}
1733
+
1734
+	options = append(options, nwconfig.OptionLabels(dconfig.Labels))
1735
+	options = append(options, driverOptions(dconfig)...)
1736
+	return options, nil
1737
+}
... ...
@@ -518,48 +518,6 @@ func configureKernelSecuritySupport(config *Config, driverName string) error {
518 518
 	return nil
519 519
 }
520 520
 
521
-func isBridgeNetworkDisabled(config *Config) bool {
522
-	return config.bridgeConfig.Iface == disableNetworkBridge
523
-}
524
-
525
-func (daemon *Daemon) networkOptions(dconfig *Config) ([]nwconfig.Option, error) {
526
-	options := []nwconfig.Option{}
527
-	if dconfig == nil {
528
-		return options, nil
529
-	}
530
-
531
-	options = append(options, nwconfig.OptionDataDir(dconfig.Root))
532
-
533
-	dd := runconfig.DefaultDaemonNetworkMode()
534
-	dn := runconfig.DefaultDaemonNetworkMode().NetworkName()
535
-	options = append(options, nwconfig.OptionDefaultDriver(string(dd)))
536
-	options = append(options, nwconfig.OptionDefaultNetwork(dn))
537
-
538
-	if strings.TrimSpace(dconfig.ClusterStore) != "" {
539
-		kv := strings.Split(dconfig.ClusterStore, "://")
540
-		if len(kv) != 2 {
541
-			return nil, fmt.Errorf("kv store daemon config must be of the form KV-PROVIDER://KV-URL")
542
-		}
543
-		options = append(options, nwconfig.OptionKVProvider(kv[0]))
544
-		options = append(options, nwconfig.OptionKVProviderURL(kv[1]))
545
-	}
546
-	if len(dconfig.ClusterOpts) > 0 {
547
-		options = append(options, nwconfig.OptionKVOpts(dconfig.ClusterOpts))
548
-	}
549
-
550
-	if daemon.discoveryWatcher != nil {
551
-		options = append(options, nwconfig.OptionDiscoveryWatcher(daemon.discoveryWatcher))
552
-	}
553
-
554
-	if dconfig.ClusterAdvertise != "" {
555
-		options = append(options, nwconfig.OptionDiscoveryAddress(dconfig.ClusterAdvertise))
556
-	}
557
-
558
-	options = append(options, nwconfig.OptionLabels(dconfig.Labels))
559
-	options = append(options, driverOptions(dconfig)...)
560
-	return options, nil
561
-}
562
-
563 521
 func (daemon *Daemon) initNetworkController(config *Config) (libnetwork.NetworkController, error) {
564 522
 	netOptions, err := daemon.networkOptions(config)
565 523
 	if err != nil {
... ...
@@ -9,6 +9,7 @@ import (
9 9
 	"runtime"
10 10
 	"strings"
11 11
 
12
+	"github.com/Microsoft/hcsshim"
12 13
 	"github.com/Sirupsen/logrus"
13 14
 	"github.com/docker/docker/container"
14 15
 	"github.com/docker/docker/daemon/graphdriver"
... ...
@@ -16,6 +17,7 @@ import (
16 16
 	"github.com/docker/docker/image"
17 17
 	"github.com/docker/docker/layer"
18 18
 	"github.com/docker/docker/reference"
19
+	"github.com/docker/docker/runconfig"
19 20
 	containertypes "github.com/docker/engine-api/types/container"
20 21
 	// register the windows graph driver
21 22
 	"github.com/docker/docker/daemon/graphdriver/windows"
... ...
@@ -23,11 +25,15 @@ import (
23 23
 	"github.com/docker/docker/pkg/system"
24 24
 	"github.com/docker/libnetwork"
25 25
 	nwconfig "github.com/docker/libnetwork/config"
26
+	winlibnetwork "github.com/docker/libnetwork/drivers/windows"
27
+	"github.com/docker/libnetwork/netlabel"
28
+	"github.com/docker/libnetwork/options"
26 29
 	blkiodev "github.com/opencontainers/runc/libcontainer/configs"
27 30
 )
28 31
 
29 32
 const (
30 33
 	defaultVirtualSwitch = "Virtual Switch"
34
+	defaultNetworkSpace  = "172.16.0.0/12"
31 35
 	platformSupported    = true
32 36
 	windowsMinCPUShares  = 1
33 37
 	windowsMaxCPUShares  = 10000
... ...
@@ -125,16 +131,154 @@ func configureMaxThreads(config *Config) error {
125 125
 	return nil
126 126
 }
127 127
 
128
-func isBridgeNetworkDisabled(config *Config) bool {
129
-	return false
128
+func (daemon *Daemon) initNetworkController(config *Config) (libnetwork.NetworkController, error) {
129
+	// TODO Windows: Remove this check once TP4 is no longer supported
130
+	osv, err := system.GetOSVersion()
131
+	if err != nil {
132
+		return nil, err
133
+	}
134
+
135
+	if osv.Build < 14260 {
136
+		// Set the name of the virtual switch if not specified by -b on daemon start
137
+		if config.bridgeConfig.Iface == "" {
138
+			config.bridgeConfig.Iface = defaultVirtualSwitch
139
+		}
140
+		logrus.Warnf("Network controller is not supported by the current platform build version")
141
+		return nil, nil
142
+	}
143
+
144
+	netOptions, err := daemon.networkOptions(config)
145
+	if err != nil {
146
+		return nil, err
147
+	}
148
+	controller, err := libnetwork.New(netOptions...)
149
+	if err != nil {
150
+		return nil, fmt.Errorf("error obtaining controller instance: %v", err)
151
+	}
152
+
153
+	hnsresponse, err := hcsshim.HNSListNetworkRequest("GET", "", "")
154
+	if err != nil {
155
+		return nil, err
156
+	}
157
+
158
+	// Remove networks not present in HNS
159
+	for _, v := range controller.Networks() {
160
+		options := v.Info().DriverOptions()
161
+		hnsid := options[winlibnetwork.HNSID]
162
+		found := false
163
+
164
+		for _, v := range hnsresponse {
165
+			if v.Id == hnsid {
166
+				found = true
167
+				break
168
+			}
169
+		}
170
+
171
+		if !found {
172
+			err = v.Delete()
173
+			if err != nil {
174
+				return nil, err
175
+			}
176
+		}
177
+	}
178
+
179
+	_, err = controller.NewNetwork("null", "none", libnetwork.NetworkOptionPersist(false))
180
+	if err != nil {
181
+		return nil, err
182
+	}
183
+
184
+	// discover and add HNS networks to windows
185
+	// network that exist are removed and added again
186
+	for _, v := range hnsresponse {
187
+		var n libnetwork.Network
188
+		s := func(current libnetwork.Network) bool {
189
+			options := current.Info().DriverOptions()
190
+			if options[winlibnetwork.HNSID] == v.Id {
191
+				n = current
192
+				return true
193
+			}
194
+			return false
195
+		}
196
+
197
+		controller.WalkNetworks(s)
198
+		if n != nil {
199
+			v.Name = n.Name()
200
+			n.Delete()
201
+		}
202
+
203
+		netOption := map[string]string{
204
+			winlibnetwork.NetworkName: v.Name,
205
+			winlibnetwork.HNSID:       v.Id,
206
+		}
207
+
208
+		v4Conf := []*libnetwork.IpamConf{}
209
+		for _, subnet := range v.Subnets {
210
+			ipamV4Conf := libnetwork.IpamConf{}
211
+			ipamV4Conf.PreferredPool = subnet.AddressPrefix
212
+			ipamV4Conf.Gateway = subnet.GatewayAddress
213
+			v4Conf = append(v4Conf, &ipamV4Conf)
214
+		}
215
+
216
+		name := v.Name
217
+		// There is only one nat network supported in windows.
218
+		// If it exists with a different name add it as the default name
219
+		if runconfig.DefaultDaemonNetworkMode() == containertypes.NetworkMode(strings.ToLower(v.Type)) {
220
+			name = runconfig.DefaultDaemonNetworkMode().NetworkName()
221
+		}
222
+
223
+		v6Conf := []*libnetwork.IpamConf{}
224
+		_, err := controller.NewNetwork(strings.ToLower(v.Type), name,
225
+			libnetwork.NetworkOptionGeneric(options.Generic{
226
+				netlabel.GenericData: netOption,
227
+			}),
228
+			libnetwork.NetworkOptionIpam("default", "", v4Conf, v6Conf, nil),
229
+		)
230
+
231
+		if err != nil {
232
+			logrus.Errorf("Error occurred when creating network %v", err)
233
+		}
234
+	}
235
+
236
+	if !config.DisableBridge {
237
+		// Initialize default driver "bridge"
238
+		if err := initBridgeDriver(controller, config); err != nil {
239
+			return nil, err
240
+		}
241
+	}
242
+
243
+	return controller, nil
130 244
 }
131 245
 
132
-func (daemon *Daemon) initNetworkController(config *Config) (libnetwork.NetworkController, error) {
133
-	// Set the name of the virtual switch if not specified by -b on daemon start
134
-	if config.bridgeConfig.VirtualSwitchName == "" {
135
-		config.bridgeConfig.VirtualSwitchName = defaultVirtualSwitch
246
+func initBridgeDriver(controller libnetwork.NetworkController, config *Config) error {
247
+	if _, err := controller.NetworkByName(runconfig.DefaultDaemonNetworkMode().NetworkName()); err == nil {
248
+		return nil
136 249
 	}
137
-	return nil, nil
250
+
251
+	netOption := map[string]string{
252
+		winlibnetwork.NetworkName: runconfig.DefaultDaemonNetworkMode().NetworkName(),
253
+	}
254
+
255
+	ipamV4Conf := libnetwork.IpamConf{}
256
+	if config.bridgeConfig.FixedCIDR == "" {
257
+		ipamV4Conf.PreferredPool = defaultNetworkSpace
258
+	} else {
259
+		ipamV4Conf.PreferredPool = config.bridgeConfig.FixedCIDR
260
+	}
261
+
262
+	v4Conf := []*libnetwork.IpamConf{&ipamV4Conf}
263
+	v6Conf := []*libnetwork.IpamConf{}
264
+
265
+	_, err := controller.NewNetwork(string(runconfig.DefaultDaemonNetworkMode()), runconfig.DefaultDaemonNetworkMode().NetworkName(),
266
+		libnetwork.NetworkOptionGeneric(options.Generic{
267
+			netlabel.GenericData: netOption,
268
+		}),
269
+		libnetwork.NetworkOptionIpam("default", "", v4Conf, v6Conf, nil),
270
+	)
271
+
272
+	if err != nil {
273
+		return fmt.Errorf("Error creating default network: %v", err)
274
+	}
275
+	return nil
138 276
 }
139 277
 
140 278
 // registerLinks sets up links between containers and writes the
... ...
@@ -257,6 +401,6 @@ func restoreCustomImage(is image.Store, ls layer.Store, rs reference.Store) erro
257 257
 	return nil
258 258
 }
259 259
 
260
-func (daemon *Daemon) networkOptions(dconfig *Config) ([]nwconfig.Option, error) {
261
-	return nil, fmt.Errorf("Network controller config reload not aavailable on Windows yet")
260
+func driverOptions(config *Config) []nwconfig.Option {
261
+	return []nwconfig.Option{}
262 262
 }
... ...
@@ -56,6 +56,7 @@ type Command struct {
56 56
 	Isolation   string   `json:"isolation"`    // Isolation technology for the container
57 57
 	ArgsEscaped bool     `json:"args_escaped"` // True if args are already escaped
58 58
 	HvPartition bool     `json:"hv_partition"` // True if it's an hypervisor partition
59
+	EpList      []string `json:"endpoints"`    // List of network endpoints for HNS
59 60
 }
60 61
 
61 62
 // ExitStatus provides exit reasons for a container.
... ...
@@ -89,6 +89,7 @@ type containerInit struct {
89 89
 	MappedDirectories       []mappedDir // List of mapped directories (volumes/mounts)
90 90
 	SandboxPath             string      // Location of unmounted sandbox (used for Hyper-V containers, not Windows Server containers)
91 91
 	HvPartition             bool        // True if it a Hyper-V Container
92
+	EndpointList            []string    // List of endpoints to be attached to container
92 93
 }
93 94
 
94 95
 // defaultOwner is a tag passed to HCS to allow it to differentiate between
... ...
@@ -104,6 +105,7 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, hooks execd
104 104
 		err  error
105 105
 	)
106 106
 
107
+	// Allocate Network only if there is no network interface
107 108
 	cu := &containerInit{
108 109
 		SystemType:              "Container",
109 110
 		Name:                    c.ID,
... ...
@@ -114,6 +116,7 @@ func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, hooks execd
114 114
 		LayerFolderPath:         c.LayerFolder,
115 115
 		ProcessorWeight:         c.Resources.CPUShares,
116 116
 		HostName:                c.Hostname,
117
+		EndpointList:            c.EpList,
117 118
 	}
118 119
 
119 120
 	cu.HvPartition = c.HvPartition
120 121
new file mode 100644
... ...
@@ -0,0 +1,20 @@
0
+#!/bin/bash
1
+set -e
2
+
3
+# explicit list of os/arch combos that support being a daemon
4
+declare -A daemonSupporting
5
+daemonSupporting=(
6
+	[linux/amd64]=1
7
+	[windows/amd64]=1
8
+)
9
+platform="windows/amd64"
10
+export DEST="$DEST/$platform" # bundles/VERSION/cross/GOOS/GOARCH/docker-VERSION
11
+mkdir -p "$DEST"
12
+ABS_DEST="$(cd "$DEST" && pwd -P)"
13
+export GOOS=${platform%/*}
14
+export GOARCH=${platform##*/}
15
+if [ -z "${daemonSupporting[$platform]}" ]; then
16
+	export LDFLAGS_STATIC_DOCKER="" # we just need a simple client for these platforms
17
+	export BUILDFLAGS=( "${ORIG_BUILDFLAGS[@]/ daemon/}" ) # remove the "daemon" build tag from platforms that aren't supported
18
+fi
19
+source "${MAKEDIR}/binary"
... ...
@@ -10,25 +10,22 @@ import (
10 10
 // DefaultDaemonNetworkMode returns the default network stack the daemon should
11 11
 // use.
12 12
 func DefaultDaemonNetworkMode() container.NetworkMode {
13
-	return container.NetworkMode("default")
13
+	return container.NetworkMode("nat")
14 14
 }
15 15
 
16 16
 // IsPreDefinedNetwork indicates if a network is predefined by the daemon
17 17
 func IsPreDefinedNetwork(network string) bool {
18
-	return false
18
+	return !container.NetworkMode(network).IsUserDefined()
19 19
 }
20 20
 
21 21
 // ValidateNetMode ensures that the various combinations of requested
22 22
 // network settings are valid.
23 23
 func ValidateNetMode(c *container.Config, hc *container.HostConfig) error {
24
-	// We may not be passed a host config, such as in the case of docker commit
25 24
 	if hc == nil {
26 25
 		return nil
27 26
 	}
28 27
 	parts := strings.Split(string(hc.NetworkMode), ":")
29
-	switch mode := parts[0]; mode {
30
-	case "default", "none":
31
-	default:
28
+	if len(parts) > 1 {
32 29
 		return fmt.Errorf("invalid --net: %s", hc.NetworkMode)
33 30
 	}
34 31
 	return nil