Daemon to support network restore

Signed-off-by: Lei Jitang <leijitang@huawei.com>
This commit is contained in:
Lei Jitang 2016-06-14 09:13:53 -07:00 committed by Alessandro Boch
parent 5b79122146
commit ecffb6d58c
12 changed files with 102 additions and 44 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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