mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Remove attachable network on swarm leave
- When the node leaves the cluster, if any user run
container(s) is connected to the swarm network,
then daemon needs to detach the container(s) and
remove the network.
Signed-off-by: Alessandro Boch <aboch@docker.com>
(cherry picked from commit 3cedca5d53
)
Signed-off-by: Victor Vieux <vieux@docker.com>
This commit is contained in:
parent
017381aea4
commit
819bcf8182
5 changed files with 76 additions and 5 deletions
|
@ -351,7 +351,7 @@ func (c *Cluster) startNewNode(conf nodeStartConfig) (*node, error) {
|
||||||
c.actualLocalAddr = actualLocalAddr // not saved
|
c.actualLocalAddr = actualLocalAddr // not saved
|
||||||
c.saveState(conf)
|
c.saveState(conf)
|
||||||
|
|
||||||
c.config.Backend.SetClusterProvider(c)
|
c.config.Backend.DaemonJoinsCluster(c)
|
||||||
go func() {
|
go func() {
|
||||||
err := detectLockedError(n.Err(ctx))
|
err := detectLockedError(n.Err(ctx))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -724,6 +724,7 @@ func (c *Cluster) Leave(force bool) error {
|
||||||
if err := c.clearState(); err != nil {
|
if err := c.clearState(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -751,7 +752,7 @@ func (c *Cluster) clearState() error {
|
||||||
if err := os.MkdirAll(c.root, 0700); err != nil {
|
if err := os.MkdirAll(c.root, 0700); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
c.config.Backend.SetClusterProvider(nil)
|
c.config.Backend.DaemonLeavesCluster()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,8 @@ type Backend interface {
|
||||||
VolumeCreate(name, driverName string, opts, labels map[string]string) (*types.Volume, error)
|
VolumeCreate(name, driverName string, opts, labels map[string]string) (*types.Volume, error)
|
||||||
Containers(config *types.ContainerListOptions) ([]*types.Container, error)
|
Containers(config *types.ContainerListOptions) ([]*types.Container, error)
|
||||||
SetNetworkBootstrapKeys([]*networktypes.EncryptionKey) error
|
SetNetworkBootstrapKeys([]*networktypes.EncryptionKey) error
|
||||||
SetClusterProvider(provider cluster.Provider)
|
DaemonJoinsCluster(provider cluster.Provider)
|
||||||
|
DaemonLeavesCluster()
|
||||||
IsSwarmCompatible() error
|
IsSwarmCompatible() error
|
||||||
SubscribeToEvents(since, until time.Time, filter filters.Args) ([]events.Message, chan interface{})
|
SubscribeToEvents(since, until time.Time, filter filters.Args) ([]events.Message, chan interface{})
|
||||||
UnsubscribeFromEvents(listener chan interface{})
|
UnsubscribeFromEvents(listener chan interface{})
|
||||||
|
|
|
@ -446,8 +446,22 @@ func (daemon *Daemon) registerLink(parent, child *container.Container, alias str
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetClusterProvider sets a component for querying the current cluster state.
|
// DaemonJoinsCluster informs the daemon has joined the cluster and provides
|
||||||
func (daemon *Daemon) SetClusterProvider(clusterProvider cluster.Provider) {
|
// the handler to query the cluster component
|
||||||
|
func (daemon *Daemon) DaemonJoinsCluster(clusterProvider cluster.Provider) {
|
||||||
|
daemon.setClusterProvider(clusterProvider)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DaemonLeavesCluster informs the daemon has left the cluster
|
||||||
|
func (daemon *Daemon) DaemonLeavesCluster() {
|
||||||
|
// Daemon is in charge of removing the attachable networks with
|
||||||
|
// connected containers when the node leaves the swarm
|
||||||
|
daemon.clearAttachableNetworks()
|
||||||
|
daemon.setClusterProvider(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// setClusterProvider sets a component for querying the current cluster state.
|
||||||
|
func (daemon *Daemon) setClusterProvider(clusterProvider cluster.Provider) {
|
||||||
daemon.clusterProvider = clusterProvider
|
daemon.clusterProvider = clusterProvider
|
||||||
daemon.netController.SetClusterProvider(clusterProvider)
|
daemon.netController.SetClusterProvider(clusterProvider)
|
||||||
}
|
}
|
||||||
|
|
|
@ -468,3 +468,31 @@ func (daemon *Daemon) deleteNetwork(networkID string, dynamic bool) error {
|
||||||
func (daemon *Daemon) GetNetworks() []libnetwork.Network {
|
func (daemon *Daemon) GetNetworks() []libnetwork.Network {
|
||||||
return daemon.getAllNetworks()
|
return daemon.getAllNetworks()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clearAttachableNetworks removes the attachable networks
|
||||||
|
// after disconnecting any connected container
|
||||||
|
func (daemon *Daemon) clearAttachableNetworks() {
|
||||||
|
for _, n := range daemon.GetNetworks() {
|
||||||
|
if !n.Info().Attachable() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, ep := range n.Endpoints() {
|
||||||
|
epInfo := ep.Info()
|
||||||
|
if epInfo == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
sb := epInfo.Sandbox()
|
||||||
|
if sb == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
containerID := sb.ContainerID()
|
||||||
|
if err := daemon.DisconnectContainerFromNetwork(containerID, n.ID(), true); err != nil {
|
||||||
|
logrus.Warnf("Failed to disconnect container %s from swarm network %s on cluster leave: %v",
|
||||||
|
containerID, n.Name(), err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := daemon.DeleteManagedNetwork(n.ID()); err != nil {
|
||||||
|
logrus.Warnf("Failed to remove swarm network %s on cluster leave: %v", n.Name(), err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -393,6 +393,33 @@ func (s *DockerSwarmSuite) TestOverlayAttachable(c *check.C) {
|
||||||
c.Assert(strings.TrimSpace(out), checker.Equals, "true")
|
c.Assert(strings.TrimSpace(out), checker.Equals, "true")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *DockerSwarmSuite) TestOverlayAttachableOnSwarmLeave(c *check.C) {
|
||||||
|
d := s.AddDaemon(c, true, true)
|
||||||
|
|
||||||
|
// Create an attachable swarm network
|
||||||
|
nwName := "attovl"
|
||||||
|
out, err := d.Cmd("network", "create", "-d", "overlay", "--attachable", nwName)
|
||||||
|
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||||
|
|
||||||
|
// Connect a container to the network
|
||||||
|
out, err = d.Cmd("run", "-d", "--network", nwName, "--name", "c1", "busybox", "top")
|
||||||
|
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||||
|
|
||||||
|
// Leave the swarm
|
||||||
|
err = d.Leave(true)
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
|
// Check the container is disconnected
|
||||||
|
out, err = d.Cmd("inspect", "c1", "--format", "{{.NetworkSettings.Networks."+nwName+"}}")
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
c.Assert(strings.TrimSpace(out), checker.Equals, "<no value>")
|
||||||
|
|
||||||
|
// Check the network is gone
|
||||||
|
out, err = d.Cmd("network", "ls", "--format", "{{.Name}}")
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
c.Assert(out, checker.Not(checker.Contains), nwName)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *DockerSwarmSuite) TestSwarmRemoveInternalNetwork(c *check.C) {
|
func (s *DockerSwarmSuite) TestSwarmRemoveInternalNetwork(c *check.C) {
|
||||||
d := s.AddDaemon(c, true, true)
|
d := s.AddDaemon(c, true, true)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue