Browse code

(*) Support --net:container:<containername/id> for windows (*) (vdemeester) Removed duplicate code across Windows and Unix wrt Net:Containers (*) Return unsupported error for network sharing for hyperv isolation containers

Signed-off-by: Madhan Raj Mookkandy <MadhanRaj.Mookkandy@microsoft.com>

Madhan Raj Mookkandy authored on 2017/03/01 13:03:43
Showing 12 changed files
... ...
@@ -10,9 +10,6 @@ import (
10 10
 	"github.com/docker/go-units"
11 11
 )
12 12
 
13
-// NetworkMode represents the container network stack.
14
-type NetworkMode string
15
-
16 13
 // Isolation represents the isolation technology of a container. The supported
17 14
 // values are platform specific
18 15
 type Isolation string
... ...
@@ -66,6 +63,47 @@ func (n IpcMode) Container() string {
66 66
 	return ""
67 67
 }
68 68
 
69
+// NetworkMode represents the container network stack.
70
+type NetworkMode string
71
+
72
+// IsNone indicates whether container isn't using a network stack.
73
+func (n NetworkMode) IsNone() bool {
74
+	return n == "none"
75
+}
76
+
77
+// IsDefault indicates whether container uses the default network stack.
78
+func (n NetworkMode) IsDefault() bool {
79
+	return n == "default"
80
+}
81
+
82
+// IsPrivate indicates whether container uses its private network stack.
83
+func (n NetworkMode) IsPrivate() bool {
84
+	return !(n.IsHost() || n.IsContainer())
85
+}
86
+
87
+// IsContainer indicates whether container uses a container network stack.
88
+func (n NetworkMode) IsContainer() bool {
89
+	parts := strings.SplitN(string(n), ":", 2)
90
+	return len(parts) > 1 && parts[0] == "container"
91
+}
92
+
93
+// ConnectedContainer is the id of the container which network this container is connected to.
94
+func (n NetworkMode) ConnectedContainer() string {
95
+	parts := strings.SplitN(string(n), ":", 2)
96
+	if len(parts) > 1 {
97
+		return parts[1]
98
+	}
99
+	return ""
100
+}
101
+
102
+//UserDefined indicates user-created network
103
+func (n NetworkMode) UserDefined() string {
104
+	if n.IsUserDefined() {
105
+		return string(n)
106
+	}
107
+	return ""
108
+}
109
+
69 110
 // UsernsMode represents userns mode in the container.
70 111
 type UsernsMode string
71 112
 
... ...
@@ -2,23 +2,11 @@
2 2
 
3 3
 package container
4 4
 
5
-import "strings"
6
-
7 5
 // IsValid indicates if an isolation technology is valid
8 6
 func (i Isolation) IsValid() bool {
9 7
 	return i.IsDefault()
10 8
 }
11 9
 
12
-// IsPrivate indicates whether container uses its private network stack.
13
-func (n NetworkMode) IsPrivate() bool {
14
-	return !(n.IsHost() || n.IsContainer())
15
-}
16
-
17
-// IsDefault indicates whether container uses the default network stack.
18
-func (n NetworkMode) IsDefault() bool {
19
-	return n == "default"
20
-}
21
-
22 10
 // NetworkName returns the name of the network stack.
23 11
 func (n NetworkMode) NetworkName() string {
24 12
 	if n.IsBridge() {
... ...
@@ -47,35 +35,7 @@ func (n NetworkMode) IsHost() bool {
47 47
 	return n == "host"
48 48
 }
49 49
 
50
-// IsContainer indicates whether container uses a container network stack.
51
-func (n NetworkMode) IsContainer() bool {
52
-	parts := strings.SplitN(string(n), ":", 2)
53
-	return len(parts) > 1 && parts[0] == "container"
54
-}
55
-
56
-// IsNone indicates whether container isn't using a network stack.
57
-func (n NetworkMode) IsNone() bool {
58
-	return n == "none"
59
-}
60
-
61
-// ConnectedContainer is the id of the container which network this container is connected to.
62
-func (n NetworkMode) ConnectedContainer() string {
63
-	parts := strings.SplitN(string(n), ":", 2)
64
-	if len(parts) > 1 {
65
-		return parts[1]
66
-	}
67
-	return ""
68
-}
69
-
70 50
 // IsUserDefined indicates user-created network
71 51
 func (n NetworkMode) IsUserDefined() bool {
72 52
 	return !n.IsDefault() && !n.IsBridge() && !n.IsHost() && !n.IsNone() && !n.IsContainer()
73 53
 }
74
-
75
-//UserDefined indicates user-created network
76
-func (n NetworkMode) UserDefined() string {
77
-	if n.IsUserDefined() {
78
-		return string(n)
79
-	}
80
-	return ""
81
-}
... ...
@@ -4,22 +4,6 @@ import (
4 4
 	"strings"
5 5
 )
6 6
 
7
-// IsDefault indicates whether container uses the default network stack.
8
-func (n NetworkMode) IsDefault() bool {
9
-	return n == "default"
10
-}
11
-
12
-// IsNone indicates whether container isn't using a network stack.
13
-func (n NetworkMode) IsNone() bool {
14
-	return n == "none"
15
-}
16
-
17
-// IsContainer indicates whether container uses a container network stack.
18
-// Returns false as windows doesn't support this mode
19
-func (n NetworkMode) IsContainer() bool {
20
-	return false
21
-}
22
-
23 7
 // IsBridge indicates whether container uses the bridge network stack
24 8
 // in windows it is given the name NAT
25 9
 func (n NetworkMode) IsBridge() bool {
... ...
@@ -32,20 +16,9 @@ func (n NetworkMode) IsHost() bool {
32 32
 	return false
33 33
 }
34 34
 
35
-// IsPrivate indicates whether container uses its private network stack.
36
-func (n NetworkMode) IsPrivate() bool {
37
-	return !(n.IsHost() || n.IsContainer())
38
-}
39
-
40
-// ConnectedContainer is the id of the container which network this container is connected to.
41
-// Returns blank string on windows
42
-func (n NetworkMode) ConnectedContainer() string {
43
-	return ""
44
-}
45
-
46 35
 // IsUserDefined indicates user-created network
47 36
 func (n NetworkMode) IsUserDefined() bool {
48
-	return !n.IsDefault() && !n.IsNone() && !n.IsBridge()
37
+	return !n.IsDefault() && !n.IsNone() && !n.IsBridge() && !n.IsContainer()
49 38
 }
50 39
 
51 40
 // IsHyperV indicates the use of a Hyper-V partition for isolation
... ...
@@ -71,17 +44,11 @@ func (n NetworkMode) NetworkName() string {
71 71
 		return "nat"
72 72
 	} else if n.IsNone() {
73 73
 		return "none"
74
+	} else if n.IsContainer() {
75
+		return "container"
74 76
 	} else if n.IsUserDefined() {
75 77
 		return n.UserDefined()
76 78
 	}
77 79
 
78 80
 	return ""
79 81
 }
80
-
81
-//UserDefined indicates user-created network
82
-func (n NetworkMode) UserDefined() string {
83
-	if n.IsUserDefined() {
84
-		return string(n)
85
-	}
86
-	return ""
87
-}
... ...
@@ -16,6 +16,7 @@ type Container struct {
16 16
 	CommonContainer
17 17
 
18 18
 	// Fields below here are platform specific.
19
+	NetworkSharedContainerID string
19 20
 }
20 21
 
21 22
 // ExitStatus provides exit reasons for a container.
... ...
@@ -505,12 +505,13 @@ func (daemon *Daemon) allocateNetwork(container *container.Container) error {
505 505
 		logrus.Errorf("failed to cleanup up stale network sandbox for container %s", container.ID)
506 506
 	}
507 507
 
508
+	if container.Config.NetworkDisabled || container.HostConfig.NetworkMode.IsContainer() {
509
+		return nil
510
+	}
511
+
508 512
 	updateSettings := false
509
-	if len(container.NetworkSettings.Networks) == 0 {
510
-		if container.Config.NetworkDisabled || container.HostConfig.NetworkMode.IsContainer() {
511
-			return nil
512
-		}
513 513
 
514
+	if len(container.NetworkSettings.Networks) == 0 {
514 515
 		daemon.updateContainerNetworkSettings(container, nil)
515 516
 		updateSettings = true
516 517
 	}
... ...
@@ -56,4 +56,5 @@ func setupPathsAndSandboxOptions(container *container.Container, sboxOptions *[]
56 56
 }
57 57
 
58 58
 func initializeNetworkingPaths(container *container.Container, nc *container.Container) {
59
+	container.NetworkSharedContainerID = nc.ID
59 60
 }
... ...
@@ -157,14 +157,17 @@ func (daemon *Daemon) getLibcontainerdCreateOptions(container *container.Contain
157 157
 	createOptions = append(createOptions, &libcontainerd.FlushOption{IgnoreFlushesDuringBoot: !container.HasBeenStartedBefore})
158 158
 	createOptions = append(createOptions, hvOpts)
159 159
 	createOptions = append(createOptions, layerOpts)
160
-	if epList != nil {
161
-		createOptions = append(createOptions, &libcontainerd.NetworkEndpointsOption{
162
-			Endpoints:                epList,
163
-			AllowUnqualifiedDNSQuery: AllowUnqualifiedDNSQuery,
164
-			DNSSearchList:            dnsSearch,
165
-		})
166
-	}
167 160
 
161
+	var networkSharedContainerID string
162
+	if container.HostConfig.NetworkMode.IsContainer() {
163
+		networkSharedContainerID = container.NetworkSharedContainerID
164
+	}
165
+	createOptions = append(createOptions, &libcontainerd.NetworkEndpointsOption{
166
+		Endpoints:                epList,
167
+		AllowUnqualifiedDNSQuery: AllowUnqualifiedDNSQuery,
168
+		DNSSearchList:            dnsSearch,
169
+		NetworkSharedContainerID: networkSharedContainerID,
170
+	})
168 171
 	return createOptions, nil
169 172
 }
170 173
 
... ...
@@ -170,6 +170,7 @@ func (clnt *client) Create(containerID string, checkpoint string, checkpointDir
170 170
 			if n.DNSSearchList != nil {
171 171
 				configuration.DNSSearchList = strings.Join(n.DNSSearchList, ",")
172 172
 			}
173
+			configuration.NetworkSharedContainerName = n.NetworkSharedContainerID
173 174
 			continue
174 175
 		}
175 176
 		if c, ok := option.(*CredentialsOption); ok {
... ...
@@ -60,6 +60,7 @@ type NetworkEndpointsOption struct {
60 60
 	Endpoints                []string
61 61
 	AllowUnqualifiedDNSQuery bool
62 62
 	DNSSearchList            []string
63
+	NetworkSharedContainerID string
63 64
 }
64 65
 
65 66
 // CredentialsOption is a CreateOption that indicates the credentials from
... ...
@@ -2,7 +2,9 @@ package runconfig
2 2
 
3 3
 import (
4 4
 	"encoding/json"
5
+	"fmt"
5 6
 	"io"
7
+	"strings"
6 8
 
7 9
 	"github.com/docker/docker/api/types/container"
8 10
 )
... ...
@@ -32,3 +34,47 @@ func SetDefaultNetModeIfBlank(hc *container.HostConfig) {
32 32
 		}
33 33
 	}
34 34
 }
35
+
36
+// ValidateNetContainerMode ensures that the various combinations of requested
37
+// network settings wrt container mode are valid.
38
+func ValidateNetContainerMode(c *container.Config, hc *container.HostConfig) error {
39
+	// We may not be passed a host config, such as in the case of docker commit
40
+	if hc == nil {
41
+		return nil
42
+	}
43
+	parts := strings.Split(string(hc.NetworkMode), ":")
44
+	if parts[0] == "container" {
45
+		if len(parts) < 2 || parts[1] == "" {
46
+			return fmt.Errorf("--net: invalid net mode: invalid container format container:<name|id>")
47
+		}
48
+	}
49
+
50
+	if hc.NetworkMode.IsContainer() && c.Hostname != "" {
51
+		return ErrConflictNetworkHostname
52
+	}
53
+
54
+	if hc.NetworkMode.IsContainer() && len(hc.Links) > 0 {
55
+		return ErrConflictContainerNetworkAndLinks
56
+	}
57
+
58
+	if hc.NetworkMode.IsContainer() && len(hc.DNS) > 0 {
59
+		return ErrConflictNetworkAndDNS
60
+	}
61
+
62
+	if hc.NetworkMode.IsContainer() && len(hc.ExtraHosts) > 0 {
63
+		return ErrConflictNetworkHosts
64
+	}
65
+
66
+	if (hc.NetworkMode.IsContainer() || hc.NetworkMode.IsHost()) && c.MacAddress != "" {
67
+		return ErrConflictContainerNetworkAndMac
68
+	}
69
+
70
+	if hc.NetworkMode.IsContainer() && (len(hc.PortBindings) > 0 || hc.PublishAllPorts == true) {
71
+		return ErrConflictNetworkPublishPorts
72
+	}
73
+
74
+	if hc.NetworkMode.IsContainer() && len(c.ExposedPorts) > 0 {
75
+		return ErrConflictNetworkExposePorts
76
+	}
77
+	return nil
78
+}
... ...
@@ -5,7 +5,6 @@ package runconfig
5 5
 import (
6 6
 	"fmt"
7 7
 	"runtime"
8
-	"strings"
9 8
 
10 9
 	"github.com/docker/docker/api/types/container"
11 10
 	"github.com/docker/docker/pkg/sysinfo"
... ...
@@ -30,15 +29,10 @@ func ValidateNetMode(c *container.Config, hc *container.HostConfig) error {
30 30
 	if hc == nil {
31 31
 		return nil
32 32
 	}
33
-	parts := strings.Split(string(hc.NetworkMode), ":")
34
-	if parts[0] == "container" {
35
-		if len(parts) < 2 || parts[1] == "" {
36
-			return fmt.Errorf("--net: invalid net mode: invalid container format container:<name|id>")
37
-		}
38
-	}
39 33
 
40
-	if hc.NetworkMode.IsContainer() && c.Hostname != "" {
41
-		return ErrConflictNetworkHostname
34
+	err := ValidateNetContainerMode(c, hc)
35
+	if err != nil {
36
+		return err
42 37
 	}
43 38
 
44 39
 	if hc.UTSMode.IsHost() && c.Hostname != "" {
... ...
@@ -49,29 +43,6 @@ func ValidateNetMode(c *container.Config, hc *container.HostConfig) error {
49 49
 		return ErrConflictHostNetworkAndLinks
50 50
 	}
51 51
 
52
-	if hc.NetworkMode.IsContainer() && len(hc.Links) > 0 {
53
-		return ErrConflictContainerNetworkAndLinks
54
-	}
55
-
56
-	if hc.NetworkMode.IsContainer() && len(hc.DNS) > 0 {
57
-		return ErrConflictNetworkAndDNS
58
-	}
59
-
60
-	if hc.NetworkMode.IsContainer() && len(hc.ExtraHosts) > 0 {
61
-		return ErrConflictNetworkHosts
62
-	}
63
-
64
-	if (hc.NetworkMode.IsContainer() || hc.NetworkMode.IsHost()) && c.MacAddress != "" {
65
-		return ErrConflictContainerNetworkAndMac
66
-	}
67
-
68
-	if hc.NetworkMode.IsContainer() && (len(hc.PortBindings) > 0 || hc.PublishAllPorts == true) {
69
-		return ErrConflictNetworkPublishPorts
70
-	}
71
-
72
-	if hc.NetworkMode.IsContainer() && len(c.ExposedPorts) > 0 {
73
-		return ErrConflictNetworkExposePorts
74
-	}
75 52
 	return nil
76 53
 }
77 54
 
... ...
@@ -2,7 +2,6 @@ package runconfig
2 2
 
3 3
 import (
4 4
 	"fmt"
5
-	"strings"
6 5
 
7 6
 	"github.com/docker/docker/api/types/container"
8 7
 	"github.com/docker/docker/pkg/sysinfo"
... ...
@@ -25,10 +24,16 @@ func ValidateNetMode(c *container.Config, hc *container.HostConfig) error {
25 25
 	if hc == nil {
26 26
 		return nil
27 27
 	}
28
-	parts := strings.Split(string(hc.NetworkMode), ":")
29
-	if len(parts) > 1 {
30
-		return fmt.Errorf("invalid --net: %s", hc.NetworkMode)
28
+
29
+	err := ValidateNetContainerMode(c, hc)
30
+	if err != nil {
31
+		return err
32
+	}
33
+
34
+	if hc.NetworkMode.IsContainer() && hc.Isolation.IsHyperV() {
35
+		return fmt.Errorf("net mode --net=container:<NameOrId> unsupported for hyperv isolation")
31 36
 	}
37
+
32 38
 	return nil
33 39
 }
34 40