Support container disconnect for non-existing network
There are cases such as migrating from classic overlay network to the swarm-mode networking (without kv-store), such a mechanism to allow disconnecting a container even when a network isnt available will be useful. Signed-off-by: Madhu Venugopal <madhu@docker.com>
This commit is contained in:
parent
91ec7fa811
commit
05a3f2666e
8 changed files with 50 additions and 30 deletions
|
@ -15,6 +15,6 @@ type Backend interface {
|
|||
GetNetworks() []libnetwork.Network
|
||||
CreateNetwork(nc types.NetworkCreateRequest) (*types.NetworkCreateResponse, error)
|
||||
ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error
|
||||
DisconnectContainerFromNetwork(containerName string, network libnetwork.Network, force bool) error
|
||||
DisconnectContainerFromNetwork(containerName string, networkName string, force bool) error
|
||||
DeleteNetwork(name string) error
|
||||
}
|
||||
|
|
|
@ -143,17 +143,14 @@ func (n *networkRouter) postNetworkDisconnect(ctx context.Context, w http.Respon
|
|||
return err
|
||||
}
|
||||
|
||||
nw, err := n.backend.FindNetwork(vars["id"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
nw, _ := n.backend.FindNetwork(vars["id"])
|
||||
|
||||
if nw.Info().Dynamic() {
|
||||
if nw != nil && nw.Info().Dynamic() {
|
||||
err := fmt.Errorf("operation not supported for swarm scoped networks")
|
||||
return errors.NewRequestForbiddenError(err)
|
||||
}
|
||||
|
||||
return n.backend.DisconnectContainerFromNetwork(disconnect.Container, nw, disconnect.Force)
|
||||
return n.backend.DisconnectContainerFromNetwork(disconnect.Container, vars["id"], disconnect.Force)
|
||||
}
|
||||
|
||||
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
|
|||
return nil
|
||||
}
|
||||
|
||||
// ForceEndpointDelete deletes an endpoing from a network forcefully
|
||||
func (daemon *Daemon) ForceEndpointDelete(name string, n libnetwork.Network) error {
|
||||
// ForceEndpointDelete deletes an endpoint from a network forcefully
|
||||
func (daemon *Daemon) ForceEndpointDelete(name string, networkName string) error {
|
||||
n, err := daemon.FindNetwork(networkName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ep, err := n.EndpointByName(name)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
|
||||
"github.com/docker/docker/container"
|
||||
networktypes "github.com/docker/engine-api/types/network"
|
||||
"github.com/docker/libnetwork"
|
||||
)
|
||||
|
||||
func (daemon *Daemon) setupLinkedContainers(container *container.Container) ([]string, error) {
|
||||
|
@ -25,7 +24,7 @@ func (daemon *Daemon) getSize(container *container.Container) (int64, int64) {
|
|||
}
|
||||
|
||||
// DisconnectFromNetwork disconnects a container from the network
|
||||
func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, n libnetwork.Network, force bool) error {
|
||||
func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, networkName string, force bool) error {
|
||||
return fmt.Errorf("Solaris does not support disconnecting a running container from a network")
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ import (
|
|||
"github.com/docker/docker/runconfig"
|
||||
containertypes "github.com/docker/engine-api/types/container"
|
||||
networktypes "github.com/docker/engine-api/types/network"
|
||||
"github.com/docker/libnetwork"
|
||||
"github.com/opencontainers/runc/libcontainer/configs"
|
||||
"github.com/opencontainers/runc/libcontainer/devices"
|
||||
"github.com/opencontainers/runc/libcontainer/label"
|
||||
|
@ -124,33 +123,38 @@ func (daemon *Daemon) ConnectToNetwork(container *container.Container, idOrName
|
|||
}
|
||||
|
||||
// DisconnectFromNetwork disconnects container from network n.
|
||||
func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, n libnetwork.Network, force bool) error {
|
||||
if container.HostConfig.NetworkMode.IsHost() && containertypes.NetworkMode(n.Type()).IsHost() {
|
||||
return runconfig.ErrConflictHostNetwork
|
||||
}
|
||||
if !container.Running {
|
||||
func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, networkName string, force bool) error {
|
||||
n, err := daemon.FindNetwork(networkName)
|
||||
if !container.Running || (err != nil && force) {
|
||||
if container.RemovalInProgress || container.Dead {
|
||||
return errRemovalContainer(container.ID)
|
||||
}
|
||||
if _, ok := container.NetworkSettings.Networks[n.Name()]; ok {
|
||||
delete(container.NetworkSettings.Networks, n.Name())
|
||||
} else {
|
||||
return fmt.Errorf("container %s is not connected to the network %s", container.ID, n.Name())
|
||||
if _, ok := container.NetworkSettings.Networks[networkName]; !ok {
|
||||
return fmt.Errorf("container %s is not connected to the network %s", container.ID, networkName)
|
||||
}
|
||||
} else {
|
||||
delete(container.NetworkSettings.Networks, networkName)
|
||||
} else if err == nil {
|
||||
if container.HostConfig.NetworkMode.IsHost() && containertypes.NetworkMode(n.Type()).IsHost() {
|
||||
return runconfig.ErrConflictHostNetwork
|
||||
}
|
||||
|
||||
if err := disconnectFromNetwork(container, n, false); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := container.ToDiskLocking(); err != nil {
|
||||
return fmt.Errorf("Error saving container to disk: %v", err)
|
||||
}
|
||||
|
||||
attributes := map[string]string{
|
||||
"container": container.ID,
|
||||
if n != nil {
|
||||
attributes := map[string]string{
|
||||
"container": container.ID,
|
||||
}
|
||||
daemon.LogNetworkEventWithAttributes(n, "disconnect", attributes)
|
||||
}
|
||||
daemon.LogNetworkEventWithAttributes(n, "disconnect", attributes)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
|
||||
"github.com/docker/docker/container"
|
||||
networktypes "github.com/docker/engine-api/types/network"
|
||||
"github.com/docker/libnetwork"
|
||||
)
|
||||
|
||||
func (daemon *Daemon) setupLinkedContainers(container *container.Container) ([]string, error) {
|
||||
|
@ -20,7 +19,7 @@ func (daemon *Daemon) ConnectToNetwork(container *container.Container, idOrName
|
|||
}
|
||||
|
||||
// DisconnectFromNetwork disconnects container from a network.
|
||||
func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, n libnetwork.Network, force bool) error {
|
||||
func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, networkName string, force bool) error {
|
||||
return fmt.Errorf("Windows does not support disconnecting a running container from a network")
|
||||
}
|
||||
|
||||
|
|
|
@ -316,15 +316,15 @@ func (daemon *Daemon) ConnectContainerToNetwork(containerName, networkName strin
|
|||
|
||||
// DisconnectContainerFromNetwork disconnects the given container from
|
||||
// the given network. If either cannot be found, an err is returned.
|
||||
func (daemon *Daemon) DisconnectContainerFromNetwork(containerName string, network libnetwork.Network, force bool) error {
|
||||
func (daemon *Daemon) DisconnectContainerFromNetwork(containerName string, networkName string, force bool) error {
|
||||
container, err := daemon.GetContainer(containerName)
|
||||
if err != nil {
|
||||
if force {
|
||||
return daemon.ForceEndpointDelete(containerName, network)
|
||||
return daemon.ForceEndpointDelete(containerName, networkName)
|
||||
}
|
||||
return err
|
||||
}
|
||||
return daemon.DisconnectFromNetwork(container, network, force)
|
||||
return daemon.DisconnectFromNetwork(container, networkName, force)
|
||||
}
|
||||
|
||||
// GetNetworkDriverList returns the list of plugins drivers
|
||||
|
|
|
@ -1274,6 +1274,22 @@ func (s *DockerNetworkSuite) TestDockerNetworkConnectDisconnectToStoppedContaine
|
|||
|
||||
}
|
||||
|
||||
func (s *DockerNetworkSuite) TestDockerNetworkDisconnectContainerNonexistingNetwork(c *check.C) {
|
||||
dockerCmd(c, "network", "create", "test")
|
||||
dockerCmd(c, "run", "--net=test", "-d", "--name=foo", "busybox", "top")
|
||||
networks := inspectField(c, "foo", "NetworkSettings.Networks")
|
||||
c.Assert(networks, checker.Contains, "test", check.Commentf("Should contain 'test' network"))
|
||||
|
||||
// Stop container and remove network
|
||||
dockerCmd(c, "stop", "foo")
|
||||
dockerCmd(c, "network", "rm", "test")
|
||||
|
||||
// Test disconnecting stopped container from nonexisting network
|
||||
dockerCmd(c, "network", "disconnect", "-f", "test", "foo")
|
||||
networks = inspectField(c, "foo", "NetworkSettings.Networks")
|
||||
c.Assert(networks, checker.Not(checker.Contains), "test", check.Commentf("Should not contain 'test' network"))
|
||||
}
|
||||
|
||||
func (s *DockerNetworkSuite) TestDockerNetworkConnectPreferredIP(c *check.C) {
|
||||
// create two networks
|
||||
dockerCmd(c, "network", "create", "--ipv6", "--subnet=172.28.0.0/16", "--subnet=2001:db8:1234::/64", "n0")
|
||||
|
|
Loading…
Reference in a new issue