Browse code

Daemon to support network restore

Signed-off-by: Lei Jitang <leijitang@huawei.com>

Lei Jitang authored on 2016/06/15 01:13:53
Showing 12 changed files
... ...
@@ -121,14 +121,6 @@ func New(config Config) (*Cluster, error) {
121 121
 	return c, nil
122 122
 }
123 123
 
124
-func (c *Cluster) checkCompatibility() error {
125
-	info, _ := c.config.Backend.SystemInfo()
126
-	if info != nil && (info.ClusterStore != "" || info.ClusterAdvertise != "") {
127
-		return fmt.Errorf("swarm mode is incompatible with `--cluster-store` and `--cluster-advertise daemon configuration")
128
-	}
129
-	return nil
130
-}
131
-
132 124
 func (c *Cluster) saveState() error {
133 125
 	dt, err := json.Marshal(state{ListenAddr: c.listenAddr})
134 126
 	if err != nil {
... ...
@@ -173,7 +165,7 @@ func (c *Cluster) reconnectOnFailure(ctx context.Context) {
173 173
 }
174 174
 
175 175
 func (c *Cluster) startNewNode(forceNewCluster bool, listenAddr, joinAddr, secret, cahash string, ismanager bool) (*swarmagent.Node, context.Context, error) {
176
-	if err := c.checkCompatibility(); err != nil {
176
+	if err := c.config.Backend.IsSwarmCompatible(); err != nil {
177 177
 		return nil, nil, err
178 178
 	}
179 179
 	c.node = nil
... ...
@@ -32,4 +32,5 @@ type Backend interface {
32 32
 	ListContainersForNode(nodeID string) []string
33 33
 	SetNetworkBootstrapKeys([]*networktypes.EncryptionKey) error
34 34
 	SetClusterProvider(provider cluster.Provider)
35
+	IsSwarmCompatible() error
35 36
 }
... ...
@@ -37,3 +37,7 @@ func (config *Config) InstallFlags(cmd *flag.FlagSet, usageFn func(string) strin
37 37
 	// Then platform-specific install flags
38 38
 	config.attachExperimentalFlags(cmd, usageFn)
39 39
 }
40
+
41
+func (config *Config) isSwarmCompatible() error {
42
+	return nil
43
+}
... ...
@@ -3,6 +3,7 @@
3 3
 package daemon
4 4
 
5 5
 import (
6
+	"fmt"
6 7
 	"net"
7 8
 
8 9
 	"github.com/docker/docker/opts"
... ...
@@ -120,3 +121,13 @@ func (config *Config) GetAllRuntimes() map[string]types.Runtime {
120 120
 	config.reloadLock.Unlock()
121 121
 	return rts
122 122
 }
123
+
124
+func (config *Config) isSwarmCompatible() error {
125
+	if config.IsValueSet("cluster-store") || config.IsValueSet("cluster-advertise") {
126
+		return fmt.Errorf("--cluster-store and --cluster-advertise daemon configurations are incompatible with swarm mode")
127
+	}
128
+	if config.LiveRestore {
129
+		return fmt.Errorf("--live-restore daemon configuration is incompatible with swarm mode")
130
+	}
131
+	return nil
132
+}
... ...
@@ -57,3 +57,7 @@ func (config *Config) GetDefaultRuntimeName() string {
57 57
 func (config *Config) GetAllRuntimes() map[string]types.Runtime {
58 58
 	return map[string]types.Runtime{}
59 59
 }
60
+
61
+func (config *Config) isSwarmCompatible() error {
62
+	return nil
63
+}
... ...
@@ -30,7 +30,7 @@ var (
30 30
 	getPortMapInfo    = container.GetSandboxPortMapInfo
31 31
 )
32 32
 
33
-func (daemon *Daemon) buildSandboxOptions(container *container.Container, n libnetwork.Network) ([]libnetwork.SandboxOption, error) {
33
+func (daemon *Daemon) buildSandboxOptions(container *container.Container) ([]libnetwork.SandboxOption, error) {
34 34
 	var (
35 35
 		sboxOptions []libnetwork.SandboxOption
36 36
 		err         error
... ...
@@ -176,16 +176,19 @@ func (daemon *Daemon) buildSandboxOptions(container *container.Container, n libn
176 176
 
177 177
 	// Legacy Link feature is supported only for the default bridge network.
178 178
 	// return if this call to build join options is not for default bridge network
179
-	if n.Name() != defaultNetName {
179
+	// Legacy Link is only supported by docker run --link
180
+	if _, ok := container.NetworkSettings.Networks[defaultNetName]; !container.HostConfig.NetworkMode.IsDefault() || !ok {
180 181
 		return sboxOptions, nil
181 182
 	}
182 183
 
183
-	ep, _ := container.GetEndpointInNetwork(n)
184
-	if ep == nil {
184
+	if container.NetworkSettings.Networks[defaultNetName].EndpointID == "" {
185 185
 		return sboxOptions, nil
186 186
 	}
187 187
 
188
-	var childEndpoints, parentEndpoints []string
188
+	var (
189
+		childEndpoints, parentEndpoints []string
190
+		cEndpointID                     string
191
+	)
189 192
 
190 193
 	children := daemon.children(container)
191 194
 	for linkAlias, child := range children {
... ...
@@ -200,9 +203,9 @@ func (daemon *Daemon) buildSandboxOptions(container *container.Container, n libn
200 200
 			aliasList = aliasList + " " + child.Name[1:]
201 201
 		}
202 202
 		sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(aliasList, child.NetworkSettings.Networks[defaultNetName].IPAddress))
203
-		cEndpoint, _ := child.GetEndpointInNetwork(n)
204
-		if cEndpoint != nil && cEndpoint.ID() != "" {
205
-			childEndpoints = append(childEndpoints, cEndpoint.ID())
203
+		cEndpointID = child.NetworkSettings.Networks[defaultNetName].EndpointID
204
+		if cEndpointID != "" {
205
+			childEndpoints = append(childEndpoints, cEndpointID)
206 206
 		}
207 207
 	}
208 208
 
... ...
@@ -219,8 +222,8 @@ func (daemon *Daemon) buildSandboxOptions(container *container.Container, n libn
219 219
 			alias,
220 220
 			bridgeSettings.IPAddress,
221 221
 		))
222
-		if ep.ID() != "" {
223
-			parentEndpoints = append(parentEndpoints, ep.ID())
222
+		if cEndpointID != "" {
223
+			parentEndpoints = append(parentEndpoints, cEndpointID)
224 224
 		}
225 225
 	}
226 226
 
... ...
@@ -312,7 +315,7 @@ func (daemon *Daemon) updateNetwork(container *container.Container) error {
312 312
 		return nil
313 313
 	}
314 314
 
315
-	options, err := daemon.buildSandboxOptions(container, n)
315
+	options, err := daemon.buildSandboxOptions(container)
316 316
 	if err != nil {
317 317
 		return fmt.Errorf("Update network failed: %v", err)
318 318
 	}
... ...
@@ -570,7 +573,7 @@ func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName
570 570
 	}
571 571
 
572 572
 	if sb == nil {
573
-		options, err := daemon.buildSandboxOptions(container, n)
573
+		options, err := daemon.buildSandboxOptions(container)
574 574
 		if err != nil {
575 575
 			return err
576 576
 		}
... ...
@@ -709,6 +712,9 @@ func (daemon *Daemon) getNetworkedContainer(containerID, connectedContainerID st
709 709
 }
710 710
 
711 711
 func (daemon *Daemon) releaseNetwork(container *container.Container) {
712
+	if daemon.netController == nil {
713
+		return
714
+	}
712 715
 	if container.HostConfig.NetworkMode.IsContainer() || container.Config.NetworkDisabled {
713 716
 		return
714 717
 	}
... ...
@@ -146,6 +146,7 @@ func (daemon *Daemon) restore() error {
146 146
 
147 147
 	var migrateLegacyLinks bool
148 148
 	restartContainers := make(map[*container.Container]chan struct{})
149
+	activeSandboxes := make(map[string]interface{})
149 150
 	for _, c := range containers {
150 151
 		if err := daemon.registerName(c); err != nil {
151 152
 			logrus.Errorf("Failed to register container %s: %s", c.ID, err)
... ...
@@ -178,6 +179,16 @@ func (daemon *Daemon) restore() error {
178 178
 					logrus.Errorf("Failed to restore with containerd: %q", err)
179 179
 					return
180 180
 				}
181
+				if !c.HostConfig.NetworkMode.IsContainer() {
182
+					options, err := daemon.buildSandboxOptions(c)
183
+					if err != nil {
184
+						logrus.Warnf("Failed build sandbox option to restore container %s: %v", c.ID, err)
185
+					}
186
+					mapLock.Lock()
187
+					activeSandboxes[c.NetworkSettings.SandboxID] = options
188
+					mapLock.Unlock()
189
+				}
190
+
181 191
 			}
182 192
 			// fixme: only if not running
183 193
 			// get list of containers we need to restart
... ...
@@ -209,6 +220,10 @@ func (daemon *Daemon) restore() error {
209 209
 		}(c)
210 210
 	}
211 211
 	wg.Wait()
212
+	daemon.netController, err = daemon.initNetworkController(daemon.configStore, activeSandboxes)
213
+	if err != nil {
214
+		return fmt.Errorf("Error initializing network controller: %v", err)
215
+	}
212 216
 
213 217
 	// migrate any legacy links from sqlite
214 218
 	linkdbFile := filepath.Join(daemon.root, "linkgraph.db")
... ...
@@ -356,6 +371,15 @@ func (daemon *Daemon) SetClusterProvider(clusterProvider cluster.Provider) {
356 356
 	daemon.netController.SetClusterProvider(clusterProvider)
357 357
 }
358 358
 
359
+// IsSwarmCompatible verifies if the current daemon
360
+// configuration is compatible with the swarm mode
361
+func (daemon *Daemon) IsSwarmCompatible() error {
362
+	if daemon.configStore == nil {
363
+		return nil
364
+	}
365
+	return daemon.configStore.isSwarmCompatible()
366
+}
367
+
359 368
 // NewDaemon sets up everything for the daemon to be able to service
360 369
 // requests from the webserver.
361 370
 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
530 530
 		return nil, err
531 531
 	}
532 532
 
533
-	d.netController, err = d.initNetworkController(config)
534
-	if err != nil {
535
-		return nil, fmt.Errorf("Error initializing network controller: %v", err)
536
-	}
537
-
538 533
 	sysInfo := sysinfo.New(false)
539 534
 	// Check if Devices cgroup is mounted, it is hard requirement for container security,
540 535
 	// on Linux.
... ...
@@ -912,15 +931,17 @@ func (daemon *Daemon) reloadClusterDiscovery(config *Config) error {
912 912
 		}
913 913
 	}
914 914
 
915
+	if daemon.clusterProvider != nil {
916
+		if err := config.isSwarmCompatible(); err != nil {
917
+			return err
918
+		}
919
+	}
920
+
915 921
 	// check discovery modifications
916 922
 	if !modifiedDiscoverySettings(daemon.configStore, newAdvertise, newClusterStore, config.ClusterOpts) {
917 923
 		return nil
918 924
 	}
919 925
 
920
-	if daemon.clusterProvider != nil {
921
-		return fmt.Errorf("--cluster-store and --cluster-advertise daemon configurations are incompatible with swarm mode")
922
-	}
923
-
924 926
 	// enable discovery for the first time if it was not previously enabled
925 927
 	if daemon.discoveryWatcher == nil {
926 928
 		discoveryWatcher, err := initDiscovery(newClusterStore, newAdvertise, config.ClusterOpts)
... ...
@@ -947,7 +968,7 @@ func (daemon *Daemon) reloadClusterDiscovery(config *Config) error {
947 947
 	if daemon.netController == nil {
948 948
 		return nil
949 949
 	}
950
-	netOptions, err := daemon.networkOptions(daemon.configStore)
950
+	netOptions, err := daemon.networkOptions(daemon.configStore, nil)
951 951
 	if err != nil {
952 952
 		logrus.Warnf("Failed to reload configuration with network controller: %v", err)
953 953
 		return nil
... ...
@@ -964,7 +985,7 @@ func isBridgeNetworkDisabled(config *Config) bool {
964 964
 	return config.bridgeConfig.Iface == disableNetworkBridge
965 965
 }
966 966
 
967
-func (daemon *Daemon) networkOptions(dconfig *Config) ([]nwconfig.Option, error) {
967
+func (daemon *Daemon) networkOptions(dconfig *Config, activeSandboxes map[string]interface{}) ([]nwconfig.Option, error) {
968 968
 	options := []nwconfig.Option{}
969 969
 	if dconfig == nil {
970 970
 		return options, nil
... ...
@@ -999,6 +1020,11 @@ func (daemon *Daemon) networkOptions(dconfig *Config) ([]nwconfig.Option, error)
999 999
 
1000 1000
 	options = append(options, nwconfig.OptionLabels(dconfig.Labels))
1001 1001
 	options = append(options, driverOptions(dconfig)...)
1002
+
1003
+	if daemon.configStore != nil && daemon.configStore.LiveRestore && len(activeSandboxes) != 0 {
1004
+		options = append(options, nwconfig.OptionActiveSandboxes(activeSandboxes))
1005
+	}
1006
+
1002 1007
 	return options, nil
1003 1008
 }
1004 1009
 
... ...
@@ -113,7 +113,7 @@ func configureKernelSecuritySupport(config *Config, driverName string) error {
113 113
 	return nil
114 114
 }
115 115
 
116
-func (daemon *Daemon) initNetworkController(config *Config) (libnetwork.NetworkController, error) {
116
+func (daemon *Daemon) initNetworkController(config *Config, activeSandboxes map[string]interface{}) (libnetwork.NetworkController, error) {
117 117
 	return nil, nil
118 118
 }
119 119
 
... ...
@@ -627,8 +627,8 @@ func configureKernelSecuritySupport(config *Config, driverName string) error {
627 627
 	return nil
628 628
 }
629 629
 
630
-func (daemon *Daemon) initNetworkController(config *Config) (libnetwork.NetworkController, error) {
631
-	netOptions, err := daemon.networkOptions(config)
630
+func (daemon *Daemon) initNetworkController(config *Config, activeSandboxes map[string]interface{}) (libnetwork.NetworkController, error) {
631
+	netOptions, err := daemon.networkOptions(config, activeSandboxes)
632 632
 	if err != nil {
633 633
 		return nil, err
634 634
 	}
... ...
@@ -638,16 +638,24 @@ func (daemon *Daemon) initNetworkController(config *Config) (libnetwork.NetworkC
638 638
 		return nil, fmt.Errorf("error obtaining controller instance: %v", err)
639 639
 	}
640 640
 
641
+	if len(activeSandboxes) > 0 {
642
+		logrus.Infof("There are old running containers, the network config will not take affect")
643
+		return controller, nil
644
+	}
645
+
641 646
 	// Initialize default network on "null"
642
-	if _, err := controller.NewNetwork("null", "none", "", libnetwork.NetworkOptionPersist(false)); err != nil {
643
-		return nil, fmt.Errorf("Error creating default \"null\" network: %v", err)
647
+	if n, _ := controller.NetworkByName("none"); n == nil {
648
+		if _, err := controller.NewNetwork("null", "none", "", libnetwork.NetworkOptionPersist(true)); err != nil {
649
+			return nil, fmt.Errorf("Error creating default \"null\" network: %v", err)
650
+		}
644 651
 	}
645 652
 
646 653
 	// Initialize default network on "host"
647
-	if _, err := controller.NewNetwork("host", "host", "", libnetwork.NetworkOptionPersist(false)); err != nil {
648
-		return nil, fmt.Errorf("Error creating default \"host\" network: %v", err)
654
+	if n, _ := controller.NetworkByName("host"); n == nil {
655
+		if _, err := controller.NewNetwork("host", "host", "", libnetwork.NetworkOptionPersist(true)); err != nil {
656
+			return nil, fmt.Errorf("Error creating default \"host\" network: %v", err)
657
+		}
649 658
 	}
650
-
651 659
 	if !config.DisableBridge {
652 660
 		// Initialize default driver "bridge"
653 661
 		if err := initBridgeDriver(controller, config); err != nil {
... ...
@@ -183,7 +183,7 @@ func TestNetworkOptions(t *testing.T) {
183 183
 		},
184 184
 	}
185 185
 
186
-	if _, err := daemon.networkOptions(dconfigCorrect); err != nil {
186
+	if _, err := daemon.networkOptions(dconfigCorrect, nil); err != nil {
187 187
 		t.Fatalf("Expect networkOptions success, got error: %v", err)
188 188
 	}
189 189
 
... ...
@@ -193,7 +193,7 @@ func TestNetworkOptions(t *testing.T) {
193 193
 		},
194 194
 	}
195 195
 
196
-	if _, err := daemon.networkOptions(dconfigWrong); err == nil {
196
+	if _, err := daemon.networkOptions(dconfigWrong, nil); err == nil {
197 197
 		t.Fatalf("Expected networkOptions error, got nil")
198 198
 	}
199 199
 }
... ...
@@ -189,8 +189,8 @@ func configureMaxThreads(config *Config) error {
189 189
 	return nil
190 190
 }
191 191
 
192
-func (daemon *Daemon) initNetworkController(config *Config) (libnetwork.NetworkController, error) {
193
-	netOptions, err := daemon.networkOptions(config)
192
+func (daemon *Daemon) initNetworkController(config *Config, activeSandboxes map[string]interface{}) (libnetwork.NetworkController, error) {
193
+	netOptions, err := daemon.networkOptions(config, nil)
194 194
 	if err != nil {
195 195
 		return nil, err
196 196
 	}
... ...
@@ -59,6 +59,9 @@ func (daemon *Daemon) GetNetworkByID(partialID string) (libnetwork.Network, erro
59 59
 // GetNetworkByName function returns a network for a given network name.
60 60
 func (daemon *Daemon) GetNetworkByName(name string) (libnetwork.Network, error) {
61 61
 	c := daemon.netController
62
+	if c == nil {
63
+		return nil, libnetwork.ErrNoSuchNetwork(name)
64
+	}
62 65
 	if name == "" {
63 66
 		name = c.Config().Daemon.DefaultNetwork
64 67
 	}
... ...
@@ -68,6 +71,9 @@ func (daemon *Daemon) GetNetworkByName(name string) (libnetwork.Network, error)
68 68
 // GetNetworksByID returns a list of networks whose ID partially matches zero or more networks
69 69
 func (daemon *Daemon) GetNetworksByID(partialID string) []libnetwork.Network {
70 70
 	c := daemon.netController
71
+	if c == nil {
72
+		return nil
73
+	}
71 74
 	list := []libnetwork.Network{}
72 75
 	l := func(nw libnetwork.Network) bool {
73 76
 		if strings.HasPrefix(nw.ID(), partialID) {