mirror of
https://github.com/moby/moby.git
synced 2025-08-01 05:47:11 +03:00
Merge pull request #20419 from aboch/cr
Allow passing global datastore to libnetwork and v0.7.0-dev1 vendoring
This commit is contained in:
@ -1598,12 +1598,12 @@ func (daemon *Daemon) initDiscovery(config *Config) error {
|
|||||||
// daemon according to those changes.
|
// daemon according to those changes.
|
||||||
// This are the settings that Reload changes:
|
// This are the settings that Reload changes:
|
||||||
// - Daemon labels.
|
// - Daemon labels.
|
||||||
|
// - Cluster discovery (reconfigure and restart).
|
||||||
func (daemon *Daemon) Reload(config *Config) error {
|
func (daemon *Daemon) Reload(config *Config) error {
|
||||||
daemon.configStore.reloadLock.Lock()
|
daemon.configStore.reloadLock.Lock()
|
||||||
|
defer daemon.configStore.reloadLock.Unlock()
|
||||||
daemon.configStore.Labels = config.Labels
|
daemon.configStore.Labels = config.Labels
|
||||||
daemon.configStore.reloadLock.Unlock()
|
return daemon.reloadClusterDiscovery(config)
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (daemon *Daemon) reloadClusterDiscovery(config *Config) error {
|
func (daemon *Daemon) reloadClusterDiscovery(config *Config) error {
|
||||||
@ -1640,6 +1640,19 @@ func (daemon *Daemon) reloadClusterDiscovery(config *Config) error {
|
|||||||
daemon.configStore.ClusterOpts = config.ClusterOpts
|
daemon.configStore.ClusterOpts = config.ClusterOpts
|
||||||
daemon.configStore.ClusterAdvertise = newAdvertise
|
daemon.configStore.ClusterAdvertise = newAdvertise
|
||||||
|
|
||||||
|
if daemon.netController == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
netOptions, err := daemon.networkOptions(daemon.configStore)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Warnf("Failed to reload configuration with network controller: %v", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err = daemon.netController.ReloadConfiguration(netOptions...)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Warnf("Failed to reload configuration with network controller: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,7 +371,7 @@ func TestDaemonDiscoveryReload(t *testing.T) {
|
|||||||
&discovery.Entry{Host: "127.0.0.1", Port: "5555"},
|
&discovery.Entry{Host: "127.0.0.1", Port: "5555"},
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := daemon.reloadClusterDiscovery(newConfig); err != nil {
|
if err := daemon.Reload(newConfig); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
ch, errCh = daemon.discoveryWatcher.Watch(stopCh)
|
ch, errCh = daemon.discoveryWatcher.Watch(stopCh)
|
||||||
@ -403,7 +403,7 @@ func TestDaemonDiscoveryReloadFromEmptyDiscovery(t *testing.T) {
|
|||||||
&discovery.Entry{Host: "127.0.0.1", Port: "5555"},
|
&discovery.Entry{Host: "127.0.0.1", Port: "5555"},
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := daemon.reloadClusterDiscovery(newConfig); err != nil {
|
if err := daemon.Reload(newConfig); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
stopCh := make(chan struct{})
|
stopCh := make(chan struct{})
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
"github.com/docker/docker/pkg/idtools"
|
"github.com/docker/docker/pkg/idtools"
|
||||||
"github.com/docker/docker/pkg/system"
|
"github.com/docker/docker/pkg/system"
|
||||||
"github.com/docker/libnetwork"
|
"github.com/docker/libnetwork"
|
||||||
|
nwconfig "github.com/docker/libnetwork/config"
|
||||||
blkiodev "github.com/opencontainers/runc/libcontainer/configs"
|
blkiodev "github.com/opencontainers/runc/libcontainer/configs"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -251,3 +252,7 @@ func restoreCustomImage(is image.Store, ls layer.Store, rs reference.Store) erro
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (daemon *Daemon) networkOptions(dconfig *Config) ([]nwconfig.Option, error) {
|
||||||
|
return nil, fmt.Errorf("Network controller config reload not aavailable on Windows yet")
|
||||||
|
}
|
||||||
|
@ -890,4 +890,13 @@ if there are conflicts, but it won't stop execution.
|
|||||||
The list of currently supported options that can be reconfigured is this:
|
The list of currently supported options that can be reconfigured is this:
|
||||||
|
|
||||||
- `debug`: it changes the daemon to debug mode when set to true.
|
- `debug`: it changes the daemon to debug mode when set to true.
|
||||||
|
- `cluster-store`: it reloads the discovery store with the new address.
|
||||||
|
- `cluster-store-opts`: it uses the new options to reload the discovery store.
|
||||||
|
- `cluster-advertise`: it modifies the address advertised after reloading.
|
||||||
- `labels`: it replaces the daemon labels with a new set of labels.
|
- `labels`: it replaces the daemon labels with a new set of labels.
|
||||||
|
|
||||||
|
Updating and reloading the cluster configurations such as `--cluster-store`,
|
||||||
|
`--cluster-advertise` and `--cluster-store-opts` will take effect only if
|
||||||
|
these configurations were not previously configured. Configuration reload will
|
||||||
|
log a warning message if it detects a change in previously configured cluster
|
||||||
|
configurations.
|
@ -29,7 +29,7 @@ clone git github.com/RackSec/srslog 6eb773f331e46fbba8eecb8e794e635e75fc04de
|
|||||||
clone git github.com/imdario/mergo 0.2.1
|
clone git github.com/imdario/mergo 0.2.1
|
||||||
|
|
||||||
#get libnetwork packages
|
#get libnetwork packages
|
||||||
clone git github.com/docker/libnetwork v0.7.0-dev.2
|
clone git github.com/docker/libnetwork v0.7.0-dev.3
|
||||||
clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
|
clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
|
||||||
clone git github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b
|
clone git github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b
|
||||||
clone git github.com/hashicorp/memberlist 9a1e242e454d2443df330bdd51a436d5a9058fc4
|
clone git github.com/hashicorp/memberlist 9a1e242e454d2443df330bdd51a436d5a9058fc4
|
||||||
|
@ -17,6 +17,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/docker/docker/pkg/integration/checker"
|
"github.com/docker/docker/pkg/integration/checker"
|
||||||
@ -2156,3 +2157,43 @@ func (s *DockerDaemonSuite) TestDaemonDebugLog(c *check.C) {
|
|||||||
newD.Stop()
|
newD.Stop()
|
||||||
c.Assert(b.String(), checker.Contains, debugLog)
|
c.Assert(b.String(), checker.Contains, debugLog)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *DockerSuite) TestDaemonDiscoveryBackendConfigReload(c *check.C) {
|
||||||
|
testRequires(c, SameHostDaemon, DaemonIsLinux)
|
||||||
|
|
||||||
|
// daemon config file
|
||||||
|
daemonConfig := `{ "debug" : false }`
|
||||||
|
configFilePath := "test.json"
|
||||||
|
|
||||||
|
configFile, err := os.Create(configFilePath)
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
fmt.Fprintf(configFile, "%s", daemonConfig)
|
||||||
|
|
||||||
|
d := NewDaemon(c)
|
||||||
|
err = d.Start(fmt.Sprintf("--config-file=%s", configFilePath))
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
defer d.Stop()
|
||||||
|
|
||||||
|
// daemon config file
|
||||||
|
daemonConfig = `{
|
||||||
|
"cluster-store": "consul://consuladdr:consulport/some/path",
|
||||||
|
"cluster-advertise": "192.168.56.100:0",
|
||||||
|
"debug" : false
|
||||||
|
}`
|
||||||
|
|
||||||
|
configFile.Close()
|
||||||
|
os.Remove(configFilePath)
|
||||||
|
|
||||||
|
configFile, err = os.Create(configFilePath)
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
fmt.Fprintf(configFile, "%s", daemonConfig)
|
||||||
|
|
||||||
|
syscall.Kill(d.cmd.Process.Pid, syscall.SIGHUP)
|
||||||
|
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
|
||||||
|
out, err := d.Cmd("info")
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
c.Assert(out, checker.Contains, fmt.Sprintf("Cluster store: consul://consuladdr:consulport/some/path"))
|
||||||
|
c.Assert(out, checker.Contains, fmt.Sprintf("Cluster advertise: 192.168.56.100:0"))
|
||||||
|
}
|
||||||
|
@ -1389,6 +1389,14 @@ func (s *DockerSuite) TestUserDefinedNetworkConnectivity(c *check.C) {
|
|||||||
c.Assert(err, check.NotNil)
|
c.Assert(err, check.NotNil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *DockerSuite) TestEmbeddedDNSInvalidInput(c *check.C) {
|
||||||
|
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||||
|
dockerCmd(c, "network", "create", "-d", "bridge", "nw1")
|
||||||
|
|
||||||
|
// Sending garbge to embedded DNS shouldn't crash the daemon
|
||||||
|
dockerCmd(c, "run", "-i", "--net=nw1", "--name=c1", "debian:jessie", "bash", "-c", "echo InvalidQuery > /dev/udp/127.0.0.11/53")
|
||||||
|
}
|
||||||
|
|
||||||
func (s *DockerSuite) TestDockerNetworkConnectFailsNoInspectChange(c *check.C) {
|
func (s *DockerSuite) TestDockerNetworkConnectFailsNoInspectChange(c *check.C) {
|
||||||
dockerCmd(c, "run", "-d", "--name=bb", "busybox", "top")
|
dockerCmd(c, "run", "-d", "--name=bb", "busybox", "top")
|
||||||
c.Assert(waitRun("bb"), check.IsNil)
|
c.Assert(waitRun("bb"), check.IsNil)
|
||||||
|
@ -1,5 +1,13 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.7.0-dev.3 (2016-02-17)
|
||||||
|
- Fixes https://github.com/docker/docker/issues/20350
|
||||||
|
- Fixes https://github.com/docker/docker/issues/20145
|
||||||
|
- Initial Windows HNS integration
|
||||||
|
- Allow passing global datastore config to libnetwork after boot
|
||||||
|
- Set Recursion Available bit in DNS query responses
|
||||||
|
- Make sure iptables chains are recreated on firewalld reload
|
||||||
|
|
||||||
## 0.7.0-dev.2 (2016-02-11)
|
## 0.7.0-dev.2 (2016-02-11)
|
||||||
- Fixes https://github.com/docker/docker/issues/20140
|
- Fixes https://github.com/docker/docker/issues/20140
|
||||||
|
|
||||||
|
@ -8,6 +8,5 @@ RUN cd /go/src && mkdir -p golang.org/x && \
|
|||||||
RUN go get github.com/tools/godep \
|
RUN go get github.com/tools/godep \
|
||||||
github.com/golang/lint/golint \
|
github.com/golang/lint/golint \
|
||||||
golang.org/x/tools/cmd/vet \
|
golang.org/x/tools/cmd/vet \
|
||||||
golang.org/x/tools/cmd/goimports \
|
|
||||||
golang.org/x/tools/cmd/cover\
|
golang.org/x/tools/cmd/cover\
|
||||||
github.com/mattn/goveralls
|
github.com/mattn/goveralls
|
||||||
|
@ -53,7 +53,7 @@ check-code:
|
|||||||
|
|
||||||
check-format:
|
check-format:
|
||||||
@echo "Checking format... "
|
@echo "Checking format... "
|
||||||
test -z "$$(goimports -l . | grep -v Godeps/_workspace/src/ | tee /dev/stderr)"
|
test -z "$$(gofmt -s -l . | grep -v Godeps/_workspace/src/ | tee /dev/stderr)"
|
||||||
@echo "Done checking format"
|
@echo "Done checking format"
|
||||||
|
|
||||||
run-tests:
|
run-tests:
|
||||||
|
@ -61,6 +61,22 @@ func ParseConfig(tomlCfgFile string) (*Config, error) {
|
|||||||
return cfg, nil
|
return cfg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseConfigOptions parses the configuration options and returns
|
||||||
|
// a reference to the corresponding Config structure
|
||||||
|
func ParseConfigOptions(cfgOptions ...Option) *Config {
|
||||||
|
cfg := &Config{
|
||||||
|
Daemon: DaemonCfg{
|
||||||
|
DriverCfg: make(map[string]interface{}),
|
||||||
|
},
|
||||||
|
Scopes: make(map[string]*datastore.ScopeCfg),
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg.ProcessOptions(cfgOptions...)
|
||||||
|
cfg.LoadDefaultScopes(cfg.Daemon.DataDir)
|
||||||
|
|
||||||
|
return cfg
|
||||||
|
}
|
||||||
|
|
||||||
// Option is an option setter function type used to pass various configurations
|
// Option is an option setter function type used to pass various configurations
|
||||||
// to the controller
|
// to the controller
|
||||||
type Option func(c *Config)
|
type Option func(c *Config)
|
||||||
|
@ -106,6 +106,9 @@ type NetworkController interface {
|
|||||||
|
|
||||||
// Stop network controller
|
// Stop network controller
|
||||||
Stop()
|
Stop()
|
||||||
|
|
||||||
|
// ReloadCondfiguration updates the controller configuration
|
||||||
|
ReloadConfiguration(cfgOptions ...config.Option) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// NetworkWalker is a client provided function which will be used to walk the Networks.
|
// NetworkWalker is a client provided function which will be used to walk the Networks.
|
||||||
@ -129,7 +132,6 @@ type ipamData struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type driverTable map[string]*driverData
|
type driverTable map[string]*driverData
|
||||||
|
|
||||||
type ipamTable map[string]*ipamData
|
type ipamTable map[string]*ipamData
|
||||||
type sandboxTable map[string]*sandbox
|
type sandboxTable map[string]*sandbox
|
||||||
|
|
||||||
@ -153,22 +155,9 @@ type controller struct {
|
|||||||
|
|
||||||
// New creates a new instance of network controller.
|
// New creates a new instance of network controller.
|
||||||
func New(cfgOptions ...config.Option) (NetworkController, error) {
|
func New(cfgOptions ...config.Option) (NetworkController, error) {
|
||||||
var cfg *config.Config
|
|
||||||
cfg = &config.Config{
|
|
||||||
Daemon: config.DaemonCfg{
|
|
||||||
DriverCfg: make(map[string]interface{}),
|
|
||||||
},
|
|
||||||
Scopes: make(map[string]*datastore.ScopeCfg),
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(cfgOptions) > 0 {
|
|
||||||
cfg.ProcessOptions(cfgOptions...)
|
|
||||||
}
|
|
||||||
cfg.LoadDefaultScopes(cfg.Daemon.DataDir)
|
|
||||||
|
|
||||||
c := &controller{
|
c := &controller{
|
||||||
id: stringid.GenerateRandomID(),
|
id: stringid.GenerateRandomID(),
|
||||||
cfg: cfg,
|
cfg: config.ParseConfigOptions(cfgOptions...),
|
||||||
sandboxes: sandboxTable{},
|
sandboxes: sandboxTable{},
|
||||||
drivers: driverTable{},
|
drivers: driverTable{},
|
||||||
ipamDrivers: ipamTable{},
|
ipamDrivers: ipamTable{},
|
||||||
@ -179,8 +168,8 @@ func New(cfgOptions ...config.Option) (NetworkController, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg != nil && cfg.Cluster.Watcher != nil {
|
if c.cfg != nil && c.cfg.Cluster.Watcher != nil {
|
||||||
if err := c.initDiscovery(cfg.Cluster.Watcher); err != nil {
|
if err := c.initDiscovery(c.cfg.Cluster.Watcher); err != nil {
|
||||||
// Failing to initalize discovery is a bad situation to be in.
|
// Failing to initalize discovery is a bad situation to be in.
|
||||||
// But it cannot fail creating the Controller
|
// But it cannot fail creating the Controller
|
||||||
log.Errorf("Failed to Initialize Discovery : %v", err)
|
log.Errorf("Failed to Initialize Discovery : %v", err)
|
||||||
@ -206,6 +195,83 @@ func New(cfgOptions ...config.Option) (NetworkController, error) {
|
|||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var procReloadConfig = make(chan (bool), 1)
|
||||||
|
|
||||||
|
func (c *controller) ReloadConfiguration(cfgOptions ...config.Option) error {
|
||||||
|
procReloadConfig <- true
|
||||||
|
defer func() { <-procReloadConfig }()
|
||||||
|
|
||||||
|
// For now we accept the configuration reload only as a mean to provide a global store config after boot.
|
||||||
|
// Refuse the configuration if it alters an existing datastore client configuration.
|
||||||
|
update := false
|
||||||
|
cfg := config.ParseConfigOptions(cfgOptions...)
|
||||||
|
for s := range c.cfg.Scopes {
|
||||||
|
if _, ok := cfg.Scopes[s]; !ok {
|
||||||
|
return types.ForbiddenErrorf("cannot accept new configuration because it removes an existing datastore client")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for s, nSCfg := range cfg.Scopes {
|
||||||
|
if eSCfg, ok := c.cfg.Scopes[s]; ok {
|
||||||
|
if eSCfg.Client.Provider != nSCfg.Client.Provider ||
|
||||||
|
eSCfg.Client.Address != nSCfg.Client.Address {
|
||||||
|
return types.ForbiddenErrorf("cannot accept new configuration because it modifies an existing datastore client")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
update = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !update {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Lock()
|
||||||
|
c.cfg = cfg
|
||||||
|
c.Unlock()
|
||||||
|
|
||||||
|
if err := c.initStores(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.discovery == nil && c.cfg.Cluster.Watcher != nil {
|
||||||
|
if err := c.initDiscovery(c.cfg.Cluster.Watcher); err != nil {
|
||||||
|
log.Errorf("Failed to Initialize Discovery after configuration update: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var dsConfig *discoverapi.DatastoreConfigData
|
||||||
|
for scope, sCfg := range cfg.Scopes {
|
||||||
|
if scope == datastore.LocalScope || !sCfg.IsValid() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
dsConfig = &discoverapi.DatastoreConfigData{
|
||||||
|
Scope: scope,
|
||||||
|
Provider: sCfg.Client.Provider,
|
||||||
|
Address: sCfg.Client.Address,
|
||||||
|
Config: sCfg.Client.Config,
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if dsConfig == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for nm, id := range c.getIpamDrivers() {
|
||||||
|
err := id.driver.DiscoverNew(discoverapi.DatastoreConfig, *dsConfig)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Failed to set datastore in driver %s: %v", nm, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for nm, id := range c.getNetDrivers() {
|
||||||
|
err := id.driver.DiscoverNew(discoverapi.DatastoreConfig, *dsConfig)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Failed to set datastore in driver %s: %v", nm, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *controller) ID() string {
|
func (c *controller) ID() string {
|
||||||
return c.id
|
return c.id
|
||||||
}
|
}
|
||||||
@ -726,6 +792,26 @@ func (c *controller) getIpamDriver(name string) (ipamapi.Ipam, error) {
|
|||||||
return id.driver, nil
|
return id.driver, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *controller) getIpamDrivers() ipamTable {
|
||||||
|
c.Lock()
|
||||||
|
defer c.Unlock()
|
||||||
|
table := ipamTable{}
|
||||||
|
for i, d := range c.ipamDrivers {
|
||||||
|
table[i] = d
|
||||||
|
}
|
||||||
|
return table
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *controller) getNetDrivers() driverTable {
|
||||||
|
c.Lock()
|
||||||
|
defer c.Unlock()
|
||||||
|
table := driverTable{}
|
||||||
|
for i, d := range c.drivers {
|
||||||
|
table[i] = d
|
||||||
|
}
|
||||||
|
return table
|
||||||
|
}
|
||||||
|
|
||||||
func (c *controller) Stop() {
|
func (c *controller) Stop() {
|
||||||
c.closeStores()
|
c.closeStores()
|
||||||
c.stopExternalKeyListener()
|
c.stopExternalKeyListener()
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/docker/libkv/store/consul"
|
"github.com/docker/libkv/store/consul"
|
||||||
"github.com/docker/libkv/store/etcd"
|
"github.com/docker/libkv/store/etcd"
|
||||||
"github.com/docker/libkv/store/zookeeper"
|
"github.com/docker/libkv/store/zookeeper"
|
||||||
|
"github.com/docker/libnetwork/discoverapi"
|
||||||
"github.com/docker/libnetwork/types"
|
"github.com/docker/libnetwork/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -253,6 +254,34 @@ func NewDataStore(scope string, cfg *ScopeCfg) (DataStore, error) {
|
|||||||
return newClient(scope, cfg.Client.Provider, cfg.Client.Address, cfg.Client.Config, cached)
|
return newClient(scope, cfg.Client.Provider, cfg.Client.Address, cfg.Client.Config, cached)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewDataStoreFromConfig creates a new instance of LibKV data store starting from the datastore config data
|
||||||
|
func NewDataStoreFromConfig(dsc discoverapi.DatastoreConfigData) (DataStore, error) {
|
||||||
|
var (
|
||||||
|
ok bool
|
||||||
|
sCfgP *store.Config
|
||||||
|
)
|
||||||
|
|
||||||
|
sCfgP, ok = dsc.Config.(*store.Config)
|
||||||
|
if !ok && dsc.Config != nil {
|
||||||
|
return nil, fmt.Errorf("cannot parse store configuration: %v", dsc.Config)
|
||||||
|
}
|
||||||
|
|
||||||
|
scopeCfg := &ScopeCfg{
|
||||||
|
Client: ScopeClientCfg{
|
||||||
|
Address: dsc.Address,
|
||||||
|
Provider: dsc.Provider,
|
||||||
|
Config: sCfgP,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
ds, err := NewDataStore(dsc.Scope, scopeCfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to construct datastore client from datastore configuration %v: %v", dsc, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ds, err
|
||||||
|
}
|
||||||
|
|
||||||
func (ds *datastore) Close() {
|
func (ds *datastore) Close() {
|
||||||
ds.store.Close()
|
ds.store.Close()
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,8 @@ type DiscoveryType int
|
|||||||
const (
|
const (
|
||||||
// NodeDiscovery represents Node join/leave events provided by discovery
|
// NodeDiscovery represents Node join/leave events provided by discovery
|
||||||
NodeDiscovery = iota + 1
|
NodeDiscovery = iota + 1
|
||||||
// DatastoreUpdate represents a add/remove datastore event
|
// DatastoreConfig represents a add/remove datastore event
|
||||||
DatastoreUpdate
|
DatastoreConfig
|
||||||
)
|
)
|
||||||
|
|
||||||
// NodeDiscoveryData represents the structure backing the node discovery data json string
|
// NodeDiscoveryData represents the structure backing the node discovery data json string
|
||||||
@ -26,8 +26,9 @@ type NodeDiscoveryData struct {
|
|||||||
Self bool
|
Self bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// DatastoreUpdateData is the data for the datastore update event message
|
// DatastoreConfigData is the data for the datastore update event message
|
||||||
type DatastoreUpdateData struct {
|
type DatastoreConfigData struct {
|
||||||
|
Scope string
|
||||||
Provider string
|
Provider string
|
||||||
Address string
|
Address string
|
||||||
Config interface{}
|
Config interface{}
|
||||||
|
@ -3,11 +3,13 @@ package libnetwork
|
|||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/docker/libnetwork/discoverapi"
|
||||||
"github.com/docker/libnetwork/driverapi"
|
"github.com/docker/libnetwork/driverapi"
|
||||||
"github.com/docker/libnetwork/ipamapi"
|
"github.com/docker/libnetwork/ipamapi"
|
||||||
|
"github.com/docker/libnetwork/netlabel"
|
||||||
|
|
||||||
builtinIpam "github.com/docker/libnetwork/ipams/builtin"
|
builtinIpam "github.com/docker/libnetwork/ipams/builtin"
|
||||||
remoteIpam "github.com/docker/libnetwork/ipams/remote"
|
remoteIpam "github.com/docker/libnetwork/ipams/remote"
|
||||||
"github.com/docker/libnetwork/netlabel"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type initializer struct {
|
type initializer struct {
|
||||||
@ -56,10 +58,12 @@ func makeDriverConfig(c *controller, ntype string) map[string]interface{} {
|
|||||||
if !v.IsValid() {
|
if !v.IsValid() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
config[netlabel.MakeKVClient(k)] = discoverapi.DatastoreConfigData{
|
||||||
config[netlabel.MakeKVProvider(k)] = v.Client.Provider
|
Scope: k,
|
||||||
config[netlabel.MakeKVProviderURL(k)] = v.Client.Address
|
Provider: v.Client.Provider,
|
||||||
config[netlabel.MakeKVProviderConfig(k)] = v.Client.Config
|
Address: v.Client.Address,
|
||||||
|
Config: v.Client.Config,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return config
|
return config
|
||||||
|
@ -133,6 +133,9 @@ func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
|||||||
if out, err := exec.Command("modprobe", "-va", "nf_nat").CombinedOutput(); err != nil {
|
if out, err := exec.Command("modprobe", "-va", "nf_nat").CombinedOutput(); err != nil {
|
||||||
logrus.Warnf("Running modprobe nf_nat failed with message: `%s`, error: %v", strings.TrimSpace(string(out)), err)
|
logrus.Warnf("Running modprobe nf_nat failed with message: `%s`, error: %v", strings.TrimSpace(string(out)), err)
|
||||||
}
|
}
|
||||||
|
if out, err := exec.Command("modprobe", "-va", "xt_conntrack").CombinedOutput(); err != nil {
|
||||||
|
logrus.Warnf("Running modprobe xt_conntrack failed with message: `%s`, error: %v", strings.TrimSpace(string(out)), err)
|
||||||
|
}
|
||||||
if err := iptables.FirewalldInit(); err != nil {
|
if err := iptables.FirewalldInit(); err != nil {
|
||||||
logrus.Debugf("Fail to initialize firewalld: %v, using raw iptables instead", err)
|
logrus.Debugf("Fail to initialize firewalld: %v, using raw iptables instead", err)
|
||||||
}
|
}
|
||||||
@ -384,6 +387,8 @@ func (d *driver) configure(option map[string]interface{}) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// Make sure on firewall reload, first thing being re-played is chains creation
|
||||||
|
iptables.OnReloaded(func() { logrus.Debugf("Recreating iptables chains on firewall reload"); setupIPChains(config) })
|
||||||
}
|
}
|
||||||
|
|
||||||
d.Lock()
|
d.Lock()
|
||||||
|
@ -6,9 +6,9 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/docker/libkv/store"
|
|
||||||
"github.com/docker/libkv/store/boltdb"
|
"github.com/docker/libkv/store/boltdb"
|
||||||
"github.com/docker/libnetwork/datastore"
|
"github.com/docker/libnetwork/datastore"
|
||||||
|
"github.com/docker/libnetwork/discoverapi"
|
||||||
"github.com/docker/libnetwork/netlabel"
|
"github.com/docker/libnetwork/netlabel"
|
||||||
"github.com/docker/libnetwork/types"
|
"github.com/docker/libnetwork/types"
|
||||||
)
|
)
|
||||||
@ -16,27 +16,15 @@ import (
|
|||||||
const bridgePrefix = "bridge"
|
const bridgePrefix = "bridge"
|
||||||
|
|
||||||
func (d *driver) initStore(option map[string]interface{}) error {
|
func (d *driver) initStore(option map[string]interface{}) error {
|
||||||
var err error
|
if data, ok := option[netlabel.LocalKVClient]; ok {
|
||||||
|
var err error
|
||||||
provider, provOk := option[netlabel.LocalKVProvider]
|
dsc, ok := data.(discoverapi.DatastoreConfigData)
|
||||||
provURL, urlOk := option[netlabel.LocalKVProviderURL]
|
if !ok {
|
||||||
|
return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
|
||||||
if provOk && urlOk {
|
|
||||||
cfg := &datastore.ScopeCfg{
|
|
||||||
Client: datastore.ScopeClientCfg{
|
|
||||||
Provider: provider.(string),
|
|
||||||
Address: provURL.(string),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
d.store, err = datastore.NewDataStoreFromConfig(dsc)
|
||||||
provConfig, confOk := option[netlabel.LocalKVProviderConfig]
|
|
||||||
if confOk {
|
|
||||||
cfg.Client.Config = provConfig.(*store.Config)
|
|
||||||
}
|
|
||||||
|
|
||||||
d.store, err = datastore.NewDataStore(datastore.LocalScope, cfg)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("bridge driver failed to initialize data store: %v", err)
|
return types.InternalErrorf("bridge driver failed to initialize data store: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return d.populateNetworks()
|
return d.populateNetworks()
|
||||||
|
@ -6,12 +6,12 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/docker/libkv/store"
|
|
||||||
"github.com/docker/libnetwork/datastore"
|
"github.com/docker/libnetwork/datastore"
|
||||||
"github.com/docker/libnetwork/discoverapi"
|
"github.com/docker/libnetwork/discoverapi"
|
||||||
"github.com/docker/libnetwork/driverapi"
|
"github.com/docker/libnetwork/driverapi"
|
||||||
"github.com/docker/libnetwork/idm"
|
"github.com/docker/libnetwork/idm"
|
||||||
"github.com/docker/libnetwork/netlabel"
|
"github.com/docker/libnetwork/netlabel"
|
||||||
|
"github.com/docker/libnetwork/types"
|
||||||
"github.com/hashicorp/serf/serf"
|
"github.com/hashicorp/serf/serf"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -25,6 +25,8 @@ const (
|
|||||||
vxlanVethMTU = 1450
|
vxlanVethMTU = 1450
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var initVxlanIdm = make(chan (bool), 1)
|
||||||
|
|
||||||
type driver struct {
|
type driver struct {
|
||||||
eventCh chan serf.Event
|
eventCh chan serf.Event
|
||||||
notifyCh chan ovNotify
|
notifyCh chan ovNotify
|
||||||
@ -56,6 +58,18 @@ func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
|||||||
config: config,
|
config: config,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if data, ok := config[netlabel.GlobalKVClient]; ok {
|
||||||
|
var err error
|
||||||
|
dsc, ok := data.(discoverapi.DatastoreConfigData)
|
||||||
|
if !ok {
|
||||||
|
return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
|
||||||
|
}
|
||||||
|
d.store, err = datastore.NewDataStoreFromConfig(dsc)
|
||||||
|
if err != nil {
|
||||||
|
return types.InternalErrorf("failed to initialize data store: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return dc.RegisterDriver(networkType, d, c)
|
return dc.RegisterDriver(networkType, d, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,42 +87,33 @@ func Fini(drv driverapi.Driver) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *driver) configure() error {
|
func (d *driver) configure() error {
|
||||||
|
if d.store == nil {
|
||||||
|
return types.NoServiceErrorf("datastore is not available")
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.vxlanIdm == nil {
|
||||||
|
return d.initializeVxlanIdm()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *driver) initializeVxlanIdm() error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if len(d.config) == 0 {
|
initVxlanIdm <- true
|
||||||
|
defer func() { <-initVxlanIdm }()
|
||||||
|
|
||||||
|
if d.vxlanIdm != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
d.once.Do(func() {
|
d.vxlanIdm, err = idm.New(d.store, "vxlan-id", vxlanIDStart, vxlanIDEnd)
|
||||||
provider, provOk := d.config[netlabel.GlobalKVProvider]
|
if err != nil {
|
||||||
provURL, urlOk := d.config[netlabel.GlobalKVProviderURL]
|
return fmt.Errorf("failed to initialize vxlan id manager: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
if provOk && urlOk {
|
return nil
|
||||||
cfg := &datastore.ScopeCfg{
|
|
||||||
Client: datastore.ScopeClientCfg{
|
|
||||||
Provider: provider.(string),
|
|
||||||
Address: provURL.(string),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
provConfig, confOk := d.config[netlabel.GlobalKVProviderConfig]
|
|
||||||
if confOk {
|
|
||||||
cfg.Client.Config = provConfig.(*store.Config)
|
|
||||||
}
|
|
||||||
d.store, err = datastore.NewDataStore(datastore.GlobalScope, cfg)
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("failed to initialize data store: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
d.vxlanIdm, err = idm.New(d.store, "vxlan-id", vxlanIDStart, vxlanIDEnd)
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("failed to initialize vxlan id manager: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *driver) Type() string {
|
func (d *driver) Type() string {
|
||||||
@ -187,12 +192,27 @@ func (d *driver) pushLocalEndpointEvent(action, nid, eid string) {
|
|||||||
|
|
||||||
// DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster
|
// DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster
|
||||||
func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
|
func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||||
if dType == discoverapi.NodeDiscovery {
|
switch dType {
|
||||||
|
case discoverapi.NodeDiscovery:
|
||||||
nodeData, ok := data.(discoverapi.NodeDiscoveryData)
|
nodeData, ok := data.(discoverapi.NodeDiscoveryData)
|
||||||
if !ok || nodeData.Address == "" {
|
if !ok || nodeData.Address == "" {
|
||||||
return fmt.Errorf("invalid discovery data")
|
return fmt.Errorf("invalid discovery data")
|
||||||
}
|
}
|
||||||
d.nodeJoin(nodeData.Address, nodeData.Self)
|
d.nodeJoin(nodeData.Address, nodeData.Self)
|
||||||
|
case discoverapi.DatastoreConfig:
|
||||||
|
var err error
|
||||||
|
if d.store != nil {
|
||||||
|
return types.ForbiddenErrorf("cannot accept datastore configuration: Overlay driver has a datastore configured already")
|
||||||
|
}
|
||||||
|
dsc, ok := data.(discoverapi.DatastoreConfigData)
|
||||||
|
if !ok {
|
||||||
|
return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
|
||||||
|
}
|
||||||
|
d.store, err = datastore.NewDataStoreFromConfig(dsc)
|
||||||
|
if err != nil {
|
||||||
|
return types.InternalErrorf("failed to initialize data store: %v", err)
|
||||||
|
}
|
||||||
|
default:
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
12
vendor/src/github.com/docker/libnetwork/drivers/windows/labels.go
vendored
Normal file
12
vendor/src/github.com/docker/libnetwork/drivers/windows/labels.go
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package windows
|
||||||
|
|
||||||
|
const (
|
||||||
|
// NetworkName label for bridge driver
|
||||||
|
NetworkName = "com.docker.network.windowsshim.networkname"
|
||||||
|
|
||||||
|
// HNSID of the discovered network
|
||||||
|
HNSID = "com.docker.network.windowsshim.hnsid"
|
||||||
|
|
||||||
|
// RoutingDomain of the network
|
||||||
|
RoutingDomain = "com.docker.network.windowsshim.routingdomain"
|
||||||
|
)
|
@ -1,57 +1,419 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
// Shim for the Host Network Service (HNS) to manage networking for
|
||||||
|
// Windows Server containers and Hyper-V containers. This module
|
||||||
|
// is a basic libnetwork driver that passes all the calls to HNS
|
||||||
|
// It implements the 4 networking modes supported by HNS L2Bridge,
|
||||||
|
// L2Tunnel, NAT and Transparent(DHCP)
|
||||||
|
//
|
||||||
|
// The network are stored in memory and docker daemon ensures discovering
|
||||||
|
// and loading these networks on startup
|
||||||
|
|
||||||
package windows
|
package windows
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/Microsoft/hcsshim"
|
||||||
|
log "github.com/Sirupsen/logrus"
|
||||||
"github.com/docker/libnetwork/datastore"
|
"github.com/docker/libnetwork/datastore"
|
||||||
"github.com/docker/libnetwork/discoverapi"
|
"github.com/docker/libnetwork/discoverapi"
|
||||||
"github.com/docker/libnetwork/driverapi"
|
"github.com/docker/libnetwork/driverapi"
|
||||||
|
"github.com/docker/libnetwork/netlabel"
|
||||||
|
"github.com/docker/libnetwork/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
const networkType = "windows"
|
// networkConfiguration for network specific configuration
|
||||||
|
type networkConfiguration struct {
|
||||||
// TODO Windows. This is a placeholder for now
|
ID string
|
||||||
|
Type string
|
||||||
type driver struct{}
|
Name string
|
||||||
|
HnsID string
|
||||||
// Init registers a new instance of null driver
|
RDID string
|
||||||
func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
|
||||||
c := driverapi.Capability{
|
|
||||||
DataScope: datastore.LocalScope,
|
|
||||||
}
|
|
||||||
return dc.RegisterDriver(networkType, &driver{}, c)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type hnsEndpoint struct {
|
||||||
|
id string
|
||||||
|
profileID string
|
||||||
|
macAddress net.HardwareAddr
|
||||||
|
addr *net.IPNet
|
||||||
|
}
|
||||||
|
|
||||||
|
type hnsNetwork struct {
|
||||||
|
id string
|
||||||
|
config *networkConfiguration
|
||||||
|
endpoints map[string]*hnsEndpoint // key: endpoint id
|
||||||
|
driver *driver // The network's driver
|
||||||
|
sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
type driver struct {
|
||||||
|
name string
|
||||||
|
networks map[string]*hnsNetwork
|
||||||
|
sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func isValidNetworkType(networkType string) bool {
|
||||||
|
if "L2Bridge" == networkType || "L2Tunnel" == networkType || "NAT" == networkType || "Transparent" == networkType {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// New constructs a new bridge driver
|
||||||
|
func newDriver(networkType string) *driver {
|
||||||
|
return &driver{name: networkType, networks: map[string]*hnsNetwork{}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetInit returns an initializer for the given network type
|
||||||
|
func GetInit(networkType string) func(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
||||||
|
return func(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
||||||
|
if !isValidNetworkType(networkType) {
|
||||||
|
return types.BadRequestErrorf("Network type not supported: %s", networkType)
|
||||||
|
}
|
||||||
|
|
||||||
|
return dc.RegisterDriver(networkType, newDriver(networkType), driverapi.Capability{
|
||||||
|
DataScope: datastore.LocalScope,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *driver) getNetwork(id string) (*hnsNetwork, error) {
|
||||||
|
d.Lock()
|
||||||
|
defer d.Unlock()
|
||||||
|
|
||||||
|
if nw, ok := d.networks[id]; ok {
|
||||||
|
return nw, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, types.NotFoundErrorf("network not found: %s", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *hnsNetwork) getEndpoint(eid string) (*hnsEndpoint, error) {
|
||||||
|
n.Lock()
|
||||||
|
defer n.Unlock()
|
||||||
|
|
||||||
|
if ep, ok := n.endpoints[eid]; ok {
|
||||||
|
return ep, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, types.NotFoundErrorf("Endpoint not found: %s", eid)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *driver) parseNetworkOptions(id string, genericOptions map[string]string) (*networkConfiguration, error) {
|
||||||
|
config := &networkConfiguration{}
|
||||||
|
|
||||||
|
for label, value := range genericOptions {
|
||||||
|
switch label {
|
||||||
|
case NetworkName:
|
||||||
|
config.Name = value
|
||||||
|
case HNSID:
|
||||||
|
config.HnsID = value
|
||||||
|
case RoutingDomain:
|
||||||
|
config.RDID = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
config.ID = id
|
||||||
|
config.Type = d.name
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *networkConfiguration) processIPAM(id string, ipamV4Data, ipamV6Data []driverapi.IPAMData) error {
|
||||||
|
if len(ipamV6Data) > 0 {
|
||||||
|
return types.ForbiddenErrorf("windowsshim driver doesnt support v6 subnets")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ipamV4Data) == 0 {
|
||||||
|
return types.BadRequestErrorf("network %s requires ipv4 configuration", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new network
|
||||||
func (d *driver) CreateNetwork(id string, option map[string]interface{}, ipV4Data, ipV6Data []driverapi.IPAMData) error {
|
func (d *driver) CreateNetwork(id string, option map[string]interface{}, ipV4Data, ipV6Data []driverapi.IPAMData) error {
|
||||||
|
if _, err := d.getNetwork(id); err == nil {
|
||||||
|
return types.ForbiddenErrorf("network %s exists", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
genData, ok := option[netlabel.GenericData].(map[string]string)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Unknown generic data option")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse and validate the config. It should not conflict with existing networks' config
|
||||||
|
config, err := d.parseNetworkOptions(id, genData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = config.processIPAM(id, ipV4Data, ipV6Data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
network := &hnsNetwork{
|
||||||
|
id: config.ID,
|
||||||
|
endpoints: make(map[string]*hnsEndpoint),
|
||||||
|
config: config,
|
||||||
|
driver: d,
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Lock()
|
||||||
|
d.networks[config.ID] = network
|
||||||
|
d.Unlock()
|
||||||
|
|
||||||
|
// A non blank hnsid indicates that the network was discovered
|
||||||
|
// from HNS. No need to call HNS if this network was discovered
|
||||||
|
// from HNS
|
||||||
|
if config.HnsID == "" {
|
||||||
|
subnets := []hcsshim.Subnet{}
|
||||||
|
|
||||||
|
for _, ipData := range ipV4Data {
|
||||||
|
subnet := hcsshim.Subnet{
|
||||||
|
AddressPrefix: ipData.Pool.String(),
|
||||||
|
GatewayAddress: ipData.Gateway.IP.String(),
|
||||||
|
}
|
||||||
|
|
||||||
|
subnets = append(subnets, subnet)
|
||||||
|
}
|
||||||
|
|
||||||
|
network := &hcsshim.HNSNetwork{
|
||||||
|
Name: config.Name,
|
||||||
|
Type: d.name,
|
||||||
|
Subnets: subnets,
|
||||||
|
}
|
||||||
|
|
||||||
|
if network.Name == "" {
|
||||||
|
network.Name = id
|
||||||
|
}
|
||||||
|
|
||||||
|
configurationb, err := json.Marshal(network)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
configuration := string(configurationb)
|
||||||
|
log.Debugf("HNSNetwork Request =%v Address Space=%v", configuration, subnets)
|
||||||
|
|
||||||
|
hnsresponse, err := hcsshim.HNSNetworkRequest("POST", "", configuration)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
config.HnsID = hnsresponse.Id
|
||||||
|
genData[HNSID] = config.HnsID
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *driver) DeleteNetwork(nid string) error {
|
func (d *driver) DeleteNetwork(nid string) error {
|
||||||
|
n, err := d.getNetwork(nid)
|
||||||
|
if err != nil {
|
||||||
|
return types.InternalMaskableErrorf("%s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
n.Lock()
|
||||||
|
config := n.config
|
||||||
|
n.Unlock()
|
||||||
|
|
||||||
|
// Cannot remove network if endpoints are still present
|
||||||
|
if len(n.endpoints) != 0 {
|
||||||
|
return fmt.Errorf("network %s has active endpoint", n.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = hcsshim.HNSNetworkRequest("DELETE", config.HnsID, "")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Lock()
|
||||||
|
delete(d.networks, nid)
|
||||||
|
d.Unlock()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func convertPortBindings(portBindings []types.PortBinding) ([]json.RawMessage, error) {
|
||||||
|
var pbs []json.RawMessage
|
||||||
|
|
||||||
|
// Enumerate through the port bindings specified by the user and convert
|
||||||
|
// them into the internal structure matching the JSON blob that can be
|
||||||
|
// understood by the HCS.
|
||||||
|
for _, elem := range portBindings {
|
||||||
|
proto := strings.ToUpper(elem.Proto.String())
|
||||||
|
if proto != "TCP" && proto != "UDP" {
|
||||||
|
return nil, fmt.Errorf("invalid protocol %s", elem.Proto.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
if elem.HostPort != elem.HostPortEnd {
|
||||||
|
return nil, fmt.Errorf("Windows does not support more than one host port in NAT settings")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(elem.HostIP) != 0 {
|
||||||
|
return nil, fmt.Errorf("Windows does not support host IP addresses in NAT settings")
|
||||||
|
}
|
||||||
|
|
||||||
|
encodedPolicy, err := json.Marshal(hcsshim.NatPolicy{
|
||||||
|
Type: "NAT",
|
||||||
|
ExternalPort: elem.HostPort,
|
||||||
|
InternalPort: elem.Port,
|
||||||
|
Protocol: elem.Proto.String(),
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pbs = append(pbs, encodedPolicy)
|
||||||
|
}
|
||||||
|
return pbs, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error {
|
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error {
|
||||||
|
n, err := d.getNetwork(nid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if endpoint id is good and retrieve corresponding endpoint
|
||||||
|
ep, err := n.getEndpoint(eid)
|
||||||
|
if err == nil && ep != nil {
|
||||||
|
return driverapi.ErrEndpointExists(eid)
|
||||||
|
}
|
||||||
|
|
||||||
|
endpointStruct := &hcsshim.HNSEndpoint{
|
||||||
|
VirtualNetwork: n.config.HnsID,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the port mapping for the network
|
||||||
|
if opt, ok := epOptions[netlabel.PortMap]; ok {
|
||||||
|
if bs, ok := opt.([]types.PortBinding); ok {
|
||||||
|
endpointStruct.Policies, err = convertPortBindings(bs)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("Invalid endpoint configuration for endpoint id%s", eid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configurationb, err := json.Marshal(endpointStruct)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
hnsresponse, err := hcsshim.HNSEndpointRequest("POST", "", string(configurationb))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mac, err := net.ParseMAC(hnsresponse.MacAddress)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO For now the ip mask is not in the info generated by HNS
|
||||||
|
endpoint := &hnsEndpoint{
|
||||||
|
id: eid,
|
||||||
|
addr: &net.IPNet{IP: hnsresponse.IPAddress, Mask: hnsresponse.IPAddress.DefaultMask()},
|
||||||
|
macAddress: mac,
|
||||||
|
}
|
||||||
|
endpoint.profileID = hnsresponse.Id
|
||||||
|
n.Lock()
|
||||||
|
n.endpoints[eid] = endpoint
|
||||||
|
n.Unlock()
|
||||||
|
|
||||||
|
ifInfo.SetIPAddress(endpoint.addr)
|
||||||
|
ifInfo.SetMacAddress(endpoint.macAddress)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *driver) DeleteEndpoint(nid, eid string) error {
|
func (d *driver) DeleteEndpoint(nid, eid string) error {
|
||||||
|
n, err := d.getNetwork(nid)
|
||||||
|
if err != nil {
|
||||||
|
return types.InternalMaskableErrorf("%s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ep, err := n.getEndpoint(eid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
n.Lock()
|
||||||
|
delete(n.endpoints, eid)
|
||||||
|
n.Unlock()
|
||||||
|
|
||||||
|
_, err = hcsshim.HNSEndpointRequest("DELETE", ep.profileID, "")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) {
|
func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) {
|
||||||
return make(map[string]interface{}, 0), nil
|
network, err := d.getNetwork(nid)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoint, err := network.getEndpoint(eid)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
data := make(map[string]interface{}, 1)
|
||||||
|
data["hnsid"] = endpoint.profileID
|
||||||
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Join method is invoked when a Sandbox is attached to an endpoint.
|
// Join method is invoked when a Sandbox is attached to an endpoint.
|
||||||
func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
||||||
|
network, err := d.getNetwork(nid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that the endpoint exists
|
||||||
|
_, err = network.getEndpoint(eid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is just a stub for now
|
||||||
|
|
||||||
|
jinfo.DisableGatewayService()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Leave method is invoked when a Sandbox detaches from an endpoint.
|
// Leave method is invoked when a Sandbox detaches from an endpoint.
|
||||||
func (d *driver) Leave(nid, eid string) error {
|
func (d *driver) Leave(nid, eid string) error {
|
||||||
|
network, err := d.getNetwork(nid)
|
||||||
|
if err != nil {
|
||||||
|
return types.InternalMaskableErrorf("%s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that the endpoint exists
|
||||||
|
_, err = network.getEndpoint(eid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is just a stub for now
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *driver) Type() string {
|
func (d *driver) Type() string {
|
||||||
return networkType
|
return d.name
|
||||||
}
|
}
|
||||||
|
|
||||||
// DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster
|
// DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster
|
||||||
|
@ -1,9 +1,16 @@
|
|||||||
package libnetwork
|
package libnetwork
|
||||||
|
|
||||||
import "github.com/docker/libnetwork/drivers/windows"
|
import (
|
||||||
|
"github.com/docker/libnetwork/drivers/null"
|
||||||
|
"github.com/docker/libnetwork/drivers/windows"
|
||||||
|
)
|
||||||
|
|
||||||
func getInitializers() []initializer {
|
func getInitializers() []initializer {
|
||||||
return []initializer{
|
return []initializer{
|
||||||
{windows.Init, "windows"},
|
{null.Init, "null"},
|
||||||
|
{windows.GetInit("Transparent"), "Transparent"},
|
||||||
|
{windows.GetInit("L2Bridge"), "L2Bridge"},
|
||||||
|
{windows.GetInit("L2Tunnel"), "L2Tunnel"},
|
||||||
|
{windows.GetInit("NAT"), "NAT"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
log "github.com/Sirupsen/logrus"
|
log "github.com/Sirupsen/logrus"
|
||||||
"github.com/docker/libnetwork/bitseq"
|
"github.com/docker/libnetwork/bitseq"
|
||||||
"github.com/docker/libnetwork/datastore"
|
"github.com/docker/libnetwork/datastore"
|
||||||
|
"github.com/docker/libnetwork/discoverapi"
|
||||||
"github.com/docker/libnetwork/ipamapi"
|
"github.com/docker/libnetwork/ipamapi"
|
||||||
"github.com/docker/libnetwork/ipamutils"
|
"github.com/docker/libnetwork/ipamutils"
|
||||||
"github.com/docker/libnetwork/types"
|
"github.com/docker/libnetwork/types"
|
||||||
@ -60,19 +61,9 @@ func NewAllocator(lcDs, glDs datastore.DataStore) (*Allocator, error) {
|
|||||||
if aspc.ds == nil {
|
if aspc.ds == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
a.initializeAddressSpace(aspc.as, aspc.ds)
|
||||||
a.addrSpaces[aspc.as] = &addrSpace{
|
|
||||||
subnets: map[SubnetKey]*PoolData{},
|
|
||||||
id: dsConfigKey + "/" + aspc.as,
|
|
||||||
scope: aspc.ds.Scope(),
|
|
||||||
ds: aspc.ds,
|
|
||||||
alloc: a,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
a.checkConsistency(localAddressSpace)
|
|
||||||
a.checkConsistency(globalAddressSpace)
|
|
||||||
|
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,25 +109,83 @@ func (a *Allocator) updateBitMasks(aSpace *addrSpace) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks for and fixes damaged bitmask. Meant to be called in constructor only.
|
// Checks for and fixes damaged bitmask.
|
||||||
func (a *Allocator) checkConsistency(as string) {
|
func (a *Allocator) checkConsistency(as string) {
|
||||||
|
var sKeyList []SubnetKey
|
||||||
|
|
||||||
// Retrieve this address space's configuration and bitmasks from the datastore
|
// Retrieve this address space's configuration and bitmasks from the datastore
|
||||||
a.refresh(as)
|
a.refresh(as)
|
||||||
|
a.Lock()
|
||||||
aSpace, ok := a.addrSpaces[as]
|
aSpace, ok := a.addrSpaces[as]
|
||||||
|
a.Unlock()
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
a.updateBitMasks(aSpace)
|
a.updateBitMasks(aSpace)
|
||||||
|
|
||||||
|
aSpace.Lock()
|
||||||
for sk, pd := range aSpace.subnets {
|
for sk, pd := range aSpace.subnets {
|
||||||
if pd.Range != nil {
|
if pd.Range != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := a.addresses[sk].CheckConsistency(); err != nil {
|
sKeyList = append(sKeyList, sk)
|
||||||
|
}
|
||||||
|
aSpace.Unlock()
|
||||||
|
|
||||||
|
for _, sk := range sKeyList {
|
||||||
|
a.Lock()
|
||||||
|
bm := a.addresses[sk]
|
||||||
|
a.Unlock()
|
||||||
|
if err := bm.CheckConsistency(); err != nil {
|
||||||
log.Warnf("Error while running consistency check for %s: %v", sk, err)
|
log.Warnf("Error while running consistency check for %s: %v", sk, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *Allocator) initializeAddressSpace(as string, ds datastore.DataStore) error {
|
||||||
|
a.Lock()
|
||||||
|
if _, ok := a.addrSpaces[as]; ok {
|
||||||
|
a.Unlock()
|
||||||
|
return types.ForbiddenErrorf("tried to add an axisting address space: %s", as)
|
||||||
|
}
|
||||||
|
a.addrSpaces[as] = &addrSpace{
|
||||||
|
subnets: map[SubnetKey]*PoolData{},
|
||||||
|
id: dsConfigKey + "/" + as,
|
||||||
|
scope: ds.Scope(),
|
||||||
|
ds: ds,
|
||||||
|
alloc: a,
|
||||||
|
}
|
||||||
|
a.Unlock()
|
||||||
|
|
||||||
|
a.checkConsistency(as)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DiscoverNew informs the allocator about a new global scope datastore
|
||||||
|
func (a *Allocator) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||||
|
if dType != discoverapi.DatastoreConfig {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
dsc, ok := data.(discoverapi.DatastoreConfigData)
|
||||||
|
if !ok {
|
||||||
|
return types.InternalErrorf("incorrect data in datastore update notification: %v", data)
|
||||||
|
}
|
||||||
|
|
||||||
|
ds, err := datastore.NewDataStoreFromConfig(dsc)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.initializeAddressSpace(globalAddressSpace, ds)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DiscoverDelete is a notification of no interest for the allocator
|
||||||
|
func (a *Allocator) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetDefaultAddressSpaces returns the local and global default address spaces
|
// GetDefaultAddressSpaces returns the local and global default address spaces
|
||||||
func (a *Allocator) GetDefaultAddressSpaces() (string, string, error) {
|
func (a *Allocator) GetDefaultAddressSpaces() (string, string, error) {
|
||||||
return localAddressSpace, globalAddressSpace, nil
|
return localAddressSpace, globalAddressSpace, nil
|
||||||
|
@ -4,6 +4,7 @@ package ipamapi
|
|||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
"github.com/docker/libnetwork/discoverapi"
|
||||||
"github.com/docker/libnetwork/types"
|
"github.com/docker/libnetwork/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -56,6 +57,8 @@ var (
|
|||||||
// Ipam represents the interface the IPAM service plugins must implement
|
// Ipam represents the interface the IPAM service plugins must implement
|
||||||
// in order to allow injection/modification of IPAM database.
|
// in order to allow injection/modification of IPAM database.
|
||||||
type Ipam interface {
|
type Ipam interface {
|
||||||
|
discoverapi.Discover
|
||||||
|
|
||||||
// GetDefaultAddressSpaces returns the default local and global address spaces for this ipam
|
// GetDefaultAddressSpaces returns the default local and global address spaces for this ipam
|
||||||
GetDefaultAddressSpaces() (string, string, error)
|
GetDefaultAddressSpaces() (string, string, error)
|
||||||
// RequestPool returns an address pool along with its unique id. Address space is a mandatory field
|
// RequestPool returns an address pool along with its unique id. Address space is a mandatory field
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
// +build linux freebsd
|
||||||
|
|
||||||
package builtin
|
package builtin
|
||||||
|
|
||||||
import (
|
import (
|
16
vendor/src/github.com/docker/libnetwork/ipams/builtin/builtin_windows.go
vendored
Normal file
16
vendor/src/github.com/docker/libnetwork/ipams/builtin/builtin_windows.go
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
package builtin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/docker/libnetwork/ipamapi"
|
||||||
|
|
||||||
|
windowsipam "github.com/docker/libnetwork/ipams/windowsipam"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Init registers the built-in ipam service with libnetwork
|
||||||
|
func Init(ic ipamapi.Callback, l, g interface{}) error {
|
||||||
|
initFunc := windowsipam.GetInit(ipamapi.DefaultIPAM)
|
||||||
|
|
||||||
|
return initFunc(ic, l, g)
|
||||||
|
}
|
@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
log "github.com/Sirupsen/logrus"
|
log "github.com/Sirupsen/logrus"
|
||||||
"github.com/docker/docker/pkg/plugins"
|
"github.com/docker/docker/pkg/plugins"
|
||||||
|
"github.com/docker/libnetwork/discoverapi"
|
||||||
"github.com/docker/libnetwork/ipamapi"
|
"github.com/docker/libnetwork/ipamapi"
|
||||||
"github.com/docker/libnetwork/ipams/remote/api"
|
"github.com/docker/libnetwork/ipams/remote/api"
|
||||||
"github.com/docker/libnetwork/types"
|
"github.com/docker/libnetwork/types"
|
||||||
@ -124,3 +125,13 @@ func (a *allocator) ReleaseAddress(poolID string, address net.IP) error {
|
|||||||
res := &api.ReleaseAddressResponse{}
|
res := &api.ReleaseAddressResponse{}
|
||||||
return a.call("ReleaseAddress", req, res)
|
return a.call("ReleaseAddress", req, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DiscoverNew is a notification for a new discovery event, such as a new global datastore
|
||||||
|
func (a *allocator) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster
|
||||||
|
func (a *allocator) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
93
vendor/src/github.com/docker/libnetwork/ipams/windowsipam/windowsipam.go
vendored
Normal file
93
vendor/src/github.com/docker/libnetwork/ipams/windowsipam/windowsipam.go
vendored
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
package windowsipam
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
|
log "github.com/Sirupsen/logrus"
|
||||||
|
"github.com/docker/libnetwork/discoverapi"
|
||||||
|
"github.com/docker/libnetwork/ipamapi"
|
||||||
|
"github.com/docker/libnetwork/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
localAddressSpace = "LocalDefault"
|
||||||
|
globalAddressSpace = "GlobalDefault"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
defaultPool, _ = types.ParseCIDR("0.0.0.0/0")
|
||||||
|
)
|
||||||
|
|
||||||
|
type allocator struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetInit registers the built-in ipam service with libnetwork
|
||||||
|
func GetInit(ipamName string) func(ic ipamapi.Callback, l, g interface{}) error {
|
||||||
|
return func(ic ipamapi.Callback, l, g interface{}) error {
|
||||||
|
return ic.RegisterIpamDriver(ipamName, &allocator{})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *allocator) GetDefaultAddressSpaces() (string, string, error) {
|
||||||
|
return localAddressSpace, globalAddressSpace, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RequestPool returns an address pool along with its unique id. This is a null ipam driver. It allocates the
|
||||||
|
// subnet user asked and does not validate anything. Doesnt support subpool allocation
|
||||||
|
func (a *allocator) RequestPool(addressSpace, pool, subPool string, options map[string]string, v6 bool) (string, *net.IPNet, map[string]string, error) {
|
||||||
|
log.Debugf("RequestPool(%s, %s, %s, %v, %t)", addressSpace, pool, subPool, options, v6)
|
||||||
|
if subPool != "" || v6 {
|
||||||
|
return "", nil, nil, types.InternalErrorf("This request is not supported by null ipam driver")
|
||||||
|
}
|
||||||
|
|
||||||
|
var ipNet *net.IPNet
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if pool != "" {
|
||||||
|
_, ipNet, err = net.ParseCIDR(pool)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ipNet = defaultPool
|
||||||
|
}
|
||||||
|
|
||||||
|
return ipNet.String(), ipNet, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReleasePool releases the address pool - always succeeds
|
||||||
|
func (a *allocator) ReleasePool(poolID string) error {
|
||||||
|
log.Debugf("ReleasePool(%s)", poolID)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RequestAddress returns an address from the specified pool ID.
|
||||||
|
// Always allocate the 0.0.0.0/32 ip if no preferred address was specified
|
||||||
|
func (a *allocator) RequestAddress(poolID string, prefAddress net.IP, opts map[string]string) (*net.IPNet, map[string]string, error) {
|
||||||
|
log.Debugf("RequestAddress(%s, %v, %v) %s", poolID, prefAddress, opts, opts["RequestAddressType"])
|
||||||
|
_, ipNet, err := net.ParseCIDR(poolID)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if prefAddress == nil {
|
||||||
|
return ipNet, nil, nil
|
||||||
|
}
|
||||||
|
return &net.IPNet{IP: prefAddress, Mask: ipNet.Mask}, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReleaseAddress releases the address - always succeeds
|
||||||
|
func (a *allocator) ReleaseAddress(poolID string, address net.IP) error {
|
||||||
|
log.Debugf("ReleaseAddress(%s, %v)", poolID, address)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DiscoverNew informs the allocator about a new global scope datastore
|
||||||
|
func (a *allocator) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DiscoverDelete is a notification of no interest for the allocator
|
||||||
|
func (a *allocator) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||||
|
return nil
|
||||||
|
}
|
@ -56,6 +56,9 @@ var (
|
|||||||
// GlobalKVProviderConfig constant represents the KV provider Config
|
// GlobalKVProviderConfig constant represents the KV provider Config
|
||||||
GlobalKVProviderConfig = MakeKVProviderConfig("global")
|
GlobalKVProviderConfig = MakeKVProviderConfig("global")
|
||||||
|
|
||||||
|
// GlobalKVClient constants represents the global kv store client
|
||||||
|
GlobalKVClient = MakeKVClient("global")
|
||||||
|
|
||||||
// LocalKVProvider constant represents the KV provider backend
|
// LocalKVProvider constant represents the KV provider backend
|
||||||
LocalKVProvider = MakeKVProvider("local")
|
LocalKVProvider = MakeKVProvider("local")
|
||||||
|
|
||||||
@ -64,6 +67,9 @@ var (
|
|||||||
|
|
||||||
// LocalKVProviderConfig constant represents the KV provider Config
|
// LocalKVProviderConfig constant represents the KV provider Config
|
||||||
LocalKVProviderConfig = MakeKVProviderConfig("local")
|
LocalKVProviderConfig = MakeKVProviderConfig("local")
|
||||||
|
|
||||||
|
// LocalKVClient constants represents the local kv store client
|
||||||
|
LocalKVClient = MakeKVClient("local")
|
||||||
)
|
)
|
||||||
|
|
||||||
// MakeKVProvider returns the kvprovider label for the scope
|
// MakeKVProvider returns the kvprovider label for the scope
|
||||||
@ -81,6 +87,11 @@ func MakeKVProviderConfig(scope string) string {
|
|||||||
return DriverPrivatePrefix + scope + "kv_provider_config"
|
return DriverPrivatePrefix + scope + "kv_provider_config"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MakeKVClient returns the kv client label for the scope
|
||||||
|
func MakeKVClient(scope string) string {
|
||||||
|
return DriverPrivatePrefix + scope + "kv_client"
|
||||||
|
}
|
||||||
|
|
||||||
// Key extracts the key portion of the label
|
// Key extracts the key portion of the label
|
||||||
func Key(label string) (key string) {
|
func Key(label string) (key string) {
|
||||||
if kv := strings.SplitN(label, "=", 2); len(kv) > 0 {
|
if kv := strings.SplitN(label, "=", 2); len(kv) > 0 {
|
||||||
|
@ -1004,7 +1004,7 @@ func (n *network) ipamAllocateVersion(ipVer int, ipam ipamapi.Ipam) error {
|
|||||||
if ipVer == 6 {
|
if ipVer == 6 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
*cfgList = []*IpamConf{&IpamConf{}}
|
*cfgList = []*IpamConf{{}}
|
||||||
}
|
}
|
||||||
|
|
||||||
*infoList = make([]*IpamInfo, len(*cfgList))
|
*infoList = make([]*IpamInfo, len(*cfgList))
|
||||||
|
@ -85,7 +85,7 @@ func handleStopSignals(p proxy.Proxy) {
|
|||||||
s := make(chan os.Signal, 10)
|
s := make(chan os.Signal, 10)
|
||||||
signal.Notify(s, os.Interrupt, syscall.SIGTERM, syscall.SIGSTOP)
|
signal.Notify(s, os.Interrupt, syscall.SIGTERM, syscall.SIGSTOP)
|
||||||
|
|
||||||
for _ = range s {
|
for range s {
|
||||||
p.Close()
|
p.Close()
|
||||||
|
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
|
@ -35,7 +35,7 @@ const (
|
|||||||
dnsPort = "53"
|
dnsPort = "53"
|
||||||
ptrIPv4domain = ".in-addr.arpa."
|
ptrIPv4domain = ".in-addr.arpa."
|
||||||
ptrIPv6domain = ".ip6.arpa."
|
ptrIPv6domain = ".ip6.arpa."
|
||||||
respTTL = 1800
|
respTTL = 600
|
||||||
maxExtDNS = 3 //max number of external servers to try
|
maxExtDNS = 3 //max number of external servers to try
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -147,6 +147,10 @@ func (r *resolver) ResolverOptions() []string {
|
|||||||
return []string{"ndots:0"}
|
return []string{"ndots:0"}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setCommonFlags(msg *dns.Msg) {
|
||||||
|
msg.RecursionAvailable = true
|
||||||
|
}
|
||||||
|
|
||||||
func (r *resolver) handleIPv4Query(name string, query *dns.Msg) (*dns.Msg, error) {
|
func (r *resolver) handleIPv4Query(name string, query *dns.Msg) (*dns.Msg, error) {
|
||||||
addr := r.sb.ResolveName(name)
|
addr := r.sb.ResolveName(name)
|
||||||
if addr == nil {
|
if addr == nil {
|
||||||
@ -157,6 +161,7 @@ func (r *resolver) handleIPv4Query(name string, query *dns.Msg) (*dns.Msg, error
|
|||||||
|
|
||||||
resp := new(dns.Msg)
|
resp := new(dns.Msg)
|
||||||
resp.SetReply(query)
|
resp.SetReply(query)
|
||||||
|
setCommonFlags(resp)
|
||||||
|
|
||||||
rr := new(dns.A)
|
rr := new(dns.A)
|
||||||
rr.Hdr = dns.RR_Header{Name: name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: respTTL}
|
rr.Hdr = dns.RR_Header{Name: name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: respTTL}
|
||||||
@ -186,6 +191,7 @@ func (r *resolver) handlePTRQuery(ptr string, query *dns.Msg) (*dns.Msg, error)
|
|||||||
|
|
||||||
resp := new(dns.Msg)
|
resp := new(dns.Msg)
|
||||||
resp.SetReply(query)
|
resp.SetReply(query)
|
||||||
|
setCommonFlags(resp)
|
||||||
|
|
||||||
rr := new(dns.PTR)
|
rr := new(dns.PTR)
|
||||||
rr.Hdr = dns.RR_Header{Name: ptr, Rrtype: dns.TypePTR, Class: dns.ClassINET, Ttl: respTTL}
|
rr.Hdr = dns.RR_Header{Name: ptr, Rrtype: dns.TypePTR, Class: dns.ClassINET, Ttl: respTTL}
|
||||||
@ -200,6 +206,9 @@ func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) {
|
|||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if query == nil || len(query.Question) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
name := query.Question[0].Name
|
name := query.Question[0].Name
|
||||||
if query.Question[0].Qtype == dns.TypeA {
|
if query.Question[0].Qtype == dns.TypeA {
|
||||||
resp, err = r.handleIPv4Query(name, query)
|
resp, err = r.handleIPv4Query(name, query)
|
||||||
|
312
vendor/src/github.com/docker/libnetwork/sandbox.go
vendored
312
vendor/src/github.com/docker/libnetwork/sandbox.go
vendored
@ -4,19 +4,13 @@ import (
|
|||||||
"container/heap"
|
"container/heap"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
"net"
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
log "github.com/Sirupsen/logrus"
|
log "github.com/Sirupsen/logrus"
|
||||||
"github.com/docker/libnetwork/etchosts"
|
"github.com/docker/libnetwork/etchosts"
|
||||||
"github.com/docker/libnetwork/netutils"
|
|
||||||
"github.com/docker/libnetwork/osl"
|
"github.com/docker/libnetwork/osl"
|
||||||
"github.com/docker/libnetwork/resolvconf"
|
|
||||||
"github.com/docker/libnetwork/types"
|
"github.com/docker/libnetwork/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -309,46 +303,6 @@ func (sb *sandbox) UnmarshalJSON(b []byte) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sb *sandbox) startResolver() {
|
|
||||||
sb.resolverOnce.Do(func() {
|
|
||||||
var err error
|
|
||||||
sb.resolver = NewResolver(sb)
|
|
||||||
defer func() {
|
|
||||||
if err != nil {
|
|
||||||
sb.resolver = nil
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
err = sb.rebuildDNS()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Updating resolv.conf failed for container %s, %q", sb.ContainerID(), err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sb.resolver.SetExtServers(sb.extDNS)
|
|
||||||
|
|
||||||
sb.osSbox.InvokeFunc(sb.resolver.SetupFunc())
|
|
||||||
if err = sb.resolver.Start(); err != nil {
|
|
||||||
log.Errorf("Resolver Setup/Start failed for container %s, %q", sb.ContainerID(), err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sb *sandbox) setupResolutionFiles() error {
|
|
||||||
if err := sb.buildHostsFile(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := sb.updateParentHosts(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := sb.setupDNS(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sb *sandbox) Endpoints() []Endpoint {
|
func (sb *sandbox) Endpoints() []Endpoint {
|
||||||
sb.Lock()
|
sb.Lock()
|
||||||
defer sb.Unlock()
|
defer sb.Unlock()
|
||||||
@ -753,243 +707,6 @@ func (sb *sandbox) clearNetworkResources(origEp *endpoint) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
defaultPrefix = "/var/lib/docker/network/files"
|
|
||||||
dirPerm = 0755
|
|
||||||
filePerm = 0644
|
|
||||||
)
|
|
||||||
|
|
||||||
func (sb *sandbox) buildHostsFile() error {
|
|
||||||
if sb.config.hostsPath == "" {
|
|
||||||
sb.config.hostsPath = defaultPrefix + "/" + sb.id + "/hosts"
|
|
||||||
}
|
|
||||||
|
|
||||||
dir, _ := filepath.Split(sb.config.hostsPath)
|
|
||||||
if err := createBasePath(dir); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is for the host mode networking
|
|
||||||
if sb.config.originHostsPath != "" {
|
|
||||||
if err := copyFile(sb.config.originHostsPath, sb.config.hostsPath); err != nil && !os.IsNotExist(err) {
|
|
||||||
return types.InternalErrorf("could not copy source hosts file %s to %s: %v", sb.config.originHostsPath, sb.config.hostsPath, err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
extraContent := make([]etchosts.Record, 0, len(sb.config.extraHosts))
|
|
||||||
for _, extraHost := range sb.config.extraHosts {
|
|
||||||
extraContent = append(extraContent, etchosts.Record{Hosts: extraHost.name, IP: extraHost.IP})
|
|
||||||
}
|
|
||||||
|
|
||||||
return etchosts.Build(sb.config.hostsPath, "", sb.config.hostName, sb.config.domainName, extraContent)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sb *sandbox) updateHostsFile(ifaceIP string) error {
|
|
||||||
var mhost string
|
|
||||||
|
|
||||||
if sb.config.originHostsPath != "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if sb.config.domainName != "" {
|
|
||||||
mhost = fmt.Sprintf("%s.%s %s", sb.config.hostName, sb.config.domainName,
|
|
||||||
sb.config.hostName)
|
|
||||||
} else {
|
|
||||||
mhost = sb.config.hostName
|
|
||||||
}
|
|
||||||
|
|
||||||
extraContent := []etchosts.Record{{Hosts: mhost, IP: ifaceIP}}
|
|
||||||
|
|
||||||
sb.addHostsEntries(extraContent)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sb *sandbox) addHostsEntries(recs []etchosts.Record) {
|
|
||||||
if err := etchosts.Add(sb.config.hostsPath, recs); err != nil {
|
|
||||||
log.Warnf("Failed adding service host entries to the running container: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sb *sandbox) deleteHostsEntries(recs []etchosts.Record) {
|
|
||||||
if err := etchosts.Delete(sb.config.hostsPath, recs); err != nil {
|
|
||||||
log.Warnf("Failed deleting service host entries to the running container: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sb *sandbox) updateParentHosts() error {
|
|
||||||
var pSb Sandbox
|
|
||||||
|
|
||||||
for _, update := range sb.config.parentUpdates {
|
|
||||||
sb.controller.WalkSandboxes(SandboxContainerWalker(&pSb, update.cid))
|
|
||||||
if pSb == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err := etchosts.Update(pSb.(*sandbox).config.hostsPath, update.ip, update.name); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sb *sandbox) setupDNS() error {
|
|
||||||
var newRC *resolvconf.File
|
|
||||||
|
|
||||||
if sb.config.resolvConfPath == "" {
|
|
||||||
sb.config.resolvConfPath = defaultPrefix + "/" + sb.id + "/resolv.conf"
|
|
||||||
}
|
|
||||||
|
|
||||||
sb.config.resolvConfHashFile = sb.config.resolvConfPath + ".hash"
|
|
||||||
|
|
||||||
dir, _ := filepath.Split(sb.config.resolvConfPath)
|
|
||||||
if err := createBasePath(dir); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is for the host mode networking
|
|
||||||
if sb.config.originResolvConfPath != "" {
|
|
||||||
if err := copyFile(sb.config.originResolvConfPath, sb.config.resolvConfPath); err != nil {
|
|
||||||
return fmt.Errorf("could not copy source resolv.conf file %s to %s: %v", sb.config.originResolvConfPath, sb.config.resolvConfPath, err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
currRC, err := resolvconf.Get()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(sb.config.dnsList) > 0 || len(sb.config.dnsSearchList) > 0 || len(sb.config.dnsOptionsList) > 0 {
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
dnsList = resolvconf.GetNameservers(currRC.Content, netutils.IP)
|
|
||||||
dnsSearchList = resolvconf.GetSearchDomains(currRC.Content)
|
|
||||||
dnsOptionsList = resolvconf.GetOptions(currRC.Content)
|
|
||||||
)
|
|
||||||
if len(sb.config.dnsList) > 0 {
|
|
||||||
dnsList = sb.config.dnsList
|
|
||||||
}
|
|
||||||
if len(sb.config.dnsSearchList) > 0 {
|
|
||||||
dnsSearchList = sb.config.dnsSearchList
|
|
||||||
}
|
|
||||||
if len(sb.config.dnsOptionsList) > 0 {
|
|
||||||
dnsOptionsList = sb.config.dnsOptionsList
|
|
||||||
}
|
|
||||||
newRC, err = resolvconf.Build(sb.config.resolvConfPath, dnsList, dnsSearchList, dnsOptionsList)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Replace any localhost/127.* (at this point we have no info about ipv6, pass it as true)
|
|
||||||
if newRC, err = resolvconf.FilterResolvDNS(currRC.Content, true); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// No contention on container resolv.conf file at sandbox creation
|
|
||||||
if err := ioutil.WriteFile(sb.config.resolvConfPath, newRC.Content, filePerm); err != nil {
|
|
||||||
return types.InternalErrorf("failed to write unhaltered resolv.conf file content when setting up dns for sandbox %s: %v", sb.ID(), err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write hash
|
|
||||||
if err := ioutil.WriteFile(sb.config.resolvConfHashFile, []byte(newRC.Hash), filePerm); err != nil {
|
|
||||||
return types.InternalErrorf("failed to write resolv.conf hash file when setting up dns for sandbox %s: %v", sb.ID(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sb *sandbox) updateDNS(ipv6Enabled bool) error {
|
|
||||||
var (
|
|
||||||
currHash string
|
|
||||||
hashFile = sb.config.resolvConfHashFile
|
|
||||||
)
|
|
||||||
|
|
||||||
// This is for the host mode networking
|
|
||||||
if sb.config.originResolvConfPath != "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(sb.config.dnsList) > 0 || len(sb.config.dnsSearchList) > 0 || len(sb.config.dnsOptionsList) > 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
currRC, err := resolvconf.GetSpecific(sb.config.resolvConfPath)
|
|
||||||
if err != nil {
|
|
||||||
if !os.IsNotExist(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
h, err := ioutil.ReadFile(hashFile)
|
|
||||||
if err != nil {
|
|
||||||
if !os.IsNotExist(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
currHash = string(h)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if currHash != "" && currHash != currRC.Hash {
|
|
||||||
// Seems the user has changed the container resolv.conf since the last time
|
|
||||||
// we checked so return without doing anything.
|
|
||||||
log.Infof("Skipping update of resolv.conf file with ipv6Enabled: %t because file was touched by user", ipv6Enabled)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// replace any localhost/127.* and remove IPv6 nameservers if IPv6 disabled.
|
|
||||||
newRC, err := resolvconf.FilterResolvDNS(currRC.Content, ipv6Enabled)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = ioutil.WriteFile(sb.config.resolvConfPath, newRC.Content, 0644)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// write the new hash in a temp file and rename it to make the update atomic
|
|
||||||
dir := path.Dir(sb.config.resolvConfPath)
|
|
||||||
tmpHashFile, err := ioutil.TempFile(dir, "hash")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err = ioutil.WriteFile(tmpHashFile.Name(), []byte(newRC.Hash), filePerm); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return os.Rename(tmpHashFile.Name(), hashFile)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Embedded DNS server has to be enabled for this sandbox. Rebuild the container's
|
|
||||||
// resolv.conf by doing the follwing
|
|
||||||
// - Save the external name servers in resolv.conf in the sandbox
|
|
||||||
// - Add only the embedded server's IP to container's resolv.conf
|
|
||||||
// - If the embedded server needs any resolv.conf options add it to the current list
|
|
||||||
func (sb *sandbox) rebuildDNS() error {
|
|
||||||
currRC, err := resolvconf.GetSpecific(sb.config.resolvConfPath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// localhost entries have already been filtered out from the list
|
|
||||||
// retain only the v4 servers in sb for forwarding the DNS queries
|
|
||||||
sb.extDNS = resolvconf.GetNameservers(currRC.Content, netutils.IPv4)
|
|
||||||
|
|
||||||
var (
|
|
||||||
dnsList = []string{sb.resolver.NameServer()}
|
|
||||||
dnsOptionsList = resolvconf.GetOptions(currRC.Content)
|
|
||||||
dnsSearchList = resolvconf.GetSearchDomains(currRC.Content)
|
|
||||||
)
|
|
||||||
|
|
||||||
// external v6 DNS servers has to be listed in resolv.conf
|
|
||||||
dnsList = append(dnsList, resolvconf.GetNameservers(currRC.Content, netutils.IPv6)...)
|
|
||||||
|
|
||||||
// Resolver returns the options in the format resolv.conf expects
|
|
||||||
dnsOptionsList = append(dnsOptionsList, sb.resolver.ResolverOptions()...)
|
|
||||||
|
|
||||||
_, err = resolvconf.Build(sb.config.resolvConfPath, dnsList, dnsSearchList, dnsOptionsList)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// joinLeaveStart waits to ensure there are no joins or leaves in progress and
|
// joinLeaveStart waits to ensure there are no joins or leaves in progress and
|
||||||
// marks this join/leave in progress without race
|
// marks this join/leave in progress without race
|
||||||
func (sb *sandbox) joinLeaveStart() {
|
func (sb *sandbox) joinLeaveStart() {
|
||||||
@ -1191,32 +908,3 @@ func (eh *epHeap) Pop() interface{} {
|
|||||||
*eh = old[0 : n-1]
|
*eh = old[0 : n-1]
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
func createBasePath(dir string) error {
|
|
||||||
return os.MkdirAll(dir, dirPerm)
|
|
||||||
}
|
|
||||||
|
|
||||||
func createFile(path string) error {
|
|
||||||
var f *os.File
|
|
||||||
|
|
||||||
dir, _ := filepath.Split(path)
|
|
||||||
err := createBasePath(dir)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err = os.Create(path)
|
|
||||||
if err == nil {
|
|
||||||
f.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func copyFile(src, dst string) error {
|
|
||||||
sBytes, err := ioutil.ReadFile(src)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return ioutil.WriteFile(dst, sBytes, filePerm)
|
|
||||||
}
|
|
||||||
|
323
vendor/src/github.com/docker/libnetwork/sandbox_dns_unix.go
vendored
Normal file
323
vendor/src/github.com/docker/libnetwork/sandbox_dns_unix.go
vendored
Normal file
@ -0,0 +1,323 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package libnetwork
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
log "github.com/Sirupsen/logrus"
|
||||||
|
"github.com/docker/libnetwork/etchosts"
|
||||||
|
"github.com/docker/libnetwork/netutils"
|
||||||
|
"github.com/docker/libnetwork/resolvconf"
|
||||||
|
"github.com/docker/libnetwork/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultPrefix = "/var/lib/docker/network/files"
|
||||||
|
dirPerm = 0755
|
||||||
|
filePerm = 0644
|
||||||
|
)
|
||||||
|
|
||||||
|
func (sb *sandbox) startResolver() {
|
||||||
|
sb.resolverOnce.Do(func() {
|
||||||
|
var err error
|
||||||
|
sb.resolver = NewResolver(sb)
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
sb.resolver = nil
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
err = sb.rebuildDNS()
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Updating resolv.conf failed for container %s, %q", sb.ContainerID(), err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sb.resolver.SetExtServers(sb.extDNS)
|
||||||
|
|
||||||
|
sb.osSbox.InvokeFunc(sb.resolver.SetupFunc())
|
||||||
|
if err = sb.resolver.Start(); err != nil {
|
||||||
|
log.Errorf("Resolver Setup/Start failed for container %s, %q", sb.ContainerID(), err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sb *sandbox) setupResolutionFiles() error {
|
||||||
|
if err := sb.buildHostsFile(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := sb.updateParentHosts(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := sb.setupDNS(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sb *sandbox) buildHostsFile() error {
|
||||||
|
if sb.config.hostsPath == "" {
|
||||||
|
sb.config.hostsPath = defaultPrefix + "/" + sb.id + "/hosts"
|
||||||
|
}
|
||||||
|
|
||||||
|
dir, _ := filepath.Split(sb.config.hostsPath)
|
||||||
|
if err := createBasePath(dir); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is for the host mode networking
|
||||||
|
if sb.config.originHostsPath != "" {
|
||||||
|
if err := copyFile(sb.config.originHostsPath, sb.config.hostsPath); err != nil && !os.IsNotExist(err) {
|
||||||
|
return types.InternalErrorf("could not copy source hosts file %s to %s: %v", sb.config.originHostsPath, sb.config.hostsPath, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
extraContent := make([]etchosts.Record, 0, len(sb.config.extraHosts))
|
||||||
|
for _, extraHost := range sb.config.extraHosts {
|
||||||
|
extraContent = append(extraContent, etchosts.Record{Hosts: extraHost.name, IP: extraHost.IP})
|
||||||
|
}
|
||||||
|
|
||||||
|
return etchosts.Build(sb.config.hostsPath, "", sb.config.hostName, sb.config.domainName, extraContent)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sb *sandbox) updateHostsFile(ifaceIP string) error {
|
||||||
|
var mhost string
|
||||||
|
|
||||||
|
if sb.config.originHostsPath != "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if sb.config.domainName != "" {
|
||||||
|
mhost = fmt.Sprintf("%s.%s %s", sb.config.hostName, sb.config.domainName,
|
||||||
|
sb.config.hostName)
|
||||||
|
} else {
|
||||||
|
mhost = sb.config.hostName
|
||||||
|
}
|
||||||
|
|
||||||
|
extraContent := []etchosts.Record{{Hosts: mhost, IP: ifaceIP}}
|
||||||
|
|
||||||
|
sb.addHostsEntries(extraContent)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sb *sandbox) addHostsEntries(recs []etchosts.Record) {
|
||||||
|
if err := etchosts.Add(sb.config.hostsPath, recs); err != nil {
|
||||||
|
log.Warnf("Failed adding service host entries to the running container: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sb *sandbox) deleteHostsEntries(recs []etchosts.Record) {
|
||||||
|
if err := etchosts.Delete(sb.config.hostsPath, recs); err != nil {
|
||||||
|
log.Warnf("Failed deleting service host entries to the running container: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sb *sandbox) updateParentHosts() error {
|
||||||
|
var pSb Sandbox
|
||||||
|
|
||||||
|
for _, update := range sb.config.parentUpdates {
|
||||||
|
sb.controller.WalkSandboxes(SandboxContainerWalker(&pSb, update.cid))
|
||||||
|
if pSb == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err := etchosts.Update(pSb.(*sandbox).config.hostsPath, update.ip, update.name); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sb *sandbox) setupDNS() error {
|
||||||
|
var newRC *resolvconf.File
|
||||||
|
|
||||||
|
if sb.config.resolvConfPath == "" {
|
||||||
|
sb.config.resolvConfPath = defaultPrefix + "/" + sb.id + "/resolv.conf"
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.config.resolvConfHashFile = sb.config.resolvConfPath + ".hash"
|
||||||
|
|
||||||
|
dir, _ := filepath.Split(sb.config.resolvConfPath)
|
||||||
|
if err := createBasePath(dir); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is for the host mode networking
|
||||||
|
if sb.config.originResolvConfPath != "" {
|
||||||
|
if err := copyFile(sb.config.originResolvConfPath, sb.config.resolvConfPath); err != nil {
|
||||||
|
return fmt.Errorf("could not copy source resolv.conf file %s to %s: %v", sb.config.originResolvConfPath, sb.config.resolvConfPath, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
currRC, err := resolvconf.Get()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(sb.config.dnsList) > 0 || len(sb.config.dnsSearchList) > 0 || len(sb.config.dnsOptionsList) > 0 {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
dnsList = resolvconf.GetNameservers(currRC.Content, netutils.IP)
|
||||||
|
dnsSearchList = resolvconf.GetSearchDomains(currRC.Content)
|
||||||
|
dnsOptionsList = resolvconf.GetOptions(currRC.Content)
|
||||||
|
)
|
||||||
|
if len(sb.config.dnsList) > 0 {
|
||||||
|
dnsList = sb.config.dnsList
|
||||||
|
}
|
||||||
|
if len(sb.config.dnsSearchList) > 0 {
|
||||||
|
dnsSearchList = sb.config.dnsSearchList
|
||||||
|
}
|
||||||
|
if len(sb.config.dnsOptionsList) > 0 {
|
||||||
|
dnsOptionsList = sb.config.dnsOptionsList
|
||||||
|
}
|
||||||
|
newRC, err = resolvconf.Build(sb.config.resolvConfPath, dnsList, dnsSearchList, dnsOptionsList)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Replace any localhost/127.* (at this point we have no info about ipv6, pass it as true)
|
||||||
|
if newRC, err = resolvconf.FilterResolvDNS(currRC.Content, true); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// No contention on container resolv.conf file at sandbox creation
|
||||||
|
if err := ioutil.WriteFile(sb.config.resolvConfPath, newRC.Content, filePerm); err != nil {
|
||||||
|
return types.InternalErrorf("failed to write unhaltered resolv.conf file content when setting up dns for sandbox %s: %v", sb.ID(), err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write hash
|
||||||
|
if err := ioutil.WriteFile(sb.config.resolvConfHashFile, []byte(newRC.Hash), filePerm); err != nil {
|
||||||
|
return types.InternalErrorf("failed to write resolv.conf hash file when setting up dns for sandbox %s: %v", sb.ID(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sb *sandbox) updateDNS(ipv6Enabled bool) error {
|
||||||
|
var (
|
||||||
|
currHash string
|
||||||
|
hashFile = sb.config.resolvConfHashFile
|
||||||
|
)
|
||||||
|
|
||||||
|
// This is for the host mode networking
|
||||||
|
if sb.config.originResolvConfPath != "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(sb.config.dnsList) > 0 || len(sb.config.dnsSearchList) > 0 || len(sb.config.dnsOptionsList) > 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
currRC, err := resolvconf.GetSpecific(sb.config.resolvConfPath)
|
||||||
|
if err != nil {
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
h, err := ioutil.ReadFile(hashFile)
|
||||||
|
if err != nil {
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
currHash = string(h)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if currHash != "" && currHash != currRC.Hash {
|
||||||
|
// Seems the user has changed the container resolv.conf since the last time
|
||||||
|
// we checked so return without doing anything.
|
||||||
|
log.Infof("Skipping update of resolv.conf file with ipv6Enabled: %t because file was touched by user", ipv6Enabled)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// replace any localhost/127.* and remove IPv6 nameservers if IPv6 disabled.
|
||||||
|
newRC, err := resolvconf.FilterResolvDNS(currRC.Content, ipv6Enabled)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ioutil.WriteFile(sb.config.resolvConfPath, newRC.Content, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// write the new hash in a temp file and rename it to make the update atomic
|
||||||
|
dir := path.Dir(sb.config.resolvConfPath)
|
||||||
|
tmpHashFile, err := ioutil.TempFile(dir, "hash")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err = ioutil.WriteFile(tmpHashFile.Name(), []byte(newRC.Hash), filePerm); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return os.Rename(tmpHashFile.Name(), hashFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Embedded DNS server has to be enabled for this sandbox. Rebuild the container's
|
||||||
|
// resolv.conf by doing the follwing
|
||||||
|
// - Save the external name servers in resolv.conf in the sandbox
|
||||||
|
// - Add only the embedded server's IP to container's resolv.conf
|
||||||
|
// - If the embedded server needs any resolv.conf options add it to the current list
|
||||||
|
func (sb *sandbox) rebuildDNS() error {
|
||||||
|
currRC, err := resolvconf.GetSpecific(sb.config.resolvConfPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// localhost entries have already been filtered out from the list
|
||||||
|
// retain only the v4 servers in sb for forwarding the DNS queries
|
||||||
|
sb.extDNS = resolvconf.GetNameservers(currRC.Content, netutils.IPv4)
|
||||||
|
|
||||||
|
var (
|
||||||
|
dnsList = []string{sb.resolver.NameServer()}
|
||||||
|
dnsOptionsList = resolvconf.GetOptions(currRC.Content)
|
||||||
|
dnsSearchList = resolvconf.GetSearchDomains(currRC.Content)
|
||||||
|
)
|
||||||
|
|
||||||
|
// external v6 DNS servers has to be listed in resolv.conf
|
||||||
|
dnsList = append(dnsList, resolvconf.GetNameservers(currRC.Content, netutils.IPv6)...)
|
||||||
|
|
||||||
|
// Resolver returns the options in the format resolv.conf expects
|
||||||
|
dnsOptionsList = append(dnsOptionsList, sb.resolver.ResolverOptions()...)
|
||||||
|
|
||||||
|
_, err = resolvconf.Build(sb.config.resolvConfPath, dnsList, dnsSearchList, dnsOptionsList)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func createBasePath(dir string) error {
|
||||||
|
return os.MkdirAll(dir, dirPerm)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createFile(path string) error {
|
||||||
|
var f *os.File
|
||||||
|
|
||||||
|
dir, _ := filepath.Split(path)
|
||||||
|
err := createBasePath(dir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err = os.Create(path)
|
||||||
|
if err == nil {
|
||||||
|
f.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyFile(src, dst string) error {
|
||||||
|
sBytes, err := ioutil.ReadFile(src)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return ioutil.WriteFile(dst, sBytes, filePerm)
|
||||||
|
}
|
32
vendor/src/github.com/docker/libnetwork/sandbox_dns_windows.go
vendored
Normal file
32
vendor/src/github.com/docker/libnetwork/sandbox_dns_windows.go
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
package libnetwork
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/docker/libnetwork/etchosts"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Stub implementations for DNS related functions
|
||||||
|
|
||||||
|
func (sb *sandbox) startResolver() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sb *sandbox) setupResolutionFiles() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sb *sandbox) updateHostsFile(ifaceIP string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sb *sandbox) addHostsEntries(recs []etchosts.Record) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sb *sandbox) deleteHostsEntries(recs []etchosts.Record) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sb *sandbox) updateDNS(ipv6Enabled bool) error {
|
||||||
|
return nil
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
// +build !windows
|
// +build linux freebsd
|
||||||
|
|
||||||
package libnetwork
|
package libnetwork
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ func (c *controller) initStores() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
scopeConfigs := c.cfg.Scopes
|
scopeConfigs := c.cfg.Scopes
|
||||||
|
c.stores = nil
|
||||||
c.Unlock()
|
c.Unlock()
|
||||||
|
|
||||||
for scope, scfg := range scopeConfigs {
|
for scope, scfg := range scopeConfigs {
|
||||||
@ -418,6 +419,9 @@ func (c *controller) watchLoop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *controller) startWatch() {
|
func (c *controller) startWatch() {
|
||||||
|
if c.watchCh != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
c.watchCh = make(chan *endpoint)
|
c.watchCh = make(chan *endpoint)
|
||||||
c.unWatchCh = make(chan *endpoint)
|
c.unWatchCh = make(chan *endpoint)
|
||||||
c.nmap = make(map[string]*netWatch)
|
c.nmap = make(map[string]*netWatch)
|
||||||
|
Reference in New Issue
Block a user