Windows: Refactor network modes

Signed-off-by: John Howard <jhoward@microsoft.com>
This commit is contained in:
John Howard 2015-06-23 10:13:42 -07:00
parent aa4f495cae
commit c5e6a4b307
10 changed files with 250 additions and 131 deletions

View file

@ -65,22 +65,17 @@ func populateCommand(c *Container, env []string) error {
Interface: nil,
}
// TODO Windows. Appropriate network mode (will refactor as part of
// libnetwork. For now, even through bridge not used, let it succeed to
// allow the Windows daemon to limp during its bring-up
parts := strings.SplitN(string(c.hostConfig.NetworkMode), ":", 2)
switch parts[0] {
case "none":
case "bridge", "": // empty string to support existing containers
case "default", "": // empty string to support existing containers
if !c.Config.NetworkDisabled {
network := c.NetworkSettings
en.Interface = &execdriver.NetworkInterface{
Bridge: network.Bridge,
MacAddress: network.MacAddress,
}
}
case "host", "container":
return fmt.Errorf("unsupported network mode: %s", c.hostConfig.NetworkMode)
default:
return fmt.Errorf("invalid network mode: %s", c.hostConfig.NetworkMode)
}

View file

@ -29,7 +29,6 @@ import (
"github.com/docker/docker/pkg/graphdb"
"github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/namesgenerator"
"github.com/docker/docker/pkg/parsers"
"github.com/docker/docker/pkg/stringid"
"github.com/docker/docker/pkg/sysinfo"
"github.com/docker/docker/pkg/system"
@ -553,43 +552,6 @@ func (daemon *Daemon) RegisterLink(parent, child *Container, alias string) error
return nil
}
func (daemon *Daemon) RegisterLinks(container *Container, hostConfig *runconfig.HostConfig) error {
if hostConfig != nil && hostConfig.Links != nil {
for _, l := range hostConfig.Links {
name, alias, err := parsers.ParseLink(l)
if err != nil {
return err
}
child, err := daemon.Get(name)
if err != nil {
//An error from daemon.Get() means this name could not be found
return fmt.Errorf("Could not get container for %s", name)
}
for child.hostConfig.NetworkMode.IsContainer() {
parts := strings.SplitN(string(child.hostConfig.NetworkMode), ":", 2)
child, err = daemon.Get(parts[1])
if err != nil {
return fmt.Errorf("Could not get container for %s", parts[1])
}
}
if child.hostConfig.NetworkMode.IsHost() {
return runconfig.ErrConflictHostNetworkAndLinks
}
if err := daemon.RegisterLink(container, child, alias); err != nil {
return err
}
}
// After we load all the links into the daemon
// set them to nil on the hostconfig
hostConfig.Links = nil
if err := container.WriteHostConfig(); err != nil {
return err
}
}
return nil
}
func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemon, err error) {
setDefaultMtu(config)

View file

@ -17,6 +17,7 @@ import (
"github.com/docker/docker/daemon/graphdriver"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/fileutils"
"github.com/docker/docker/pkg/parsers"
"github.com/docker/docker/pkg/parsers/kernel"
"github.com/docker/docker/pkg/system"
"github.com/docker/docker/runconfig"
@ -460,3 +461,44 @@ func setupInitLayer(initLayer string) error {
func (daemon *Daemon) NetworkApiRouter() func(w http.ResponseWriter, req *http.Request) {
return nwapi.NewHTTPHandler(daemon.netController)
}
func (daemon *Daemon) RegisterLinks(container *Container, hostConfig *runconfig.HostConfig) error {
if hostConfig == nil || hostConfig.Links == nil {
return nil
}
for _, l := range hostConfig.Links {
name, alias, err := parsers.ParseLink(l)
if err != nil {
return err
}
child, err := daemon.Get(name)
if err != nil {
//An error from daemon.Get() means this name could not be found
return fmt.Errorf("Could not get container for %s", name)
}
for child.hostConfig.NetworkMode.IsContainer() {
parts := strings.SplitN(string(child.hostConfig.NetworkMode), ":", 2)
child, err = daemon.Get(parts[1])
if err != nil {
return fmt.Errorf("Could not get container for %s", parts[1])
}
}
if child.hostConfig.NetworkMode.IsHost() {
return runconfig.ErrConflictHostNetworkAndLinks
}
if err := daemon.RegisterLink(container, child, alias); err != nil {
return err
}
}
// After we load all the links into the daemon
// set them to nil on the hostconfig
hostConfig.Links = nil
if err := container.WriteHostConfig(); err != nil {
return err
}
return nil
}

View file

@ -8,6 +8,7 @@ import (
"github.com/docker/docker/daemon/graphdriver"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/parsers"
"github.com/docker/docker/runconfig"
"github.com/docker/libnetwork"
)
@ -103,3 +104,35 @@ func initNetworkController(config *Config) (libnetwork.NetworkController, error)
// TODO Windows
return nil, nil
}
func (daemon *Daemon) RegisterLinks(container *Container, hostConfig *runconfig.HostConfig) error {
// TODO Windows. Factored out for network modes. There may be more
// refactoring required here.
if hostConfig == nil || hostConfig.Links == nil {
return nil
}
for _, l := range hostConfig.Links {
name, alias, err := parsers.ParseLink(l)
if err != nil {
return err
}
child, err := daemon.Get(name)
if err != nil {
//An error from daemon.Get() means this name could not be found
return fmt.Errorf("Could not get container for %s", name)
}
if err := daemon.RegisterLink(container, child, alias); err != nil {
return err
}
}
// After we load all the links into the daemon
// set them to nil on the hostconfig
hostConfig.Links = nil
if err := container.WriteHostConfig(); err != nil {
return err
}
return nil
}

View file

@ -16,51 +16,6 @@ type KeyValuePair struct {
type NetworkMode string
// IsPrivate indicates whether container use it's private network stack
func (n NetworkMode) IsPrivate() bool {
return !(n.IsHost() || n.IsContainer())
}
func (n NetworkMode) IsDefault() bool {
return n == "default"
}
func DefaultDaemonNetworkMode() NetworkMode {
return NetworkMode("bridge")
}
func (n NetworkMode) NetworkName() string {
if n.IsBridge() {
return "bridge"
} else if n.IsHost() {
return "host"
} else if n.IsContainer() {
return "container"
} else if n.IsNone() {
return "none"
} else if n.IsDefault() {
return "default"
}
return ""
}
func (n NetworkMode) IsBridge() bool {
return n == "bridge"
}
func (n NetworkMode) IsHost() bool {
return n == "host"
}
func (n NetworkMode) IsContainer() bool {
parts := strings.SplitN(string(n), ":", 2)
return len(parts) > 1 && parts[0] == "container"
}
func (n NetworkMode) IsNone() bool {
return n == "none"
}
type IpcMode string
// IsPrivate indicates whether container use it's private ipc stack

View file

@ -0,0 +1,52 @@
// +build !windows
package runconfig
import (
"strings"
)
// IsPrivate indicates whether container use it's private network stack
func (n NetworkMode) IsPrivate() bool {
return !(n.IsHost() || n.IsContainer())
}
func (n NetworkMode) IsDefault() bool {
return n == "default"
}
func DefaultDaemonNetworkMode() NetworkMode {
return NetworkMode("bridge")
}
func (n NetworkMode) NetworkName() string {
if n.IsBridge() {
return "bridge"
} else if n.IsHost() {
return "host"
} else if n.IsContainer() {
return "container"
} else if n.IsNone() {
return "none"
} else if n.IsDefault() {
return "default"
}
return ""
}
func (n NetworkMode) IsBridge() bool {
return n == "bridge"
}
func (n NetworkMode) IsHost() bool {
return n == "host"
}
func (n NetworkMode) IsContainer() bool {
parts := strings.SplitN(string(n), ":", 2)
return len(parts) > 1 && parts[0] == "container"
}
func (n NetworkMode) IsNone() bool {
return n == "none"
}

View file

@ -0,0 +1,18 @@
// +build !windows
package runconfig
func (n NetworkMode) IsDefault() bool {
return n == "default"
}
func DefaultDaemonNetworkMode() NetworkMode {
return NetworkMode("default")
}
func (n NetworkMode) NetworkName() string {
if n.IsDefault() {
return "default"
}
return ""
}

View file

@ -24,6 +24,19 @@ var (
ErrConflictNetworkExposePorts = fmt.Errorf("Conflicting options: --expose and the network mode (--expose)")
)
// validateNM is the set of fields passed to validateNetMode()
type validateNM struct {
netMode NetworkMode
flHostname *string
flLinks opts.ListOpts
flDns opts.ListOpts
flExtraHosts opts.ListOpts
flMacAddress *string
flPublish opts.ListOpts
flPublishAll *bool
flExpose opts.ListOpts
}
func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSet, error) {
var (
// FIXME: use utils.ListOpts for attach and volumes?
@ -121,37 +134,22 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
return nil, nil, cmd, fmt.Errorf("--net: invalid net mode: %v", err)
}
if (netMode.IsHost() || netMode.IsContainer()) && *flHostname != "" {
return nil, nil, cmd, ErrConflictNetworkHostname
vals := validateNM{
netMode: netMode,
flHostname: flHostname,
flLinks: flLinks,
flDns: flDns,
flExtraHosts: flExtraHosts,
flMacAddress: flMacAddress,
flPublish: flPublish,
flPublishAll: flPublishAll,
flExpose: flExpose,
}
if netMode.IsHost() && flLinks.Len() > 0 {
return nil, nil, cmd, ErrConflictHostNetworkAndLinks
if err := validateNetMode(&vals); err != nil {
return nil, nil, cmd, err
}
if netMode.IsContainer() && flLinks.Len() > 0 {
return nil, nil, cmd, ErrConflictContainerNetworkAndLinks
}
if (netMode.IsHost() || netMode.IsContainer()) && flDns.Len() > 0 {
return nil, nil, cmd, ErrConflictNetworkAndDns
}
if (netMode.IsContainer() || netMode.IsHost()) && flExtraHosts.Len() > 0 {
return nil, nil, cmd, ErrConflictNetworkHosts
}
if (netMode.IsContainer() || netMode.IsHost()) && *flMacAddress != "" {
return nil, nil, cmd, ErrConflictContainerNetworkAndMac
}
if netMode.IsContainer() && (flPublish.Len() > 0 || *flPublishAll == true) {
return nil, nil, cmd, ErrConflictNetworkPublishPorts
}
if netMode.IsContainer() && flExpose.Len() > 0 {
return nil, nil, cmd, ErrConflictNetworkExposePorts
}
// Validate the input mac address
if *flMacAddress != "" {
if _, err := opts.ValidateMACAddress(*flMacAddress); err != nil {
@ -463,20 +461,6 @@ func parseKeyValueOpts(opts opts.ListOpts) ([]KeyValuePair, error) {
return out, nil
}
func parseNetMode(netMode string) (NetworkMode, error) {
parts := strings.Split(netMode, ":")
switch mode := parts[0]; mode {
case "default", "bridge", "none", "host":
case "container":
if len(parts) < 2 || parts[1] == "" {
return "", fmt.Errorf("invalid container format container:<name|id>")
}
default:
return "", fmt.Errorf("invalid --net: %s", netMode)
}
return NetworkMode(netMode), nil
}
func ParseDevice(device string) (DeviceMapping, error) {
src := ""
dst := ""

58
runconfig/parse_unix.go Normal file
View file

@ -0,0 +1,58 @@
// +build !windows
package runconfig
import (
"fmt"
"strings"
)
func parseNetMode(netMode string) (NetworkMode, error) {
parts := strings.Split(netMode, ":")
switch mode := parts[0]; mode {
case "default", "bridge", "none", "host":
case "container":
if len(parts) < 2 || parts[1] == "" {
return "", fmt.Errorf("invalid container format container:<name|id>")
}
default:
return "", fmt.Errorf("invalid --net: %s", netMode)
}
return NetworkMode(netMode), nil
}
func validateNetMode(vals *validateNM) error {
if (vals.netMode.IsHost() || vals.netMode.IsContainer()) && *vals.flHostname != "" {
return ErrConflictNetworkHostname
}
if vals.netMode.IsHost() && vals.flLinks.Len() > 0 {
return ErrConflictHostNetworkAndLinks
}
if vals.netMode.IsContainer() && vals.flLinks.Len() > 0 {
return ErrConflictContainerNetworkAndLinks
}
if (vals.netMode.IsHost() || vals.netMode.IsContainer()) && vals.flDns.Len() > 0 {
return ErrConflictNetworkAndDns
}
if (vals.netMode.IsContainer() || vals.netMode.IsHost()) && vals.flExtraHosts.Len() > 0 {
return ErrConflictNetworkHosts
}
if (vals.netMode.IsContainer() || vals.netMode.IsHost()) && *vals.flMacAddress != "" {
return ErrConflictContainerNetworkAndMac
}
if vals.netMode.IsContainer() && (vals.flPublish.Len() > 0 || *vals.flPublishAll == true) {
return ErrConflictNetworkPublishPorts
}
if vals.netMode.IsContainer() && vals.flExpose.Len() > 0 {
return ErrConflictNetworkExposePorts
}
return nil
}

View file

@ -0,0 +1,20 @@
package runconfig
import (
"fmt"
"strings"
)
func parseNetMode(netMode string) (NetworkMode, error) {
parts := strings.Split(netMode, ":")
switch mode := parts[0]; mode {
case "default":
default:
return "", fmt.Errorf("invalid --net: %s", netMode)
}
return NetworkMode(netMode), nil
}
func validateNetMode(vals *validateNM) error {
return nil
}