Sfoglia il codice sorgente

Docker side changes for the newly introduced IPAM driver

* Made use of IPAM driver primitives for legacy IP configurations
* Replaced custom Generics with backend labels

Signed-off-by: Madhu Venugopal <madhu@docker.com>
Madhu Venugopal 9 anni fa
parent
commit
0f351ce364

+ 4 - 4
api/server/router/network/network_routes.go

@@ -204,12 +204,12 @@ func buildEndpointResource(e libnetwork.Endpoint) types.EndpointResource {
 		if mac := iface.MacAddress(); mac != nil {
 			er.MacAddress = mac.String()
 		}
-		if ip := iface.Address(); len(ip.IP) > 0 {
-			er.IPv4Address = (&ip).String()
+		if ip := iface.Address(); ip != nil && len(ip.IP) > 0 {
+			er.IPv4Address = ip.String()
 		}
 
-		if ipv6 := iface.AddressIPv6(); len(ipv6.IP) > 0 {
-			er.IPv6Address = (&ipv6).String()
+		if ipv6 := iface.AddressIPv6(); ipv6 != nil && len(ipv6.IP) > 0 {
+			er.IPv6Address = ipv6.String()
 		}
 	}
 	return er

+ 10 - 8
daemon/container_unix.go

@@ -30,6 +30,7 @@ import (
 	"github.com/docker/docker/volume"
 	"github.com/docker/docker/volume/store"
 	"github.com/docker/libnetwork"
+	"github.com/docker/libnetwork/drivers/bridge"
 	"github.com/docker/libnetwork/netlabel"
 	"github.com/docker/libnetwork/options"
 	"github.com/docker/libnetwork/types"
@@ -651,11 +652,13 @@ func (container *Container) buildEndpointInfo(ep libnetwork.Endpoint, networkSet
 		return networkSettings, nil
 	}
 
-	ones, _ := iface.Address().Mask.Size()
-	networkSettings.IPAddress = iface.Address().IP.String()
-	networkSettings.IPPrefixLen = ones
+	if iface.Address() != nil {
+		ones, _ := iface.Address().Mask.Size()
+		networkSettings.IPAddress = iface.Address().IP.String()
+		networkSettings.IPPrefixLen = ones
+	}
 
-	if iface.AddressIPv6().IP.To16() != nil {
+	if iface.AddressIPv6() != nil && iface.AddressIPv6().IP.To16() != nil {
 		onesv6, _ := iface.AddressIPv6().Mask.Size()
 		networkSettings.GlobalIPv6Address = iface.AddressIPv6().IP.String()
 		networkSettings.GlobalIPv6PrefixLen = onesv6
@@ -861,9 +864,8 @@ func createNetwork(controller libnetwork.NetworkController, dnet string, driver
 
 	// Bridge driver is special due to legacy reasons
 	if runconfig.NetworkMode(driver).IsBridge() {
-		genericOption[netlabel.GenericData] = map[string]interface{}{
-			"BridgeName":            dnet,
-			"AllowNonDefaultBridge": "true",
+		genericOption[netlabel.GenericData] = map[string]string{
+			bridge.BridgeName: dnet,
 		}
 		networkOption := libnetwork.NetworkOptionGeneric(genericOption)
 		createOptions = append(createOptions, networkOption)
@@ -1163,7 +1165,7 @@ func (container *Container) disconnectFromNetwork(n libnetwork.Network, updateSe
 	n.WalkEndpoints(s)
 
 	if ep == nil {
-		return fmt.Errorf("could not locate network endpoint for container %s", container.ID)
+		return fmt.Errorf("container %s is not connected to the network", container.ID)
 	}
 
 	if err := ep.Leave(sbox); err != nil {

+ 62 - 23
daemon/daemon_unix.go

@@ -7,6 +7,7 @@ import (
 	"net"
 	"os"
 	"path/filepath"
+	"strconv"
 	"strings"
 	"syscall"
 
@@ -23,8 +24,11 @@ import (
 	"github.com/docker/docker/utils"
 	"github.com/docker/libnetwork"
 	nwconfig "github.com/docker/libnetwork/config"
+	"github.com/docker/libnetwork/drivers/bridge"
+	"github.com/docker/libnetwork/ipamutils"
 	"github.com/docker/libnetwork/netlabel"
 	"github.com/docker/libnetwork/options"
+	"github.com/docker/libnetwork/types"
 	"github.com/opencontainers/runc/libcontainer/label"
 	"github.com/vishvananda/netlink"
 )
@@ -312,6 +316,9 @@ func (daemon *Daemon) networkOptions(dconfig *Config) ([]nwconfig.Option, error)
 	if dconfig == nil {
 		return options, nil
 	}
+
+	options = append(options, nwconfig.OptionDataDir(dconfig.Root))
+
 	if strings.TrimSpace(dconfig.DefaultNetwork) != "" {
 		dn := strings.Split(dconfig.DefaultNetwork, ":")
 		if len(dn) < 2 {
@@ -392,22 +399,48 @@ func driverOptions(config *Config) []nwconfig.Option {
 }
 
 func initBridgeDriver(controller libnetwork.NetworkController, config *Config) error {
-	netOption := options.Generic{
-		"BridgeName":         config.Bridge.Iface,
-		"DefaultBridge":      true,
-		"Mtu":                config.Mtu,
-		"EnableIPMasquerade": config.Bridge.EnableIPMasq,
-		"EnableICC":          config.Bridge.InterContainerCommunication,
+	if n, err := controller.NetworkByName("bridge"); err == nil {
+		if err = n.Delete(); err != nil {
+			return fmt.Errorf("could not delete the default bridge network: %v", err)
+		}
+	}
+
+	bridgeName := bridge.DefaultBridgeName
+	if config.Bridge.Iface != "" {
+		bridgeName = config.Bridge.Iface
+	}
+	netOption := map[string]string{
+		bridge.BridgeName:         bridgeName,
+		bridge.DefaultBridge:      strconv.FormatBool(true),
+		netlabel.DriverMTU:        strconv.Itoa(config.Mtu),
+		bridge.EnableIPMasquerade: strconv.FormatBool(config.Bridge.EnableIPMasq),
+		bridge.EnableICC:          strconv.FormatBool(config.Bridge.InterContainerCommunication),
+	}
+
+	// --ip processing
+	if config.Bridge.DefaultIP != nil {
+		netOption[bridge.DefaultBindingIP] = config.Bridge.DefaultIP.String()
+	}
+
+	ipamV4Conf := libnetwork.IpamConf{}
+
+	ipamV4Conf.AuxAddresses = make(map[string]string)
+
+	if nw, _, err := ipamutils.ElectInterfaceAddresses(bridgeName); err == nil {
+		ipamV4Conf.PreferredPool = nw.String()
+		hip, _ := types.GetHostPartIP(nw.IP, nw.Mask)
+		if hip.IsGlobalUnicast() {
+			ipamV4Conf.Gateway = nw.IP.String()
+		}
 	}
 
 	if config.Bridge.IP != "" {
-		ip, bipNet, err := net.ParseCIDR(config.Bridge.IP)
+		ipamV4Conf.PreferredPool = config.Bridge.IP
+		ip, _, err := net.ParseCIDR(config.Bridge.IP)
 		if err != nil {
 			return err
 		}
-
-		bipNet.IP = ip
-		netOption["AddressIPv4"] = bipNet
+		ipamV4Conf.Gateway = ip.String()
 	}
 
 	if config.Bridge.FixedCIDR != "" {
@@ -416,38 +449,44 @@ func initBridgeDriver(controller libnetwork.NetworkController, config *Config) e
 			return err
 		}
 
-		netOption["FixedCIDR"] = fCIDR
+		ipamV4Conf.SubPool = fCIDR.String()
 	}
 
+	if config.Bridge.DefaultGatewayIPv4 != nil {
+		ipamV4Conf.AuxAddresses["DefaultGatewayIPv4"] = config.Bridge.DefaultGatewayIPv4.String()
+	}
+
+	var ipamV6Conf *libnetwork.IpamConf
 	if config.Bridge.FixedCIDRv6 != "" {
 		_, fCIDRv6, err := net.ParseCIDR(config.Bridge.FixedCIDRv6)
 		if err != nil {
 			return err
 		}
-
-		netOption["FixedCIDRv6"] = fCIDRv6
-	}
-
-	if config.Bridge.DefaultGatewayIPv4 != nil {
-		netOption["DefaultGatewayIPv4"] = config.Bridge.DefaultGatewayIPv4
+		if ipamV6Conf == nil {
+			ipamV6Conf = &libnetwork.IpamConf{}
+		}
+		ipamV6Conf.PreferredPool = fCIDRv6.String()
 	}
 
 	if config.Bridge.DefaultGatewayIPv6 != nil {
-		netOption["DefaultGatewayIPv6"] = config.Bridge.DefaultGatewayIPv6
+		if ipamV6Conf == nil {
+			ipamV6Conf = &libnetwork.IpamConf{}
+		}
+		ipamV6Conf.AuxAddresses["DefaultGatewayIPv6"] = config.Bridge.DefaultGatewayIPv6.String()
 	}
 
-	// --ip processing
-	if config.Bridge.DefaultIP != nil {
-		netOption["DefaultBindingIP"] = config.Bridge.DefaultIP
+	v4Conf := []*libnetwork.IpamConf{&ipamV4Conf}
+	v6Conf := []*libnetwork.IpamConf{}
+	if ipamV6Conf != nil {
+		v6Conf = append(v6Conf, ipamV6Conf)
 	}
-
 	// Initialize default network on "bridge" with the same name
 	_, err := controller.NewNetwork("bridge", "bridge",
 		libnetwork.NetworkOptionGeneric(options.Generic{
 			netlabel.GenericData: netOption,
 			netlabel.EnableIPv6:  config.Bridge.EnableIPv6,
 		}),
-		libnetwork.NetworkOptionPersist(false))
+		libnetwork.NetworkOptionIpam("default", "", v4Conf, v6Conf))
 	if err != nil {
 		return fmt.Errorf("Error creating default \"bridge\" network: %v", err)
 	}

+ 6 - 20
daemon/network.go

@@ -6,6 +6,7 @@ import (
 
 	"github.com/docker/libnetwork"
 	"github.com/docker/libnetwork/netlabel"
+	"github.com/docker/libnetwork/options"
 )
 
 const (
@@ -78,29 +79,14 @@ func (daemon *Daemon) GetNetworksByID(partialID string) []libnetwork.Network {
 }
 
 // CreateNetwork creates a network with the given name, driver and other optional parameters
-func (daemon *Daemon) CreateNetwork(name, driver string, options map[string]interface{}) (libnetwork.Network, error) {
+func (daemon *Daemon) CreateNetwork(name, driver string, labels map[string]interface{}) (libnetwork.Network, error) {
 	c := daemon.netController
 	if driver == "" {
 		driver = c.Config().Daemon.DefaultDriver
 	}
+	option := libnetwork.NetworkOptionGeneric(options.Generic{
+		netlabel.GenericData: map[string]string{},
+	})
 
-	if options == nil {
-		options = make(map[string]interface{})
-	}
-	_, ok := options[netlabel.GenericData]
-	if !ok {
-		options[netlabel.GenericData] = make(map[string]interface{})
-	}
-
-	return c.NewNetwork(driver, name, parseOptions(options)...)
-}
-
-func parseOptions(options map[string]interface{}) []libnetwork.NetworkOption {
-	var setFctList []libnetwork.NetworkOption
-
-	if options != nil {
-		setFctList = append(setFctList, libnetwork.NetworkOptionGeneric(options))
-	}
-
-	return setFctList
+	return c.NewNetwork(driver, name, option)
 }

+ 2 - 2
daemon/stats.go

@@ -8,7 +8,7 @@ import (
 	"github.com/docker/docker/api/types/versions/v1p20"
 	"github.com/docker/docker/daemon/execdriver"
 	"github.com/docker/docker/pkg/version"
-	"github.com/docker/libnetwork/osl"
+	lntypes "github.com/docker/libnetwork/types"
 	"github.com/opencontainers/runc/libcontainer"
 )
 
@@ -166,7 +166,7 @@ func (daemon *Daemon) getNetworkStats(c *Container) ([]*libcontainer.NetworkInte
 	return list, nil
 }
 
-func convertLnNetworkStats(name string, stats *osl.InterfaceStatistics) *libcontainer.NetworkInterface {
+func convertLnNetworkStats(name string, stats *lntypes.InterfaceStatistics) *libcontainer.NetworkInterface {
 	n := &libcontainer.NetworkInterface{Name: name}
 	n.RxBytes = stats.RxBytes
 	n.RxPackets = stats.RxPackets

+ 1 - 1
integration-cli/docker_cli_daemon_test.go

@@ -787,7 +787,7 @@ func (s *DockerDaemonSuite) TestDaemonBridgeFixedCidr(c *check.C) {
 		cName := "Container" + strconv.Itoa(i)
 		out, err := d.Cmd("run", "-d", "--name", cName, "busybox", "top")
 		if err != nil {
-			c.Assert(strings.Contains(out, "no available ip addresses"), check.Equals, true,
+			c.Assert(strings.Contains(out, "no available IPv4 addresses"), check.Equals, true,
 				check.Commentf("Could not run a Container : %s %s", err.Error(), out))
 		}
 	}