Kaynağa Gözat

Integrate local datascope network with swarm

Signed-off-by: Alessandro Boch <aboch@docker.com>
Alessandro Boch 8 yıl önce
ebeveyn
işleme
b34d3e730f

+ 12 - 6
api/types/swarm/network.go

@@ -1,5 +1,9 @@
 package swarm
 package swarm
 
 
+import (
+	"github.com/docker/docker/api/types/network"
+)
+
 // Endpoint represents an endpoint.
 // Endpoint represents an endpoint.
 type Endpoint struct {
 type Endpoint struct {
 	Spec       EndpointSpec        `json:",omitempty"`
 	Spec       EndpointSpec        `json:",omitempty"`
@@ -78,12 +82,14 @@ type Network struct {
 // NetworkSpec represents the spec of a network.
 // NetworkSpec represents the spec of a network.
 type NetworkSpec struct {
 type NetworkSpec struct {
 	Annotations
 	Annotations
-	DriverConfiguration *Driver      `json:",omitempty"`
-	IPv6Enabled         bool         `json:",omitempty"`
-	Internal            bool         `json:",omitempty"`
-	Attachable          bool         `json:",omitempty"`
-	Ingress             bool         `json:",omitempty"`
-	IPAMOptions         *IPAMOptions `json:",omitempty"`
+	DriverConfiguration *Driver                  `json:",omitempty"`
+	IPv6Enabled         bool                     `json:",omitempty"`
+	Internal            bool                     `json:",omitempty"`
+	Attachable          bool                     `json:",omitempty"`
+	Ingress             bool                     `json:",omitempty"`
+	IPAMOptions         *IPAMOptions             `json:",omitempty"`
+	ConfigFrom          *network.ConfigReference `json:",omitempty"`
+	Scope               string                   `json:",omitempty"`
 }
 }
 
 
 // NetworkAttachmentConfig represents the configuration of a network attachment.
 // NetworkAttachmentConfig represents the configuration of a network attachment.

+ 18 - 1
daemon/cluster/convert/network.go

@@ -6,6 +6,7 @@ import (
 	basictypes "github.com/docker/docker/api/types"
 	basictypes "github.com/docker/docker/api/types"
 	networktypes "github.com/docker/docker/api/types/network"
 	networktypes "github.com/docker/docker/api/types/network"
 	types "github.com/docker/docker/api/types/swarm"
 	types "github.com/docker/docker/api/types/swarm"
+	netconst "github.com/docker/libnetwork/datastore"
 	swarmapi "github.com/docker/swarmkit/api"
 	swarmapi "github.com/docker/swarmkit/api"
 	gogotypes "github.com/gogo/protobuf/types"
 	gogotypes "github.com/gogo/protobuf/types"
 )
 )
@@ -30,10 +31,17 @@ func networkFromGRPC(n *swarmapi.Network) types.Network {
 				Attachable:  n.Spec.Attachable,
 				Attachable:  n.Spec.Attachable,
 				Ingress:     n.Spec.Ingress,
 				Ingress:     n.Spec.Ingress,
 				IPAMOptions: ipamFromGRPC(n.Spec.IPAM),
 				IPAMOptions: ipamFromGRPC(n.Spec.IPAM),
+				Scope:       netconst.SwarmScope,
 			},
 			},
 			IPAMOptions: ipamFromGRPC(n.IPAM),
 			IPAMOptions: ipamFromGRPC(n.IPAM),
 		}
 		}
 
 
+		if n.Spec.ConfigFrom != "" {
+			network.Spec.ConfigFrom = &networktypes.ConfigReference{
+				Network: n.Spec.ConfigFrom,
+			}
+		}
+
 		// Meta
 		// Meta
 		network.Version.Index = n.Meta.Version.Index
 		network.Version.Index = n.Meta.Version.Index
 		network.CreatedAt, _ = gogotypes.TimestampFromProto(n.Meta.CreatedAt)
 		network.CreatedAt, _ = gogotypes.TimestampFromProto(n.Meta.CreatedAt)
@@ -152,7 +160,7 @@ func BasicNetworkFromGRPC(n swarmapi.Network) basictypes.NetworkResource {
 	nr := basictypes.NetworkResource{
 	nr := basictypes.NetworkResource{
 		ID:         n.ID,
 		ID:         n.ID,
 		Name:       n.Spec.Annotations.Name,
 		Name:       n.Spec.Annotations.Name,
-		Scope:      "swarm",
+		Scope:      netconst.SwarmScope,
 		EnableIPv6: spec.Ipv6Enabled,
 		EnableIPv6: spec.Ipv6Enabled,
 		IPAM:       ipam,
 		IPAM:       ipam,
 		Internal:   spec.Internal,
 		Internal:   spec.Internal,
@@ -161,6 +169,12 @@ func BasicNetworkFromGRPC(n swarmapi.Network) basictypes.NetworkResource {
 		Labels:     n.Spec.Annotations.Labels,
 		Labels:     n.Spec.Annotations.Labels,
 	}
 	}
 
 
+	if n.Spec.ConfigFrom != "" {
+		nr.ConfigFrom = networktypes.ConfigReference{
+			Network: n.Spec.ConfigFrom,
+		}
+	}
+
 	if n.DriverState != nil {
 	if n.DriverState != nil {
 		nr.Driver = n.DriverState.Name
 		nr.Driver = n.DriverState.Name
 		nr.Options = n.DriverState.Options
 		nr.Options = n.DriverState.Options
@@ -206,5 +220,8 @@ func BasicNetworkCreateToGRPC(create basictypes.NetworkCreateRequest) swarmapi.N
 		}
 		}
 		ns.IPAM.Configs = ipamSpec
 		ns.IPAM.Configs = ipamSpec
 	}
 	}
+	if create.ConfigFrom != nil {
+		ns.ConfigFrom = create.ConfigFrom.Network
+	}
 	return ns
 	return ns
 }
 }

+ 4 - 5
daemon/cluster/executor/container/adapter.go

@@ -176,7 +176,7 @@ func (c *containerAdapter) removeNetworks(ctx context.Context) error {
 }
 }
 
 
 func (c *containerAdapter) networkAttach(ctx context.Context) error {
 func (c *containerAdapter) networkAttach(ctx context.Context) error {
-	config := c.container.createNetworkingConfig()
+	config := c.container.createNetworkingConfig(c.backend)
 
 
 	var (
 	var (
 		networkName string
 		networkName string
@@ -195,7 +195,7 @@ func (c *containerAdapter) networkAttach(ctx context.Context) error {
 }
 }
 
 
 func (c *containerAdapter) waitForDetach(ctx context.Context) error {
 func (c *containerAdapter) waitForDetach(ctx context.Context) error {
-	config := c.container.createNetworkingConfig()
+	config := c.container.createNetworkingConfig(c.backend)
 
 
 	var (
 	var (
 		networkName string
 		networkName string
@@ -216,20 +216,19 @@ func (c *containerAdapter) waitForDetach(ctx context.Context) error {
 func (c *containerAdapter) create(ctx context.Context) error {
 func (c *containerAdapter) create(ctx context.Context) error {
 	var cr containertypes.ContainerCreateCreatedBody
 	var cr containertypes.ContainerCreateCreatedBody
 	var err error
 	var err error
-
 	if cr, err = c.backend.CreateManagedContainer(types.ContainerCreateConfig{
 	if cr, err = c.backend.CreateManagedContainer(types.ContainerCreateConfig{
 		Name:       c.container.name(),
 		Name:       c.container.name(),
 		Config:     c.container.config(),
 		Config:     c.container.config(),
 		HostConfig: c.container.hostConfig(),
 		HostConfig: c.container.hostConfig(),
 		// Use the first network in container create
 		// Use the first network in container create
-		NetworkingConfig: c.container.createNetworkingConfig(),
+		NetworkingConfig: c.container.createNetworkingConfig(c.backend),
 	}); err != nil {
 	}); err != nil {
 		return err
 		return err
 	}
 	}
 
 
 	// Docker daemon currently doesn't support multiple networks in container create
 	// Docker daemon currently doesn't support multiple networks in container create
 	// Connect to all other networks
 	// Connect to all other networks
-	nc := c.container.connectNetworkingConfig()
+	nc := c.container.connectNetworkingConfig(c.backend)
 
 
 	if nc != nil {
 	if nc != nil {
 		for n, ep := range nc.EndpointsConfig {
 		for n, ep := range nc.EndpointsConfig {

+ 45 - 19
daemon/cluster/executor/container/container.go

@@ -18,8 +18,10 @@ import (
 	enginemount "github.com/docker/docker/api/types/mount"
 	enginemount "github.com/docker/docker/api/types/mount"
 	"github.com/docker/docker/api/types/network"
 	"github.com/docker/docker/api/types/network"
 	volumetypes "github.com/docker/docker/api/types/volume"
 	volumetypes "github.com/docker/docker/api/types/volume"
+	executorpkg "github.com/docker/docker/daemon/cluster/executor"
 	clustertypes "github.com/docker/docker/daemon/cluster/provider"
 	clustertypes "github.com/docker/docker/daemon/cluster/provider"
 	"github.com/docker/go-connections/nat"
 	"github.com/docker/go-connections/nat"
+	netconst "github.com/docker/libnetwork/datastore"
 	"github.com/docker/swarmkit/agent/exec"
 	"github.com/docker/swarmkit/agent/exec"
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/template"
 	"github.com/docker/swarmkit/template"
@@ -374,6 +376,14 @@ func (c *containerConfig) hostConfig() *enginecontainer.HostConfig {
 		}
 		}
 	}
 	}
 
 
+	if len(c.task.Networks) > 0 {
+		labels := c.task.Networks[0].Network.Spec.Annotations.Labels
+		name := c.task.Networks[0].Network.Spec.Annotations.Name
+		if v, ok := labels["com.docker.swarm.predefined"]; ok && v == "true" {
+			hc.NetworkMode = enginecontainer.NetworkMode(name)
+		}
+	}
+
 	return hc
 	return hc
 }
 }
 
 
@@ -428,7 +438,7 @@ func (c *containerConfig) resources() enginecontainer.Resources {
 }
 }
 
 
 // Docker daemon supports just 1 network during container create.
 // Docker daemon supports just 1 network during container create.
-func (c *containerConfig) createNetworkingConfig() *network.NetworkingConfig {
+func (c *containerConfig) createNetworkingConfig(b executorpkg.Backend) *network.NetworkingConfig {
 	var networks []*api.NetworkAttachment
 	var networks []*api.NetworkAttachment
 	if c.task.Spec.GetContainer() != nil || c.task.Spec.GetAttachment() != nil {
 	if c.task.Spec.GetContainer() != nil || c.task.Spec.GetAttachment() != nil {
 		networks = c.task.Networks
 		networks = c.task.Networks
@@ -436,19 +446,18 @@ func (c *containerConfig) createNetworkingConfig() *network.NetworkingConfig {
 
 
 	epConfig := make(map[string]*network.EndpointSettings)
 	epConfig := make(map[string]*network.EndpointSettings)
 	if len(networks) > 0 {
 	if len(networks) > 0 {
-		epConfig[networks[0].Network.Spec.Annotations.Name] = getEndpointConfig(networks[0])
+		epConfig[networks[0].Network.Spec.Annotations.Name] = getEndpointConfig(networks[0], b)
 	}
 	}
 
 
 	return &network.NetworkingConfig{EndpointsConfig: epConfig}
 	return &network.NetworkingConfig{EndpointsConfig: epConfig}
 }
 }
 
 
 // TODO: Merge this function with createNetworkingConfig after daemon supports multiple networks in container create
 // TODO: Merge this function with createNetworkingConfig after daemon supports multiple networks in container create
-func (c *containerConfig) connectNetworkingConfig() *network.NetworkingConfig {
+func (c *containerConfig) connectNetworkingConfig(b executorpkg.Backend) *network.NetworkingConfig {
 	var networks []*api.NetworkAttachment
 	var networks []*api.NetworkAttachment
 	if c.task.Spec.GetContainer() != nil {
 	if c.task.Spec.GetContainer() != nil {
 		networks = c.task.Networks
 		networks = c.task.Networks
 	}
 	}
-
 	// First network is used during container create. Other networks are used in "docker network connect"
 	// First network is used during container create. Other networks are used in "docker network connect"
 	if len(networks) < 2 {
 	if len(networks) < 2 {
 		return nil
 		return nil
@@ -456,12 +465,12 @@ func (c *containerConfig) connectNetworkingConfig() *network.NetworkingConfig {
 
 
 	epConfig := make(map[string]*network.EndpointSettings)
 	epConfig := make(map[string]*network.EndpointSettings)
 	for _, na := range networks[1:] {
 	for _, na := range networks[1:] {
-		epConfig[na.Network.Spec.Annotations.Name] = getEndpointConfig(na)
+		epConfig[na.Network.Spec.Annotations.Name] = getEndpointConfig(na, b)
 	}
 	}
 	return &network.NetworkingConfig{EndpointsConfig: epConfig}
 	return &network.NetworkingConfig{EndpointsConfig: epConfig}
 }
 }
 
 
-func getEndpointConfig(na *api.NetworkAttachment) *network.EndpointSettings {
+func getEndpointConfig(na *api.NetworkAttachment, b executorpkg.Backend) *network.EndpointSettings {
 	var ipv4, ipv6 string
 	var ipv4, ipv6 string
 	for _, addr := range na.Addresses {
 	for _, addr := range na.Addresses {
 		ip, _, err := net.ParseCIDR(addr)
 		ip, _, err := net.ParseCIDR(addr)
@@ -479,13 +488,19 @@ func getEndpointConfig(na *api.NetworkAttachment) *network.EndpointSettings {
 		}
 		}
 	}
 	}
 
 
-	return &network.EndpointSettings{
+	n := &network.EndpointSettings{
 		NetworkID: na.Network.ID,
 		NetworkID: na.Network.ID,
 		IPAMConfig: &network.EndpointIPAMConfig{
 		IPAMConfig: &network.EndpointIPAMConfig{
 			IPv4Address: ipv4,
 			IPv4Address: ipv4,
 			IPv6Address: ipv6,
 			IPv6Address: ipv6,
 		},
 		},
 	}
 	}
+	if v, ok := na.Network.Spec.Annotations.Labels["com.docker.swarm.predefined"]; ok && v == "true" {
+		if ln, err := b.FindNetwork(na.Network.Spec.Annotations.Name); err == nil {
+			n.NetworkID = ln.ID()
+		}
+	}
+	return n
 }
 }
 
 
 func (c *containerConfig) virtualIP(networkID string) string {
 func (c *containerConfig) virtualIP(networkID string) string {
@@ -570,27 +585,38 @@ func (c *containerConfig) networkCreateRequest(name string) (clustertypes.Networ
 
 
 	options := types.NetworkCreate{
 	options := types.NetworkCreate{
 		// ID:     na.Network.ID,
 		// ID:     na.Network.ID,
-		Driver: na.Network.DriverState.Name,
-		IPAM: &network.IPAM{
-			Driver:  na.Network.IPAM.Driver.Name,
-			Options: na.Network.IPAM.Driver.Options,
-		},
-		Options:        na.Network.DriverState.Options,
 		Labels:         na.Network.Spec.Annotations.Labels,
 		Labels:         na.Network.Spec.Annotations.Labels,
 		Internal:       na.Network.Spec.Internal,
 		Internal:       na.Network.Spec.Internal,
 		Attachable:     na.Network.Spec.Attachable,
 		Attachable:     na.Network.Spec.Attachable,
 		Ingress:        na.Network.Spec.Ingress,
 		Ingress:        na.Network.Spec.Ingress,
 		EnableIPv6:     na.Network.Spec.Ipv6Enabled,
 		EnableIPv6:     na.Network.Spec.Ipv6Enabled,
 		CheckDuplicate: true,
 		CheckDuplicate: true,
+		Scope:          netconst.SwarmScope,
 	}
 	}
 
 
-	for _, ic := range na.Network.IPAM.Configs {
-		c := network.IPAMConfig{
-			Subnet:  ic.Subnet,
-			IPRange: ic.Range,
-			Gateway: ic.Gateway,
+	if na.Network.Spec.ConfigFrom != "" {
+		options.ConfigFrom = &network.ConfigReference{
+			Network: na.Network.Spec.ConfigFrom,
+		}
+	}
+
+	if na.Network.DriverState != nil {
+		options.Driver = na.Network.DriverState.Name
+		options.Options = na.Network.DriverState.Options
+	}
+	if na.Network.IPAM != nil {
+		options.IPAM = &network.IPAM{
+			Driver:  na.Network.IPAM.Driver.Name,
+			Options: na.Network.IPAM.Driver.Options,
+		}
+		for _, ic := range na.Network.IPAM.Configs {
+			c := network.IPAMConfig{
+				Subnet:  ic.Subnet,
+				IPRange: ic.Range,
+				Gateway: ic.Gateway,
+			}
+			options.IPAM.Config = append(options.IPAM.Config, c)
 		}
 		}
-		options.IPAM.Config = append(options.IPAM.Config, c)
 	}
 	}
 
 
 	return clustertypes.NetworkCreateRequest{
 	return clustertypes.NetworkCreateRequest{

+ 35 - 3
daemon/cluster/networks.go

@@ -17,7 +17,28 @@ import (
 
 
 // GetNetworks returns all current cluster managed networks.
 // GetNetworks returns all current cluster managed networks.
 func (c *Cluster) GetNetworks() ([]apitypes.NetworkResource, error) {
 func (c *Cluster) GetNetworks() ([]apitypes.NetworkResource, error) {
-	return c.getNetworks(nil)
+	list, err := c.getNetworks(nil)
+	if err != nil {
+		return nil, err
+	}
+	removePredefinedNetworks(&list)
+	return list, nil
+}
+
+func removePredefinedNetworks(networks *[]apitypes.NetworkResource) {
+	if networks == nil {
+		return
+	}
+	var idxs []int
+	for i, n := range *networks {
+		if v, ok := n.Labels["com.docker.swarm.predefined"]; ok && v == "true" {
+			idxs = append(idxs, i)
+		}
+	}
+	for i, idx := range idxs {
+		idx -= i
+		*networks = append((*networks)[:idx], (*networks)[idx+1:]...)
+	}
 }
 }
 
 
 func (c *Cluster) getNetworks(filters *swarmapi.ListNetworksRequest_Filters) ([]apitypes.NetworkResource, error) {
 func (c *Cluster) getNetworks(filters *swarmapi.ListNetworksRequest_Filters) ([]apitypes.NetworkResource, error) {
@@ -269,16 +290,27 @@ func (c *Cluster) populateNetworkID(ctx context.Context, client swarmapi.Control
 	if len(networks) == 0 {
 	if len(networks) == 0 {
 		networks = s.Networks
 		networks = s.Networks
 	}
 	}
-
 	for i, n := range networks {
 	for i, n := range networks {
 		apiNetwork, err := getNetwork(ctx, client, n.Target)
 		apiNetwork, err := getNetwork(ctx, client, n.Target)
 		if err != nil {
 		if err != nil {
-			if ln, _ := c.config.Backend.FindNetwork(n.Target); ln != nil && !ln.Info().Dynamic() {
+			ln, _ := c.config.Backend.FindNetwork(n.Target)
+			if ln != nil && runconfig.IsPreDefinedNetwork(ln.Name()) {
+				// Need to retrieve the corresponding predefined swarm network
+				// and use its id for the request.
+				apiNetwork, err = getNetwork(ctx, client, ln.Name())
+				if err != nil {
+					err = fmt.Errorf("could not find the corresponding predefined swarm network: %v", err)
+					return apierrors.NewRequestNotFoundError(err)
+				}
+				goto setid
+			}
+			if ln != nil && !ln.Info().Dynamic() {
 				err = fmt.Errorf("The network %s cannot be used with services. Only networks scoped to the swarm can be used, such as those created with the overlay driver.", ln.Name())
 				err = fmt.Errorf("The network %s cannot be used with services. Only networks scoped to the swarm can be used, such as those created with the overlay driver.", ln.Name())
 				return apierrors.NewRequestForbiddenError(err)
 				return apierrors.NewRequestForbiddenError(err)
 			}
 			}
 			return err
 			return err
 		}
 		}
+	setid:
 		networks[i].Target = apiNetwork.ID
 		networks[i].Target = apiNetwork.ID
 	}
 	}
 	return nil
 	return nil

+ 10 - 0
daemon/network.go

@@ -507,6 +507,16 @@ func (daemon *Daemon) deleteNetwork(networkID string, dynamic bool) error {
 		return apierrors.NewRequestForbiddenError(err)
 		return apierrors.NewRequestForbiddenError(err)
 	}
 	}
 
 
+	if dynamic && !nw.Info().Dynamic() {
+		if runconfig.IsPreDefinedNetwork(nw.Name()) {
+			// Predefined networks now support swarm services. Make this
+			// a no-op when cluster requests to remove the predefined network.
+			return nil
+		}
+		err := fmt.Errorf("%s is not a dynamic network", nw.Name())
+		return apierrors.NewRequestForbiddenError(err)
+	}
+
 	if err := nw.Delete(); err != nil {
 	if err := nw.Delete(); err != nil {
 		return err
 		return err
 	}
 	}