diff --git a/daemon/container_unix.go b/daemon/container_unix.go index 2cda0402f..5864e7db7 100644 --- a/daemon/container_unix.go +++ b/daemon/container_unix.go @@ -910,6 +910,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 } @@ -934,23 +936,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 } @@ -972,9 +983,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 @@ -1120,14 +1131,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) } @@ -1139,10 +1142,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 @@ -1172,20 +1175,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 }