diff --git a/daemon/container_unix.go b/daemon/container_unix.go index ef708c104e..2e80646ac0 100644 --- a/daemon/container_unix.go +++ b/daemon/container_unix.go @@ -914,6 +914,8 @@ func (container *Container) ConnectToNetwork(idOrName string) error { } func (container *Container) connectToNetwork(idOrName string, updateSettings bool) error { + var err error + if container.hostConfig.NetworkMode.IsContainer() { return runconfig.ErrConflictSharedNetwork } @@ -938,23 +940,32 @@ func (container *Container) connectToNetwork(idOrName string, updateSettings boo } ep, err := container.getEndpointInNetwork(n) - if err != nil { - if _, ok := err.(libnetwork.ErrNoSuchEndpoint); !ok { - return err - } - - createOptions, err := container.buildCreateEndpointOptions() - if err != nil { - return err - } - - endpointName := strings.TrimPrefix(container.Name, "/") - ep, err = n.CreateEndpoint(endpointName, createOptions...) - if err != nil { - return err - } + if err == nil { + return fmt.Errorf("container already connected to network %s", idOrName) } + if _, ok := err.(libnetwork.ErrNoSuchEndpoint); !ok { + return err + } + + createOptions, err := container.buildCreateEndpointOptions() + if err != nil { + return err + } + + endpointName := strings.TrimPrefix(container.Name, "/") + ep, err = n.CreateEndpoint(endpointName, createOptions...) + if err != nil { + return err + } + defer func() { + if err != nil { + if e := ep.Delete(); e != nil { + logrus.Warnf("Could not rollback container connection to network %s", idOrName) + } + } + }() + if err := container.updateEndpointNetworkSettings(n, ep); err != nil { return err } @@ -976,9 +987,9 @@ func (container *Container) connectToNetwork(idOrName string, updateSettings boo if err != nil { return err } - } - container.updateSandboxNetworkSettings(sb) + container.updateSandboxNetworkSettings(sb) + } if err := ep.Join(sb); err != nil { return err @@ -1124,14 +1135,6 @@ func (container *Container) releaseNetwork() { return } - for _, ns := range networks { - n, err := container.daemon.FindNetwork(ns) - if err != nil { - continue - } - container.disconnectFromNetwork(n, false) - } - if err := sb.Delete(); err != nil { logrus.Errorf("Error deleting sandbox id %s for container %s: %v", sid, container.ID, err) } @@ -1143,10 +1146,10 @@ func (container *Container) DisconnectFromNetwork(n libnetwork.Network) error { return derr.ErrorCodeNotRunning.WithArgs(container.ID) } - return container.disconnectFromNetwork(n, true) + return container.disconnectFromNetwork(n) } -func (container *Container) disconnectFromNetwork(n libnetwork.Network, updateSettings bool) error { +func (container *Container) disconnectFromNetwork(n libnetwork.Network) error { var ( ep libnetwork.Endpoint sbox libnetwork.Sandbox @@ -1176,20 +1179,19 @@ func (container *Container) disconnectFromNetwork(n libnetwork.Network, updateSe return fmt.Errorf("endpoint delete failed for container %s on network %s: %v", container.ID, n.Name(), err) } - if updateSettings { - networks := container.NetworkSettings.Networks - for i, s := range networks { - sn, err := container.daemon.FindNetwork(s) - if err != nil { - continue - } - if sn.Name() == n.Name() { - networks = append(networks[:i], networks[i+1:]...) - container.NetworkSettings.Networks = networks - break - } + networks := container.NetworkSettings.Networks + for i, s := range networks { + sn, err := container.daemon.FindNetwork(s) + if err != nil { + continue + } + if sn.Name() == n.Name() { + networks = append(networks[:i], networks[i+1:]...) + container.NetworkSettings.Networks = networks + break } } + return nil }