diff --git a/daemon/container_operations.go b/daemon/container_operations.go index 22883e0360..64335b0218 100644 --- a/daemon/container_operations.go +++ b/daemon/container_operations.go @@ -6,6 +6,7 @@ import ( "net" "os" "path" + "runtime" "strings" "github.com/Sirupsen/logrus" @@ -907,3 +908,83 @@ func (daemon *Daemon) releaseNetwork(container *container.Container) { daemon.LogNetworkEventWithAttributes(nw, "disconnect", attributes) } } + +func errRemovalContainer(containerID string) error { + return fmt.Errorf("Container %s is marked for removal and cannot be connected or disconnected to the network", containerID) +} + +// ConnectToNetwork connects a container to a network +func (daemon *Daemon) ConnectToNetwork(container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings) error { + if endpointConfig == nil { + endpointConfig = &networktypes.EndpointSettings{} + } + if !container.Running { + if container.RemovalInProgress || container.Dead { + return errRemovalContainer(container.ID) + } + + n, err := daemon.FindNetwork(idOrName) + if err == nil && n != nil { + if err := daemon.updateNetworkConfig(container, n, endpointConfig, true); err != nil { + return err + } + } else { + container.NetworkSettings.Networks[idOrName] = &network.EndpointSettings{ + EndpointSettings: endpointConfig, + } + } + } else if !daemon.isNetworkHotPluggable() { + return fmt.Errorf(runtime.GOOS + " does not support connecting a running container to a network") + } else { + if err := daemon.connectToNetwork(container, idOrName, endpointConfig, true); err != nil { + return err + } + } + if err := container.ToDiskLocking(); err != nil { + return fmt.Errorf("Error saving container to disk: %v", err) + } + return nil +} + +// DisconnectFromNetwork disconnects container from network n. +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) + } + // In case networkName is resolved we will use n.Name() + // this will cover the case where network id is passed. + if n != nil { + networkName = n.Name() + } + if _, ok := container.NetworkSettings.Networks[networkName]; !ok { + return fmt.Errorf("container %s is not connected to the network %s", container.ID, networkName) + } + delete(container.NetworkSettings.Networks, networkName) + } else if err == nil && !daemon.isNetworkHotPluggable() { + return fmt.Errorf(runtime.GOOS + " does not support connecting a running container to a network") + } else if err == nil { + if container.HostConfig.NetworkMode.IsHost() && containertypes.NetworkMode(n.Type()).IsHost() { + return runconfig.ErrConflictHostNetwork + } + + if err := daemon.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) + } + + if n != nil { + attributes := map[string]string{ + "container": container.ID, + } + daemon.LogNetworkEventWithAttributes(n, "disconnect", attributes) + } + return nil +} diff --git a/daemon/container_operations_solaris.go b/daemon/container_operations_solaris.go index 4294cd7b4f..dbc531fec3 100644 --- a/daemon/container_operations_solaris.go +++ b/daemon/container_operations_solaris.go @@ -2,32 +2,17 @@ package daemon -import ( - "fmt" - - networktypes "github.com/docker/docker/api/types/network" - "github.com/docker/docker/container" -) +import "github.com/docker/docker/container" func (daemon *Daemon) setupLinkedContainers(container *container.Container) ([]string, error) { return nil, nil } -// ConnectToNetwork connects a container to a network -func (daemon *Daemon) ConnectToNetwork(container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings) error { - return fmt.Errorf("Solaris does not support connecting a running container to a network") -} - // getSize returns real size & virtual size func (daemon *Daemon) getSize(container *container.Container) (int64, int64) { return 0, 0 } -// DisconnectFromNetwork disconnects a container from the network -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") -} - func (daemon *Daemon) setupIpcDirs(container *container.Container) error { return nil } @@ -47,3 +32,7 @@ func detachMounted(path string) error { func isLinkable(child *container.Container) bool { return false } + +func (daemon *Daemon) isNetworkHotPluggable() bool { + return false +} diff --git a/daemon/container_operations_unix.go b/daemon/container_operations_unix.go index b39115c710..930da7e7b3 100644 --- a/daemon/container_operations_unix.go +++ b/daemon/container_operations_unix.go @@ -13,10 +13,8 @@ import ( "github.com/Sirupsen/logrus" containertypes "github.com/docker/docker/api/types/container" - networktypes "github.com/docker/docker/api/types/network" "github.com/docker/docker/container" "github.com/docker/docker/daemon/links" - "github.com/docker/docker/daemon/network" "github.com/docker/docker/pkg/fileutils" "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/mount" @@ -99,78 +97,6 @@ func (daemon *Daemon) getSize(container *container.Container) (int64, int64) { return sizeRw, sizeRootfs } -// ConnectToNetwork connects a container to a network -func (daemon *Daemon) ConnectToNetwork(container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings) error { - if endpointConfig == nil { - endpointConfig = &networktypes.EndpointSettings{} - } - if !container.Running { - if container.RemovalInProgress || container.Dead { - return errRemovalContainer(container.ID) - } - - n, err := daemon.FindNetwork(idOrName) - if err == nil && n != nil { - if err := daemon.updateNetworkConfig(container, n, endpointConfig, true); err != nil { - return err - } - } else { - container.NetworkSettings.Networks[idOrName] = &network.EndpointSettings{ - EndpointSettings: endpointConfig, - } - } - } else { - if err := daemon.connectToNetwork(container, idOrName, endpointConfig, true); err != nil { - return err - } - } - if err := container.ToDiskLocking(); err != nil { - return fmt.Errorf("Error saving container to disk: %v", err) - } - return nil -} - -// DisconnectFromNetwork disconnects container from network n. -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) - } - // In case networkName is resolved we will use n.Name() - // this will cover the case where network id is passed. - if n != nil { - networkName = n.Name() - } - if _, ok := container.NetworkSettings.Networks[networkName]; !ok { - return fmt.Errorf("container %s is not connected to the network %s", container.ID, networkName) - } - delete(container.NetworkSettings.Networks, networkName) - } else if err == nil { - if container.HostConfig.NetworkMode.IsHost() && containertypes.NetworkMode(n.Type()).IsHost() { - return runconfig.ErrConflictHostNetwork - } - - if err := daemon.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) - } - - if n != nil { - attributes := map[string]string{ - "container": container.ID, - } - daemon.LogNetworkEventWithAttributes(n, "disconnect", attributes) - } - return nil -} - func (daemon *Daemon) getIpcContainer(container *container.Container) (*container.Container, error) { containerID := container.HostConfig.IpcMode.Container() c, err := daemon.GetContainer(containerID) @@ -397,10 +323,10 @@ func isLinkable(child *container.Container) bool { return ok } -func errRemovalContainer(containerID string) error { - return fmt.Errorf("Container %s is marked for removal and cannot be connected or disconnected to the network", containerID) -} - func enableIPOnPredefinedNetwork() bool { return false } + +func (daemon *Daemon) isNetworkHotPluggable() bool { + return true +} diff --git a/daemon/container_operations_windows.go b/daemon/container_operations_windows.go index 817f1a07f9..aa08aee36d 100644 --- a/daemon/container_operations_windows.go +++ b/daemon/container_operations_windows.go @@ -2,27 +2,12 @@ package daemon -import ( - "fmt" - - networktypes "github.com/docker/docker/api/types/network" - "github.com/docker/docker/container" -) +import "github.com/docker/docker/container" func (daemon *Daemon) setupLinkedContainers(container *container.Container) ([]string, error) { return nil, nil } -// ConnectToNetwork connects a container to a network -func (daemon *Daemon) ConnectToNetwork(container *container.Container, idOrName string, endpointConfig *networktypes.EndpointSettings) error { - return fmt.Errorf("Windows does not support connecting a running container to a network") -} - -// DisconnectFromNetwork disconnects container from a network. -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") -} - // getSize returns real size & virtual size func (daemon *Daemon) getSize(container *container.Container) (int64, int64) { // TODO Windows @@ -58,3 +43,7 @@ func isLinkable(child *container.Container) bool { func enableIPOnPredefinedNetwork() bool { return true } + +func (daemon *Daemon) isNetworkHotPluggable() bool { + return false +}