Browse code

Merge pull request #23524 from aboch/restore

Daemon to support network restore

Arnaud Porterie authored on 2016/06/15 11:33:16
Showing 52 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) {
... ...
@@ -65,7 +65,7 @@ clone git github.com/RackSec/srslog 259aed10dfa74ea2961eddd1d9847619f6e98837
65 65
 clone git github.com/imdario/mergo 0.2.1
66 66
 
67 67
 #get libnetwork packages
68
-clone git github.com/docker/libnetwork e8da32ce5693f0ed6823d59c8415baf76c0809ea
68
+clone git github.com/docker/libnetwork 452dff166e0abd9455b07c835613197f078a34de
69 69
 clone git github.com/docker/go-events 39718a26497694185f8fb58a7d6f31947f3dc42d
70 70
 clone git github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80
71 71
 clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
... ...
@@ -1586,3 +1586,67 @@ func (s *DockerNetworkSuite) TestDockerNetworkCreateDeleteSpecialCharacters(c *c
1586 1586
 	dockerCmd(c, "network", "rm", "kiwl$%^")
1587 1587
 	assertNwNotAvailable(c, "kiwl$%^")
1588 1588
 }
1589
+
1590
+func (s *DockerDaemonSuite) TestDaemonRestartRestoreBridgeNetwork(t *check.C) {
1591
+	testRequires(t, DaemonIsLinux)
1592
+	if err := s.d.StartWithBusybox("--live-restore"); err != nil {
1593
+		t.Fatal(err)
1594
+	}
1595
+	defer s.d.Stop()
1596
+	oldCon := "old"
1597
+
1598
+	_, err := s.d.Cmd("run", "-d", "--name", oldCon, "-p", "80:80", "busybox", "top")
1599
+	if err != nil {
1600
+		t.Fatal(err)
1601
+	}
1602
+	oldContainerIP, err := s.d.Cmd("inspect", "-f", "{{ .NetworkSettings.Networks.bridge.IPAddress }}", oldCon)
1603
+	if err != nil {
1604
+		t.Fatal(err)
1605
+	}
1606
+	// Kill the daemon
1607
+	if err := s.d.Kill(); err != nil {
1608
+		t.Fatal(err)
1609
+	}
1610
+
1611
+	// restart the daemon
1612
+	if err := s.d.Start("--live-restore"); err != nil {
1613
+		t.Fatal(err)
1614
+	}
1615
+
1616
+	// start a new container, the new container's ip should not be the same with
1617
+	// old running container.
1618
+	newCon := "new"
1619
+	_, err = s.d.Cmd("run", "-d", "--name", newCon, "busybox", "top")
1620
+	if err != nil {
1621
+		t.Fatal(err)
1622
+	}
1623
+	newContainerIP, err := s.d.Cmd("inspect", "-f", "{{ .NetworkSettings.Networks.bridge.IPAddress }}", newCon)
1624
+	if err != nil {
1625
+		t.Fatal(err)
1626
+	}
1627
+	if strings.Compare(strings.TrimSpace(oldContainerIP), strings.TrimSpace(newContainerIP)) == 0 {
1628
+		t.Fatalf("new container ip should not equal to old running container  ip")
1629
+	}
1630
+
1631
+	// start a new container, the new container should ping old running container
1632
+	_, err = s.d.Cmd("run", "-t", "busybox", "ping", "-c", "1", oldContainerIP)
1633
+	if err != nil {
1634
+		t.Fatal(err)
1635
+	}
1636
+
1637
+	// start a new container try to publist port 80:80 will failed
1638
+	out, err := s.d.Cmd("run", "-p", "80:80", "-d", "busybox", "top")
1639
+	if err == nil || !strings.Contains(out, "Bind for 0.0.0.0:80 failed: port is already allocated") {
1640
+		t.Fatalf("80 port is allocated to old running container, it should failed on allocating to new container")
1641
+	}
1642
+
1643
+	// kill old running container and try to allocate again
1644
+	_, err = s.d.Cmd("kill", oldCon)
1645
+	if err != nil {
1646
+		t.Fatal(err)
1647
+	}
1648
+	_, err = s.d.Cmd("run", "-p", "80:80", "-d", "busybox", "top")
1649
+	if err != nil {
1650
+		t.Fatal(err)
1651
+	}
1652
+}
... ...
@@ -15,9 +15,10 @@ import (
15 15
 
16 16
 // Config encapsulates configurations of various Libnetwork components
17 17
 type Config struct {
18
-	Daemon  DaemonCfg
19
-	Cluster ClusterCfg
20
-	Scopes  map[string]*datastore.ScopeCfg
18
+	Daemon          DaemonCfg
19
+	Cluster         ClusterCfg
20
+	Scopes          map[string]*datastore.ScopeCfg
21
+	ActiveSandboxes map[string]interface{}
21 22
 }
22 23
 
23 24
 // DaemonCfg represents libnetwork core configuration
... ...
@@ -245,3 +246,11 @@ func OptionLocalKVProviderConfig(config *store.Config) Option {
245 245
 		c.Scopes[datastore.LocalScope].Client.Config = config
246 246
 	}
247 247
 }
248
+
249
+// OptionActiveSandboxes function returns an option setter for passing the sandboxes
250
+// which were active during previous daemon life
251
+func OptionActiveSandboxes(sandboxes map[string]interface{}) Option {
252
+	return func(c *Config) {
253
+		c.ActiveSandboxes = sandboxes
254
+	}
255
+}
... ...
@@ -203,15 +203,13 @@ func New(cfgOptions ...config.Option) (NetworkController, error) {
203 203
 		}
204 204
 	}
205 205
 
206
-	// Reserve pools first before doing cleanup. This is because
207
-	// if the pools are not populated properly, the cleanups of
208
-	// endpoint/network and sandbox below will not be able to
209
-	// release ip subnets and addresses properly into the pool
210
-	// because the pools won't exist.
206
+	// Reserve pools first before doing cleanup. Otherwise the
207
+	// cleanups of endpoint/network and sandbox below will
208
+	// generate many unnecessary warnings
211 209
 	c.reservePools()
212 210
 
213 211
 	// Cleanup resources
214
-	c.sandboxCleanup()
212
+	c.sandboxCleanup(c.cfg.ActiveSandboxes)
215 213
 	c.cleanupLocalEndpoints()
216 214
 	c.networkCleanup()
217 215
 
... ...
@@ -671,9 +669,27 @@ func (c *controller) reservePools() {
671 671
 				c.Gateway = n.ipamV6Info[i].Gateway.IP.String()
672 672
 			}
673 673
 		}
674
+		// Reserve pools
674 675
 		if err := n.ipamAllocate(); err != nil {
675 676
 			log.Warnf("Failed to allocate ipam pool(s) for network %q (%s): %v", n.Name(), n.ID(), err)
676 677
 		}
678
+		// Reserve existing endpoints' addresses
679
+		ipam, _, err := n.getController().getIPAMDriver(n.ipamType)
680
+		if err != nil {
681
+			log.Warnf("Failed to retrieve ipam driver for network %q (%s) during address reservation", n.Name(), n.ID())
682
+			continue
683
+		}
684
+		epl, err := n.getEndpointsFromStore()
685
+		if err != nil {
686
+			log.Warnf("Failed to retrieve list of current endpoints on network %q (%s)", n.Name(), n.ID())
687
+			continue
688
+		}
689
+		for _, ep := range epl {
690
+			if err := ep.assignAddress(ipam, true, ep.Iface().AddressIPv6() != nil); err != nil {
691
+				log.Warnf("Failed to reserve current adress for endpoint %q (%s) on network %q (%s)",
692
+					ep.Name(), ep.ID(), n.Name(), n.ID())
693
+			}
694
+		}
677 695
 	}
678 696
 }
679 697
 
... ...
@@ -832,7 +848,7 @@ func (c *controller) NewSandbox(containerID string, options ...SandboxOption) (s
832 832
 
833 833
 	if sb.config.useDefaultSandBox {
834 834
 		c.sboxOnce.Do(func() {
835
-			c.defOsSbox, err = osl.NewSandbox(sb.Key(), false)
835
+			c.defOsSbox, err = osl.NewSandbox(sb.Key(), false, false)
836 836
 		})
837 837
 
838 838
 		if err != nil {
... ...
@@ -844,7 +860,7 @@ func (c *controller) NewSandbox(containerID string, options ...SandboxOption) (s
844 844
 	}
845 845
 
846 846
 	if sb.osSbox == nil && !sb.config.useExternalKey {
847
-		if sb.osSbox, err = osl.NewSandbox(sb.Key(), !sb.config.useDefaultSandBox); err != nil {
847
+		if sb.osSbox, err = osl.NewSandbox(sb.Key(), !sb.config.useDefaultSandBox, false); err != nil {
848 848
 			return nil, fmt.Errorf("failed to create new osl sandbox: %v", err)
849 849
 		}
850 850
 	}
... ...
@@ -86,25 +86,52 @@ out:
86 86
 	return kmap, nil
87 87
 }
88 88
 
89
-func (c *cache) add(kvObject KVObject) error {
89
+func (c *cache) add(kvObject KVObject, atomic bool) error {
90 90
 	kmap, err := c.kmap(kvObject)
91 91
 	if err != nil {
92 92
 		return err
93 93
 	}
94 94
 
95 95
 	c.Lock()
96
+	// If atomic is true, cache needs to maintain its own index
97
+	// for atomicity and the add needs to be atomic.
98
+	if atomic {
99
+		if prev, ok := kmap[Key(kvObject.Key()...)]; ok {
100
+			if prev.Index() != kvObject.Index() {
101
+				c.Unlock()
102
+				return ErrKeyModified
103
+			}
104
+		}
105
+
106
+		// Increment index
107
+		index := kvObject.Index()
108
+		index++
109
+		kvObject.SetIndex(index)
110
+	}
111
+
96 112
 	kmap[Key(kvObject.Key()...)] = kvObject
97 113
 	c.Unlock()
98 114
 	return nil
99 115
 }
100 116
 
101
-func (c *cache) del(kvObject KVObject) error {
117
+func (c *cache) del(kvObject KVObject, atomic bool) error {
102 118
 	kmap, err := c.kmap(kvObject)
103 119
 	if err != nil {
104 120
 		return err
105 121
 	}
106 122
 
107 123
 	c.Lock()
124
+	// If atomic is true, cache needs to maintain its own index
125
+	// for atomicity and del needs to be atomic.
126
+	if atomic {
127
+		if prev, ok := kmap[Key(kvObject.Key()...)]; ok {
128
+			if prev.Index() != kvObject.Index() {
129
+				c.Unlock()
130
+				return ErrKeyModified
131
+			}
132
+		}
133
+	}
134
+
108 135
 	delete(kmap, Key(kvObject.Key()...))
109 136
 	c.Unlock()
110 137
 	return nil
... ...
@@ -410,7 +410,9 @@ func (ds *datastore) PutObjectAtomic(kvObject KVObject) error {
410 410
 
411 411
 add_cache:
412 412
 	if ds.cache != nil {
413
-		return ds.cache.add(kvObject)
413
+		// If persistent store is skipped, sequencing needs to
414
+		// happen in cache.
415
+		return ds.cache.add(kvObject, kvObject.Skip())
414 416
 	}
415 417
 
416 418
 	return nil
... ...
@@ -435,7 +437,9 @@ func (ds *datastore) PutObject(kvObject KVObject) error {
435 435
 
436 436
 add_cache:
437 437
 	if ds.cache != nil {
438
-		return ds.cache.add(kvObject)
438
+		// If persistent store is skipped, sequencing needs to
439
+		// happen in cache.
440
+		return ds.cache.add(kvObject, kvObject.Skip())
439 441
 	}
440 442
 
441 443
 	return nil
... ...
@@ -537,7 +541,9 @@ func (ds *datastore) DeleteObject(kvObject KVObject) error {
537 537
 
538 538
 	// cleaup the cache first
539 539
 	if ds.cache != nil {
540
-		ds.cache.del(kvObject)
540
+		// If persistent store is skipped, sequencing needs to
541
+		// happen in cache.
542
+		ds.cache.del(kvObject, kvObject.Skip())
541 543
 	}
542 544
 
543 545
 	if kvObject.Skip() {
... ...
@@ -572,7 +578,9 @@ func (ds *datastore) DeleteObjectAtomic(kvObject KVObject) error {
572 572
 del_cache:
573 573
 	// cleanup the cache only if AtomicDelete went through successfully
574 574
 	if ds.cache != nil {
575
-		return ds.cache.del(kvObject)
575
+		// If persistent store is skipped, sequencing needs to
576
+		// happen in cache.
577
+		return ds.cache.del(kvObject, kvObject.Skip())
576 578
 	}
577 579
 
578 580
 	return nil
... ...
@@ -585,7 +593,9 @@ func (ds *datastore) DeleteTree(kvObject KVObject) error {
585 585
 
586 586
 	// cleaup the cache first
587 587
 	if ds.cache != nil {
588
-		ds.cache.del(kvObject)
588
+		// If persistent store is skipped, sequencing needs to
589
+		// happen in cache.
590
+		ds.cache.del(kvObject, kvObject.Skip())
589 591
 	}
590 592
 
591 593
 	if kvObject.Skip() {
... ...
@@ -91,6 +91,7 @@ type connectivityConfiguration struct {
91 91
 
92 92
 type bridgeEndpoint struct {
93 93
 	id              string
94
+	nid             string
94 95
 	srcName         string
95 96
 	addr            *net.IPNet
96 97
 	addrv6          *net.IPNet
... ...
@@ -99,6 +100,8 @@ type bridgeEndpoint struct {
99 99
 	containerConfig *containerConfiguration
100 100
 	extConnConfig   *connectivityConfiguration
101 101
 	portMapping     []types.PortBinding // Operation port bindings
102
+	dbIndex         uint64
103
+	dbExists        bool
102 104
 }
103 105
 
104 106
 type bridgeNetwork struct {
... ...
@@ -882,7 +885,7 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
882 882
 
883 883
 	// Create and add the endpoint
884 884
 	n.Lock()
885
-	endpoint := &bridgeEndpoint{id: eid, config: epConfig}
885
+	endpoint := &bridgeEndpoint{id: eid, nid: nid, config: epConfig}
886 886
 	n.endpoints[eid] = endpoint
887 887
 	n.Unlock()
888 888
 
... ...
@@ -1009,6 +1012,10 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
1009 1009
 		}
1010 1010
 	}
1011 1011
 
1012
+	if err = d.storeUpdate(endpoint); err != nil {
1013
+		return fmt.Errorf("failed to save bridge endpoint %s to store: %v", ep.id[0:7], err)
1014
+	}
1015
+
1012 1016
 	return nil
1013 1017
 }
1014 1018
 
... ...
@@ -1069,6 +1076,10 @@ func (d *driver) DeleteEndpoint(nid, eid string) error {
1069 1069
 		d.nlh.LinkDel(link)
1070 1070
 	}
1071 1071
 
1072
+	if err := d.storeDelete(ep); err != nil {
1073
+		logrus.Warnf("Failed to remove bridge endpoint %s from store: %v", ep.id[0:7], err)
1074
+	}
1075
+
1072 1076
 	return nil
1073 1077
 }
1074 1078
 
... ...
@@ -1225,6 +1236,11 @@ func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string
1225 1225
 		return err
1226 1226
 	}
1227 1227
 
1228
+	if err = d.storeUpdate(endpoint); err != nil {
1229
+		endpoint.portMapping = nil
1230
+		return fmt.Errorf("failed to update bridge endpoint %s to store: %v", endpoint.id[0:7], err)
1231
+	}
1232
+
1228 1233
 	if !network.config.EnableICC {
1229 1234
 		return d.link(network, endpoint, true)
1230 1235
 	}
... ...
@@ -12,7 +12,13 @@ import (
12 12
 	"github.com/docker/libnetwork/types"
13 13
 )
14 14
 
15
-const bridgePrefix = "bridge"
15
+const (
16
+	// network config prefix was not specific enough.
17
+	// To be backward compatible, need custom endpoint
18
+	// prefix with different root
19
+	bridgePrefix         = "bridge"
20
+	bridgeEndpointPrefix = "bridge-endpoint"
21
+)
16 22
 
17 23
 func (d *driver) initStore(option map[string]interface{}) error {
18 24
 	if data, ok := option[netlabel.LocalKVClient]; ok {
... ...
@@ -26,7 +32,15 @@ func (d *driver) initStore(option map[string]interface{}) error {
26 26
 			return types.InternalErrorf("bridge driver failed to initialize data store: %v", err)
27 27
 		}
28 28
 
29
-		return d.populateNetworks()
29
+		err = d.populateNetworks()
30
+		if err != nil {
31
+			return err
32
+		}
33
+
34
+		err = d.populateEndpoints()
35
+		if err != nil {
36
+			return err
37
+		}
30 38
 	}
31 39
 
32 40
 	return nil
... ...
@@ -48,6 +62,36 @@ func (d *driver) populateNetworks() error {
48 48
 		if err = d.createNetwork(ncfg); err != nil {
49 49
 			logrus.Warnf("could not create bridge network for id %s bridge name %s while booting up from persistent state: %v", ncfg.ID, ncfg.BridgeName, err)
50 50
 		}
51
+		logrus.Debugf("Network (%s) restored", ncfg.ID[0:7])
52
+	}
53
+
54
+	return nil
55
+}
56
+
57
+func (d *driver) populateEndpoints() error {
58
+	kvol, err := d.store.List(datastore.Key(bridgeEndpointPrefix), &bridgeEndpoint{})
59
+	if err != nil && err != datastore.ErrKeyNotFound {
60
+		return fmt.Errorf("failed to get bridge endpoints from store: %v", err)
61
+	}
62
+
63
+	if err == datastore.ErrKeyNotFound {
64
+		return nil
65
+	}
66
+
67
+	for _, kvo := range kvol {
68
+		ep := kvo.(*bridgeEndpoint)
69
+		n, ok := d.networks[ep.nid]
70
+		if !ok {
71
+			logrus.Debugf("Network (%s) not found for restored bridge endpoint (%s)", ep.nid[0:7], ep.id[0:7])
72
+			logrus.Debugf("Deleting stale bridge endpoint (%s) from store", ep.nid[0:7])
73
+			if err := d.storeDelete(ep); err != nil {
74
+				logrus.Debugf("Failed to delete stale bridge endpoint (%s) from store", ep.nid[0:7])
75
+			}
76
+			continue
77
+		}
78
+		n.endpoints[ep.id] = ep
79
+		n.restorePortAllocations(ep)
80
+		logrus.Debugf("Endpoint (%s) restored to network (%s)", ep.id[0:7], ep.nid[0:7])
51 81
 	}
52 82
 
53 83
 	return nil
... ...
@@ -184,7 +228,7 @@ func (ncfg *networkConfiguration) Exists() bool {
184 184
 }
185 185
 
186 186
 func (ncfg *networkConfiguration) Skip() bool {
187
-	return ncfg.DefaultBridge
187
+	return false
188 188
 }
189 189
 
190 190
 func (ncfg *networkConfiguration) New() datastore.KVObject {
... ...
@@ -200,3 +244,135 @@ func (ncfg *networkConfiguration) CopyTo(o datastore.KVObject) error {
200 200
 func (ncfg *networkConfiguration) DataScope() string {
201 201
 	return datastore.LocalScope
202 202
 }
203
+
204
+func (ep *bridgeEndpoint) MarshalJSON() ([]byte, error) {
205
+	epMap := make(map[string]interface{})
206
+	epMap["id"] = ep.id
207
+	epMap["nid"] = ep.nid
208
+	epMap["SrcName"] = ep.srcName
209
+	epMap["MacAddress"] = ep.macAddress.String()
210
+	epMap["Addr"] = ep.addr.String()
211
+	if ep.addrv6 != nil {
212
+		epMap["Addrv6"] = ep.addrv6.String()
213
+	}
214
+	epMap["Config"] = ep.config
215
+	epMap["ContainerConfig"] = ep.containerConfig
216
+	epMap["ExternalConnConfig"] = ep.extConnConfig
217
+	epMap["PortMapping"] = ep.portMapping
218
+
219
+	return json.Marshal(epMap)
220
+}
221
+
222
+func (ep *bridgeEndpoint) UnmarshalJSON(b []byte) error {
223
+	var (
224
+		err   error
225
+		epMap map[string]interface{}
226
+	)
227
+
228
+	if err = json.Unmarshal(b, &epMap); err != nil {
229
+		return fmt.Errorf("Failed to unmarshal to bridge endpoint: %v", err)
230
+	}
231
+
232
+	if v, ok := epMap["MacAddress"]; ok {
233
+		if ep.macAddress, err = net.ParseMAC(v.(string)); err != nil {
234
+			return types.InternalErrorf("failed to decode bridge endpoint MAC address (%s) after json unmarshal: %v", v.(string), err)
235
+		}
236
+	}
237
+	if v, ok := epMap["Addr"]; ok {
238
+		if ep.addr, err = types.ParseCIDR(v.(string)); err != nil {
239
+			return types.InternalErrorf("failed to decode bridge endpoint IPv4 address (%s) after json unmarshal: %v", v.(string), err)
240
+		}
241
+	}
242
+	if v, ok := epMap["Addrv6"]; ok {
243
+		if ep.addrv6, err = types.ParseCIDR(v.(string)); err != nil {
244
+			return types.InternalErrorf("failed to decode bridge endpoint IPv6 address (%s) after json unmarshal: %v", v.(string), err)
245
+		}
246
+	}
247
+	ep.id = epMap["id"].(string)
248
+	ep.nid = epMap["nid"].(string)
249
+	ep.srcName = epMap["SrcName"].(string)
250
+	d, _ := json.Marshal(epMap["Config"])
251
+	if err := json.Unmarshal(d, &ep.config); err != nil {
252
+		logrus.Warnf("Failed to decode endpoint config %v", err)
253
+	}
254
+	d, _ = json.Marshal(epMap["ContainerConfig"])
255
+	if err := json.Unmarshal(d, &ep.containerConfig); err != nil {
256
+		logrus.Warnf("Failed to decode endpoint container config %v", err)
257
+	}
258
+	d, _ = json.Marshal(epMap["ExternalConnConfig"])
259
+	if err := json.Unmarshal(d, &ep.extConnConfig); err != nil {
260
+		logrus.Warnf("Failed to decode endpoint external connectivity configuration %v", err)
261
+	}
262
+	d, _ = json.Marshal(epMap["PortMapping"])
263
+	if err := json.Unmarshal(d, &ep.portMapping); err != nil {
264
+		logrus.Warnf("Failed to decode endpoint port mapping %v", err)
265
+	}
266
+
267
+	return nil
268
+}
269
+
270
+func (ep *bridgeEndpoint) Key() []string {
271
+	return []string{bridgeEndpointPrefix, ep.id}
272
+}
273
+
274
+func (ep *bridgeEndpoint) KeyPrefix() []string {
275
+	return []string{bridgeEndpointPrefix}
276
+}
277
+
278
+func (ep *bridgeEndpoint) Value() []byte {
279
+	b, err := json.Marshal(ep)
280
+	if err != nil {
281
+		return nil
282
+	}
283
+	return b
284
+}
285
+
286
+func (ep *bridgeEndpoint) SetValue(value []byte) error {
287
+	return json.Unmarshal(value, ep)
288
+}
289
+
290
+func (ep *bridgeEndpoint) Index() uint64 {
291
+	return ep.dbIndex
292
+}
293
+
294
+func (ep *bridgeEndpoint) SetIndex(index uint64) {
295
+	ep.dbIndex = index
296
+	ep.dbExists = true
297
+}
298
+
299
+func (ep *bridgeEndpoint) Exists() bool {
300
+	return ep.dbExists
301
+}
302
+
303
+func (ep *bridgeEndpoint) Skip() bool {
304
+	return false
305
+}
306
+
307
+func (ep *bridgeEndpoint) New() datastore.KVObject {
308
+	return &bridgeEndpoint{}
309
+}
310
+
311
+func (ep *bridgeEndpoint) CopyTo(o datastore.KVObject) error {
312
+	dstEp := o.(*bridgeEndpoint)
313
+	*dstEp = *ep
314
+	return nil
315
+}
316
+
317
+func (ep *bridgeEndpoint) DataScope() string {
318
+	return datastore.LocalScope
319
+}
320
+
321
+func (n *bridgeNetwork) restorePortAllocations(ep *bridgeEndpoint) {
322
+	if ep.extConnConfig == nil ||
323
+		ep.extConnConfig.ExposedPorts == nil ||
324
+		ep.extConnConfig.PortBindings == nil {
325
+		return
326
+	}
327
+	tmp := ep.extConnConfig.PortBindings
328
+	ep.extConnConfig.PortBindings = ep.portMapping
329
+	_, err := n.allocatePorts(ep, n.config.DefaultBindingIP, n.driver.config.EnableUserlandProxy)
330
+	if err != nil {
331
+		logrus.Warnf("Failed to reserve existing port mapping for endpoint %s:%v", ep.id[0:7], err)
332
+	}
333
+	ep.extConnConfig.PortBindings = tmp
334
+}
... ...
@@ -36,11 +36,14 @@ type driver struct {
36 36
 }
37 37
 
38 38
 type endpoint struct {
39
-	id      string
40
-	mac     net.HardwareAddr
41
-	addr    *net.IPNet
42
-	addrv6  *net.IPNet
43
-	srcName string
39
+	id       string
40
+	nid      string
41
+	mac      net.HardwareAddr
42
+	addr     *net.IPNet
43
+	addrv6   *net.IPNet
44
+	srcName  string
45
+	dbIndex  uint64
46
+	dbExists bool
44 47
 }
45 48
 
46 49
 type network struct {
... ...
@@ -28,9 +28,9 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
28 28
 	}
29 29
 	ep := &endpoint{
30 30
 		id:     eid,
31
+		nid:    nid,
31 32
 		addr:   ifInfo.Address(),
32 33
 		addrv6: ifInfo.AddressIPv6(),
33
-		mac:    ifInfo.MacAddress(),
34 34
 	}
35 35
 	if ep.addr == nil {
36 36
 		return fmt.Errorf("create endpoint was not passed an IP address")
... ...
@@ -51,6 +51,11 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
51 51
 			}
52 52
 		}
53 53
 	}
54
+
55
+	if err := d.storeUpdate(ep); err != nil {
56
+		return fmt.Errorf("failed to save ipvlan endpoint %s to store: %v", ep.id[0:7], err)
57
+	}
58
+
54 59
 	n.addEndpoint(ep)
55 60
 
56 61
 	return nil
... ...
@@ -74,5 +79,9 @@ func (d *driver) DeleteEndpoint(nid, eid string) error {
74 74
 		ns.NlHandle().LinkDel(link)
75 75
 	}
76 76
 
77
+	if err := d.storeDelete(ep); err != nil {
78
+		logrus.Warnf("Failed to remove ipvlan endpoint %s from store: %v", ep.id[0:7], err)
79
+	}
80
+
77 81
 	return nil
78 82
 }
... ...
@@ -116,6 +116,9 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
116 116
 	if err != nil {
117 117
 		return err
118 118
 	}
119
+	if err = d.storeUpdate(ep); err != nil {
120
+		return fmt.Errorf("failed to save ipvlan endpoint %s to store: %v", ep.id[0:7], err)
121
+	}
119 122
 
120 123
 	return nil
121 124
 }
... ...
@@ -3,6 +3,7 @@ package ipvlan
3 3
 import (
4 4
 	"encoding/json"
5 5
 	"fmt"
6
+	"net"
6 7
 
7 8
 	"github.com/Sirupsen/logrus"
8 9
 	"github.com/docker/libnetwork/datastore"
... ...
@@ -11,7 +12,11 @@ import (
11 11
 	"github.com/docker/libnetwork/types"
12 12
 )
13 13
 
14
-const ipvlanPrefix = "ipvlan" // prefix used for persistent driver storage
14
+const (
15
+	ipvlanPrefix         = "ipvlan"
16
+	ipvlanNetworkPrefix  = ipvlanPrefix + "/network"
17
+	ipvlanEndpointPrefix = ipvlanPrefix + "/endpoint"
18
+)
15 19
 
16 20
 // networkConfiguration for this driver's network specific configuration
17 21
 type configuration struct {
... ...
@@ -58,7 +63,7 @@ func (d *driver) initStore(option map[string]interface{}) error {
58 58
 
59 59
 // populateNetworks is invoked at driver init to recreate persistently stored networks
60 60
 func (d *driver) populateNetworks() error {
61
-	kvol, err := d.store.List(datastore.Key(ipvlanPrefix), &configuration{})
61
+	kvol, err := d.store.List(datastore.Key(ipvlanNetworkPrefix), &configuration{})
62 62
 	if err != nil && err != datastore.ErrKeyNotFound {
63 63
 		return fmt.Errorf("failed to get ipvlan network configurations from store: %v", err)
64 64
 	}
... ...
@@ -76,6 +81,34 @@ func (d *driver) populateNetworks() error {
76 76
 	return nil
77 77
 }
78 78
 
79
+func (d *driver) populateEndpoints() error {
80
+	kvol, err := d.store.List(datastore.Key(ipvlanEndpointPrefix), &endpoint{})
81
+	if err != nil && err != datastore.ErrKeyNotFound {
82
+		return fmt.Errorf("failed to get ipvlan endpoints from store: %v", err)
83
+	}
84
+
85
+	if err == datastore.ErrKeyNotFound {
86
+		return nil
87
+	}
88
+
89
+	for _, kvo := range kvol {
90
+		ep := kvo.(*endpoint)
91
+		n, ok := d.networks[ep.nid]
92
+		if !ok {
93
+			logrus.Debugf("Network (%s) not found for restored ipvlan endpoint (%s)", ep.nid[0:7], ep.id[0:7])
94
+			logrus.Debugf("Deleting stale ipvlan endpoint (%s) from store", ep.nid[0:7])
95
+			if err := d.storeDelete(ep); err != nil {
96
+				logrus.Debugf("Failed to delete stale ipvlan endpoint (%s) from store", ep.nid[0:7])
97
+			}
98
+			continue
99
+		}
100
+		n.endpoints[ep.id] = ep
101
+		logrus.Debugf("Endpoint (%s) restored to network (%s)", ep.id[0:7], ep.nid[0:7])
102
+	}
103
+
104
+	return nil
105
+}
106
+
79 107
 // storeUpdate used to update persistent ipvlan network records as they are created
80 108
 func (d *driver) storeUpdate(kvObject datastore.KVObject) error {
81 109
 	if d.store == nil {
... ...
@@ -165,11 +198,11 @@ func (config *configuration) UnmarshalJSON(b []byte) error {
165 165
 }
166 166
 
167 167
 func (config *configuration) Key() []string {
168
-	return []string{ipvlanPrefix, config.ID}
168
+	return []string{ipvlanNetworkPrefix, config.ID}
169 169
 }
170 170
 
171 171
 func (config *configuration) KeyPrefix() []string {
172
-	return []string{ipvlanPrefix}
172
+	return []string{ipvlanNetworkPrefix}
173 173
 }
174 174
 
175 175
 func (config *configuration) Value() []byte {
... ...
@@ -214,3 +247,103 @@ func (config *configuration) CopyTo(o datastore.KVObject) error {
214 214
 func (config *configuration) DataScope() string {
215 215
 	return datastore.LocalScope
216 216
 }
217
+
218
+func (ep *endpoint) MarshalJSON() ([]byte, error) {
219
+	epMap := make(map[string]interface{})
220
+	epMap["id"] = ep.id
221
+	epMap["nid"] = ep.nid
222
+	epMap["SrcName"] = ep.srcName
223
+	if len(ep.mac) != 0 {
224
+		epMap["MacAddress"] = ep.mac.String()
225
+	}
226
+	if ep.addr != nil {
227
+		epMap["Addr"] = ep.addr.String()
228
+	}
229
+	if ep.addrv6 != nil {
230
+		epMap["Addrv6"] = ep.addrv6.String()
231
+	}
232
+	return json.Marshal(epMap)
233
+}
234
+
235
+func (ep *endpoint) UnmarshalJSON(b []byte) error {
236
+	var (
237
+		err   error
238
+		epMap map[string]interface{}
239
+	)
240
+
241
+	if err = json.Unmarshal(b, &epMap); err != nil {
242
+		return fmt.Errorf("Failed to unmarshal to ipvlan endpoint: %v", err)
243
+	}
244
+
245
+	if v, ok := epMap["MacAddress"]; ok {
246
+		if ep.mac, err = net.ParseMAC(v.(string)); err != nil {
247
+			return types.InternalErrorf("failed to decode ipvlan endpoint MAC address (%s) after json unmarshal: %v", v.(string), err)
248
+		}
249
+	}
250
+	if v, ok := epMap["Addr"]; ok {
251
+		if ep.addr, err = types.ParseCIDR(v.(string)); err != nil {
252
+			return types.InternalErrorf("failed to decode ipvlan endpoint IPv4 address (%s) after json unmarshal: %v", v.(string), err)
253
+		}
254
+	}
255
+	if v, ok := epMap["Addrv6"]; ok {
256
+		if ep.addrv6, err = types.ParseCIDR(v.(string)); err != nil {
257
+			return types.InternalErrorf("failed to decode ipvlan endpoint IPv6 address (%s) after json unmarshal: %v", v.(string), err)
258
+		}
259
+	}
260
+	ep.id = epMap["id"].(string)
261
+	ep.nid = epMap["nid"].(string)
262
+	ep.srcName = epMap["SrcName"].(string)
263
+
264
+	return nil
265
+}
266
+
267
+func (ep *endpoint) Key() []string {
268
+	return []string{ipvlanEndpointPrefix, ep.id}
269
+}
270
+
271
+func (ep *endpoint) KeyPrefix() []string {
272
+	return []string{ipvlanEndpointPrefix}
273
+}
274
+
275
+func (ep *endpoint) Value() []byte {
276
+	b, err := json.Marshal(ep)
277
+	if err != nil {
278
+		return nil
279
+	}
280
+	return b
281
+}
282
+
283
+func (ep *endpoint) SetValue(value []byte) error {
284
+	return json.Unmarshal(value, ep)
285
+}
286
+
287
+func (ep *endpoint) Index() uint64 {
288
+	return ep.dbIndex
289
+}
290
+
291
+func (ep *endpoint) SetIndex(index uint64) {
292
+	ep.dbIndex = index
293
+	ep.dbExists = true
294
+}
295
+
296
+func (ep *endpoint) Exists() bool {
297
+	return ep.dbExists
298
+}
299
+
300
+func (ep *endpoint) Skip() bool {
301
+	return false
302
+}
303
+
304
+func (ep *endpoint) New() datastore.KVObject {
305
+	return &endpoint{}
306
+}
307
+
308
+func (ep *endpoint) CopyTo(o datastore.KVObject) error {
309
+	dstEp := o.(*endpoint)
310
+	*dstEp = *ep
311
+	return nil
312
+}
313
+
314
+func (ep *endpoint) DataScope() string {
315
+	return datastore.LocalScope
316
+}
... ...
@@ -38,11 +38,14 @@ type driver struct {
38 38
 }
39 39
 
40 40
 type endpoint struct {
41
-	id      string
42
-	mac     net.HardwareAddr
43
-	addr    *net.IPNet
44
-	addrv6  *net.IPNet
45
-	srcName string
41
+	id       string
42
+	nid      string
43
+	mac      net.HardwareAddr
44
+	addr     *net.IPNet
45
+	addrv6   *net.IPNet
46
+	srcName  string
47
+	dbIndex  uint64
48
+	dbExists bool
46 49
 }
47 50
 
48 51
 type network struct {
... ...
@@ -26,6 +26,7 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
26 26
 	}
27 27
 	ep := &endpoint{
28 28
 		id:     eid,
29
+		nid:    nid,
29 30
 		addr:   ifInfo.Address(),
30 31
 		addrv6: ifInfo.AddressIPv6(),
31 32
 		mac:    ifInfo.MacAddress(),
... ...
@@ -55,6 +56,11 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
55 55
 			}
56 56
 		}
57 57
 	}
58
+
59
+	if err := d.storeUpdate(ep); err != nil {
60
+		return fmt.Errorf("failed to save macvlan endpoint %s to store: %v", ep.id[0:7], err)
61
+	}
62
+
58 63
 	n.addEndpoint(ep)
59 64
 
60 65
 	return nil
... ...
@@ -77,6 +83,8 @@ func (d *driver) DeleteEndpoint(nid, eid string) error {
77 77
 	if link, err := ns.NlHandle().LinkByName(ep.srcName); err == nil {
78 78
 		ns.NlHandle().LinkDel(link)
79 79
 	}
80
-
80
+	if err := d.storeDelete(ep); err != nil {
81
+		logrus.Warnf("Failed to remove macvlan endpoint %s from store: %v", ep.id[0:7], err)
82
+	}
81 83
 	return nil
82 84
 }
... ...
@@ -77,7 +77,9 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
77 77
 	if err != nil {
78 78
 		return err
79 79
 	}
80
-
80
+	if err := d.storeUpdate(ep); err != nil {
81
+		return fmt.Errorf("failed to save macvlan endpoint %s to store: %v", ep.id[0:7], err)
82
+	}
81 83
 	return nil
82 84
 }
83 85
 
... ...
@@ -3,6 +3,7 @@ package macvlan
3 3
 import (
4 4
 	"encoding/json"
5 5
 	"fmt"
6
+	"net"
6 7
 
7 8
 	"github.com/Sirupsen/logrus"
8 9
 	"github.com/docker/libnetwork/datastore"
... ...
@@ -11,7 +12,11 @@ import (
11 11
 	"github.com/docker/libnetwork/types"
12 12
 )
13 13
 
14
-const macvlanPrefix = "macvlan" // prefix used for persistent driver storage
14
+const (
15
+	macvlanPrefix         = "macvlan"
16
+	macvlanNetworkPrefix  = macvlanPrefix + "/network"
17
+	macvlanEndpointPrefix = macvlanPrefix + "/endpoint"
18
+)
15 19
 
16 20
 // networkConfiguration for this driver's network specific configuration
17 21
 type configuration struct {
... ...
@@ -76,6 +81,34 @@ func (d *driver) populateNetworks() error {
76 76
 	return nil
77 77
 }
78 78
 
79
+func (d *driver) populateEndpoints() error {
80
+	kvol, err := d.store.List(datastore.Key(macvlanEndpointPrefix), &endpoint{})
81
+	if err != nil && err != datastore.ErrKeyNotFound {
82
+		return fmt.Errorf("failed to get macvlan endpoints from store: %v", err)
83
+	}
84
+
85
+	if err == datastore.ErrKeyNotFound {
86
+		return nil
87
+	}
88
+
89
+	for _, kvo := range kvol {
90
+		ep := kvo.(*endpoint)
91
+		n, ok := d.networks[ep.nid]
92
+		if !ok {
93
+			logrus.Debugf("Network (%s) not found for restored macvlan endpoint (%s)", ep.nid[0:7], ep.id[0:7])
94
+			logrus.Debugf("Deleting stale macvlan endpoint (%s) from store", ep.nid[0:7])
95
+			if err := d.storeDelete(ep); err != nil {
96
+				logrus.Debugf("Failed to delete stale macvlan endpoint (%s) from store", ep.nid[0:7])
97
+			}
98
+			continue
99
+		}
100
+		n.endpoints[ep.id] = ep
101
+		logrus.Debugf("Endpoint (%s) restored to network (%s)", ep.id[0:7], ep.nid[0:7])
102
+	}
103
+
104
+	return nil
105
+}
106
+
79 107
 // storeUpdate used to update persistent macvlan network records as they are created
80 108
 func (d *driver) storeUpdate(kvObject datastore.KVObject) error {
81 109
 	if d.store == nil {
... ...
@@ -165,11 +198,11 @@ func (config *configuration) UnmarshalJSON(b []byte) error {
165 165
 }
166 166
 
167 167
 func (config *configuration) Key() []string {
168
-	return []string{macvlanPrefix, config.ID}
168
+	return []string{macvlanNetworkPrefix, config.ID}
169 169
 }
170 170
 
171 171
 func (config *configuration) KeyPrefix() []string {
172
-	return []string{macvlanPrefix}
172
+	return []string{macvlanNetworkPrefix}
173 173
 }
174 174
 
175 175
 func (config *configuration) Value() []byte {
... ...
@@ -216,3 +249,103 @@ func (config *configuration) CopyTo(o datastore.KVObject) error {
216 216
 func (config *configuration) DataScope() string {
217 217
 	return datastore.LocalScope
218 218
 }
219
+
220
+func (ep *endpoint) MarshalJSON() ([]byte, error) {
221
+	epMap := make(map[string]interface{})
222
+	epMap["id"] = ep.id
223
+	epMap["nid"] = ep.nid
224
+	epMap["SrcName"] = ep.srcName
225
+	if len(ep.mac) != 0 {
226
+		epMap["MacAddress"] = ep.mac.String()
227
+	}
228
+	if ep.addr != nil {
229
+		epMap["Addr"] = ep.addr.String()
230
+	}
231
+	if ep.addrv6 != nil {
232
+		epMap["Addrv6"] = ep.addrv6.String()
233
+	}
234
+	return json.Marshal(epMap)
235
+}
236
+
237
+func (ep *endpoint) UnmarshalJSON(b []byte) error {
238
+	var (
239
+		err   error
240
+		epMap map[string]interface{}
241
+	)
242
+
243
+	if err = json.Unmarshal(b, &epMap); err != nil {
244
+		return fmt.Errorf("Failed to unmarshal to macvlan endpoint: %v", err)
245
+	}
246
+
247
+	if v, ok := epMap["MacAddress"]; ok {
248
+		if ep.mac, err = net.ParseMAC(v.(string)); err != nil {
249
+			return types.InternalErrorf("failed to decode macvlan endpoint MAC address (%s) after json unmarshal: %v", v.(string), err)
250
+		}
251
+	}
252
+	if v, ok := epMap["Addr"]; ok {
253
+		if ep.addr, err = types.ParseCIDR(v.(string)); err != nil {
254
+			return types.InternalErrorf("failed to decode macvlan endpoint IPv4 address (%s) after json unmarshal: %v", v.(string), err)
255
+		}
256
+	}
257
+	if v, ok := epMap["Addrv6"]; ok {
258
+		if ep.addrv6, err = types.ParseCIDR(v.(string)); err != nil {
259
+			return types.InternalErrorf("failed to decode macvlan endpoint IPv6 address (%s) after json unmarshal: %v", v.(string), err)
260
+		}
261
+	}
262
+	ep.id = epMap["id"].(string)
263
+	ep.nid = epMap["nid"].(string)
264
+	ep.srcName = epMap["SrcName"].(string)
265
+
266
+	return nil
267
+}
268
+
269
+func (ep *endpoint) Key() []string {
270
+	return []string{macvlanEndpointPrefix, ep.id}
271
+}
272
+
273
+func (ep *endpoint) KeyPrefix() []string {
274
+	return []string{macvlanEndpointPrefix}
275
+}
276
+
277
+func (ep *endpoint) Value() []byte {
278
+	b, err := json.Marshal(ep)
279
+	if err != nil {
280
+		return nil
281
+	}
282
+	return b
283
+}
284
+
285
+func (ep *endpoint) SetValue(value []byte) error {
286
+	return json.Unmarshal(value, ep)
287
+}
288
+
289
+func (ep *endpoint) Index() uint64 {
290
+	return ep.dbIndex
291
+}
292
+
293
+func (ep *endpoint) SetIndex(index uint64) {
294
+	ep.dbIndex = index
295
+	ep.dbExists = true
296
+}
297
+
298
+func (ep *endpoint) Exists() bool {
299
+	return ep.dbExists
300
+}
301
+
302
+func (ep *endpoint) Skip() bool {
303
+	return false
304
+}
305
+
306
+func (ep *endpoint) New() datastore.KVObject {
307
+	return &endpoint{}
308
+}
309
+
310
+func (ep *endpoint) CopyTo(o datastore.KVObject) error {
311
+	dstEp := o.(*endpoint)
312
+	*dstEp = *ep
313
+	return nil
314
+}
315
+
316
+func (ep *endpoint) DataScope() string {
317
+	return datastore.LocalScope
318
+}
... ...
@@ -10,6 +10,7 @@ import (
10 10
 
11 11
 	log "github.com/Sirupsen/logrus"
12 12
 	"github.com/docker/libnetwork/iptables"
13
+	"github.com/docker/libnetwork/ns"
13 14
 	"github.com/docker/libnetwork/types"
14 15
 	"github.com/vishvananda/netlink"
15 16
 	"strconv"
... ...
@@ -214,12 +215,12 @@ func programSA(localIP, remoteIP net.IP, spi *spi, k *key, dir int, add bool) (f
214 214
 	var (
215 215
 		crypt       *netlink.XfrmStateAlgo
216 216
 		action      = "Removing"
217
-		xfrmProgram = netlink.XfrmStateDel
217
+		xfrmProgram = ns.NlHandle().XfrmStateDel
218 218
 	)
219 219
 
220 220
 	if add {
221 221
 		action = "Adding"
222
-		xfrmProgram = netlink.XfrmStateAdd
222
+		xfrmProgram = ns.NlHandle().XfrmStateAdd
223 223
 		crypt = &netlink.XfrmStateAlgo{Name: "cbc(aes)", Key: k.value}
224 224
 	}
225 225
 
... ...
@@ -278,10 +279,10 @@ func programSA(localIP, remoteIP net.IP, spi *spi, k *key, dir int, add bool) (f
278 278
 
279 279
 func programSP(fSA *netlink.XfrmState, rSA *netlink.XfrmState, add bool) error {
280 280
 	action := "Removing"
281
-	xfrmProgram := netlink.XfrmPolicyDel
281
+	xfrmProgram := ns.NlHandle().XfrmPolicyDel
282 282
 	if add {
283 283
 		action = "Adding"
284
-		xfrmProgram = netlink.XfrmPolicyAdd
284
+		xfrmProgram = ns.NlHandle().XfrmPolicyAdd
285 285
 	}
286 286
 
287 287
 	fullMask := net.CIDRMask(8*len(fSA.Src), 8*len(fSA.Src))
... ...
@@ -322,7 +323,7 @@ func programSP(fSA *netlink.XfrmState, rSA *netlink.XfrmState, add bool) error {
322 322
 }
323 323
 
324 324
 func saExists(sa *netlink.XfrmState) (bool, error) {
325
-	_, err := netlink.XfrmStateGet(sa)
325
+	_, err := ns.NlHandle().XfrmStateGet(sa)
326 326
 	switch err {
327 327
 	case nil:
328 328
 		return true, nil
... ...
@@ -336,7 +337,7 @@ func saExists(sa *netlink.XfrmState) (bool, error) {
336 336
 }
337 337
 
338 338
 func spExists(sp *netlink.XfrmPolicy) (bool, error) {
339
-	_, err := netlink.XfrmPolicyGet(sp)
339
+	_, err := ns.NlHandle().XfrmPolicyGet(sp)
340 340
 	switch err {
341 341
 	case nil:
342 342
 		return true, nil
... ...
@@ -482,7 +483,7 @@ func updateNodeKey(lIP, rIP net.IP, idxs []*spi, curKeys []*key, newIdx, priIdx,
482 482
 			Limits: netlink.XfrmStateLimits{TimeSoft: timeout},
483 483
 		}
484 484
 		log.Infof("Updating rSA0{%s}", rSA0)
485
-		if err := netlink.XfrmStateUpdate(rSA0); err != nil {
485
+		if err := ns.NlHandle().XfrmStateUpdate(rSA0); err != nil {
486 486
 			log.Warnf("Failed to update rSA0{%s}: %v", rSA0, err)
487 487
 		}
488 488
 	}
... ...
@@ -518,7 +519,7 @@ func updateNodeKey(lIP, rIP net.IP, idxs []*spi, curKeys []*key, newIdx, priIdx,
518 518
 			},
519 519
 		}
520 520
 		log.Infof("Updating fSP{%s}", fSP1)
521
-		if err := netlink.XfrmPolicyUpdate(fSP1); err != nil {
521
+		if err := ns.NlHandle().XfrmPolicyUpdate(fSP1); err != nil {
522 522
 			log.Warnf("Failed to update fSP{%s}: %v", fSP1, err)
523 523
 		}
524 524
 
... ...
@@ -533,7 +534,7 @@ func updateNodeKey(lIP, rIP net.IP, idxs []*spi, curKeys []*key, newIdx, priIdx,
533 533
 			Limits: netlink.XfrmStateLimits{TimeHard: timeout},
534 534
 		}
535 535
 		log.Infof("Removing fSA0{%s}", fSA0)
536
-		if err := netlink.XfrmStateUpdate(fSA0); err != nil {
536
+		if err := ns.NlHandle().XfrmStateUpdate(fSA0); err != nil {
537 537
 			log.Warnf("Failed to remove fSA0{%s}: %v", fSA0, err)
538 538
 		}
539 539
 	}
... ...
@@ -40,11 +40,11 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
40 40
 		return fmt.Errorf("couldn't get vxlan id for %q: %v", s.subnetIP.String(), err)
41 41
 	}
42 42
 
43
-	if err := n.joinSandbox(); err != nil {
43
+	if err := n.joinSandbox(false); err != nil {
44 44
 		return fmt.Errorf("network sandbox join failed: %v", err)
45 45
 	}
46 46
 
47
-	if err := n.joinSubnetSandbox(s); err != nil {
47
+	if err := n.joinSubnetSandbox(s, false); err != nil {
48 48
 		return fmt.Errorf("subnet sandbox join failed for %q: %v", s.subnetIP.String(), err)
49 49
 	}
50 50
 
... ...
@@ -61,6 +61,10 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
61 61
 
62 62
 	ep.ifName = containerIfName
63 63
 
64
+	if err := d.writeEndpointToStore(ep); err != nil {
65
+		return fmt.Errorf("failed to update overlay endpoint %s to local data store: %v", ep.id[0:7], err)
66
+	}
67
+
64 68
 	nlh := ns.NlHandle()
65 69
 
66 70
 	// Set the container interface and its peer MTU to 1450 to allow
... ...
@@ -1,22 +1,30 @@
1 1
 package overlay
2 2
 
3 3
 import (
4
+	"encoding/json"
4 5
 	"fmt"
5 6
 	"net"
6 7
 
7 8
 	log "github.com/Sirupsen/logrus"
9
+	"github.com/docker/libnetwork/datastore"
8 10
 	"github.com/docker/libnetwork/driverapi"
9 11
 	"github.com/docker/libnetwork/netutils"
10 12
 	"github.com/docker/libnetwork/ns"
13
+	"github.com/docker/libnetwork/types"
11 14
 )
12 15
 
13 16
 type endpointTable map[string]*endpoint
14 17
 
18
+const overlayEndpointPrefix = "overlay/endpoint"
19
+
15 20
 type endpoint struct {
16
-	id     string
17
-	ifName string
18
-	mac    net.HardwareAddr
19
-	addr   *net.IPNet
21
+	id       string
22
+	nid      string
23
+	ifName   string
24
+	mac      net.HardwareAddr
25
+	addr     *net.IPNet
26
+	dbExists bool
27
+	dbIndex  uint64
20 28
 }
21 29
 
22 30
 func (n *network) endpoint(eid string) *endpoint {
... ...
@@ -60,6 +68,7 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
60 60
 
61 61
 	ep := &endpoint{
62 62
 		id:   eid,
63
+		nid:  n.id,
63 64
 		addr: ifInfo.Address(),
64 65
 		mac:  ifInfo.MacAddress(),
65 66
 	}
... ...
@@ -80,6 +89,10 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
80 80
 
81 81
 	n.addEndpoint(ep)
82 82
 
83
+	if err := d.writeEndpointToStore(ep); err != nil {
84
+		return fmt.Errorf("failed to update overlay endpoint %s to local store: %v", ep.id[0:7], err)
85
+	}
86
+
83 87
 	return nil
84 88
 }
85 89
 
... ...
@@ -102,6 +115,10 @@ func (d *driver) DeleteEndpoint(nid, eid string) error {
102 102
 
103 103
 	n.deleteEndpoint(eid)
104 104
 
105
+	if err := d.deleteEndpointFromStore(ep); err != nil {
106
+		log.Warnf("Failed to delete overlay endpoint %s from local store: %v", ep.id[0:7], err)
107
+	}
108
+
105 109
 	if ep.ifName == "" {
106 110
 		return nil
107 111
 	}
... ...
@@ -121,3 +138,122 @@ func (d *driver) DeleteEndpoint(nid, eid string) error {
121 121
 func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) {
122 122
 	return make(map[string]interface{}, 0), nil
123 123
 }
124
+
125
+func (d *driver) deleteEndpointFromStore(e *endpoint) error {
126
+	if d.localStore == nil {
127
+		return fmt.Errorf("overlay local store not initialized, ep not deleted")
128
+	}
129
+
130
+	if err := d.localStore.DeleteObjectAtomic(e); err != nil {
131
+		return err
132
+	}
133
+
134
+	return nil
135
+}
136
+
137
+func (d *driver) writeEndpointToStore(e *endpoint) error {
138
+	if d.localStore == nil {
139
+		return fmt.Errorf("overlay local store not initialized, ep not added")
140
+	}
141
+
142
+	if err := d.localStore.PutObjectAtomic(e); err != nil {
143
+		return err
144
+	}
145
+	return nil
146
+}
147
+
148
+func (ep *endpoint) DataScope() string {
149
+	return datastore.LocalScope
150
+}
151
+
152
+func (ep *endpoint) New() datastore.KVObject {
153
+	return &endpoint{}
154
+}
155
+
156
+func (ep *endpoint) CopyTo(o datastore.KVObject) error {
157
+	dstep := o.(*endpoint)
158
+	*dstep = *ep
159
+	return nil
160
+}
161
+
162
+func (ep *endpoint) Key() []string {
163
+	return []string{overlayEndpointPrefix, ep.id}
164
+}
165
+
166
+func (ep *endpoint) KeyPrefix() []string {
167
+	return []string{overlayEndpointPrefix}
168
+}
169
+
170
+func (ep *endpoint) Index() uint64 {
171
+	return ep.dbIndex
172
+}
173
+
174
+func (ep *endpoint) SetIndex(index uint64) {
175
+	ep.dbIndex = index
176
+	ep.dbExists = true
177
+}
178
+
179
+func (ep *endpoint) Exists() bool {
180
+	return ep.dbExists
181
+}
182
+
183
+func (ep *endpoint) Skip() bool {
184
+	return false
185
+}
186
+
187
+func (ep *endpoint) Value() []byte {
188
+	b, err := json.Marshal(ep)
189
+	if err != nil {
190
+		return nil
191
+	}
192
+	return b
193
+}
194
+
195
+func (ep *endpoint) SetValue(value []byte) error {
196
+	return json.Unmarshal(value, ep)
197
+}
198
+
199
+func (ep *endpoint) MarshalJSON() ([]byte, error) {
200
+	epMap := make(map[string]interface{})
201
+
202
+	epMap["id"] = ep.id
203
+	epMap["nid"] = ep.nid
204
+	if ep.ifName != "" {
205
+		epMap["ifName"] = ep.ifName
206
+	}
207
+	if ep.addr != nil {
208
+		epMap["addr"] = ep.addr.String()
209
+	}
210
+	if len(ep.mac) != 0 {
211
+		epMap["mac"] = ep.mac.String()
212
+	}
213
+
214
+	return json.Marshal(epMap)
215
+}
216
+
217
+func (ep *endpoint) UnmarshalJSON(value []byte) error {
218
+	var (
219
+		err   error
220
+		epMap map[string]interface{}
221
+	)
222
+
223
+	json.Unmarshal(value, &epMap)
224
+
225
+	ep.id = epMap["id"].(string)
226
+	ep.nid = epMap["nid"].(string)
227
+	if v, ok := epMap["mac"]; ok {
228
+		if ep.mac, err = net.ParseMAC(v.(string)); err != nil {
229
+			return types.InternalErrorf("failed to decode endpoint interface mac address after json unmarshal: %s", v.(string))
230
+		}
231
+	}
232
+	if v, ok := epMap["addr"]; ok {
233
+		if ep.addr, err = types.ParseCIDR(v.(string)); err != nil {
234
+			return types.InternalErrorf("failed to decode endpoint interface ipv4 address after json unmarshal: %v", err)
235
+		}
236
+	}
237
+	if v, ok := epMap["ifName"]; ok {
238
+		ep.ifName = v.(string)
239
+	}
240
+
241
+	return nil
242
+}
... ...
@@ -195,21 +195,21 @@ func (n *network) incEndpointCount() {
195 195
 	n.joinCnt++
196 196
 }
197 197
 
198
-func (n *network) joinSandbox() error {
198
+func (n *network) joinSandbox(restore bool) error {
199 199
 	// If there is a race between two go routines here only one will win
200 200
 	// the other will wait.
201 201
 	n.once.Do(func() {
202 202
 		// save the error status of initSandbox in n.initErr so that
203 203
 		// all the racing go routines are able to know the status.
204
-		n.initErr = n.initSandbox()
204
+		n.initErr = n.initSandbox(restore)
205 205
 	})
206 206
 
207 207
 	return n.initErr
208 208
 }
209 209
 
210
-func (n *network) joinSubnetSandbox(s *subnet) error {
210
+func (n *network) joinSubnetSandbox(s *subnet, restore bool) error {
211 211
 	s.once.Do(func() {
212
-		s.initErr = n.initSubnetSandbox(s)
212
+		s.initErr = n.initSubnetSandbox(s, restore)
213 213
 	})
214 214
 	return s.initErr
215 215
 }
... ...
@@ -386,9 +386,33 @@ func isOverlap(nw *net.IPNet) bool {
386 386
 	return false
387 387
 }
388 388
 
389
-func (n *network) initSubnetSandbox(s *subnet) error {
390
-	brName := n.generateBridgeName(s)
391
-	vxlanName := n.generateVxlanName(s)
389
+func (n *network) restoreSubnetSandbox(s *subnet, brName, vxlanName string) error {
390
+	sbox := n.sandbox()
391
+
392
+	// restore overlay osl sandbox
393
+	Ifaces := make(map[string][]osl.IfaceOption)
394
+	brIfaceOption := make([]osl.IfaceOption, 2)
395
+	brIfaceOption = append(brIfaceOption, sbox.InterfaceOptions().Address(s.gwIP))
396
+	brIfaceOption = append(brIfaceOption, sbox.InterfaceOptions().Bridge(true))
397
+	Ifaces[fmt.Sprintf("%s+%s", brName, "br")] = brIfaceOption
398
+
399
+	err := sbox.Restore(Ifaces, nil, nil, nil)
400
+	if err != nil {
401
+		return err
402
+	}
403
+
404
+	Ifaces = make(map[string][]osl.IfaceOption)
405
+	vxlanIfaceOption := make([]osl.IfaceOption, 1)
406
+	vxlanIfaceOption = append(vxlanIfaceOption, sbox.InterfaceOptions().Master(brName))
407
+	Ifaces[fmt.Sprintf("%s+%s", vxlanName, "vxlan")] = vxlanIfaceOption
408
+	err = sbox.Restore(Ifaces, nil, nil, nil)
409
+	if err != nil {
410
+		return err
411
+	}
412
+	return nil
413
+}
414
+
415
+func (n *network) setupSubnetSandbox(s *subnet, brName, vxlanName string) error {
392 416
 
393 417
 	if hostMode {
394 418
 		// Try to delete stale bridge interface if it exists
... ...
@@ -451,6 +475,19 @@ func (n *network) initSubnetSandbox(s *subnet) error {
451 451
 		}
452 452
 	}
453 453
 
454
+	return nil
455
+}
456
+
457
+func (n *network) initSubnetSandbox(s *subnet, restore bool) error {
458
+	brName := n.generateBridgeName(s)
459
+	vxlanName := n.generateVxlanName(s)
460
+
461
+	if restore {
462
+		n.restoreSubnetSandbox(s, brName, vxlanName)
463
+	} else {
464
+		n.setupSubnetSandbox(s, brName, vxlanName)
465
+	}
466
+
454 467
 	n.Lock()
455 468
 	s.vxlanName = vxlanName
456 469
 	s.brName = brName
... ...
@@ -494,32 +531,45 @@ func (n *network) cleanupStaleSandboxes() {
494 494
 		})
495 495
 }
496 496
 
497
-func (n *network) initSandbox() error {
497
+func (n *network) initSandbox(restore bool) error {
498 498
 	n.Lock()
499 499
 	n.initEpoch++
500 500
 	n.Unlock()
501 501
 
502 502
 	networkOnce.Do(networkOnceInit)
503 503
 
504
-	if hostMode {
505
-		if err := addNetworkChain(n.id[:12]); err != nil {
506
-			return err
504
+	if !restore {
505
+		if hostMode {
506
+			if err := addNetworkChain(n.id[:12]); err != nil {
507
+				return err
508
+			}
507 509
 		}
510
+
511
+		// If there are any stale sandboxes related to this network
512
+		// from previous daemon life clean it up here
513
+		n.cleanupStaleSandboxes()
508 514
 	}
509 515
 
510
-	// If there are any stale sandboxes related to this network
511
-	// from previous daemon life clean it up here
512
-	n.cleanupStaleSandboxes()
516
+	// In the restore case network sandbox already exist; but we don't know
517
+	// what epoch number it was created with. It has to be retrieved by
518
+	// searching the net namespaces.
519
+	key := ""
520
+	if restore {
521
+		key = osl.GenerateKey("-" + n.id)
522
+	} else {
523
+		key = osl.GenerateKey(fmt.Sprintf("%d-", n.initEpoch) + n.id)
524
+	}
513 525
 
514
-	sbox, err := osl.NewSandbox(
515
-		osl.GenerateKey(fmt.Sprintf("%d-", n.initEpoch)+n.id), !hostMode)
526
+	sbox, err := osl.NewSandbox(key, !hostMode, restore)
516 527
 	if err != nil {
517
-		return fmt.Errorf("could not create network sandbox: %v", err)
528
+		return fmt.Errorf("could not get network sandbox (oper %t): %v", restore, err)
518 529
 	}
519 530
 
520 531
 	n.setSandbox(sbox)
521 532
 
522
-	n.driver.peerDbUpdateSandbox(n.id)
533
+	if !restore {
534
+		n.driver.peerDbUpdateSandbox(n.id)
535
+	}
523 536
 
524 537
 	var nlSock *nl.NetlinkSocket
525 538
 	sbox.InvokeFunc(func() {
... ...
@@ -13,6 +13,7 @@ import (
13 13
 	"github.com/docker/libnetwork/driverapi"
14 14
 	"github.com/docker/libnetwork/idm"
15 15
 	"github.com/docker/libnetwork/netlabel"
16
+	"github.com/docker/libnetwork/osl"
16 17
 	"github.com/docker/libnetwork/types"
17 18
 	"github.com/hashicorp/serf/serf"
18 19
 )
... ...
@@ -41,6 +42,7 @@ type driver struct {
41 41
 	serfInstance *serf.Serf
42 42
 	networks     networkTable
43 43
 	store        datastore.DataStore
44
+	localStore   datastore.DataStore
44 45
 	vxlanIdm     *idm.Idm
45 46
 	once         sync.Once
46 47
 	joinOnce     sync.Once
... ...
@@ -74,9 +76,75 @@ func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
74 74
 		}
75 75
 	}
76 76
 
77
+	if data, ok := config[netlabel.LocalKVClient]; ok {
78
+		var err error
79
+		dsc, ok := data.(discoverapi.DatastoreConfigData)
80
+		if !ok {
81
+			return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
82
+		}
83
+		d.localStore, err = datastore.NewDataStoreFromConfig(dsc)
84
+		if err != nil {
85
+			return types.InternalErrorf("failed to initialize local data store: %v", err)
86
+		}
87
+	}
88
+
89
+	d.restoreEndpoints()
90
+
77 91
 	return dc.RegisterDriver(networkType, d, c)
78 92
 }
79 93
 
94
+// Endpoints are stored in the local store. Restore them and reconstruct the overlay sandbox
95
+func (d *driver) restoreEndpoints() error {
96
+	if d.localStore == nil {
97
+		logrus.Warnf("Cannot restore overlay endpoints because local datastore is missing")
98
+		return nil
99
+	}
100
+	kvol, err := d.localStore.List(datastore.Key(overlayEndpointPrefix), &endpoint{})
101
+	if err != nil && err != datastore.ErrKeyNotFound {
102
+		return fmt.Errorf("failed to read overlay endpoint from store: %v", err)
103
+	}
104
+
105
+	if err == datastore.ErrKeyNotFound {
106
+		return nil
107
+	}
108
+	for _, kvo := range kvol {
109
+		ep := kvo.(*endpoint)
110
+		n := d.network(ep.nid)
111
+		if n == nil {
112
+			logrus.Debugf("Network (%s) not found for restored endpoint (%s)", ep.nid, ep.id)
113
+			continue
114
+		}
115
+		n.addEndpoint(ep)
116
+
117
+		s := n.getSubnetforIP(ep.addr)
118
+		if s == nil {
119
+			return fmt.Errorf("could not find subnet for endpoint %s", ep.id)
120
+		}
121
+
122
+		if err := n.joinSandbox(true); err != nil {
123
+			return fmt.Errorf("restore network sandbox failed: %v", err)
124
+		}
125
+
126
+		if err := n.joinSubnetSandbox(s, true); err != nil {
127
+			return fmt.Errorf("restore subnet sandbox failed for %q: %v", s.subnetIP.String(), err)
128
+		}
129
+
130
+		Ifaces := make(map[string][]osl.IfaceOption)
131
+		vethIfaceOption := make([]osl.IfaceOption, 1)
132
+		vethIfaceOption = append(vethIfaceOption, n.sbox.InterfaceOptions().Master(s.brName))
133
+		Ifaces[fmt.Sprintf("%s+%s", "veth", "veth")] = vethIfaceOption
134
+
135
+		err := n.sbox.Restore(Ifaces, nil, nil, nil)
136
+		if err != nil {
137
+			return fmt.Errorf("failed to restore overlay sandbox: %v", err)
138
+		}
139
+
140
+		n.incEndpointCount()
141
+		d.peerDbAdd(ep.nid, ep.id, ep.addr.IP, ep.addr.Mask, ep.mac, net.ParseIP(d.bindAddress), true)
142
+	}
143
+	return nil
144
+}
145
+
80 146
 // Fini cleans up the driver resources
81 147
 func Fini(drv driverapi.Driver) {
82 148
 	d := drv.(*driver)
... ...
@@ -271,7 +271,7 @@ func (d *driver) peerAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask,
271 271
 		return fmt.Errorf("couldn't get vxlan id for %q: %v", s.subnetIP.String(), err)
272 272
 	}
273 273
 
274
-	if err := n.joinSubnetSandbox(s); err != nil {
274
+	if err := n.joinSubnetSandbox(s, false); err != nil {
275 275
 		return fmt.Errorf("subnet sandbox join failed for %q: %v", s.subnetIP.String(), err)
276 276
 	}
277 277
 
... ...
@@ -2,14 +2,10 @@
2 2
 
3 3
 package libnetwork
4 4
 
5
-import (
6
-	"github.com/docker/libnetwork/drivers/ipvlan"
7
-	"github.com/docker/libnetwork/drivers/macvlan"
8
-)
5
+import "github.com/docker/libnetwork/drivers/ipvlan"
9 6
 
10 7
 func additionalDrivers() []initializer {
11 8
 	return []initializer{
12
-		{macvlan.Init, "macvlan"},
13 9
 		{ipvlan.Init, "ipvlan"},
14 10
 	}
15 11
 }
... ...
@@ -3,6 +3,7 @@ package libnetwork
3 3
 import (
4 4
 	"github.com/docker/libnetwork/drivers/bridge"
5 5
 	"github.com/docker/libnetwork/drivers/host"
6
+	"github.com/docker/libnetwork/drivers/macvlan"
6 7
 	"github.com/docker/libnetwork/drivers/null"
7 8
 	"github.com/docker/libnetwork/drivers/overlay"
8 9
 	"github.com/docker/libnetwork/drivers/remote"
... ...
@@ -12,6 +13,7 @@ func getInitializers() []initializer {
12 12
 	in := []initializer{
13 13
 		{bridge.Init, "bridge"},
14 14
 		{host.Init, "host"},
15
+		{macvlan.Init, "macvlan"},
15 16
 		{null.Init, "null"},
16 17
 		{remote.Init, "remote"},
17 18
 		{overlay.Init, "overlay"},
... ...
@@ -84,6 +84,7 @@ func (ep *endpoint) MarshalJSON() ([]byte, error) {
84 84
 	epMap["name"] = ep.name
85 85
 	epMap["id"] = ep.id
86 86
 	epMap["ep_iface"] = ep.iface
87
+	epMap["joinInfo"] = ep.joinInfo
87 88
 	epMap["exposed_ports"] = ep.exposedPorts
88 89
 	if ep.generic != nil {
89 90
 		epMap["generic"] = ep.generic
... ...
@@ -115,6 +116,9 @@ func (ep *endpoint) UnmarshalJSON(b []byte) (err error) {
115 115
 	ib, _ := json.Marshal(epMap["ep_iface"])
116 116
 	json.Unmarshal(ib, &ep.iface)
117 117
 
118
+	jb, _ := json.Marshal(epMap["joinInfo"])
119
+	json.Unmarshal(jb, &ep.joinInfo)
120
+
118 121
 	tb, _ := json.Marshal(epMap["exposed_ports"])
119 122
 	var tPorts []types.TransportPort
120 123
 	json.Unmarshal(tb, &tPorts)
... ...
@@ -235,6 +239,11 @@ func (ep *endpoint) CopyTo(o datastore.KVObject) error {
235 235
 		ep.iface.CopyTo(dstEp.iface)
236 236
 	}
237 237
 
238
+	if ep.joinInfo != nil {
239
+		dstEp.joinInfo = &endpointJoinInfo{}
240
+		ep.joinInfo.CopyTo(dstEp.joinInfo)
241
+	}
242
+
238 243
 	dstEp.exposedPorts = make([]types.TransportPort, len(ep.exposedPorts))
239 244
 	copy(dstEp.exposedPorts, ep.exposedPorts)
240 245
 
... ...
@@ -1073,6 +1082,13 @@ func (ep *endpoint) releaseAddress() {
1073 1073
 }
1074 1074
 
1075 1075
 func (c *controller) cleanupLocalEndpoints() {
1076
+	// Get used endpoints
1077
+	eps := make(map[string]interface{})
1078
+	for _, sb := range c.sandboxes {
1079
+		for _, ep := range sb.endpoints {
1080
+			eps[ep.id] = true
1081
+		}
1082
+	}
1076 1083
 	nl, err := c.getNetworksForScope(datastore.LocalScope)
1077 1084
 	if err != nil {
1078 1085
 		log.Warnf("Could not get list of networks during endpoint cleanup: %v", err)
... ...
@@ -1087,6 +1103,9 @@ func (c *controller) cleanupLocalEndpoints() {
1087 1087
 		}
1088 1088
 
1089 1089
 		for _, ep := range epl {
1090
+			if _, ok := eps[ep.id]; ok {
1091
+				continue
1092
+			}
1090 1093
 			log.Infof("Removing stale endpoint %s (%s)", ep.name, ep.id)
1091 1094
 			if err := ep.Delete(true); err != nil {
1092 1095
 				log.Warnf("Could not delete local endpoint %s during endpoint cleanup: %v", ep.name, err)
... ...
@@ -414,3 +414,56 @@ func (ep *endpoint) DisableGatewayService() {
414 414
 
415 415
 	ep.joinInfo.disableGatewayService = true
416 416
 }
417
+
418
+func (epj *endpointJoinInfo) MarshalJSON() ([]byte, error) {
419
+	epMap := make(map[string]interface{})
420
+	if epj.gw != nil {
421
+		epMap["gw"] = epj.gw.String()
422
+	}
423
+	if epj.gw6 != nil {
424
+		epMap["gw6"] = epj.gw6.String()
425
+	}
426
+	epMap["disableGatewayService"] = epj.disableGatewayService
427
+	epMap["StaticRoutes"] = epj.StaticRoutes
428
+	return json.Marshal(epMap)
429
+}
430
+
431
+func (epj *endpointJoinInfo) UnmarshalJSON(b []byte) error {
432
+	var (
433
+		err   error
434
+		epMap map[string]interface{}
435
+	)
436
+	if err = json.Unmarshal(b, &epMap); err != nil {
437
+		return err
438
+	}
439
+	if v, ok := epMap["gw"]; ok {
440
+		epj.gw6 = net.ParseIP(v.(string))
441
+	}
442
+	if v, ok := epMap["gw6"]; ok {
443
+		epj.gw6 = net.ParseIP(v.(string))
444
+	}
445
+	epj.disableGatewayService = epMap["disableGatewayService"].(bool)
446
+
447
+	var tStaticRoute []types.StaticRoute
448
+	if v, ok := epMap["StaticRoutes"]; ok {
449
+		tb, _ := json.Marshal(v)
450
+		var tStaticRoute []types.StaticRoute
451
+		json.Unmarshal(tb, &tStaticRoute)
452
+	}
453
+	var StaticRoutes []*types.StaticRoute
454
+	for _, r := range tStaticRoute {
455
+		StaticRoutes = append(StaticRoutes, &r)
456
+	}
457
+	epj.StaticRoutes = StaticRoutes
458
+
459
+	return nil
460
+}
461
+
462
+func (epj *endpointJoinInfo) CopyTo(dstEpj *endpointJoinInfo) error {
463
+	dstEpj.disableGatewayService = epj.disableGatewayService
464
+	dstEpj.StaticRoutes = make([]*types.StaticRoute, len(epj.StaticRoutes))
465
+	copy(dstEpj.StaticRoutes, epj.StaticRoutes)
466
+	dstEpj.gw = types.GetIPCopy(epj.gw)
467
+	dstEpj.gw = types.GetIPCopy(epj.gw6)
468
+	return nil
469
+}
... ...
@@ -311,7 +311,16 @@ func (nDB *NetworkDB) bulkSyncTables() {
311 311
 		nid := networks[0]
312 312
 		networks = networks[1:]
313 313
 
314
-		completed, err := nDB.bulkSync(nid, false)
314
+		nDB.RLock()
315
+		nodes := nDB.networkNodes[nid]
316
+		nDB.RUnlock()
317
+
318
+		// No peer nodes on this network. Move on.
319
+		if len(nodes) == 0 {
320
+			continue
321
+		}
322
+
323
+		completed, err := nDB.bulkSync(nid, nodes, false)
315 324
 		if err != nil {
316 325
 			logrus.Errorf("periodic bulk sync failure for network %s: %v", nid, err)
317 326
 			continue
... ...
@@ -334,11 +343,7 @@ func (nDB *NetworkDB) bulkSyncTables() {
334 334
 	}
335 335
 }
336 336
 
337
-func (nDB *NetworkDB) bulkSync(nid string, all bool) ([]string, error) {
338
-	nDB.RLock()
339
-	nodes := nDB.networkNodes[nid]
340
-	nDB.RUnlock()
341
-
337
+func (nDB *NetworkDB) bulkSync(nid string, nodes []string, all bool) ([]string, error) {
342 338
 	if !all {
343 339
 		// If not all, then just pick one.
344 340
 		nodes = nDB.mRandomNodes(1, nodes)
... ...
@@ -2,6 +2,7 @@ package networkdb
2 2
 
3 3
 import (
4 4
 	"fmt"
5
+	"net"
5 6
 	"time"
6 7
 
7 8
 	"github.com/Sirupsen/logrus"
... ...
@@ -210,8 +211,13 @@ func (nDB *NetworkDB) handleBulkSync(buf []byte) {
210 210
 		return
211 211
 	}
212 212
 
213
+	var nodeAddr net.IP
214
+	if node, ok := nDB.nodes[bsm.NodeName]; ok {
215
+		nodeAddr = node.Addr
216
+	}
217
+
213 218
 	if err := nDB.bulkSyncNode(bsm.Networks, bsm.NodeName, false); err != nil {
214
-		logrus.Errorf("Error in responding to bulk sync from node %s: %v", nDB.nodes[bsm.NodeName].Addr, err)
219
+		logrus.Errorf("Error in responding to bulk sync from node %s: %v", nodeAddr, err)
215 220
 	}
216 221
 }
217 222
 
... ...
@@ -14,6 +14,7 @@ func (e *eventDelegate) NotifyJoin(n *memberlist.Node) {
14 14
 
15 15
 func (e *eventDelegate) NotifyLeave(n *memberlist.Node) {
16 16
 	e.nDB.deleteNodeTableEntries(n.Name)
17
+	e.nDB.deleteNetworkNodeEntries(n.Name)
17 18
 	e.nDB.Lock()
18 19
 	delete(e.nDB.nodes, n.Name)
19 20
 	e.nDB.Unlock()
... ...
@@ -286,6 +286,23 @@ func (nDB *NetworkDB) DeleteEntry(tname, nid, key string) error {
286 286
 	return nil
287 287
 }
288 288
 
289
+func (nDB *NetworkDB) deleteNetworkNodeEntries(deletedNode string) {
290
+	nDB.Lock()
291
+	for nid, nodes := range nDB.networkNodes {
292
+		updatedNodes := make([]string, 0, len(nodes))
293
+		for _, node := range nodes {
294
+			if node == deletedNode {
295
+				continue
296
+			}
297
+
298
+			updatedNodes = append(updatedNodes, node)
299
+		}
300
+
301
+		nDB.networkNodes[nid] = updatedNodes
302
+	}
303
+	nDB.Unlock()
304
+}
305
+
289 306
 func (nDB *NetworkDB) deleteNodeTableEntries(node string) {
290 307
 	nDB.Lock()
291 308
 	nDB.indexes[byTable].Walk(func(path string, v interface{}) bool {
... ...
@@ -359,6 +376,7 @@ func (nDB *NetworkDB) JoinNetwork(nid string) error {
359 359
 		RetransmitMult: 4,
360 360
 	}
361 361
 	nDB.networkNodes[nid] = append(nDB.networkNodes[nid], nDB.config.NodeName)
362
+	networkNodes := nDB.networkNodes[nid]
362 363
 	nDB.Unlock()
363 364
 
364 365
 	if err := nDB.sendNetworkEvent(nid, NetworkEventTypeJoin, ltime); err != nil {
... ...
@@ -366,7 +384,7 @@ func (nDB *NetworkDB) JoinNetwork(nid string) error {
366 366
 	}
367 367
 
368 368
 	logrus.Debugf("%s: joined network %s", nDB.config.NodeName, nid)
369
-	if _, err := nDB.bulkSync(nid, true); err != nil {
369
+	if _, err := nDB.bulkSync(nid, networkNodes, true); err != nil {
370 370
 		logrus.Errorf("Error bulk syncing while joining network %s: %v", nid, err)
371 371
 	}
372 372
 
... ...
@@ -2,10 +2,13 @@ package osl
2 2
 
3 3
 import (
4 4
 	"fmt"
5
+	"io/ioutil"
5 6
 	"net"
6 7
 	"os"
7 8
 	"os/exec"
8 9
 	"runtime"
10
+	"strconv"
11
+	"strings"
9 12
 	"sync"
10 13
 	"syscall"
11 14
 	"time"
... ...
@@ -133,6 +136,39 @@ func GC() {
133 133
 // container id.
134 134
 func GenerateKey(containerID string) string {
135 135
 	maxLen := 12
136
+	// Read sandbox key from host for overlay
137
+	if strings.HasPrefix(containerID, "-") {
138
+		var (
139
+			index    int
140
+			indexStr string
141
+			tmpkey   string
142
+		)
143
+		dir, err := ioutil.ReadDir(prefix)
144
+		if err != nil {
145
+			return ""
146
+		}
147
+
148
+		for _, v := range dir {
149
+			id := v.Name()
150
+			if strings.HasSuffix(id, containerID[:maxLen-1]) {
151
+				indexStr = strings.TrimSuffix(id, containerID[:maxLen-1])
152
+				tmpindex, err := strconv.Atoi(indexStr)
153
+				if err != nil {
154
+					return ""
155
+				}
156
+				if tmpindex > index {
157
+					index = tmpindex
158
+					tmpkey = id
159
+				}
160
+
161
+			}
162
+		}
163
+		containerID = tmpkey
164
+		if containerID == "" {
165
+			return ""
166
+		}
167
+	}
168
+
136 169
 	if len(containerID) < maxLen {
137 170
 		maxLen = len(containerID)
138 171
 	}
... ...
@@ -142,10 +178,14 @@ func GenerateKey(containerID string) string {
142 142
 
143 143
 // NewSandbox provides a new sandbox instance created in an os specific way
144 144
 // provided a key which uniquely identifies the sandbox
145
-func NewSandbox(key string, osCreate bool) (Sandbox, error) {
146
-	err := createNetworkNamespace(key, osCreate)
147
-	if err != nil {
148
-		return nil, err
145
+func NewSandbox(key string, osCreate, isRestore bool) (Sandbox, error) {
146
+	if !isRestore {
147
+		err := createNetworkNamespace(key, osCreate)
148
+		if err != nil {
149
+			return nil, err
150
+		}
151
+	} else {
152
+		once.Do(createBasePath)
149 153
 	}
150 154
 
151 155
 	n := &networkNamespace{path: key, isDefault: !osCreate}
... ...
@@ -347,3 +387,105 @@ func (n *networkNamespace) Destroy() error {
347 347
 	addToGarbagePaths(n.path)
348 348
 	return nil
349 349
 }
350
+
351
+// Restore restore the network namespace
352
+func (n *networkNamespace) Restore(ifsopt map[string][]IfaceOption, routes []*types.StaticRoute, gw net.IP, gw6 net.IP) error {
353
+	// restore interfaces
354
+	for name, opts := range ifsopt {
355
+		if !strings.Contains(name, "+") {
356
+			return fmt.Errorf("wrong iface name in restore osl sandbox interface: %s", name)
357
+		}
358
+		seps := strings.Split(name, "+")
359
+		srcName := seps[0]
360
+		dstPrefix := seps[1]
361
+		i := &nwIface{srcName: srcName, dstName: dstPrefix, ns: n}
362
+		i.processInterfaceOptions(opts...)
363
+		if i.master != "" {
364
+			i.dstMaster = n.findDst(i.master, true)
365
+			if i.dstMaster == "" {
366
+				return fmt.Errorf("could not find an appropriate master %q for %q",
367
+					i.master, i.srcName)
368
+			}
369
+		}
370
+		if n.isDefault {
371
+			i.dstName = i.srcName
372
+		} else {
373
+			links, err := n.nlHandle.LinkList()
374
+			if err != nil {
375
+				return fmt.Errorf("failed to retrieve list of links in network namespace %q during restore", n.path)
376
+			}
377
+			// due to the docker network connect/disconnect, so the dstName should
378
+			// restore from the namespace
379
+			for _, link := range links {
380
+				addrs, err := n.nlHandle.AddrList(link, netlink.FAMILY_V4)
381
+				if err != nil {
382
+					return err
383
+				}
384
+				ifaceName := link.Attrs().Name
385
+				if strings.HasPrefix(ifaceName, "vxlan") {
386
+					if i.dstName == "vxlan" {
387
+						i.dstName = ifaceName
388
+						break
389
+					}
390
+				}
391
+				// find the interface name by ip
392
+				if i.address != nil {
393
+					for _, addr := range addrs {
394
+						if addr.IPNet.String() == i.address.String() {
395
+							i.dstName = ifaceName
396
+							break
397
+						}
398
+						continue
399
+					}
400
+					if i.dstName == ifaceName {
401
+						break
402
+					}
403
+				}
404
+				// This is to find the interface name of the pair in overlay sandbox
405
+				if strings.HasPrefix(ifaceName, "veth") {
406
+					if i.master != "" && i.dstName == "veth" {
407
+						i.dstName = ifaceName
408
+					}
409
+				}
410
+			}
411
+
412
+			var index int
413
+			indexStr := strings.TrimPrefix(i.dstName, dstPrefix)
414
+			if indexStr != "" {
415
+				index, err = strconv.Atoi(indexStr)
416
+				if err != nil {
417
+					return err
418
+				}
419
+			}
420
+			index++
421
+			n.Lock()
422
+			if index > n.nextIfIndex {
423
+				n.nextIfIndex = index
424
+			}
425
+			n.iFaces = append(n.iFaces, i)
426
+			n.Unlock()
427
+		}
428
+	}
429
+
430
+	// restore routes
431
+	for _, r := range routes {
432
+		n.Lock()
433
+		n.staticRoutes = append(n.staticRoutes, r)
434
+		n.Unlock()
435
+	}
436
+
437
+	// restore gateway
438
+	if len(gw) > 0 {
439
+		n.Lock()
440
+		n.gw = gw
441
+		n.Unlock()
442
+	}
443
+
444
+	if len(gw6) > 0 {
445
+		n.Lock()
446
+		n.gwv6 = gw6
447
+		n.Unlock()
448
+	}
449
+
450
+	return nil
451
+}
... ...
@@ -15,7 +15,7 @@ func GenerateKey(containerID string) string {
15 15
 
16 16
 // NewSandbox provides a new sandbox instance created in an os specific way
17 17
 // provided a key which uniquely identifies the sandbox
18
-func NewSandbox(key string, osCreate bool) (Sandbox, error) {
18
+func NewSandbox(key string, osCreate, isRestore bool) (Sandbox, error) {
19 19
 	return nil, nil
20 20
 }
21 21
 
... ...
@@ -58,6 +58,9 @@ type Sandbox interface {
58 58
 
59 59
 	// Destroy the sandbox
60 60
 	Destroy() error
61
+
62
+	// restore sandbox
63
+	Restore(ifsopt map[string][]IfaceOption, routes []*types.StaticRoute, gw net.IP, gw6 net.IP) error
61 64
 }
62 65
 
63 66
 // NeighborOptionSetter interface defines the option setter methods for interface options
... ...
@@ -15,7 +15,7 @@ func GenerateKey(containerID string) string {
15 15
 
16 16
 // NewSandbox provides a new sandbox instance created in an os specific way
17 17
 // provided a key which uniquely identifies the sandbox
18
-func NewSandbox(key string, osCreate bool) (Sandbox, error) {
18
+func NewSandbox(key string, osCreate, isRestore bool) (Sandbox, error) {
19 19
 	return nil, nil
20 20
 }
21 21
 
... ...
@@ -11,7 +11,7 @@ var (
11 11
 
12 12
 // NewSandbox provides a new sandbox instance created in an os specific way
13 13
 // provided a key which uniquely identifies the sandbox
14
-func NewSandbox(key string, osCreate bool) (Sandbox, error) {
14
+func NewSandbox(key string, osCreate, isRestore bool) (Sandbox, error) {
15 15
 	return nil, ErrNotImplemented
16 16
 }
17 17
 
... ...
@@ -19,6 +19,13 @@ func init() {
19 19
 	reexec.Register("setup-resolver", reexecSetupResolver)
20 20
 }
21 21
 
22
+const (
23
+	// outputChain used for docker embed dns
24
+	outputChain = "DOCKER_OUTPUT"
25
+	//postroutingchain used for docker embed dns
26
+	postroutingchain = "DOCKER_POSTROUTING"
27
+)
28
+
22 29
 func reexecSetupResolver() {
23 30
 	runtime.LockOSThread()
24 31
 	defer runtime.UnlockOSThread()
... ...
@@ -31,10 +38,10 @@ func reexecSetupResolver() {
31 31
 	_, ipPort, _ := net.SplitHostPort(os.Args[2])
32 32
 	_, tcpPort, _ := net.SplitHostPort(os.Args[3])
33 33
 	rules := [][]string{
34
-		{"-t", "nat", "-A", "OUTPUT", "-d", resolverIP, "-p", "udp", "--dport", dnsPort, "-j", "DNAT", "--to-destination", os.Args[2]},
35
-		{"-t", "nat", "-A", "POSTROUTING", "-s", resolverIP, "-p", "udp", "--sport", ipPort, "-j", "SNAT", "--to-source", ":" + dnsPort},
36
-		{"-t", "nat", "-A", "OUTPUT", "-d", resolverIP, "-p", "tcp", "--dport", dnsPort, "-j", "DNAT", "--to-destination", os.Args[3]},
37
-		{"-t", "nat", "-A", "POSTROUTING", "-s", resolverIP, "-p", "tcp", "--sport", tcpPort, "-j", "SNAT", "--to-source", ":" + dnsPort},
34
+		{"-t", "nat", "-I", outputChain, "-d", resolverIP, "-p", "udp", "--dport", dnsPort, "-j", "DNAT", "--to-destination", os.Args[2]},
35
+		{"-t", "nat", "-I", postroutingchain, "-s", resolverIP, "-p", "udp", "--sport", ipPort, "-j", "SNAT", "--to-source", ":" + dnsPort},
36
+		{"-t", "nat", "-I", outputChain, "-d", resolverIP, "-p", "tcp", "--dport", dnsPort, "-j", "DNAT", "--to-destination", os.Args[3]},
37
+		{"-t", "nat", "-I", postroutingchain, "-s", resolverIP, "-p", "tcp", "--sport", tcpPort, "-j", "SNAT", "--to-source", ":" + dnsPort},
38 38
 	}
39 39
 
40 40
 	f, err := os.OpenFile(os.Args[1], os.O_RDONLY, 0)
... ...
@@ -50,6 +57,23 @@ func reexecSetupResolver() {
50 50
 		os.Exit(3)
51 51
 	}
52 52
 
53
+	// insert outputChain and postroutingchain
54
+	err = iptables.RawCombinedOutputNative("-t", "nat", "-C", "OUTPUT", "-d", resolverIP, "-j", outputChain)
55
+	if err == nil {
56
+		iptables.RawCombinedOutputNative("-t", "nat", "-F", outputChain)
57
+	} else {
58
+		iptables.RawCombinedOutputNative("-t", "nat", "-N", outputChain)
59
+		iptables.RawCombinedOutputNative("-t", "nat", "-I", "OUTPUT", "-d", resolverIP, "-j", outputChain)
60
+	}
61
+
62
+	err = iptables.RawCombinedOutputNative("-t", "nat", "-C", "POSTROUTING", "-d", resolverIP, "-j", postroutingchain)
63
+	if err == nil {
64
+		iptables.RawCombinedOutputNative("-t", "nat", "-F", postroutingchain)
65
+	} else {
66
+		iptables.RawCombinedOutputNative("-t", "nat", "-N", postroutingchain)
67
+		iptables.RawCombinedOutputNative("-t", "nat", "-I", "POSTROUTING", "-d", resolverIP, "-j", postroutingchain)
68
+	}
69
+
53 70
 	for _, rule := range rules {
54 71
 		if iptables.RawCombinedOutputNative(rule...) != nil {
55 72
 			log.Errorf("setting up rule failed, %v", rule)
... ...
@@ -700,6 +700,52 @@ func (sb *sandbox) releaseOSSbox() {
700 700
 	osSbox.Destroy()
701 701
 }
702 702
 
703
+func (sb *sandbox) restoreOslSandbox() error {
704
+	var routes []*types.StaticRoute
705
+
706
+	// restore osl sandbox
707
+	Ifaces := make(map[string][]osl.IfaceOption)
708
+	for _, ep := range sb.endpoints {
709
+		var ifaceOptions []osl.IfaceOption
710
+		ep.Lock()
711
+		joinInfo := ep.joinInfo
712
+		i := ep.iface
713
+		ep.Unlock()
714
+		ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().Address(i.addr), sb.osSbox.InterfaceOptions().Routes(i.routes))
715
+		if i.addrv6 != nil && i.addrv6.IP.To16() != nil {
716
+			ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().AddressIPv6(i.addrv6))
717
+		}
718
+		if i.mac != nil {
719
+			ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().MacAddress(i.mac))
720
+		}
721
+		if len(i.llAddrs) != 0 {
722
+			ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().LinkLocalAddresses(i.llAddrs))
723
+		}
724
+		Ifaces[fmt.Sprintf("%s+%s", i.srcName, i.dstPrefix)] = ifaceOptions
725
+		if joinInfo != nil {
726
+			for _, r := range joinInfo.StaticRoutes {
727
+				routes = append(routes, r)
728
+			}
729
+		}
730
+		if ep.needResolver() {
731
+			sb.startResolver()
732
+		}
733
+	}
734
+
735
+	gwep := sb.getGatewayEndpoint()
736
+	if gwep == nil {
737
+		return nil
738
+	}
739
+
740
+	// restore osl sandbox
741
+	err := sb.osSbox.Restore(Ifaces, routes, gwep.joinInfo.gw, gwep.joinInfo.gw6)
742
+	if err != nil {
743
+		return err
744
+	}
745
+
746
+	return nil
747
+}
748
+
703 749
 func (sb *sandbox) populateNetworkResources(ep *endpoint) error {
704 750
 	sb.Lock()
705 751
 	if sb.osSbox == nil {
... ...
@@ -139,6 +139,16 @@ func (sb *sandbox) updateParentHosts() error {
139 139
 	return nil
140 140
 }
141 141
 
142
+func (sb *sandbox) restorePath() {
143
+	if sb.config.resolvConfPath == "" {
144
+		sb.config.resolvConfPath = defaultPrefix + "/" + sb.id + "/resolv.conf"
145
+	}
146
+	sb.config.resolvConfHashFile = sb.config.resolvConfPath + ".hash"
147
+	if sb.config.hostsPath == "" {
148
+		sb.config.hostsPath = defaultPrefix + "/" + sb.id + "/hosts"
149
+	}
150
+}
151
+
142 152
 func (sb *sandbox) setupDNS() error {
143 153
 	var newRC *resolvconf.File
144 154
 
... ...
@@ -15,6 +15,9 @@ func (sb *sandbox) setupResolutionFiles() error {
15 15
 	return nil
16 16
 }
17 17
 
18
+func (sb *sandbox) restorePath() {
19
+}
20
+
18 21
 func (sb *sandbox) updateHostsFile(ifaceIP string) error {
19 22
 	return nil
20 23
 }
... ...
@@ -20,12 +20,13 @@ type epState struct {
20 20
 }
21 21
 
22 22
 type sbState struct {
23
-	ID       string
24
-	Cid      string
25
-	c        *controller
26
-	dbIndex  uint64
27
-	dbExists bool
28
-	Eps      []epState
23
+	ID         string
24
+	Cid        string
25
+	c          *controller
26
+	dbIndex    uint64
27
+	dbExists   bool
28
+	Eps        []epState
29
+	EpPriority map[string]int
29 30
 }
30 31
 
31 32
 func (sbs *sbState) Key() []string {
... ...
@@ -106,6 +107,7 @@ func (sbs *sbState) CopyTo(o datastore.KVObject) error {
106 106
 	dstSbs.Cid = sbs.Cid
107 107
 	dstSbs.dbIndex = sbs.dbIndex
108 108
 	dstSbs.dbExists = sbs.dbExists
109
+	dstSbs.EpPriority = sbs.EpPriority
109 110
 
110 111
 	for _, eps := range sbs.Eps {
111 112
 		dstSbs.Eps = append(dstSbs.Eps, eps)
... ...
@@ -120,9 +122,10 @@ func (sbs *sbState) DataScope() string {
120 120
 
121 121
 func (sb *sandbox) storeUpdate() error {
122 122
 	sbs := &sbState{
123
-		c:   sb.controller,
124
-		ID:  sb.id,
125
-		Cid: sb.containerID,
123
+		c:          sb.controller,
124
+		ID:         sb.id,
125
+		Cid:        sb.containerID,
126
+		EpPriority: sb.epPriority,
126 127
 	}
127 128
 
128 129
 retry:
... ...
@@ -166,7 +169,7 @@ func (sb *sandbox) storeDelete() error {
166 166
 	return sb.controller.deleteFromStore(sbs)
167 167
 }
168 168
 
169
-func (c *controller) sandboxCleanup() {
169
+func (c *controller) sandboxCleanup(activeSandboxes map[string]interface{}) {
170 170
 	store := c.getStore(datastore.LocalScope)
171 171
 	if store == nil {
172 172
 		logrus.Errorf("Could not find local scope store while trying to cleanup sandboxes")
... ...
@@ -192,15 +195,27 @@ func (c *controller) sandboxCleanup() {
192 192
 			controller:  sbs.c,
193 193
 			containerID: sbs.Cid,
194 194
 			endpoints:   epHeap{},
195
-			epPriority:  map[string]int{},
196 195
 			dbIndex:     sbs.dbIndex,
197 196
 			isStub:      true,
198 197
 			dbExists:    true,
199 198
 		}
200 199
 
201
-		sb.osSbox, err = osl.NewSandbox(sb.Key(), true)
200
+		msg := " for cleanup"
201
+		create := true
202
+		isRestore := false
203
+		if val, ok := activeSandboxes[sb.ID()]; ok {
204
+			msg = ""
205
+			sb.isStub = false
206
+			isRestore = true
207
+			opts := val.([]SandboxOption)
208
+			sb.processOptions(opts...)
209
+			sb.restorePath()
210
+			create = !sb.config.useDefaultSandBox
211
+			heap.Init(&sb.endpoints)
212
+		}
213
+		sb.osSbox, err = osl.NewSandbox(sb.Key(), create, isRestore)
202 214
 		if err != nil {
203
-			logrus.Errorf("failed to create new osl sandbox while trying to build sandbox for cleanup: %v", err)
215
+			logrus.Errorf("failed to create osl sandbox while trying to restore sandbox %s%s: %v", sb.ID()[0:7], msg, err)
204 216
 			continue
205 217
 		}
206 218
 
... ...
@@ -222,13 +237,34 @@ func (c *controller) sandboxCleanup() {
222 222
 					ep = &endpoint{id: eps.Eid, network: n, sandboxID: sbs.ID}
223 223
 				}
224 224
 			}
225
-
226 225
 			heap.Push(&sb.endpoints, ep)
227 226
 		}
228 227
 
229
-		logrus.Infof("Removing stale sandbox %s (%s)", sb.id, sb.containerID)
230
-		if err := sb.delete(true); err != nil {
231
-			logrus.Errorf("failed to delete sandbox %s while trying to cleanup: %v", sb.id, err)
228
+		if _, ok := activeSandboxes[sb.ID()]; !ok {
229
+			logrus.Infof("Removing stale sandbox %s (%s)", sb.id, sb.containerID)
230
+			if err := sb.delete(true); err != nil {
231
+				logrus.Errorf("Failed to delete sandbox %s while trying to cleanup: %v", sb.id, err)
232
+			}
233
+			continue
234
+		}
235
+
236
+		// reconstruct osl sandbox field
237
+		if !sb.config.useDefaultSandBox {
238
+			if err := sb.restoreOslSandbox(); err != nil {
239
+				logrus.Errorf("failed to populate fields for osl sandbox %s", sb.ID())
240
+				continue
241
+			}
242
+		} else {
243
+			c.sboxOnce.Do(func() {
244
+				c.defOsSbox = sb.osSbox
245
+			})
246
+		}
247
+
248
+		for _, ep := range sb.endpoints {
249
+			// Watch for service records
250
+			if !c.isAgent() {
251
+				c.watchSvcRecord(ep)
252
+			}
232 253
 		}
233 254
 	}
234 255
 }