浏览代码

Daemon to support network restore

Signed-off-by: Lei Jitang <leijitang@huawei.com>
Lei Jitang 9 年之前
父节点
当前提交
ecffb6d58c

+ 1 - 9
daemon/cluster/cluster.go

@@ -121,14 +121,6 @@ func New(config Config) (*Cluster, error) {
 	return c, nil
 	return c, nil
 }
 }
 
 
-func (c *Cluster) checkCompatibility() error {
-	info, _ := c.config.Backend.SystemInfo()
-	if info != nil && (info.ClusterStore != "" || info.ClusterAdvertise != "") {
-		return fmt.Errorf("swarm mode is incompatible with `--cluster-store` and `--cluster-advertise daemon configuration")
-	}
-	return nil
-}
-
 func (c *Cluster) saveState() error {
 func (c *Cluster) saveState() error {
 	dt, err := json.Marshal(state{ListenAddr: c.listenAddr})
 	dt, err := json.Marshal(state{ListenAddr: c.listenAddr})
 	if err != nil {
 	if err != nil {
@@ -173,7 +165,7 @@ func (c *Cluster) reconnectOnFailure(ctx context.Context) {
 }
 }
 
 
 func (c *Cluster) startNewNode(forceNewCluster bool, listenAddr, joinAddr, secret, cahash string, ismanager bool) (*swarmagent.Node, context.Context, error) {
 func (c *Cluster) startNewNode(forceNewCluster bool, listenAddr, joinAddr, secret, cahash string, ismanager bool) (*swarmagent.Node, context.Context, error) {
-	if err := c.checkCompatibility(); err != nil {
+	if err := c.config.Backend.IsSwarmCompatible(); err != nil {
 		return nil, nil, err
 		return nil, nil, err
 	}
 	}
 	c.node = nil
 	c.node = nil

+ 1 - 0
daemon/cluster/executor/backend.go

@@ -32,4 +32,5 @@ type Backend interface {
 	ListContainersForNode(nodeID string) []string
 	ListContainersForNode(nodeID string) []string
 	SetNetworkBootstrapKeys([]*networktypes.EncryptionKey) error
 	SetNetworkBootstrapKeys([]*networktypes.EncryptionKey) error
 	SetClusterProvider(provider cluster.Provider)
 	SetClusterProvider(provider cluster.Provider)
+	IsSwarmCompatible() error
 }
 }

+ 4 - 0
daemon/config_solaris.go

@@ -37,3 +37,7 @@ func (config *Config) InstallFlags(cmd *flag.FlagSet, usageFn func(string) strin
 	// Then platform-specific install flags
 	// Then platform-specific install flags
 	config.attachExperimentalFlags(cmd, usageFn)
 	config.attachExperimentalFlags(cmd, usageFn)
 }
 }
+
+func (config *Config) isSwarmCompatible() error {
+	return nil
+}

+ 11 - 0
daemon/config_unix.go

@@ -3,6 +3,7 @@
 package daemon
 package daemon
 
 
 import (
 import (
+	"fmt"
 	"net"
 	"net"
 
 
 	"github.com/docker/docker/opts"
 	"github.com/docker/docker/opts"
@@ -120,3 +121,13 @@ func (config *Config) GetAllRuntimes() map[string]types.Runtime {
 	config.reloadLock.Unlock()
 	config.reloadLock.Unlock()
 	return rts
 	return rts
 }
 }
+
+func (config *Config) isSwarmCompatible() error {
+	if config.IsValueSet("cluster-store") || config.IsValueSet("cluster-advertise") {
+		return fmt.Errorf("--cluster-store and --cluster-advertise daemon configurations are incompatible with swarm mode")
+	}
+	if config.LiveRestore {
+		return fmt.Errorf("--live-restore daemon configuration is incompatible with swarm mode")
+	}
+	return nil
+}

+ 4 - 0
daemon/config_windows.go

@@ -57,3 +57,7 @@ func (config *Config) GetDefaultRuntimeName() string {
 func (config *Config) GetAllRuntimes() map[string]types.Runtime {
 func (config *Config) GetAllRuntimes() map[string]types.Runtime {
 	return map[string]types.Runtime{}
 	return map[string]types.Runtime{}
 }
 }
+
+func (config *Config) isSwarmCompatible() error {
+	return nil
+}

+ 18 - 12
daemon/container_operations.go

@@ -30,7 +30,7 @@ var (
 	getPortMapInfo    = container.GetSandboxPortMapInfo
 	getPortMapInfo    = container.GetSandboxPortMapInfo
 )
 )
 
 
-func (daemon *Daemon) buildSandboxOptions(container *container.Container, n libnetwork.Network) ([]libnetwork.SandboxOption, error) {
+func (daemon *Daemon) buildSandboxOptions(container *container.Container) ([]libnetwork.SandboxOption, error) {
 	var (
 	var (
 		sboxOptions []libnetwork.SandboxOption
 		sboxOptions []libnetwork.SandboxOption
 		err         error
 		err         error
@@ -176,16 +176,19 @@ func (daemon *Daemon) buildSandboxOptions(container *container.Container, n libn
 
 
 	// Legacy Link feature is supported only for the default bridge network.
 	// Legacy Link feature is supported only for the default bridge network.
 	// return if this call to build join options is not for default bridge network
 	// return if this call to build join options is not for default bridge network
-	if n.Name() != defaultNetName {
+	// Legacy Link is only supported by docker run --link
+	if _, ok := container.NetworkSettings.Networks[defaultNetName]; !container.HostConfig.NetworkMode.IsDefault() || !ok {
 		return sboxOptions, nil
 		return sboxOptions, nil
 	}
 	}
 
 
-	ep, _ := container.GetEndpointInNetwork(n)
-	if ep == nil {
+	if container.NetworkSettings.Networks[defaultNetName].EndpointID == "" {
 		return sboxOptions, nil
 		return sboxOptions, nil
 	}
 	}
 
 
-	var childEndpoints, parentEndpoints []string
+	var (
+		childEndpoints, parentEndpoints []string
+		cEndpointID                     string
+	)
 
 
 	children := daemon.children(container)
 	children := daemon.children(container)
 	for linkAlias, child := range children {
 	for linkAlias, child := range children {
@@ -200,9 +203,9 @@ func (daemon *Daemon) buildSandboxOptions(container *container.Container, n libn
 			aliasList = aliasList + " " + child.Name[1:]
 			aliasList = aliasList + " " + child.Name[1:]
 		}
 		}
 		sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(aliasList, child.NetworkSettings.Networks[defaultNetName].IPAddress))
 		sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(aliasList, child.NetworkSettings.Networks[defaultNetName].IPAddress))
-		cEndpoint, _ := child.GetEndpointInNetwork(n)
-		if cEndpoint != nil && cEndpoint.ID() != "" {
-			childEndpoints = append(childEndpoints, cEndpoint.ID())
+		cEndpointID = child.NetworkSettings.Networks[defaultNetName].EndpointID
+		if cEndpointID != "" {
+			childEndpoints = append(childEndpoints, cEndpointID)
 		}
 		}
 	}
 	}
 
 
@@ -219,8 +222,8 @@ func (daemon *Daemon) buildSandboxOptions(container *container.Container, n libn
 			alias,
 			alias,
 			bridgeSettings.IPAddress,
 			bridgeSettings.IPAddress,
 		))
 		))
-		if ep.ID() != "" {
-			parentEndpoints = append(parentEndpoints, ep.ID())
+		if cEndpointID != "" {
+			parentEndpoints = append(parentEndpoints, cEndpointID)
 		}
 		}
 	}
 	}
 
 
@@ -312,7 +315,7 @@ func (daemon *Daemon) updateNetwork(container *container.Container) error {
 		return nil
 		return nil
 	}
 	}
 
 
-	options, err := daemon.buildSandboxOptions(container, n)
+	options, err := daemon.buildSandboxOptions(container)
 	if err != nil {
 	if err != nil {
 		return fmt.Errorf("Update network failed: %v", err)
 		return fmt.Errorf("Update network failed: %v", err)
 	}
 	}
@@ -570,7 +573,7 @@ func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName
 	}
 	}
 
 
 	if sb == nil {
 	if sb == nil {
-		options, err := daemon.buildSandboxOptions(container, n)
+		options, err := daemon.buildSandboxOptions(container)
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
@@ -709,6 +712,9 @@ func (daemon *Daemon) getNetworkedContainer(containerID, connectedContainerID st
 }
 }
 
 
 func (daemon *Daemon) releaseNetwork(container *container.Container) {
 func (daemon *Daemon) releaseNetwork(container *container.Container) {
+	if daemon.netController == nil {
+		return
+	}
 	if container.HostConfig.NetworkMode.IsContainer() || container.Config.NetworkDisabled {
 	if container.HostConfig.NetworkMode.IsContainer() || container.Config.NetworkDisabled {
 		return
 		return
 	}
 	}

+ 37 - 11
daemon/daemon.go

@@ -146,6 +146,7 @@ func (daemon *Daemon) restore() error {
 
 
 	var migrateLegacyLinks bool
 	var migrateLegacyLinks bool
 	restartContainers := make(map[*container.Container]chan struct{})
 	restartContainers := make(map[*container.Container]chan struct{})
+	activeSandboxes := make(map[string]interface{})
 	for _, c := range containers {
 	for _, c := range containers {
 		if err := daemon.registerName(c); err != nil {
 		if err := daemon.registerName(c); err != nil {
 			logrus.Errorf("Failed to register container %s: %s", c.ID, err)
 			logrus.Errorf("Failed to register container %s: %s", c.ID, err)
@@ -178,6 +179,16 @@ func (daemon *Daemon) restore() error {
 					logrus.Errorf("Failed to restore with containerd: %q", err)
 					logrus.Errorf("Failed to restore with containerd: %q", err)
 					return
 					return
 				}
 				}
+				if !c.HostConfig.NetworkMode.IsContainer() {
+					options, err := daemon.buildSandboxOptions(c)
+					if err != nil {
+						logrus.Warnf("Failed build sandbox option to restore container %s: %v", c.ID, err)
+					}
+					mapLock.Lock()
+					activeSandboxes[c.NetworkSettings.SandboxID] = options
+					mapLock.Unlock()
+				}
+
 			}
 			}
 			// fixme: only if not running
 			// fixme: only if not running
 			// get list of containers we need to restart
 			// get list of containers we need to restart
@@ -209,6 +220,10 @@ func (daemon *Daemon) restore() error {
 		}(c)
 		}(c)
 	}
 	}
 	wg.Wait()
 	wg.Wait()
+	daemon.netController, err = daemon.initNetworkController(daemon.configStore, activeSandboxes)
+	if err != nil {
+		return fmt.Errorf("Error initializing network controller: %v", err)
+	}
 
 
 	// migrate any legacy links from sqlite
 	// migrate any legacy links from sqlite
 	linkdbFile := filepath.Join(daemon.root, "linkgraph.db")
 	linkdbFile := filepath.Join(daemon.root, "linkgraph.db")
@@ -356,6 +371,15 @@ func (daemon *Daemon) SetClusterProvider(clusterProvider cluster.Provider) {
 	daemon.netController.SetClusterProvider(clusterProvider)
 	daemon.netController.SetClusterProvider(clusterProvider)
 }
 }
 
 
+// IsSwarmCompatible verifies if the current daemon
+// configuration is compatible with the swarm mode
+func (daemon *Daemon) IsSwarmCompatible() error {
+	if daemon.configStore == nil {
+		return nil
+	}
+	return daemon.configStore.isSwarmCompatible()
+}
+
 // NewDaemon sets up everything for the daemon to be able to service
 // NewDaemon sets up everything for the daemon to be able to service
 // requests from the webserver.
 // requests from the webserver.
 func NewDaemon(config *Config, registryService registry.Service, containerdRemote libcontainerd.Remote) (daemon *Daemon, err error) {
 func NewDaemon(config *Config, registryService registry.Service, containerdRemote libcontainerd.Remote) (daemon *Daemon, err error) {
@@ -530,11 +554,6 @@ func NewDaemon(config *Config, registryService registry.Service, containerdRemot
 		return nil, err
 		return nil, err
 	}
 	}
 
 
-	d.netController, err = d.initNetworkController(config)
-	if err != nil {
-		return nil, fmt.Errorf("Error initializing network controller: %v", err)
-	}
-
 	sysInfo := sysinfo.New(false)
 	sysInfo := sysinfo.New(false)
 	// Check if Devices cgroup is mounted, it is hard requirement for container security,
 	// Check if Devices cgroup is mounted, it is hard requirement for container security,
 	// on Linux.
 	// on Linux.
@@ -912,15 +931,17 @@ func (daemon *Daemon) reloadClusterDiscovery(config *Config) error {
 		}
 		}
 	}
 	}
 
 
+	if daemon.clusterProvider != nil {
+		if err := config.isSwarmCompatible(); err != nil {
+			return err
+		}
+	}
+
 	// check discovery modifications
 	// check discovery modifications
 	if !modifiedDiscoverySettings(daemon.configStore, newAdvertise, newClusterStore, config.ClusterOpts) {
 	if !modifiedDiscoverySettings(daemon.configStore, newAdvertise, newClusterStore, config.ClusterOpts) {
 		return nil
 		return nil
 	}
 	}
 
 
-	if daemon.clusterProvider != nil {
-		return fmt.Errorf("--cluster-store and --cluster-advertise daemon configurations are incompatible with swarm mode")
-	}
-
 	// enable discovery for the first time if it was not previously enabled
 	// enable discovery for the first time if it was not previously enabled
 	if daemon.discoveryWatcher == nil {
 	if daemon.discoveryWatcher == nil {
 		discoveryWatcher, err := initDiscovery(newClusterStore, newAdvertise, config.ClusterOpts)
 		discoveryWatcher, err := initDiscovery(newClusterStore, newAdvertise, config.ClusterOpts)
@@ -947,7 +968,7 @@ func (daemon *Daemon) reloadClusterDiscovery(config *Config) error {
 	if daemon.netController == nil {
 	if daemon.netController == nil {
 		return nil
 		return nil
 	}
 	}
-	netOptions, err := daemon.networkOptions(daemon.configStore)
+	netOptions, err := daemon.networkOptions(daemon.configStore, nil)
 	if err != nil {
 	if err != nil {
 		logrus.Warnf("Failed to reload configuration with network controller: %v", err)
 		logrus.Warnf("Failed to reload configuration with network controller: %v", err)
 		return nil
 		return nil
@@ -964,7 +985,7 @@ func isBridgeNetworkDisabled(config *Config) bool {
 	return config.bridgeConfig.Iface == disableNetworkBridge
 	return config.bridgeConfig.Iface == disableNetworkBridge
 }
 }
 
 
-func (daemon *Daemon) networkOptions(dconfig *Config) ([]nwconfig.Option, error) {
+func (daemon *Daemon) networkOptions(dconfig *Config, activeSandboxes map[string]interface{}) ([]nwconfig.Option, error) {
 	options := []nwconfig.Option{}
 	options := []nwconfig.Option{}
 	if dconfig == nil {
 	if dconfig == nil {
 		return options, nil
 		return options, nil
@@ -999,6 +1020,11 @@ func (daemon *Daemon) networkOptions(dconfig *Config) ([]nwconfig.Option, error)
 
 
 	options = append(options, nwconfig.OptionLabels(dconfig.Labels))
 	options = append(options, nwconfig.OptionLabels(dconfig.Labels))
 	options = append(options, driverOptions(dconfig)...)
 	options = append(options, driverOptions(dconfig)...)
+
+	if daemon.configStore != nil && daemon.configStore.LiveRestore && len(activeSandboxes) != 0 {
+		options = append(options, nwconfig.OptionActiveSandboxes(activeSandboxes))
+	}
+
 	return options, nil
 	return options, nil
 }
 }
 
 

+ 1 - 1
daemon/daemon_solaris.go

@@ -113,7 +113,7 @@ func configureKernelSecuritySupport(config *Config, driverName string) error {
 	return nil
 	return nil
 }
 }
 
 
-func (daemon *Daemon) initNetworkController(config *Config) (libnetwork.NetworkController, error) {
+func (daemon *Daemon) initNetworkController(config *Config, activeSandboxes map[string]interface{}) (libnetwork.NetworkController, error) {
 	return nil, nil
 	return nil, nil
 }
 }
 
 

+ 15 - 7
daemon/daemon_unix.go

@@ -627,8 +627,8 @@ func configureKernelSecuritySupport(config *Config, driverName string) error {
 	return nil
 	return nil
 }
 }
 
 
-func (daemon *Daemon) initNetworkController(config *Config) (libnetwork.NetworkController, error) {
-	netOptions, err := daemon.networkOptions(config)
+func (daemon *Daemon) initNetworkController(config *Config, activeSandboxes map[string]interface{}) (libnetwork.NetworkController, error) {
+	netOptions, err := daemon.networkOptions(config, activeSandboxes)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -638,16 +638,24 @@ func (daemon *Daemon) initNetworkController(config *Config) (libnetwork.NetworkC
 		return nil, fmt.Errorf("error obtaining controller instance: %v", err)
 		return nil, fmt.Errorf("error obtaining controller instance: %v", err)
 	}
 	}
 
 
+	if len(activeSandboxes) > 0 {
+		logrus.Infof("There are old running containers, the network config will not take affect")
+		return controller, nil
+	}
+
 	// Initialize default network on "null"
 	// Initialize default network on "null"
-	if _, err := controller.NewNetwork("null", "none", "", libnetwork.NetworkOptionPersist(false)); err != nil {
-		return nil, fmt.Errorf("Error creating default \"null\" network: %v", err)
+	if n, _ := controller.NetworkByName("none"); n == nil {
+		if _, err := controller.NewNetwork("null", "none", "", libnetwork.NetworkOptionPersist(true)); err != nil {
+			return nil, fmt.Errorf("Error creating default \"null\" network: %v", err)
+		}
 	}
 	}
 
 
 	// Initialize default network on "host"
 	// Initialize default network on "host"
-	if _, err := controller.NewNetwork("host", "host", "", libnetwork.NetworkOptionPersist(false)); err != nil {
-		return nil, fmt.Errorf("Error creating default \"host\" network: %v", err)
+	if n, _ := controller.NetworkByName("host"); n == nil {
+		if _, err := controller.NewNetwork("host", "host", "", libnetwork.NetworkOptionPersist(true)); err != nil {
+			return nil, fmt.Errorf("Error creating default \"host\" network: %v", err)
+		}
 	}
 	}
-
 	if !config.DisableBridge {
 	if !config.DisableBridge {
 		// Initialize default driver "bridge"
 		// Initialize default driver "bridge"
 		if err := initBridgeDriver(controller, config); err != nil {
 		if err := initBridgeDriver(controller, config); err != nil {

+ 2 - 2
daemon/daemon_unix_test.go

@@ -183,7 +183,7 @@ func TestNetworkOptions(t *testing.T) {
 		},
 		},
 	}
 	}
 
 
-	if _, err := daemon.networkOptions(dconfigCorrect); err != nil {
+	if _, err := daemon.networkOptions(dconfigCorrect, nil); err != nil {
 		t.Fatalf("Expect networkOptions success, got error: %v", err)
 		t.Fatalf("Expect networkOptions success, got error: %v", err)
 	}
 	}
 
 
@@ -193,7 +193,7 @@ func TestNetworkOptions(t *testing.T) {
 		},
 		},
 	}
 	}
 
 
-	if _, err := daemon.networkOptions(dconfigWrong); err == nil {
+	if _, err := daemon.networkOptions(dconfigWrong, nil); err == nil {
 		t.Fatalf("Expected networkOptions error, got nil")
 		t.Fatalf("Expected networkOptions error, got nil")
 	}
 	}
 }
 }

+ 2 - 2
daemon/daemon_windows.go

@@ -189,8 +189,8 @@ func configureMaxThreads(config *Config) error {
 	return nil
 	return nil
 }
 }
 
 
-func (daemon *Daemon) initNetworkController(config *Config) (libnetwork.NetworkController, error) {
-	netOptions, err := daemon.networkOptions(config)
+func (daemon *Daemon) initNetworkController(config *Config, activeSandboxes map[string]interface{}) (libnetwork.NetworkController, error) {
+	netOptions, err := daemon.networkOptions(config, nil)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}

+ 6 - 0
daemon/network.go

@@ -59,6 +59,9 @@ func (daemon *Daemon) GetNetworkByID(partialID string) (libnetwork.Network, erro
 // GetNetworkByName function returns a network for a given network name.
 // GetNetworkByName function returns a network for a given network name.
 func (daemon *Daemon) GetNetworkByName(name string) (libnetwork.Network, error) {
 func (daemon *Daemon) GetNetworkByName(name string) (libnetwork.Network, error) {
 	c := daemon.netController
 	c := daemon.netController
+	if c == nil {
+		return nil, libnetwork.ErrNoSuchNetwork(name)
+	}
 	if name == "" {
 	if name == "" {
 		name = c.Config().Daemon.DefaultNetwork
 		name = c.Config().Daemon.DefaultNetwork
 	}
 	}
@@ -68,6 +71,9 @@ func (daemon *Daemon) GetNetworkByName(name string) (libnetwork.Network, error)
 // GetNetworksByID returns a list of networks whose ID partially matches zero or more networks
 // GetNetworksByID returns a list of networks whose ID partially matches zero or more networks
 func (daemon *Daemon) GetNetworksByID(partialID string) []libnetwork.Network {
 func (daemon *Daemon) GetNetworksByID(partialID string) []libnetwork.Network {
 	c := daemon.netController
 	c := daemon.netController
+	if c == nil {
+		return nil
+	}
 	list := []libnetwork.Network{}
 	list := []libnetwork.Network{}
 	l := func(nw libnetwork.Network) bool {
 	l := func(nw libnetwork.Network) bool {
 		if strings.HasPrefix(nw.ID(), partialID) {
 		if strings.HasPrefix(nw.ID(), partialID) {