Browse code

Merge pull request #26055 from mavenugo/ndn

Support container disconnect for non-existing network

Arnaud Porterie authored on 2016/08/28 10:48:02
Showing 8 changed files
... ...
@@ -15,6 +15,6 @@ type Backend interface {
15 15
 	GetNetworks() []libnetwork.Network
16 16
 	CreateNetwork(nc types.NetworkCreateRequest) (*types.NetworkCreateResponse, error)
17 17
 	ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error
18
-	DisconnectContainerFromNetwork(containerName string, network libnetwork.Network, force bool) error
18
+	DisconnectContainerFromNetwork(containerName string, networkName string, force bool) error
19 19
 	DeleteNetwork(name string) error
20 20
 }
... ...
@@ -143,17 +143,14 @@ func (n *networkRouter) postNetworkDisconnect(ctx context.Context, w http.Respon
143 143
 		return err
144 144
 	}
145 145
 
146
-	nw, err := n.backend.FindNetwork(vars["id"])
147
-	if err != nil {
148
-		return err
149
-	}
146
+	nw, _ := n.backend.FindNetwork(vars["id"])
150 147
 
151
-	if nw.Info().Dynamic() {
148
+	if nw != nil && nw.Info().Dynamic() {
152 149
 		err := fmt.Errorf("operation not supported for swarm scoped networks")
153 150
 		return errors.NewRequestForbiddenError(err)
154 151
 	}
155 152
 
156
-	return n.backend.DisconnectContainerFromNetwork(disconnect.Container, nw, disconnect.Force)
153
+	return n.backend.DisconnectContainerFromNetwork(disconnect.Container, vars["id"], disconnect.Force)
157 154
 }
158 155
 
159 156
 func (n *networkRouter) deleteNetwork(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
... ...
@@ -618,8 +618,13 @@ func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName
618 618
 	return nil
619 619
 }
620 620
 
621
-// ForceEndpointDelete deletes an endpoing from a network forcefully
622
-func (daemon *Daemon) ForceEndpointDelete(name string, n libnetwork.Network) error {
621
+// ForceEndpointDelete deletes an endpoint from a network forcefully
622
+func (daemon *Daemon) ForceEndpointDelete(name string, networkName string) error {
623
+	n, err := daemon.FindNetwork(networkName)
624
+	if err != nil {
625
+		return err
626
+	}
627
+
623 628
 	ep, err := n.EndpointByName(name)
624 629
 	if err != nil {
625 630
 		return err
... ...
@@ -7,7 +7,6 @@ import (
7 7
 
8 8
 	"github.com/docker/docker/container"
9 9
 	networktypes "github.com/docker/engine-api/types/network"
10
-	"github.com/docker/libnetwork"
11 10
 )
12 11
 
13 12
 func (daemon *Daemon) setupLinkedContainers(container *container.Container) ([]string, error) {
... ...
@@ -25,7 +24,7 @@ func (daemon *Daemon) getSize(container *container.Container) (int64, int64) {
25 25
 }
26 26
 
27 27
 // DisconnectFromNetwork disconnects a container from the network
28
-func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, n libnetwork.Network, force bool) error {
28
+func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, networkName string, force bool) error {
29 29
 	return fmt.Errorf("Solaris does not support disconnecting a running container from a network")
30 30
 }
31 31
 
... ...
@@ -21,7 +21,6 @@ import (
21 21
 	"github.com/docker/docker/runconfig"
22 22
 	containertypes "github.com/docker/engine-api/types/container"
23 23
 	networktypes "github.com/docker/engine-api/types/network"
24
-	"github.com/docker/libnetwork"
25 24
 	"github.com/opencontainers/runc/libcontainer/configs"
26 25
 	"github.com/opencontainers/runc/libcontainer/devices"
27 26
 	"github.com/opencontainers/runc/libcontainer/label"
... ...
@@ -124,33 +123,38 @@ func (daemon *Daemon) ConnectToNetwork(container *container.Container, idOrName
124 124
 }
125 125
 
126 126
 // DisconnectFromNetwork disconnects container from network n.
127
-func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, n libnetwork.Network, force bool) error {
128
-	if container.HostConfig.NetworkMode.IsHost() && containertypes.NetworkMode(n.Type()).IsHost() {
129
-		return runconfig.ErrConflictHostNetwork
130
-	}
131
-	if !container.Running {
127
+func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, networkName string, force bool) error {
128
+	n, err := daemon.FindNetwork(networkName)
129
+	if !container.Running || (err != nil && force) {
132 130
 		if container.RemovalInProgress || container.Dead {
133 131
 			return errRemovalContainer(container.ID)
134 132
 		}
135
-		if _, ok := container.NetworkSettings.Networks[n.Name()]; ok {
136
-			delete(container.NetworkSettings.Networks, n.Name())
137
-		} else {
138
-			return fmt.Errorf("container %s is not connected to the network %s", container.ID, n.Name())
133
+		if _, ok := container.NetworkSettings.Networks[networkName]; !ok {
134
+			return fmt.Errorf("container %s is not connected to the network %s", container.ID, networkName)
139 135
 		}
140
-	} else {
136
+		delete(container.NetworkSettings.Networks, networkName)
137
+	} else if err == nil {
138
+		if container.HostConfig.NetworkMode.IsHost() && containertypes.NetworkMode(n.Type()).IsHost() {
139
+			return runconfig.ErrConflictHostNetwork
140
+		}
141
+
141 142
 		if err := disconnectFromNetwork(container, n, false); err != nil {
142 143
 			return err
143 144
 		}
145
+	} else {
146
+		return err
144 147
 	}
145 148
 
146 149
 	if err := container.ToDiskLocking(); err != nil {
147 150
 		return fmt.Errorf("Error saving container to disk: %v", err)
148 151
 	}
149 152
 
150
-	attributes := map[string]string{
151
-		"container": container.ID,
153
+	if n != nil {
154
+		attributes := map[string]string{
155
+			"container": container.ID,
156
+		}
157
+		daemon.LogNetworkEventWithAttributes(n, "disconnect", attributes)
152 158
 	}
153
-	daemon.LogNetworkEventWithAttributes(n, "disconnect", attributes)
154 159
 	return nil
155 160
 }
156 161
 
... ...
@@ -7,7 +7,6 @@ import (
7 7
 
8 8
 	"github.com/docker/docker/container"
9 9
 	networktypes "github.com/docker/engine-api/types/network"
10
-	"github.com/docker/libnetwork"
11 10
 )
12 11
 
13 12
 func (daemon *Daemon) setupLinkedContainers(container *container.Container) ([]string, error) {
... ...
@@ -20,7 +19,7 @@ func (daemon *Daemon) ConnectToNetwork(container *container.Container, idOrName
20 20
 }
21 21
 
22 22
 // DisconnectFromNetwork disconnects container from a network.
23
-func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, n libnetwork.Network, force bool) error {
23
+func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, networkName string, force bool) error {
24 24
 	return fmt.Errorf("Windows does not support disconnecting a running container from a network")
25 25
 }
26 26
 
... ...
@@ -316,15 +316,15 @@ func (daemon *Daemon) ConnectContainerToNetwork(containerName, networkName strin
316 316
 
317 317
 // DisconnectContainerFromNetwork disconnects the given container from
318 318
 // the given network. If either cannot be found, an err is returned.
319
-func (daemon *Daemon) DisconnectContainerFromNetwork(containerName string, network libnetwork.Network, force bool) error {
319
+func (daemon *Daemon) DisconnectContainerFromNetwork(containerName string, networkName string, force bool) error {
320 320
 	container, err := daemon.GetContainer(containerName)
321 321
 	if err != nil {
322 322
 		if force {
323
-			return daemon.ForceEndpointDelete(containerName, network)
323
+			return daemon.ForceEndpointDelete(containerName, networkName)
324 324
 		}
325 325
 		return err
326 326
 	}
327
-	return daemon.DisconnectFromNetwork(container, network, force)
327
+	return daemon.DisconnectFromNetwork(container, networkName, force)
328 328
 }
329 329
 
330 330
 // GetNetworkDriverList returns the list of plugins drivers
... ...
@@ -1274,6 +1274,22 @@ func (s *DockerNetworkSuite) TestDockerNetworkConnectDisconnectToStoppedContaine
1274 1274
 
1275 1275
 }
1276 1276
 
1277
+func (s *DockerNetworkSuite) TestDockerNetworkDisconnectContainerNonexistingNetwork(c *check.C) {
1278
+	dockerCmd(c, "network", "create", "test")
1279
+	dockerCmd(c, "run", "--net=test", "-d", "--name=foo", "busybox", "top")
1280
+	networks := inspectField(c, "foo", "NetworkSettings.Networks")
1281
+	c.Assert(networks, checker.Contains, "test", check.Commentf("Should contain 'test' network"))
1282
+
1283
+	// Stop container and remove network
1284
+	dockerCmd(c, "stop", "foo")
1285
+	dockerCmd(c, "network", "rm", "test")
1286
+
1287
+	// Test disconnecting stopped container from nonexisting network
1288
+	dockerCmd(c, "network", "disconnect", "-f", "test", "foo")
1289
+	networks = inspectField(c, "foo", "NetworkSettings.Networks")
1290
+	c.Assert(networks, checker.Not(checker.Contains), "test", check.Commentf("Should not contain 'test' network"))
1291
+}
1292
+
1277 1293
 func (s *DockerNetworkSuite) TestDockerNetworkConnectPreferredIP(c *check.C) {
1278 1294
 	// create two networks
1279 1295
 	dockerCmd(c, "network", "create", "--ipv6", "--subnet=172.28.0.0/16", "--subnet=2001:db8:1234::/64", "n0")