Daemon to support network restore
Signed-off-by: Lei Jitang <leijitang@huawei.com>
This commit is contained in:
parent
5b79122146
commit
ecffb6d58c
|
@ -121,14 +121,6 @@ func New(config Config) (*Cluster, error) {
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cluster) checkCompatibility() error {
|
|
||||||
info, _ := c.config.Backend.SystemInfo()
|
|
||||||
if info != nil && (info.ClusterStore != "" || info.ClusterAdvertise != "") {
|
|
||||||
return fmt.Errorf("swarm mode is incompatible with `--cluster-store` and `--cluster-advertise daemon configuration")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Cluster) saveState() error {
|
func (c *Cluster) saveState() error {
|
||||||
dt, err := json.Marshal(state{ListenAddr: c.listenAddr})
|
dt, err := json.Marshal(state{ListenAddr: c.listenAddr})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -173,7 +165,7 @@ func (c *Cluster) reconnectOnFailure(ctx context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cluster) startNewNode(forceNewCluster bool, listenAddr, joinAddr, secret, cahash string, ismanager bool) (*swarmagent.Node, context.Context, error) {
|
func (c *Cluster) startNewNode(forceNewCluster bool, listenAddr, joinAddr, secret, cahash string, ismanager bool) (*swarmagent.Node, context.Context, error) {
|
||||||
if err := c.checkCompatibility(); err != nil {
|
if err := c.config.Backend.IsSwarmCompatible(); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
c.node = nil
|
c.node = nil
|
||||||
|
|
|
@ -32,4 +32,5 @@ type Backend interface {
|
||||||
ListContainersForNode(nodeID string) []string
|
ListContainersForNode(nodeID string) []string
|
||||||
SetNetworkBootstrapKeys([]*networktypes.EncryptionKey) error
|
SetNetworkBootstrapKeys([]*networktypes.EncryptionKey) error
|
||||||
SetClusterProvider(provider cluster.Provider)
|
SetClusterProvider(provider cluster.Provider)
|
||||||
|
IsSwarmCompatible() error
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,3 +37,7 @@ func (config *Config) InstallFlags(cmd *flag.FlagSet, usageFn func(string) strin
|
||||||
// Then platform-specific install flags
|
// Then platform-specific install flags
|
||||||
config.attachExperimentalFlags(cmd, usageFn)
|
config.attachExperimentalFlags(cmd, usageFn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (config *Config) isSwarmCompatible() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
package daemon
|
package daemon
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/docker/docker/opts"
|
"github.com/docker/docker/opts"
|
||||||
|
@ -120,3 +121,13 @@ func (config *Config) GetAllRuntimes() map[string]types.Runtime {
|
||||||
config.reloadLock.Unlock()
|
config.reloadLock.Unlock()
|
||||||
return rts
|
return rts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (config *Config) isSwarmCompatible() error {
|
||||||
|
if config.IsValueSet("cluster-store") || config.IsValueSet("cluster-advertise") {
|
||||||
|
return fmt.Errorf("--cluster-store and --cluster-advertise daemon configurations are incompatible with swarm mode")
|
||||||
|
}
|
||||||
|
if config.LiveRestore {
|
||||||
|
return fmt.Errorf("--live-restore daemon configuration is incompatible with swarm mode")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -57,3 +57,7 @@ func (config *Config) GetDefaultRuntimeName() string {
|
||||||
func (config *Config) GetAllRuntimes() map[string]types.Runtime {
|
func (config *Config) GetAllRuntimes() map[string]types.Runtime {
|
||||||
return map[string]types.Runtime{}
|
return map[string]types.Runtime{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (config *Config) isSwarmCompatible() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ var (
|
||||||
getPortMapInfo = container.GetSandboxPortMapInfo
|
getPortMapInfo = container.GetSandboxPortMapInfo
|
||||||
)
|
)
|
||||||
|
|
||||||
func (daemon *Daemon) buildSandboxOptions(container *container.Container, n libnetwork.Network) ([]libnetwork.SandboxOption, error) {
|
func (daemon *Daemon) buildSandboxOptions(container *container.Container) ([]libnetwork.SandboxOption, error) {
|
||||||
var (
|
var (
|
||||||
sboxOptions []libnetwork.SandboxOption
|
sboxOptions []libnetwork.SandboxOption
|
||||||
err error
|
err error
|
||||||
|
@ -176,16 +176,19 @@ func (daemon *Daemon) buildSandboxOptions(container *container.Container, n libn
|
||||||
|
|
||||||
// Legacy Link feature is supported only for the default bridge network.
|
// Legacy Link feature is supported only for the default bridge network.
|
||||||
// return if this call to build join options is not for default bridge network
|
// return if this call to build join options is not for default bridge network
|
||||||
if n.Name() != defaultNetName {
|
// Legacy Link is only supported by docker run --link
|
||||||
|
if _, ok := container.NetworkSettings.Networks[defaultNetName]; !container.HostConfig.NetworkMode.IsDefault() || !ok {
|
||||||
return sboxOptions, nil
|
return sboxOptions, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ep, _ := container.GetEndpointInNetwork(n)
|
if container.NetworkSettings.Networks[defaultNetName].EndpointID == "" {
|
||||||
if ep == nil {
|
|
||||||
return sboxOptions, nil
|
return sboxOptions, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var childEndpoints, parentEndpoints []string
|
var (
|
||||||
|
childEndpoints, parentEndpoints []string
|
||||||
|
cEndpointID string
|
||||||
|
)
|
||||||
|
|
||||||
children := daemon.children(container)
|
children := daemon.children(container)
|
||||||
for linkAlias, child := range children {
|
for linkAlias, child := range children {
|
||||||
|
@ -200,9 +203,9 @@ func (daemon *Daemon) buildSandboxOptions(container *container.Container, n libn
|
||||||
aliasList = aliasList + " " + child.Name[1:]
|
aliasList = aliasList + " " + child.Name[1:]
|
||||||
}
|
}
|
||||||
sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(aliasList, child.NetworkSettings.Networks[defaultNetName].IPAddress))
|
sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(aliasList, child.NetworkSettings.Networks[defaultNetName].IPAddress))
|
||||||
cEndpoint, _ := child.GetEndpointInNetwork(n)
|
cEndpointID = child.NetworkSettings.Networks[defaultNetName].EndpointID
|
||||||
if cEndpoint != nil && cEndpoint.ID() != "" {
|
if cEndpointID != "" {
|
||||||
childEndpoints = append(childEndpoints, cEndpoint.ID())
|
childEndpoints = append(childEndpoints, cEndpointID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,8 +222,8 @@ func (daemon *Daemon) buildSandboxOptions(container *container.Container, n libn
|
||||||
alias,
|
alias,
|
||||||
bridgeSettings.IPAddress,
|
bridgeSettings.IPAddress,
|
||||||
))
|
))
|
||||||
if ep.ID() != "" {
|
if cEndpointID != "" {
|
||||||
parentEndpoints = append(parentEndpoints, ep.ID())
|
parentEndpoints = append(parentEndpoints, cEndpointID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,7 +315,7 @@ func (daemon *Daemon) updateNetwork(container *container.Container) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
options, err := daemon.buildSandboxOptions(container, n)
|
options, err := daemon.buildSandboxOptions(container)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Update network failed: %v", err)
|
return fmt.Errorf("Update network failed: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -570,7 +573,7 @@ func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName
|
||||||
}
|
}
|
||||||
|
|
||||||
if sb == nil {
|
if sb == nil {
|
||||||
options, err := daemon.buildSandboxOptions(container, n)
|
options, err := daemon.buildSandboxOptions(container)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -709,6 +712,9 @@ func (daemon *Daemon) getNetworkedContainer(containerID, connectedContainerID st
|
||||||
}
|
}
|
||||||
|
|
||||||
func (daemon *Daemon) releaseNetwork(container *container.Container) {
|
func (daemon *Daemon) releaseNetwork(container *container.Container) {
|
||||||
|
if daemon.netController == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
if container.HostConfig.NetworkMode.IsContainer() || container.Config.NetworkDisabled {
|
if container.HostConfig.NetworkMode.IsContainer() || container.Config.NetworkDisabled {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,6 +146,7 @@ func (daemon *Daemon) restore() error {
|
||||||
|
|
||||||
var migrateLegacyLinks bool
|
var migrateLegacyLinks bool
|
||||||
restartContainers := make(map[*container.Container]chan struct{})
|
restartContainers := make(map[*container.Container]chan struct{})
|
||||||
|
activeSandboxes := make(map[string]interface{})
|
||||||
for _, c := range containers {
|
for _, c := range containers {
|
||||||
if err := daemon.registerName(c); err != nil {
|
if err := daemon.registerName(c); err != nil {
|
||||||
logrus.Errorf("Failed to register container %s: %s", c.ID, err)
|
logrus.Errorf("Failed to register container %s: %s", c.ID, err)
|
||||||
|
@ -178,6 +179,16 @@ func (daemon *Daemon) restore() error {
|
||||||
logrus.Errorf("Failed to restore with containerd: %q", err)
|
logrus.Errorf("Failed to restore with containerd: %q", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if !c.HostConfig.NetworkMode.IsContainer() {
|
||||||
|
options, err := daemon.buildSandboxOptions(c)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Warnf("Failed build sandbox option to restore container %s: %v", c.ID, err)
|
||||||
|
}
|
||||||
|
mapLock.Lock()
|
||||||
|
activeSandboxes[c.NetworkSettings.SandboxID] = options
|
||||||
|
mapLock.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// fixme: only if not running
|
// fixme: only if not running
|
||||||
// get list of containers we need to restart
|
// get list of containers we need to restart
|
||||||
|
@ -209,6 +220,10 @@ func (daemon *Daemon) restore() error {
|
||||||
}(c)
|
}(c)
|
||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
daemon.netController, err = daemon.initNetworkController(daemon.configStore, activeSandboxes)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error initializing network controller: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
// migrate any legacy links from sqlite
|
// migrate any legacy links from sqlite
|
||||||
linkdbFile := filepath.Join(daemon.root, "linkgraph.db")
|
linkdbFile := filepath.Join(daemon.root, "linkgraph.db")
|
||||||
|
@ -356,6 +371,15 @@ func (daemon *Daemon) SetClusterProvider(clusterProvider cluster.Provider) {
|
||||||
daemon.netController.SetClusterProvider(clusterProvider)
|
daemon.netController.SetClusterProvider(clusterProvider)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsSwarmCompatible verifies if the current daemon
|
||||||
|
// configuration is compatible with the swarm mode
|
||||||
|
func (daemon *Daemon) IsSwarmCompatible() error {
|
||||||
|
if daemon.configStore == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return daemon.configStore.isSwarmCompatible()
|
||||||
|
}
|
||||||
|
|
||||||
// NewDaemon sets up everything for the daemon to be able to service
|
// NewDaemon sets up everything for the daemon to be able to service
|
||||||
// requests from the webserver.
|
// requests from the webserver.
|
||||||
func NewDaemon(config *Config, registryService registry.Service, containerdRemote libcontainerd.Remote) (daemon *Daemon, err error) {
|
func NewDaemon(config *Config, registryService registry.Service, containerdRemote libcontainerd.Remote) (daemon *Daemon, err error) {
|
||||||
|
@ -530,11 +554,6 @@ func NewDaemon(config *Config, registryService registry.Service, containerdRemot
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
d.netController, err = d.initNetworkController(config)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Error initializing network controller: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
sysInfo := sysinfo.New(false)
|
sysInfo := sysinfo.New(false)
|
||||||
// Check if Devices cgroup is mounted, it is hard requirement for container security,
|
// Check if Devices cgroup is mounted, it is hard requirement for container security,
|
||||||
// on Linux.
|
// on Linux.
|
||||||
|
@ -912,15 +931,17 @@ func (daemon *Daemon) reloadClusterDiscovery(config *Config) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if daemon.clusterProvider != nil {
|
||||||
|
if err := config.isSwarmCompatible(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// check discovery modifications
|
// check discovery modifications
|
||||||
if !modifiedDiscoverySettings(daemon.configStore, newAdvertise, newClusterStore, config.ClusterOpts) {
|
if !modifiedDiscoverySettings(daemon.configStore, newAdvertise, newClusterStore, config.ClusterOpts) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if daemon.clusterProvider != nil {
|
|
||||||
return fmt.Errorf("--cluster-store and --cluster-advertise daemon configurations are incompatible with swarm mode")
|
|
||||||
}
|
|
||||||
|
|
||||||
// enable discovery for the first time if it was not previously enabled
|
// enable discovery for the first time if it was not previously enabled
|
||||||
if daemon.discoveryWatcher == nil {
|
if daemon.discoveryWatcher == nil {
|
||||||
discoveryWatcher, err := initDiscovery(newClusterStore, newAdvertise, config.ClusterOpts)
|
discoveryWatcher, err := initDiscovery(newClusterStore, newAdvertise, config.ClusterOpts)
|
||||||
|
@ -947,7 +968,7 @@ func (daemon *Daemon) reloadClusterDiscovery(config *Config) error {
|
||||||
if daemon.netController == nil {
|
if daemon.netController == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
netOptions, err := daemon.networkOptions(daemon.configStore)
|
netOptions, err := daemon.networkOptions(daemon.configStore, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Warnf("Failed to reload configuration with network controller: %v", err)
|
logrus.Warnf("Failed to reload configuration with network controller: %v", err)
|
||||||
return nil
|
return nil
|
||||||
|
@ -964,7 +985,7 @@ func isBridgeNetworkDisabled(config *Config) bool {
|
||||||
return config.bridgeConfig.Iface == disableNetworkBridge
|
return config.bridgeConfig.Iface == disableNetworkBridge
|
||||||
}
|
}
|
||||||
|
|
||||||
func (daemon *Daemon) networkOptions(dconfig *Config) ([]nwconfig.Option, error) {
|
func (daemon *Daemon) networkOptions(dconfig *Config, activeSandboxes map[string]interface{}) ([]nwconfig.Option, error) {
|
||||||
options := []nwconfig.Option{}
|
options := []nwconfig.Option{}
|
||||||
if dconfig == nil {
|
if dconfig == nil {
|
||||||
return options, nil
|
return options, nil
|
||||||
|
@ -999,6 +1020,11 @@ func (daemon *Daemon) networkOptions(dconfig *Config) ([]nwconfig.Option, error)
|
||||||
|
|
||||||
options = append(options, nwconfig.OptionLabels(dconfig.Labels))
|
options = append(options, nwconfig.OptionLabels(dconfig.Labels))
|
||||||
options = append(options, driverOptions(dconfig)...)
|
options = append(options, driverOptions(dconfig)...)
|
||||||
|
|
||||||
|
if daemon.configStore != nil && daemon.configStore.LiveRestore && len(activeSandboxes) != 0 {
|
||||||
|
options = append(options, nwconfig.OptionActiveSandboxes(activeSandboxes))
|
||||||
|
}
|
||||||
|
|
||||||
return options, nil
|
return options, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,7 @@ func configureKernelSecuritySupport(config *Config, driverName string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (daemon *Daemon) initNetworkController(config *Config) (libnetwork.NetworkController, error) {
|
func (daemon *Daemon) initNetworkController(config *Config, activeSandboxes map[string]interface{}) (libnetwork.NetworkController, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -627,8 +627,8 @@ func configureKernelSecuritySupport(config *Config, driverName string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (daemon *Daemon) initNetworkController(config *Config) (libnetwork.NetworkController, error) {
|
func (daemon *Daemon) initNetworkController(config *Config, activeSandboxes map[string]interface{}) (libnetwork.NetworkController, error) {
|
||||||
netOptions, err := daemon.networkOptions(config)
|
netOptions, err := daemon.networkOptions(config, activeSandboxes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -638,16 +638,24 @@ func (daemon *Daemon) initNetworkController(config *Config) (libnetwork.NetworkC
|
||||||
return nil, fmt.Errorf("error obtaining controller instance: %v", err)
|
return nil, fmt.Errorf("error obtaining controller instance: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(activeSandboxes) > 0 {
|
||||||
|
logrus.Infof("There are old running containers, the network config will not take affect")
|
||||||
|
return controller, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize default network on "null"
|
// Initialize default network on "null"
|
||||||
if _, err := controller.NewNetwork("null", "none", "", libnetwork.NetworkOptionPersist(false)); err != nil {
|
if n, _ := controller.NetworkByName("none"); n == nil {
|
||||||
return nil, fmt.Errorf("Error creating default \"null\" network: %v", err)
|
if _, err := controller.NewNetwork("null", "none", "", libnetwork.NetworkOptionPersist(true)); err != nil {
|
||||||
|
return nil, fmt.Errorf("Error creating default \"null\" network: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize default network on "host"
|
// Initialize default network on "host"
|
||||||
if _, err := controller.NewNetwork("host", "host", "", libnetwork.NetworkOptionPersist(false)); err != nil {
|
if n, _ := controller.NetworkByName("host"); n == nil {
|
||||||
return nil, fmt.Errorf("Error creating default \"host\" network: %v", err)
|
if _, err := controller.NewNetwork("host", "host", "", libnetwork.NetworkOptionPersist(true)); err != nil {
|
||||||
|
return nil, fmt.Errorf("Error creating default \"host\" network: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !config.DisableBridge {
|
if !config.DisableBridge {
|
||||||
// Initialize default driver "bridge"
|
// Initialize default driver "bridge"
|
||||||
if err := initBridgeDriver(controller, config); err != nil {
|
if err := initBridgeDriver(controller, config); err != nil {
|
||||||
|
|
|
@ -183,7 +183,7 @@ func TestNetworkOptions(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := daemon.networkOptions(dconfigCorrect); err != nil {
|
if _, err := daemon.networkOptions(dconfigCorrect, nil); err != nil {
|
||||||
t.Fatalf("Expect networkOptions success, got error: %v", err)
|
t.Fatalf("Expect networkOptions success, got error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,7 +193,7 @@ func TestNetworkOptions(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := daemon.networkOptions(dconfigWrong); err == nil {
|
if _, err := daemon.networkOptions(dconfigWrong, nil); err == nil {
|
||||||
t.Fatalf("Expected networkOptions error, got nil")
|
t.Fatalf("Expected networkOptions error, got nil")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,8 +189,8 @@ func configureMaxThreads(config *Config) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (daemon *Daemon) initNetworkController(config *Config) (libnetwork.NetworkController, error) {
|
func (daemon *Daemon) initNetworkController(config *Config, activeSandboxes map[string]interface{}) (libnetwork.NetworkController, error) {
|
||||||
netOptions, err := daemon.networkOptions(config)
|
netOptions, err := daemon.networkOptions(config, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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.
|
// GetNetworkByName function returns a network for a given network name.
|
||||||
func (daemon *Daemon) GetNetworkByName(name string) (libnetwork.Network, error) {
|
func (daemon *Daemon) GetNetworkByName(name string) (libnetwork.Network, error) {
|
||||||
c := daemon.netController
|
c := daemon.netController
|
||||||
|
if c == nil {
|
||||||
|
return nil, libnetwork.ErrNoSuchNetwork(name)
|
||||||
|
}
|
||||||
if name == "" {
|
if name == "" {
|
||||||
name = c.Config().Daemon.DefaultNetwork
|
name = c.Config().Daemon.DefaultNetwork
|
||||||
}
|
}
|
||||||
|
@ -68,6 +71,9 @@ func (daemon *Daemon) GetNetworkByName(name string) (libnetwork.Network, error)
|
||||||
// GetNetworksByID returns a list of networks whose ID partially matches zero or more networks
|
// GetNetworksByID returns a list of networks whose ID partially matches zero or more networks
|
||||||
func (daemon *Daemon) GetNetworksByID(partialID string) []libnetwork.Network {
|
func (daemon *Daemon) GetNetworksByID(partialID string) []libnetwork.Network {
|
||||||
c := daemon.netController
|
c := daemon.netController
|
||||||
|
if c == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
list := []libnetwork.Network{}
|
list := []libnetwork.Network{}
|
||||||
l := func(nw libnetwork.Network) bool {
|
l := func(nw libnetwork.Network) bool {
|
||||||
if strings.HasPrefix(nw.ID(), partialID) {
|
if strings.HasPrefix(nw.ID(), partialID) {
|
||||||
|
|
Loading…
Reference in New Issue