Daemon to support network restore
Signed-off-by: Lei Jitang <leijitang@huawei.com>
This commit is contained in:
parent
5b79122146
commit
ecffb6d58c
12 changed files with 102 additions and 44 deletions
|
@ -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
|
||||
|
|
|
@ -32,4 +32,5 @@ type Backend interface {
|
|||
ListContainersForNode(nodeID string) []string
|
||||
SetNetworkBootstrapKeys([]*networktypes.EncryptionKey) error
|
||||
SetClusterProvider(provider cluster.Provider)
|
||||
IsSwarmCompatible() error
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Add table
Reference in a new issue