Signed-off-by: Sandeep Bansal <msabansal@microsoft.com>
| ... | ... |
@@ -23,7 +23,7 @@ github.com/RackSec/srslog 365bf33cd9acc21ae1c355209865f17228ca534e |
| 23 | 23 |
github.com/imdario/mergo 0.2.1 |
| 24 | 24 |
|
| 25 | 25 |
#get libnetwork packages |
| 26 |
-github.com/docker/libnetwork a98901aebe7ce920b6fbf02ebe5c3afc9ca975b8 |
|
| 26 |
+github.com/docker/libnetwork 3ab699ea36573d98f481d233c30c742ade737565 |
|
| 27 | 27 |
github.com/docker/go-events 18b43f1bc85d9cdd42c05a6cd2d444c7a200a894 |
| 28 | 28 |
github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80 |
| 29 | 29 |
github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec |
| ... | ... |
@@ -100,7 +100,7 @@ github.com/docker/containerd 8517738ba4b82aff5662c97ca4627e7e4d03b531 |
| 100 | 100 |
github.com/tonistiigi/fifo 1405643975692217d6720f8b54aeee1bf2cd5cf4 |
| 101 | 101 |
|
| 102 | 102 |
# cluster |
| 103 |
-github.com/docker/swarmkit bddd3f0fb45491987d3dec5fb48311d289d21393 |
|
| 103 |
+github.com/docker/swarmkit ce07d9f69c9b4a1b1eb508e777c44eeacca87065 |
|
| 104 | 104 |
github.com/golang/mock bd3c8e81be01eef76d4b503f5e687d2d1354d2d9 |
| 105 | 105 |
github.com/gogo/protobuf v0.3 |
| 106 | 106 |
github.com/cloudflare/cfssl 7fb22c8cba7ecaf98e4082d22d65800cf45e042a |
| ... | ... |
@@ -9,7 +9,7 @@ import ( |
| 9 | 9 |
"fmt" |
| 10 | 10 |
"sync" |
| 11 | 11 |
|
| 12 |
- log "github.com/Sirupsen/logrus" |
|
| 12 |
+ "github.com/Sirupsen/logrus" |
|
| 13 | 13 |
"github.com/docker/libnetwork/datastore" |
| 14 | 14 |
"github.com/docker/libnetwork/types" |
| 15 | 15 |
) |
| ... | ... |
@@ -286,7 +286,7 @@ func (h *Handle) CheckConsistency() error {
|
| 286 | 286 |
continue |
| 287 | 287 |
} |
| 288 | 288 |
|
| 289 |
- log.Infof("Fixed inconsistent bit sequence in datastore:\n%s\n%s", h, nh)
|
|
| 289 |
+ logrus.Infof("Fixed inconsistent bit sequence in datastore:\n%s\n%s", h, nh)
|
|
| 290 | 290 |
|
| 291 | 291 |
h.Lock() |
| 292 | 292 |
h.head = nh.head |
| ... | ... |
@@ -6,7 +6,7 @@ import ( |
| 6 | 6 |
"strings" |
| 7 | 7 |
|
| 8 | 8 |
"github.com/BurntSushi/toml" |
| 9 |
- log "github.com/Sirupsen/logrus" |
|
| 9 |
+ "github.com/Sirupsen/logrus" |
|
| 10 | 10 |
"github.com/docker/docker/pkg/discovery" |
| 11 | 11 |
"github.com/docker/docker/pkg/plugingetter" |
| 12 | 12 |
"github.com/docker/go-connections/tlsconfig" |
| ... | ... |
@@ -100,7 +100,7 @@ type Option func(c *Config) |
| 100 | 100 |
// OptionDefaultNetwork function returns an option setter for a default network |
| 101 | 101 |
func OptionDefaultNetwork(dn string) Option {
|
| 102 | 102 |
return func(c *Config) {
|
| 103 |
- log.Debugf("Option DefaultNetwork: %s", dn)
|
|
| 103 |
+ logrus.Debugf("Option DefaultNetwork: %s", dn)
|
|
| 104 | 104 |
c.Daemon.DefaultNetwork = strings.TrimSpace(dn) |
| 105 | 105 |
} |
| 106 | 106 |
} |
| ... | ... |
@@ -108,7 +108,7 @@ func OptionDefaultNetwork(dn string) Option {
|
| 108 | 108 |
// OptionDefaultDriver function returns an option setter for default driver |
| 109 | 109 |
func OptionDefaultDriver(dd string) Option {
|
| 110 | 110 |
return func(c *Config) {
|
| 111 |
- log.Debugf("Option DefaultDriver: %s", dd)
|
|
| 111 |
+ logrus.Debugf("Option DefaultDriver: %s", dd)
|
|
| 112 | 112 |
c.Daemon.DefaultDriver = strings.TrimSpace(dd) |
| 113 | 113 |
} |
| 114 | 114 |
} |
| ... | ... |
@@ -134,7 +134,7 @@ func OptionLabels(labels []string) Option {
|
| 134 | 134 |
// OptionKVProvider function returns an option setter for kvstore provider |
| 135 | 135 |
func OptionKVProvider(provider string) Option {
|
| 136 | 136 |
return func(c *Config) {
|
| 137 |
- log.Debugf("Option OptionKVProvider: %s", provider)
|
|
| 137 |
+ logrus.Debugf("Option OptionKVProvider: %s", provider)
|
|
| 138 | 138 |
if _, ok := c.Scopes[datastore.GlobalScope]; !ok {
|
| 139 | 139 |
c.Scopes[datastore.GlobalScope] = &datastore.ScopeCfg{}
|
| 140 | 140 |
} |
| ... | ... |
@@ -145,7 +145,7 @@ func OptionKVProvider(provider string) Option {
|
| 145 | 145 |
// OptionKVProviderURL function returns an option setter for kvstore url |
| 146 | 146 |
func OptionKVProviderURL(url string) Option {
|
| 147 | 147 |
return func(c *Config) {
|
| 148 |
- log.Debugf("Option OptionKVProviderURL: %s", url)
|
|
| 148 |
+ logrus.Debugf("Option OptionKVProviderURL: %s", url)
|
|
| 149 | 149 |
if _, ok := c.Scopes[datastore.GlobalScope]; !ok {
|
| 150 | 150 |
c.Scopes[datastore.GlobalScope] = &datastore.ScopeCfg{}
|
| 151 | 151 |
} |
| ... | ... |
@@ -157,14 +157,14 @@ func OptionKVProviderURL(url string) Option {
|
| 157 | 157 |
func OptionKVOpts(opts map[string]string) Option {
|
| 158 | 158 |
return func(c *Config) {
|
| 159 | 159 |
if opts["kv.cacertfile"] != "" && opts["kv.certfile"] != "" && opts["kv.keyfile"] != "" {
|
| 160 |
- log.Info("Option Initializing KV with TLS")
|
|
| 160 |
+ logrus.Info("Option Initializing KV with TLS")
|
|
| 161 | 161 |
tlsConfig, err := tlsconfig.Client(tlsconfig.Options{
|
| 162 | 162 |
CAFile: opts["kv.cacertfile"], |
| 163 | 163 |
CertFile: opts["kv.certfile"], |
| 164 | 164 |
KeyFile: opts["kv.keyfile"], |
| 165 | 165 |
}) |
| 166 | 166 |
if err != nil {
|
| 167 |
- log.Errorf("Unable to set up TLS: %s", err)
|
|
| 167 |
+ logrus.Errorf("Unable to set up TLS: %s", err)
|
|
| 168 | 168 |
return |
| 169 | 169 |
} |
| 170 | 170 |
if _, ok := c.Scopes[datastore.GlobalScope]; !ok {
|
| ... | ... |
@@ -182,7 +182,7 @@ func OptionKVOpts(opts map[string]string) Option {
|
| 182 | 182 |
KeyFile: opts["kv.keyfile"], |
| 183 | 183 |
} |
| 184 | 184 |
} else {
|
| 185 |
- log.Info("Option Initializing KV without TLS")
|
|
| 185 |
+ logrus.Info("Option Initializing KV without TLS")
|
|
| 186 | 186 |
} |
| 187 | 187 |
} |
| 188 | 188 |
} |
| ... | ... |
@@ -242,7 +242,7 @@ func ValidateName(name string) error {
|
| 242 | 242 |
// OptionLocalKVProvider function returns an option setter for kvstore provider |
| 243 | 243 |
func OptionLocalKVProvider(provider string) Option {
|
| 244 | 244 |
return func(c *Config) {
|
| 245 |
- log.Debugf("Option OptionLocalKVProvider: %s", provider)
|
|
| 245 |
+ logrus.Debugf("Option OptionLocalKVProvider: %s", provider)
|
|
| 246 | 246 |
if _, ok := c.Scopes[datastore.LocalScope]; !ok {
|
| 247 | 247 |
c.Scopes[datastore.LocalScope] = &datastore.ScopeCfg{}
|
| 248 | 248 |
} |
| ... | ... |
@@ -253,7 +253,7 @@ func OptionLocalKVProvider(provider string) Option {
|
| 253 | 253 |
// OptionLocalKVProviderURL function returns an option setter for kvstore url |
| 254 | 254 |
func OptionLocalKVProviderURL(url string) Option {
|
| 255 | 255 |
return func(c *Config) {
|
| 256 |
- log.Debugf("Option OptionLocalKVProviderURL: %s", url)
|
|
| 256 |
+ logrus.Debugf("Option OptionLocalKVProviderURL: %s", url)
|
|
| 257 | 257 |
if _, ok := c.Scopes[datastore.LocalScope]; !ok {
|
| 258 | 258 |
c.Scopes[datastore.LocalScope] = &datastore.ScopeCfg{}
|
| 259 | 259 |
} |
| ... | ... |
@@ -264,7 +264,7 @@ func OptionLocalKVProviderURL(url string) Option {
|
| 264 | 264 |
// OptionLocalKVProviderConfig function returns an option setter for kvstore config |
| 265 | 265 |
func OptionLocalKVProviderConfig(config *store.Config) Option {
|
| 266 | 266 |
return func(c *Config) {
|
| 267 |
- log.Debugf("Option OptionLocalKVProviderConfig: %v", config)
|
|
| 267 |
+ logrus.Debugf("Option OptionLocalKVProviderConfig: %v", config)
|
|
| 268 | 268 |
if _, ok := c.Scopes[datastore.LocalScope]; !ok {
|
| 269 | 269 |
c.Scopes[datastore.LocalScope] = &datastore.ScopeCfg{}
|
| 270 | 270 |
} |
| ... | ... |
@@ -51,7 +51,7 @@ import ( |
| 51 | 51 |
"sync" |
| 52 | 52 |
"time" |
| 53 | 53 |
|
| 54 |
- log "github.com/Sirupsen/logrus" |
|
| 54 |
+ "github.com/Sirupsen/logrus" |
|
| 55 | 55 |
"github.com/docker/docker/pkg/discovery" |
| 56 | 56 |
"github.com/docker/docker/pkg/locker" |
| 57 | 57 |
"github.com/docker/docker/pkg/plugingetter" |
| ... | ... |
@@ -212,7 +212,7 @@ func New(cfgOptions ...config.Option) (NetworkController, error) {
|
| 212 | 212 |
if err := c.initDiscovery(c.cfg.Cluster.Watcher); err != nil {
|
| 213 | 213 |
// Failing to initialize discovery is a bad situation to be in. |
| 214 | 214 |
// But it cannot fail creating the Controller |
| 215 |
- log.Errorf("Failed to Initialize Discovery : %v", err)
|
|
| 215 |
+ logrus.Errorf("Failed to Initialize Discovery : %v", err)
|
|
| 216 | 216 |
} |
| 217 | 217 |
} |
| 218 | 218 |
|
| ... | ... |
@@ -283,7 +283,7 @@ func (c *controller) SetKeys(keys []*types.EncryptionKey) error {
|
| 283 | 283 |
if clusterConfigAvailable {
|
| 284 | 284 |
return c.agentSetup() |
| 285 | 285 |
} |
| 286 |
- log.Debugf("received encryption keys before cluster config")
|
|
| 286 |
+ logrus.Debug("received encryption keys before cluster config")
|
|
| 287 | 287 |
return nil |
| 288 | 288 |
} |
| 289 | 289 |
if agent == nil {
|
| ... | ... |
@@ -441,7 +441,7 @@ func (c *controller) ReloadConfiguration(cfgOptions ...config.Option) error {
|
| 441 | 441 |
c.drvRegistry.WalkIPAMs(func(name string, driver ipamapi.Ipam, cap *ipamapi.Capability) bool {
|
| 442 | 442 |
err := driver.DiscoverNew(discoverapi.DatastoreConfig, *dsConfig) |
| 443 | 443 |
if err != nil {
|
| 444 |
- log.Errorf("Failed to set datastore in driver %s: %v", name, err)
|
|
| 444 |
+ logrus.Errorf("Failed to set datastore in driver %s: %v", name, err)
|
|
| 445 | 445 |
} |
| 446 | 446 |
return false |
| 447 | 447 |
}) |
| ... | ... |
@@ -449,14 +449,14 @@ func (c *controller) ReloadConfiguration(cfgOptions ...config.Option) error {
|
| 449 | 449 |
c.drvRegistry.WalkDrivers(func(name string, driver driverapi.Driver, capability driverapi.Capability) bool {
|
| 450 | 450 |
err := driver.DiscoverNew(discoverapi.DatastoreConfig, *dsConfig) |
| 451 | 451 |
if err != nil {
|
| 452 |
- log.Errorf("Failed to set datastore in driver %s: %v", name, err)
|
|
| 452 |
+ logrus.Errorf("Failed to set datastore in driver %s: %v", name, err)
|
|
| 453 | 453 |
} |
| 454 | 454 |
return false |
| 455 | 455 |
}) |
| 456 | 456 |
|
| 457 | 457 |
if c.discovery == nil && c.cfg.Cluster.Watcher != nil {
|
| 458 | 458 |
if err := c.initDiscovery(c.cfg.Cluster.Watcher); err != nil {
|
| 459 |
- log.Errorf("Failed to Initialize Discovery after configuration update: %v", err)
|
|
| 459 |
+ logrus.Errorf("Failed to Initialize Discovery after configuration update: %v", err)
|
|
| 460 | 460 |
} |
| 461 | 461 |
} |
| 462 | 462 |
|
| ... | ... |
@@ -561,7 +561,7 @@ func (c *controller) pushNodeDiscovery(d driverapi.Driver, cap driverapi.Capabil |
| 561 | 561 |
err = d.DiscoverDelete(discoverapi.NodeDiscovery, nodeData) |
| 562 | 562 |
} |
| 563 | 563 |
if err != nil {
|
| 564 |
- log.Debugf("discovery notification error : %v", err)
|
|
| 564 |
+ logrus.Debugf("discovery notification error : %v", err)
|
|
| 565 | 565 |
} |
| 566 | 566 |
} |
| 567 | 567 |
} |
| ... | ... |
@@ -634,12 +634,13 @@ func (c *controller) NewNetwork(networkType, name string, id string, options ... |
| 634 | 634 |
id = stringid.GenerateRandomID() |
| 635 | 635 |
} |
| 636 | 636 |
|
| 637 |
+ defaultIpam := defaultIpamForNetworkType(networkType) |
|
| 637 | 638 |
// Construct the network object |
| 638 | 639 |
network := &network{
|
| 639 | 640 |
name: name, |
| 640 | 641 |
networkType: networkType, |
| 641 | 642 |
generic: map[string]interface{}{netlabel.GenericData: make(map[string]string)},
|
| 642 |
- ipamType: ipamapi.DefaultIPAM, |
|
| 643 |
+ ipamType: defaultIpam, |
|
| 643 | 644 |
id: id, |
| 644 | 645 |
created: time.Now(), |
| 645 | 646 |
ctrlr: c, |
| ... | ... |
@@ -686,7 +687,7 @@ func (c *controller) NewNetwork(networkType, name string, id string, options ... |
| 686 | 686 |
defer func() {
|
| 687 | 687 |
if err != nil {
|
| 688 | 688 |
if e := network.deleteNetwork(); e != nil {
|
| 689 |
- log.Warnf("couldn't roll back driver network on network %s creation failure: %v", network.name, err)
|
|
| 689 |
+ logrus.Warnf("couldn't roll back driver network on network %s creation failure: %v", network.name, err)
|
|
| 690 | 690 |
} |
| 691 | 691 |
} |
| 692 | 692 |
}() |
| ... | ... |
@@ -701,7 +702,7 @@ func (c *controller) NewNetwork(networkType, name string, id string, options ... |
| 701 | 701 |
defer func() {
|
| 702 | 702 |
if err != nil {
|
| 703 | 703 |
if e := c.deleteFromStore(epCnt); e != nil {
|
| 704 |
- log.Warnf("couldnt rollback from store, epCnt %v on failure (%v): %v", epCnt, err, e)
|
|
| 704 |
+ logrus.Warnf("could not rollback from store, epCnt %v on failure (%v): %v", epCnt, err, e)
|
|
| 705 | 705 |
} |
| 706 | 706 |
} |
| 707 | 707 |
}() |
| ... | ... |
@@ -722,7 +723,7 @@ func (c *controller) NewNetwork(networkType, name string, id string, options ... |
| 722 | 722 |
var joinCluster NetworkWalker = func(nw Network) bool {
|
| 723 | 723 |
n := nw.(*network) |
| 724 | 724 |
if err := n.joinCluster(); err != nil {
|
| 725 |
- log.Errorf("Failed to join network %s (%s) into agent cluster: %v", n.Name(), n.ID(), err)
|
|
| 725 |
+ logrus.Errorf("Failed to join network %s (%s) into agent cluster: %v", n.Name(), n.ID(), err)
|
|
| 726 | 726 |
} |
| 727 | 727 |
n.addDriverWatches() |
| 728 | 728 |
return false |
| ... | ... |
@@ -731,7 +732,7 @@ var joinCluster NetworkWalker = func(nw Network) bool {
|
| 731 | 731 |
func (c *controller) reservePools() {
|
| 732 | 732 |
networks, err := c.getNetworksForScope(datastore.LocalScope) |
| 733 | 733 |
if err != nil {
|
| 734 |
- log.Warnf("Could not retrieve networks from local store during ipam allocation for existing networks: %v", err)
|
|
| 734 |
+ logrus.Warnf("Could not retrieve networks from local store during ipam allocation for existing networks: %v", err)
|
|
| 735 | 735 |
return |
| 736 | 736 |
} |
| 737 | 737 |
|
| ... | ... |
@@ -763,22 +764,22 @@ func (c *controller) reservePools() {
|
| 763 | 763 |
} |
| 764 | 764 |
// Reserve pools |
| 765 | 765 |
if err := n.ipamAllocate(); err != nil {
|
| 766 |
- log.Warnf("Failed to allocate ipam pool(s) for network %q (%s): %v", n.Name(), n.ID(), err)
|
|
| 766 |
+ logrus.Warnf("Failed to allocate ipam pool(s) for network %q (%s): %v", n.Name(), n.ID(), err)
|
|
| 767 | 767 |
} |
| 768 | 768 |
// Reserve existing endpoints' addresses |
| 769 | 769 |
ipam, _, err := n.getController().getIPAMDriver(n.ipamType) |
| 770 | 770 |
if err != nil {
|
| 771 |
- log.Warnf("Failed to retrieve ipam driver for network %q (%s) during address reservation", n.Name(), n.ID())
|
|
| 771 |
+ logrus.Warnf("Failed to retrieve ipam driver for network %q (%s) during address reservation", n.Name(), n.ID())
|
|
| 772 | 772 |
continue |
| 773 | 773 |
} |
| 774 | 774 |
epl, err := n.getEndpointsFromStore() |
| 775 | 775 |
if err != nil {
|
| 776 |
- log.Warnf("Failed to retrieve list of current endpoints on network %q (%s)", n.Name(), n.ID())
|
|
| 776 |
+ logrus.Warnf("Failed to retrieve list of current endpoints on network %q (%s)", n.Name(), n.ID())
|
|
| 777 | 777 |
continue |
| 778 | 778 |
} |
| 779 | 779 |
for _, ep := range epl {
|
| 780 | 780 |
if err := ep.assignAddress(ipam, true, ep.Iface().AddressIPv6() != nil); err != nil {
|
| 781 |
- log.Warnf("Failed to reserve current adress for endpoint %q (%s) on network %q (%s)",
|
|
| 781 |
+ logrus.Warnf("Failed to reserve current adress for endpoint %q (%s) on network %q (%s)",
|
|
| 782 | 782 |
ep.Name(), ep.ID(), n.Name(), n.ID()) |
| 783 | 783 |
} |
| 784 | 784 |
} |
| ... | ... |
@@ -788,7 +789,7 @@ func (c *controller) reservePools() {
|
| 788 | 788 |
func doReplayPoolReserve(n *network) bool {
|
| 789 | 789 |
_, caps, err := n.getController().getIPAMDriver(n.ipamType) |
| 790 | 790 |
if err != nil {
|
| 791 |
- log.Warnf("Failed to retrieve ipam driver for network %q (%s): %v", n.Name(), n.ID(), err)
|
|
| 791 |
+ logrus.Warnf("Failed to retrieve ipam driver for network %q (%s): %v", n.Name(), n.ID(), err)
|
|
| 792 | 792 |
return false |
| 793 | 793 |
} |
| 794 | 794 |
return caps.RequiresRequestReplay |
| ... | ... |
@@ -815,7 +816,7 @@ func (c *controller) Networks() []Network {
|
| 815 | 815 |
|
| 816 | 816 |
networks, err := c.getNetworksFromStore() |
| 817 | 817 |
if err != nil {
|
| 818 |
- log.Error(err) |
|
| 818 |
+ logrus.Error(err) |
|
| 819 | 819 |
} |
| 820 | 820 |
|
| 821 | 821 |
for _, n := range networks {
|
| ... | ... |
@@ -1132,18 +1133,18 @@ func (c *controller) clearIngress(clusterLeave bool) {
|
| 1132 | 1132 |
|
| 1133 | 1133 |
if ingressSandbox != nil {
|
| 1134 | 1134 |
if err := ingressSandbox.Delete(); err != nil {
|
| 1135 |
- log.Warnf("Could not delete ingress sandbox while leaving: %v", err)
|
|
| 1135 |
+ logrus.Warnf("Could not delete ingress sandbox while leaving: %v", err)
|
|
| 1136 | 1136 |
} |
| 1137 | 1137 |
} |
| 1138 | 1138 |
|
| 1139 | 1139 |
n, err := c.NetworkByName("ingress")
|
| 1140 | 1140 |
if err != nil && clusterLeave {
|
| 1141 |
- log.Warnf("Could not find ingress network while leaving: %v", err)
|
|
| 1141 |
+ logrus.Warnf("Could not find ingress network while leaving: %v", err)
|
|
| 1142 | 1142 |
} |
| 1143 | 1143 |
|
| 1144 | 1144 |
if n != nil {
|
| 1145 | 1145 |
if err := n.Delete(); err != nil {
|
| 1146 |
- log.Warnf("Could not delete ingress network while leaving: %v", err)
|
|
| 1146 |
+ logrus.Warnf("Could not delete ingress network while leaving: %v", err)
|
|
| 1147 | 1147 |
} |
| 1148 | 1148 |
} |
| 1149 | 1149 |
} |
| ... | ... |
@@ -6,6 +6,7 @@ import ( |
| 6 | 6 |
"reflect" |
| 7 | 7 |
"strings" |
| 8 | 8 |
"sync" |
| 9 |
+ "time" |
|
| 9 | 10 |
|
| 10 | 11 |
"github.com/docker/libkv" |
| 11 | 12 |
"github.com/docker/libkv/store" |
| ... | ... |
@@ -134,7 +135,8 @@ func makeDefaultScopes() map[string]*ScopeCfg {
|
| 134 | 134 |
Provider: string(store.BOLTDB), |
| 135 | 135 |
Address: defaultPrefix + "/local-kv.db", |
| 136 | 136 |
Config: &store.Config{
|
| 137 |
- Bucket: "libnetwork", |
|
| 137 |
+ Bucket: "libnetwork", |
|
| 138 |
+ ConnectionTimeout: time.Minute, |
|
| 138 | 139 |
}, |
| 139 | 140 |
}, |
| 140 | 141 |
} |
| ... | ... |
@@ -2,13 +2,14 @@ package libnetwork |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 | 4 |
"fmt" |
| 5 |
+ "strings" |
|
| 5 | 6 |
|
| 7 |
+ "github.com/docker/libnetwork/netlabel" |
|
| 6 | 8 |
"github.com/docker/libnetwork/types" |
| 7 | 9 |
) |
| 8 | 10 |
|
| 9 | 11 |
const ( |
| 10 |
- libnGWNetwork = "docker_gwbridge" |
|
| 11 |
- gwEPlen = 12 |
|
| 12 |
+ gwEPlen = 12 |
|
| 12 | 13 |
) |
| 13 | 14 |
|
| 14 | 15 |
var procGwNetwork = make(chan (bool), 1) |
| ... | ... |
@@ -52,6 +53,21 @@ func (sb *sandbox) setupDefaultGW() error {
|
| 52 | 52 |
eplen = len(sb.containerID) |
| 53 | 53 |
} |
| 54 | 54 |
|
| 55 |
+ sbLabels := sb.Labels() |
|
| 56 |
+ |
|
| 57 |
+ if sbLabels[netlabel.PortMap] != nil {
|
|
| 58 |
+ createOptions = append(createOptions, CreateOptionPortMapping(sbLabels[netlabel.PortMap].([]types.PortBinding))) |
|
| 59 |
+ } |
|
| 60 |
+ |
|
| 61 |
+ if sbLabels[netlabel.ExposedPorts] != nil {
|
|
| 62 |
+ createOptions = append(createOptions, CreateOptionExposedPorts(sbLabels[netlabel.ExposedPorts].([]types.TransportPort))) |
|
| 63 |
+ } |
|
| 64 |
+ |
|
| 65 |
+ epOption := getPlatformOption() |
|
| 66 |
+ if epOption != nil {
|
|
| 67 |
+ createOptions = append(createOptions, epOption) |
|
| 68 |
+ } |
|
| 69 |
+ |
|
| 55 | 70 |
newEp, err := n.CreateEndpoint("gateway_"+sb.containerID[0:eplen], createOptions...)
|
| 56 | 71 |
if err != nil {
|
| 57 | 72 |
return fmt.Errorf("container %s: endpoint create on GW Network failed: %v", sb.containerID, err)
|
| ... | ... |
@@ -119,7 +135,7 @@ func (sb *sandbox) needDefaultGW() bool {
|
| 119 | 119 |
|
| 120 | 120 |
func (sb *sandbox) getEndpointInGWNetwork() *endpoint {
|
| 121 | 121 |
for _, ep := range sb.getConnectedEndpoints() {
|
| 122 |
- if ep.getNetwork().name == libnGWNetwork {
|
|
| 122 |
+ if ep.getNetwork().name == libnGWNetwork && strings.HasPrefix(ep.Name(), "gateway_") {
|
|
| 123 | 123 |
return ep |
| 124 | 124 |
} |
| 125 | 125 |
} |
| ... | ... |
@@ -127,7 +143,7 @@ func (sb *sandbox) getEndpointInGWNetwork() *endpoint {
|
| 127 | 127 |
} |
| 128 | 128 |
|
| 129 | 129 |
func (ep *endpoint) endpointInGWNetwork() bool {
|
| 130 |
- if ep.getNetwork().name == libnGWNetwork {
|
|
| 130 |
+ if ep.getNetwork().name == libnGWNetwork && strings.HasPrefix(ep.Name(), "gateway_") {
|
|
| 131 | 131 |
return true |
| 132 | 132 |
} |
| 133 | 133 |
return false |
| ... | ... |
@@ -2,6 +2,12 @@ package libnetwork |
| 2 | 2 |
|
| 3 | 3 |
import "github.com/docker/libnetwork/types" |
| 4 | 4 |
|
| 5 |
+const libnGWNetwork = "docker_gwbridge" |
|
| 6 |
+ |
|
| 7 |
+func getPlatformOption() EndpointOption {
|
|
| 8 |
+ return nil |
|
| 9 |
+} |
|
| 10 |
+ |
|
| 5 | 11 |
func (c *controller) createGWNetwork() (Network, error) {
|
| 6 | 12 |
return nil, types.NotImplementedErrorf("default gateway functionality is not implemented in freebsd")
|
| 7 | 13 |
} |
| ... | ... |
@@ -7,6 +7,12 @@ import ( |
| 7 | 7 |
"github.com/docker/libnetwork/drivers/bridge" |
| 8 | 8 |
) |
| 9 | 9 |
|
| 10 |
+const libnGWNetwork = "docker_gwbridge" |
|
| 11 |
+ |
|
| 12 |
+func getPlatformOption() EndpointOption {
|
|
| 13 |
+ return nil |
|
| 14 |
+} |
|
| 15 |
+ |
|
| 10 | 16 |
func (c *controller) createGWNetwork() (Network, error) {
|
| 11 | 17 |
netOption := map[string]string{
|
| 12 | 18 |
bridge.BridgeName: libnGWNetwork, |
| ... | ... |
@@ -1,7 +1,32 @@ |
| 1 | 1 |
package libnetwork |
| 2 | 2 |
|
| 3 |
-import "github.com/docker/libnetwork/types" |
|
| 3 |
+import ( |
|
| 4 |
+ "fmt" |
|
| 5 |
+ "strconv" |
|
| 6 |
+ |
|
| 7 |
+ "github.com/docker/libnetwork/drivers/solaris/bridge" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+const libnGWNetwork = "docker_gwbridge" |
|
| 11 |
+ |
|
| 12 |
+func getPlatformOption() EndpointOption {
|
|
| 13 |
+ return nil |
|
| 14 |
+} |
|
| 4 | 15 |
|
| 5 | 16 |
func (c *controller) createGWNetwork() (Network, error) {
|
| 6 |
- return nil, types.NotImplementedErrorf("default gateway functionality is not implemented in solaris")
|
|
| 17 |
+ netOption := map[string]string{
|
|
| 18 |
+ bridge.BridgeName: libnGWNetwork, |
|
| 19 |
+ bridge.EnableICC: strconv.FormatBool(false), |
|
| 20 |
+ bridge.EnableIPMasquerade: strconv.FormatBool(true), |
|
| 21 |
+ } |
|
| 22 |
+ |
|
| 23 |
+ n, err := c.NewNetwork("bridge", libnGWNetwork, "",
|
|
| 24 |
+ NetworkOptionDriverOpts(netOption), |
|
| 25 |
+ NetworkOptionEnableIPv6(false), |
|
| 26 |
+ ) |
|
| 27 |
+ |
|
| 28 |
+ if err != nil {
|
|
| 29 |
+ return nil, fmt.Errorf("error creating external connectivity network: %v", err)
|
|
| 30 |
+ } |
|
| 31 |
+ return n, err |
|
| 7 | 32 |
} |
| ... | ... |
@@ -1,6 +1,21 @@ |
| 1 | 1 |
package libnetwork |
| 2 | 2 |
|
| 3 |
-import "github.com/docker/libnetwork/types" |
|
| 3 |
+import ( |
|
| 4 |
+ windriver "github.com/docker/libnetwork/drivers/windows" |
|
| 5 |
+ "github.com/docker/libnetwork/options" |
|
| 6 |
+ "github.com/docker/libnetwork/types" |
|
| 7 |
+) |
|
| 8 |
+ |
|
| 9 |
+const libnGWNetwork = "nat" |
|
| 10 |
+ |
|
| 11 |
+func getPlatformOption() EndpointOption {
|
|
| 12 |
+ |
|
| 13 |
+ epOption := options.Generic{
|
|
| 14 |
+ windriver.DisableICC: true, |
|
| 15 |
+ windriver.DisableDNS: true, |
|
| 16 |
+ } |
|
| 17 |
+ return EndpointOptionGeneric(epOption) |
|
| 18 |
+} |
|
| 4 | 19 |
|
| 5 | 20 |
func (c *controller) createGWNetwork() (Network, error) {
|
| 6 | 21 |
return nil, types.NotImplementedErrorf("default gateway functionality is not implemented in windows")
|
| ... | ... |
@@ -4,7 +4,7 @@ import ( |
| 4 | 4 |
"fmt" |
| 5 | 5 |
"net" |
| 6 | 6 |
|
| 7 |
- log "github.com/Sirupsen/logrus" |
|
| 7 |
+ "github.com/Sirupsen/logrus" |
|
| 8 | 8 |
"github.com/docker/libnetwork/iptables" |
| 9 | 9 |
"github.com/docker/libnetwork/types" |
| 10 | 10 |
) |
| ... | ... |
@@ -44,7 +44,7 @@ func (l *link) Disable() {
|
| 44 | 44 |
// -D == iptables delete flag |
| 45 | 45 |
err := linkContainers("-D", l.parentIP, l.childIP, l.ports, l.bridge, true)
|
| 46 | 46 |
if err != nil {
|
| 47 |
- log.Errorf("Error removing IPTables rules for a link %s due to %s", l.String(), err.Error())
|
|
| 47 |
+ logrus.Errorf("Error removing IPTables rules for a link %s due to %s", l.String(), err.Error())
|
|
| 48 | 48 |
} |
| 49 | 49 |
// Return proper error once we move to use a proper iptables package |
| 50 | 50 |
// that returns typed errors |
| ... | ... |
@@ -6,7 +6,7 @@ import ( |
| 6 | 6 |
"net" |
| 7 | 7 |
"path/filepath" |
| 8 | 8 |
|
| 9 |
- log "github.com/Sirupsen/logrus" |
|
| 9 |
+ "github.com/Sirupsen/logrus" |
|
| 10 | 10 |
"github.com/docker/libnetwork/types" |
| 11 | 11 |
"github.com/vishvananda/netlink" |
| 12 | 12 |
) |
| ... | ... |
@@ -39,7 +39,7 @@ func setupBridgeIPv4(config *networkConfiguration, i *bridgeInterface) error {
|
| 39 | 39 |
return fmt.Errorf("failed to remove current ip address from bridge: %v", err)
|
| 40 | 40 |
} |
| 41 | 41 |
} |
| 42 |
- log.Debugf("Assigning address to bridge interface %s: %s", config.BridgeName, config.AddressIPv4)
|
|
| 42 |
+ logrus.Debugf("Assigning address to bridge interface %s: %s", config.BridgeName, config.AddressIPv4)
|
|
| 43 | 43 |
if err := i.nlh.AddrAdd(i.Link, &netlink.Addr{IPNet: config.AddressIPv4}); err != nil {
|
| 44 | 44 |
return &IPv4AddrAddError{IP: config.AddressIPv4, Err: err}
|
| 45 | 45 |
} |
| ... | ... |
@@ -4,7 +4,7 @@ import ( |
| 4 | 4 |
"fmt" |
| 5 | 5 |
"strings" |
| 6 | 6 |
|
| 7 |
- log "github.com/Sirupsen/logrus" |
|
| 7 |
+ "github.com/Sirupsen/logrus" |
|
| 8 | 8 |
"github.com/docker/libnetwork/ns" |
| 9 | 9 |
"github.com/docker/libnetwork/types" |
| 10 | 10 |
"github.com/vishvananda/netlink" |
| ... | ... |
@@ -39,7 +39,7 @@ func setupVerifyAndReconcile(config *networkConfiguration, i *bridgeInterface) e |
| 39 | 39 |
for _, addrv6 := range addrsv6 {
|
| 40 | 40 |
if addrv6.IP.IsGlobalUnicast() && !types.CompareIPNet(addrv6.IPNet, i.bridgeIPv6) {
|
| 41 | 41 |
if err := i.nlh.AddrDel(i.Link, &addrv6); err != nil {
|
| 42 |
- log.Warnf("Failed to remove residual IPv6 address %s from bridge: %v", addrv6.IPNet, err)
|
|
| 42 |
+ logrus.Warnf("Failed to remove residual IPv6 address %s from bridge: %v", addrv6.IPNet, err)
|
|
| 43 | 43 |
} |
| 44 | 44 |
} |
| 45 | 45 |
} |
| ... | ... |
@@ -12,7 +12,7 @@ import ( |
| 12 | 12 |
|
| 13 | 13 |
"strconv" |
| 14 | 14 |
|
| 15 |
- log "github.com/Sirupsen/logrus" |
|
| 15 |
+ "github.com/Sirupsen/logrus" |
|
| 16 | 16 |
"github.com/docker/libnetwork/iptables" |
| 17 | 17 |
"github.com/docker/libnetwork/ns" |
| 18 | 18 |
"github.com/docker/libnetwork/types" |
| ... | ... |
@@ -77,7 +77,7 @@ func (e *encrMap) String() string {
|
| 77 | 77 |
} |
| 78 | 78 |
|
| 79 | 79 |
func (d *driver) checkEncryption(nid string, rIP net.IP, vxlanID uint32, isLocal, add bool) error {
|
| 80 |
- log.Debugf("checkEncryption(%s, %v, %d, %t)", nid[0:7], rIP, vxlanID, isLocal)
|
|
| 80 |
+ logrus.Debugf("checkEncryption(%s, %v, %d, %t)", nid[0:7], rIP, vxlanID, isLocal)
|
|
| 81 | 81 |
|
| 82 | 82 |
n := d.network(nid) |
| 83 | 83 |
if n == nil || !n.secure {
|
| ... | ... |
@@ -100,7 +100,7 @@ func (d *driver) checkEncryption(nid string, rIP net.IP, vxlanID uint32, isLocal |
| 100 | 100 |
} |
| 101 | 101 |
return false |
| 102 | 102 |
}); err != nil {
|
| 103 |
- log.Warnf("Failed to retrieve list of participating nodes in overlay network %s: %v", nid[0:5], err)
|
|
| 103 |
+ logrus.Warnf("Failed to retrieve list of participating nodes in overlay network %s: %v", nid[0:5], err)
|
|
| 104 | 104 |
} |
| 105 | 105 |
default: |
| 106 | 106 |
if len(d.network(nid).endpoints) > 0 {
|
| ... | ... |
@@ -108,18 +108,18 @@ func (d *driver) checkEncryption(nid string, rIP net.IP, vxlanID uint32, isLocal |
| 108 | 108 |
} |
| 109 | 109 |
} |
| 110 | 110 |
|
| 111 |
- log.Debugf("List of nodes: %s", nodes)
|
|
| 111 |
+ logrus.Debugf("List of nodes: %s", nodes)
|
|
| 112 | 112 |
|
| 113 | 113 |
if add {
|
| 114 | 114 |
for _, rIP := range nodes {
|
| 115 | 115 |
if err := setupEncryption(lIP, aIP, rIP, vxlanID, d.secMap, d.keys); err != nil {
|
| 116 |
- log.Warnf("Failed to program network encryption between %s and %s: %v", lIP, rIP, err)
|
|
| 116 |
+ logrus.Warnf("Failed to program network encryption between %s and %s: %v", lIP, rIP, err)
|
|
| 117 | 117 |
} |
| 118 | 118 |
} |
| 119 | 119 |
} else {
|
| 120 | 120 |
if len(nodes) == 0 {
|
| 121 | 121 |
if err := removeEncryption(lIP, rIP, d.secMap); err != nil {
|
| 122 |
- log.Warnf("Failed to remove network encryption between %s and %s: %v", lIP, rIP, err)
|
|
| 122 |
+ logrus.Warnf("Failed to remove network encryption between %s and %s: %v", lIP, rIP, err)
|
|
| 123 | 123 |
} |
| 124 | 124 |
} |
| 125 | 125 |
} |
| ... | ... |
@@ -128,14 +128,14 @@ func (d *driver) checkEncryption(nid string, rIP net.IP, vxlanID uint32, isLocal |
| 128 | 128 |
} |
| 129 | 129 |
|
| 130 | 130 |
func setupEncryption(localIP, advIP, remoteIP net.IP, vni uint32, em *encrMap, keys []*key) error {
|
| 131 |
- log.Debugf("Programming encryption for vxlan %d between %s and %s", vni, localIP, remoteIP)
|
|
| 131 |
+ logrus.Debugf("Programming encryption for vxlan %d between %s and %s", vni, localIP, remoteIP)
|
|
| 132 | 132 |
rIPs := remoteIP.String() |
| 133 | 133 |
|
| 134 | 134 |
indices := make([]*spi, 0, len(keys)) |
| 135 | 135 |
|
| 136 | 136 |
err := programMangle(vni, true) |
| 137 | 137 |
if err != nil {
|
| 138 |
- log.Warn(err) |
|
| 138 |
+ logrus.Warn(err) |
|
| 139 | 139 |
} |
| 140 | 140 |
|
| 141 | 141 |
for i, k := range keys {
|
| ... | ... |
@@ -146,7 +146,7 @@ func setupEncryption(localIP, advIP, remoteIP net.IP, vni uint32, em *encrMap, k |
| 146 | 146 |
} |
| 147 | 147 |
fSA, rSA, err := programSA(localIP, remoteIP, spis, k, dir, true) |
| 148 | 148 |
if err != nil {
|
| 149 |
- log.Warn(err) |
|
| 149 |
+ logrus.Warn(err) |
|
| 150 | 150 |
} |
| 151 | 151 |
indices = append(indices, spis) |
| 152 | 152 |
if i != 0 {
|
| ... | ... |
@@ -154,7 +154,7 @@ func setupEncryption(localIP, advIP, remoteIP net.IP, vni uint32, em *encrMap, k |
| 154 | 154 |
} |
| 155 | 155 |
err = programSP(fSA, rSA, true) |
| 156 | 156 |
if err != nil {
|
| 157 |
- log.Warn(err) |
|
| 157 |
+ logrus.Warn(err) |
|
| 158 | 158 |
} |
| 159 | 159 |
} |
| 160 | 160 |
|
| ... | ... |
@@ -179,14 +179,14 @@ func removeEncryption(localIP, remoteIP net.IP, em *encrMap) error {
|
| 179 | 179 |
} |
| 180 | 180 |
fSA, rSA, err := programSA(localIP, remoteIP, idxs, nil, dir, false) |
| 181 | 181 |
if err != nil {
|
| 182 |
- log.Warn(err) |
|
| 182 |
+ logrus.Warn(err) |
|
| 183 | 183 |
} |
| 184 | 184 |
if i != 0 {
|
| 185 | 185 |
continue |
| 186 | 186 |
} |
| 187 | 187 |
err = programSP(fSA, rSA, false) |
| 188 | 188 |
if err != nil {
|
| 189 |
- log.Warn(err) |
|
| 189 |
+ logrus.Warn(err) |
|
| 190 | 190 |
} |
| 191 | 191 |
} |
| 192 | 192 |
return nil |
| ... | ... |
@@ -213,7 +213,7 @@ func programMangle(vni uint32, add bool) (err error) {
|
| 213 | 213 |
} |
| 214 | 214 |
|
| 215 | 215 |
if err = iptables.RawCombinedOutput(append([]string{"-t", string(iptables.Mangle), a, chain}, rule...)...); err != nil {
|
| 216 |
- log.Warnf("could not %s mangle rule: %v", action, err)
|
|
| 216 |
+ logrus.Warnf("could not %s mangle rule: %v", action, err)
|
|
| 217 | 217 |
} |
| 218 | 218 |
|
| 219 | 219 |
return |
| ... | ... |
@@ -248,9 +248,9 @@ func programSA(localIP, remoteIP net.IP, spi *spi, k *key, dir int, add bool) (f |
| 248 | 248 |
} |
| 249 | 249 |
|
| 250 | 250 |
if add != exists {
|
| 251 |
- log.Debugf("%s: rSA{%s}", action, rSA)
|
|
| 251 |
+ logrus.Debugf("%s: rSA{%s}", action, rSA)
|
|
| 252 | 252 |
if err := xfrmProgram(rSA); err != nil {
|
| 253 |
- log.Warnf("Failed %s rSA{%s}: %v", action, rSA, err)
|
|
| 253 |
+ logrus.Warnf("Failed %s rSA{%s}: %v", action, rSA, err)
|
|
| 254 | 254 |
} |
| 255 | 255 |
} |
| 256 | 256 |
} |
| ... | ... |
@@ -273,9 +273,9 @@ func programSA(localIP, remoteIP net.IP, spi *spi, k *key, dir int, add bool) (f |
| 273 | 273 |
} |
| 274 | 274 |
|
| 275 | 275 |
if add != exists {
|
| 276 |
- log.Debugf("%s fSA{%s}", action, fSA)
|
|
| 276 |
+ logrus.Debugf("%s fSA{%s}", action, fSA)
|
|
| 277 | 277 |
if err := xfrmProgram(fSA); err != nil {
|
| 278 |
- log.Warnf("Failed %s fSA{%s}: %v.", action, fSA, err)
|
|
| 278 |
+ logrus.Warnf("Failed %s fSA{%s}: %v.", action, fSA, err)
|
|
| 279 | 279 |
} |
| 280 | 280 |
} |
| 281 | 281 |
} |
| ... | ... |
@@ -319,9 +319,9 @@ func programSP(fSA *netlink.XfrmState, rSA *netlink.XfrmState, add bool) error {
|
| 319 | 319 |
} |
| 320 | 320 |
|
| 321 | 321 |
if add != exists {
|
| 322 |
- log.Debugf("%s fSP{%s}", action, fPol)
|
|
| 322 |
+ logrus.Debugf("%s fSP{%s}", action, fPol)
|
|
| 323 | 323 |
if err := xfrmProgram(fPol); err != nil {
|
| 324 |
- log.Warnf("%s fSP{%s}: %v", action, fPol, err)
|
|
| 324 |
+ logrus.Warnf("%s fSP{%s}: %v", action, fPol, err)
|
|
| 325 | 325 |
} |
| 326 | 326 |
} |
| 327 | 327 |
|
| ... | ... |
@@ -337,7 +337,7 @@ func saExists(sa *netlink.XfrmState) (bool, error) {
|
| 337 | 337 |
return false, nil |
| 338 | 338 |
default: |
| 339 | 339 |
err = fmt.Errorf("Error while checking for SA existence: %v", err)
|
| 340 |
- log.Warn(err) |
|
| 340 |
+ logrus.Warn(err) |
|
| 341 | 341 |
return false, err |
| 342 | 342 |
} |
| 343 | 343 |
} |
| ... | ... |
@@ -351,7 +351,7 @@ func spExists(sp *netlink.XfrmPolicy) (bool, error) {
|
| 351 | 351 |
return false, nil |
| 352 | 352 |
default: |
| 353 | 353 |
err = fmt.Errorf("Error while checking for SP existence: %v", err)
|
| 354 |
- log.Warn(err) |
|
| 354 |
+ logrus.Warn(err) |
|
| 355 | 355 |
return false, err |
| 356 | 356 |
} |
| 357 | 357 |
} |
| ... | ... |
@@ -397,16 +397,16 @@ func (d *driver) setKeys(keys []*key) error {
|
| 397 | 397 |
d.keys = keys |
| 398 | 398 |
d.secMap = &encrMap{nodes: map[string][]*spi{}}
|
| 399 | 399 |
d.Unlock() |
| 400 |
- log.Debugf("Initial encryption keys: %v", d.keys)
|
|
| 400 |
+ logrus.Debugf("Initial encryption keys: %v", d.keys)
|
|
| 401 | 401 |
return nil |
| 402 | 402 |
} |
| 403 | 403 |
|
| 404 | 404 |
// updateKeys allows to add a new key and/or change the primary key and/or prune an existing key |
| 405 | 405 |
// The primary key is the key used in transmission and will go in first position in the list. |
| 406 | 406 |
func (d *driver) updateKeys(newKey, primary, pruneKey *key) error {
|
| 407 |
- log.Debugf("Updating Keys. New: %v, Primary: %v, Pruned: %v", newKey, primary, pruneKey)
|
|
| 407 |
+ logrus.Debugf("Updating Keys. New: %v, Primary: %v, Pruned: %v", newKey, primary, pruneKey)
|
|
| 408 | 408 |
|
| 409 |
- log.Debugf("Current: %v", d.keys)
|
|
| 409 |
+ logrus.Debugf("Current: %v", d.keys)
|
|
| 410 | 410 |
|
| 411 | 411 |
var ( |
| 412 | 412 |
newIdx = -1 |
| ... | ... |
@@ -459,7 +459,7 @@ func (d *driver) updateKeys(newKey, primary, pruneKey *key) error {
|
| 459 | 459 |
} |
| 460 | 460 |
d.Unlock() |
| 461 | 461 |
|
| 462 |
- log.Debugf("Updated: %v", d.keys)
|
|
| 462 |
+ logrus.Debugf("Updated: %v", d.keys)
|
|
| 463 | 463 |
|
| 464 | 464 |
return nil |
| 465 | 465 |
} |
| ... | ... |
@@ -472,10 +472,10 @@ func (d *driver) updateKeys(newKey, primary, pruneKey *key) error {
|
| 472 | 472 |
|
| 473 | 473 |
// Spis and keys are sorted in such away the one in position 0 is the primary |
| 474 | 474 |
func updateNodeKey(lIP, rIP net.IP, idxs []*spi, curKeys []*key, newIdx, priIdx, delIdx int) []*spi {
|
| 475 |
- log.Debugf("Updating keys for node: %s (%d,%d,%d)", rIP, newIdx, priIdx, delIdx)
|
|
| 475 |
+ logrus.Debugf("Updating keys for node: %s (%d,%d,%d)", rIP, newIdx, priIdx, delIdx)
|
|
| 476 | 476 |
|
| 477 | 477 |
spis := idxs |
| 478 |
- log.Debugf("Current: %v", spis)
|
|
| 478 |
+ logrus.Debugf("Current: %v", spis)
|
|
| 479 | 479 |
|
| 480 | 480 |
// add new |
| 481 | 481 |
if newIdx != -1 {
|
| ... | ... |
@@ -520,9 +520,9 @@ func updateNodeKey(lIP, rIP net.IP, idxs []*spi, curKeys []*key, newIdx, priIdx, |
| 520 | 520 |
}, |
| 521 | 521 |
}, |
| 522 | 522 |
} |
| 523 |
- log.Debugf("Updating fSP{%s}", fSP1)
|
|
| 523 |
+ logrus.Debugf("Updating fSP{%s}", fSP1)
|
|
| 524 | 524 |
if err := ns.NlHandle().XfrmPolicyUpdate(fSP1); err != nil {
|
| 525 |
- log.Warnf("Failed to update fSP{%s}: %v", fSP1, err)
|
|
| 525 |
+ logrus.Warnf("Failed to update fSP{%s}: %v", fSP1, err)
|
|
| 526 | 526 |
} |
| 527 | 527 |
|
| 528 | 528 |
// -fSA1 |
| ... | ... |
@@ -543,7 +543,7 @@ func updateNodeKey(lIP, rIP net.IP, idxs []*spi, curKeys []*key, newIdx, priIdx, |
| 543 | 543 |
spis = append(spis[:delIdx], spis[delIdx+1:]...) |
| 544 | 544 |
} |
| 545 | 545 |
|
| 546 |
- log.Debugf("Updated: %v", spis)
|
|
| 546 |
+ logrus.Debugf("Updated: %v", spis)
|
|
| 547 | 547 |
|
| 548 | 548 |
return spis |
| 549 | 549 |
} |
| ... | ... |
@@ -5,7 +5,7 @@ import ( |
| 5 | 5 |
"net" |
| 6 | 6 |
"syscall" |
| 7 | 7 |
|
| 8 |
- log "github.com/Sirupsen/logrus" |
|
| 8 |
+ "github.com/Sirupsen/logrus" |
|
| 9 | 9 |
"github.com/docker/libnetwork/driverapi" |
| 10 | 10 |
"github.com/docker/libnetwork/ns" |
| 11 | 11 |
"github.com/docker/libnetwork/types" |
| ... | ... |
@@ -109,7 +109,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, |
| 109 | 109 |
continue |
| 110 | 110 |
} |
| 111 | 111 |
if err := jinfo.AddStaticRoute(sub.subnetIP, types.NEXTHOP, s.gwIP.IP); err != nil {
|
| 112 |
- log.Errorf("Adding subnet %s static route in network %q failed\n", s.subnetIP, n.id)
|
|
| 112 |
+ logrus.Errorf("Adding subnet %s static route in network %q failed\n", s.subnetIP, n.id)
|
|
| 113 | 113 |
} |
| 114 | 114 |
} |
| 115 | 115 |
|
| ... | ... |
@@ -124,7 +124,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, |
| 124 | 124 |
net.ParseIP(d.advertiseAddress), true) |
| 125 | 125 |
|
| 126 | 126 |
if err := d.checkEncryption(nid, nil, n.vxlanID(s), true, true); err != nil {
|
| 127 |
- log.Warn(err) |
|
| 127 |
+ logrus.Warn(err) |
|
| 128 | 128 |
} |
| 129 | 129 |
|
| 130 | 130 |
buf, err := proto.Marshal(&PeerRecord{
|
| ... | ... |
@@ -137,7 +137,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, |
| 137 | 137 |
} |
| 138 | 138 |
|
| 139 | 139 |
if err := jinfo.AddTableEntry(ovPeerTable, eid, buf); err != nil {
|
| 140 |
- log.Errorf("overlay: Failed adding table entry to joininfo: %v", err)
|
|
| 140 |
+ logrus.Errorf("overlay: Failed adding table entry to joininfo: %v", err)
|
|
| 141 | 141 |
} |
| 142 | 142 |
|
| 143 | 143 |
d.pushLocalEndpointEvent("join", nid, eid)
|
| ... | ... |
@@ -147,7 +147,7 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, |
| 147 | 147 |
|
| 148 | 148 |
func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
|
| 149 | 149 |
if tableName != ovPeerTable {
|
| 150 |
- log.Errorf("Unexpected table notification for table %s received", tableName)
|
|
| 150 |
+ logrus.Errorf("Unexpected table notification for table %s received", tableName)
|
|
| 151 | 151 |
return |
| 152 | 152 |
} |
| 153 | 153 |
|
| ... | ... |
@@ -155,7 +155,7 @@ func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key stri |
| 155 | 155 |
|
| 156 | 156 |
var peer PeerRecord |
| 157 | 157 |
if err := proto.Unmarshal(value, &peer); err != nil {
|
| 158 |
- log.Errorf("Failed to unmarshal peer record: %v", err)
|
|
| 158 |
+ logrus.Errorf("Failed to unmarshal peer record: %v", err)
|
|
| 159 | 159 |
return |
| 160 | 160 |
} |
| 161 | 161 |
|
| ... | ... |
@@ -167,19 +167,19 @@ func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key stri |
| 167 | 167 |
|
| 168 | 168 |
addr, err := types.ParseCIDR(peer.EndpointIP) |
| 169 | 169 |
if err != nil {
|
| 170 |
- log.Errorf("Invalid peer IP %s received in event notify", peer.EndpointIP)
|
|
| 170 |
+ logrus.Errorf("Invalid peer IP %s received in event notify", peer.EndpointIP)
|
|
| 171 | 171 |
return |
| 172 | 172 |
} |
| 173 | 173 |
|
| 174 | 174 |
mac, err := net.ParseMAC(peer.EndpointMAC) |
| 175 | 175 |
if err != nil {
|
| 176 |
- log.Errorf("Invalid mac %s received in event notify", peer.EndpointMAC)
|
|
| 176 |
+ logrus.Errorf("Invalid mac %s received in event notify", peer.EndpointMAC)
|
|
| 177 | 177 |
return |
| 178 | 178 |
} |
| 179 | 179 |
|
| 180 | 180 |
vtep := net.ParseIP(peer.TunnelEndpointIP) |
| 181 | 181 |
if vtep == nil {
|
| 182 |
- log.Errorf("Invalid VTEP %s received in event notify", peer.TunnelEndpointIP)
|
|
| 182 |
+ logrus.Errorf("Invalid VTEP %s received in event notify", peer.TunnelEndpointIP)
|
|
| 183 | 183 |
return |
| 184 | 184 |
} |
| 185 | 185 |
|
| ... | ... |
@@ -219,7 +219,7 @@ func (d *driver) Leave(nid, eid string) error {
|
| 219 | 219 |
n.leaveSandbox() |
| 220 | 220 |
|
| 221 | 221 |
if err := d.checkEncryption(nid, nil, 0, true, false); err != nil {
|
| 222 |
- log.Warn(err) |
|
| 222 |
+ logrus.Warn(err) |
|
| 223 | 223 |
} |
| 224 | 224 |
|
| 225 | 225 |
return nil |
| ... | ... |
@@ -5,7 +5,7 @@ import ( |
| 5 | 5 |
"fmt" |
| 6 | 6 |
"net" |
| 7 | 7 |
|
| 8 |
- log "github.com/Sirupsen/logrus" |
|
| 8 |
+ "github.com/Sirupsen/logrus" |
|
| 9 | 9 |
"github.com/docker/libnetwork/datastore" |
| 10 | 10 |
"github.com/docker/libnetwork/driverapi" |
| 11 | 11 |
"github.com/docker/libnetwork/netutils" |
| ... | ... |
@@ -116,7 +116,7 @@ func (d *driver) DeleteEndpoint(nid, eid string) error {
|
| 116 | 116 |
n.deleteEndpoint(eid) |
| 117 | 117 |
|
| 118 | 118 |
if err := d.deleteEndpointFromStore(ep); err != nil {
|
| 119 |
- log.Warnf("Failed to delete overlay endpoint %s from local store: %v", ep.id[0:7], err)
|
|
| 119 |
+ logrus.Warnf("Failed to delete overlay endpoint %s from local store: %v", ep.id[0:7], err)
|
|
| 120 | 120 |
} |
| 121 | 121 |
|
| 122 | 122 |
if ep.ifName == "" {
|
| ... | ... |
@@ -125,11 +125,11 @@ func (d *driver) DeleteEndpoint(nid, eid string) error {
|
| 125 | 125 |
|
| 126 | 126 |
link, err := nlh.LinkByName(ep.ifName) |
| 127 | 127 |
if err != nil {
|
| 128 |
- log.Debugf("Failed to retrieve interface (%s)'s link on endpoint (%s) delete: %v", ep.ifName, ep.id, err)
|
|
| 128 |
+ logrus.Debugf("Failed to retrieve interface (%s)'s link on endpoint (%s) delete: %v", ep.ifName, ep.id, err)
|
|
| 129 | 129 |
return nil |
| 130 | 130 |
} |
| 131 | 131 |
if err := nlh.LinkDel(link); err != nil {
|
| 132 |
- log.Debugf("Failed to delete interface (%s)'s link on endpoint (%s) delete: %v", ep.ifName, ep.id, err)
|
|
| 132 |
+ logrus.Debugf("Failed to delete interface (%s)'s link on endpoint (%s) delete: %v", ep.ifName, ep.id, err)
|
|
| 133 | 133 |
} |
| 134 | 134 |
|
| 135 | 135 |
return nil |
| ... | ... |
@@ -111,7 +111,7 @@ func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
| 111 | 111 |
// Endpoints are stored in the local store. Restore them and reconstruct the overlay sandbox |
| 112 | 112 |
func (d *driver) restoreEndpoints() error {
|
| 113 | 113 |
if d.localStore == nil {
|
| 114 |
- logrus.Warnf("Cannot restore overlay endpoints because local datastore is missing")
|
|
| 114 |
+ logrus.Warn("Cannot restore overlay endpoints because local datastore is missing")
|
|
| 115 | 115 |
return nil |
| 116 | 116 |
} |
| 117 | 117 |
kvol, err := d.localStore.List(datastore.Key(overlayEndpointPrefix), &endpoint{})
|
| ... | ... |
@@ -18,7 +18,7 @@ import ( |
| 18 | 18 |
|
| 19 | 19 |
const ( |
| 20 | 20 |
networkType = "overlay" |
| 21 |
- vxlanIDStart = 256 |
|
| 21 |
+ vxlanIDStart = 4096 |
|
| 22 | 22 |
vxlanIDEnd = (1 << 24) - 1 |
| 23 | 23 |
) |
| 24 | 24 |
|
| ... | ... |
@@ -57,7 +57,7 @@ func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
| 57 | 57 |
config: config, |
| 58 | 58 |
} |
| 59 | 59 |
|
| 60 |
- d.vxlanIdm, err = idm.New(nil, "vxlan-id", vxlanIDStart, vxlanIDEnd) |
|
| 60 |
+ d.vxlanIdm, err = idm.New(nil, "vxlan-id", 1, vxlanIDEnd) |
|
| 61 | 61 |
if err != nil {
|
| 62 | 62 |
return fmt.Errorf("failed to initialize vxlan id manager: %v", err)
|
| 63 | 63 |
} |
| ... | ... |
@@ -164,7 +164,7 @@ func (n *network) obtainVxlanID(s *subnet) error {
|
| 164 | 164 |
n.Unlock() |
| 165 | 165 |
|
| 166 | 166 |
if vni == 0 {
|
| 167 |
- vni, err = n.driver.vxlanIdm.GetID() |
|
| 167 |
+ vni, err = n.driver.vxlanIdm.GetIDInRange(vxlanIDStart, vxlanIDEnd) |
|
| 168 | 168 |
if err != nil {
|
| 169 | 169 |
return err |
| 170 | 170 |
} |
| ... | ... |
@@ -6,7 +6,7 @@ import ( |
| 6 | 6 |
"sync" |
| 7 | 7 |
"syscall" |
| 8 | 8 |
|
| 9 |
- log "github.com/Sirupsen/logrus" |
|
| 9 |
+ "github.com/Sirupsen/logrus" |
|
| 10 | 10 |
) |
| 11 | 11 |
|
| 12 | 12 |
const ovPeerTable = "overlay_peer_table" |
| ... | ... |
@@ -90,7 +90,7 @@ func (d *driver) peerDbNetworkWalk(nid string, f func(*peerKey, *peerEntry) bool |
| 90 | 90 |
for pKeyStr, pEntry := range pMap.mp {
|
| 91 | 91 |
var pKey peerKey |
| 92 | 92 |
if _, err := fmt.Sscan(pKeyStr, &pKey); err != nil {
|
| 93 |
- log.Warnf("Peer key scan on network %s failed: %v", nid, err)
|
|
| 93 |
+ logrus.Warnf("Peer key scan on network %s failed: %v", nid, err)
|
|
| 94 | 94 |
} |
| 95 | 95 |
|
| 96 | 96 |
if f(&pKey, &pEntry) {
|
| ... | ... |
@@ -289,7 +289,7 @@ func (d *driver) peerAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask, |
| 289 | 289 |
} |
| 290 | 290 |
|
| 291 | 291 |
if err := d.checkEncryption(nid, vtep, n.vxlanID(s), false, true); err != nil {
|
| 292 |
- log.Warn(err) |
|
| 292 |
+ logrus.Warn(err) |
|
| 293 | 293 |
} |
| 294 | 294 |
|
| 295 | 295 |
// Add neighbor entry for the peer IP |
| ... | ... |
@@ -349,7 +349,7 @@ func (d *driver) peerDelete(nid, eid string, peerIP net.IP, peerIPMask net.IPMas |
| 349 | 349 |
} |
| 350 | 350 |
|
| 351 | 351 |
if err := d.checkEncryption(nid, vtep, 0, false, false); err != nil {
|
| 352 |
- log.Warn(err) |
|
| 352 |
+ logrus.Warn(err) |
|
| 353 | 353 |
} |
| 354 | 354 |
|
| 355 | 355 |
return nil |
| ... | ... |
@@ -4,7 +4,7 @@ import ( |
| 4 | 4 |
"fmt" |
| 5 | 5 |
"net" |
| 6 | 6 |
|
| 7 |
- log "github.com/Sirupsen/logrus" |
|
| 7 |
+ "github.com/Sirupsen/logrus" |
|
| 8 | 8 |
"github.com/docker/docker/pkg/plugins" |
| 9 | 9 |
"github.com/docker/libnetwork/datastore" |
| 10 | 10 |
"github.com/docker/libnetwork/discoverapi" |
| ... | ... |
@@ -39,11 +39,11 @@ func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
| 39 | 39 |
d := newDriver(name, client) |
| 40 | 40 |
c, err := d.(*driver).getCapabilities() |
| 41 | 41 |
if err != nil {
|
| 42 |
- log.Errorf("error getting capability for %s due to %v", name, err)
|
|
| 42 |
+ logrus.Errorf("error getting capability for %s due to %v", name, err)
|
|
| 43 | 43 |
return |
| 44 | 44 |
} |
| 45 | 45 |
if err = dc.RegisterDriver(name, d, *c); err != nil {
|
| 46 |
- log.Errorf("error registering driver for %s due to %v", name, err)
|
|
| 46 |
+ logrus.Errorf("error registering driver for %s due to %v", name, err)
|
|
| 47 | 47 |
} |
| 48 | 48 |
}) |
| 49 | 49 |
return nil |
| ... | ... |
@@ -390,7 +390,7 @@ func bridgeSetup(config *networkConfiguration) error {
|
| 390 | 390 |
"/usr/bin/grep " + config.DefaultBindingIP.String() |
| 391 | 391 |
out, err := exec.Command("/usr/bin/bash", "-c", ipadmCmd).Output()
|
| 392 | 392 |
if err != nil {
|
| 393 |
- logrus.Warnf("cannot find binding interface")
|
|
| 393 |
+ logrus.Warn("cannot find binding interface")
|
|
| 394 | 394 |
return err |
| 395 | 395 |
} |
| 396 | 396 |
bindingIntf = strings.SplitN(string(out), "/", 2)[0] |
| ... | ... |
@@ -456,21 +456,21 @@ func bridgeCleanup(config *networkConfiguration, logErr bool) {
|
| 456 | 456 |
|
| 457 | 457 |
err = exec.Command("/usr/sbin/pfctl", "-a", pfAnchor, "-F", "all").Run()
|
| 458 | 458 |
if err != nil && logErr {
|
| 459 |
- logrus.Warnf("cannot flush firewall rules")
|
|
| 459 |
+ logrus.Warn("cannot flush firewall rules")
|
|
| 460 | 460 |
} |
| 461 | 461 |
err = exec.Command("/usr/sbin/ifconfig", gwName, "unplumb").Run()
|
| 462 | 462 |
if err != nil && logErr {
|
| 463 |
- logrus.Warnf("cannot remove gateway interface")
|
|
| 463 |
+ logrus.Warn("cannot remove gateway interface")
|
|
| 464 | 464 |
} |
| 465 | 465 |
err = exec.Command("/usr/sbin/dladm", "delete-vnic",
|
| 466 | 466 |
"-t", gwName).Run() |
| 467 | 467 |
if err != nil && logErr {
|
| 468 |
- logrus.Warnf("cannot delete vnic")
|
|
| 468 |
+ logrus.Warn("cannot delete vnic")
|
|
| 469 | 469 |
} |
| 470 | 470 |
err = exec.Command("/usr/sbin/dladm", "delete-etherstub",
|
| 471 | 471 |
"-t", config.BridgeNameInternal).Run() |
| 472 | 472 |
if err != nil && logErr {
|
| 473 |
- logrus.Warnf("cannot delete etherstub")
|
|
| 473 |
+ logrus.Warn("cannot delete etherstub")
|
|
| 474 | 474 |
} |
| 475 | 475 |
err = exec.Command("/usr/sbin/pfctl", "-a", tableAnchor, "-t", tableName, "-T", "delete", gwIP).Run()
|
| 476 | 476 |
if err != nil && logErr {
|
| ... | ... |
@@ -36,7 +36,7 @@ func addPFRules(epid, bindIntf string, bs []types.PortBinding) {
|
| 36 | 36 |
f, err := os.OpenFile(fname, |
| 37 | 37 |
os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600) |
| 38 | 38 |
if err != nil {
|
| 39 |
- logrus.Warnf("cannot open temp pf file")
|
|
| 39 |
+ logrus.Warn("cannot open temp pf file")
|
|
| 40 | 40 |
return |
| 41 | 41 |
} |
| 42 | 42 |
for _, b := range bs {
|
| 43 | 43 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,274 @@ |
| 0 |
+package overlay |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "bytes" |
|
| 4 |
+ "encoding/binary" |
|
| 5 |
+ "encoding/hex" |
|
| 6 |
+ "fmt" |
|
| 7 |
+ "hash/fnv" |
|
| 8 |
+ "net" |
|
| 9 |
+ "sync" |
|
| 10 |
+ |
|
| 11 |
+ "github.com/Sirupsen/logrus" |
|
| 12 |
+ "github.com/docker/libnetwork/types" |
|
| 13 |
+) |
|
| 14 |
+ |
|
| 15 |
+const ( |
|
| 16 |
+ mark = uint32(0xD0C4E3) |
|
| 17 |
+ timeout = 30 |
|
| 18 |
+ pktExpansion = 26 // SPI(4) + SeqN(4) + IV(8) + PadLength(1) + NextHeader(1) + ICV(8) |
|
| 19 |
+) |
|
| 20 |
+ |
|
| 21 |
+const ( |
|
| 22 |
+ forward = iota + 1 |
|
| 23 |
+ reverse |
|
| 24 |
+ bidir |
|
| 25 |
+) |
|
| 26 |
+ |
|
| 27 |
+type key struct {
|
|
| 28 |
+ value []byte |
|
| 29 |
+ tag uint32 |
|
| 30 |
+} |
|
| 31 |
+ |
|
| 32 |
+func (k *key) String() string {
|
|
| 33 |
+ if k != nil {
|
|
| 34 |
+ return fmt.Sprintf("(key: %s, tag: 0x%x)", hex.EncodeToString(k.value)[0:5], k.tag)
|
|
| 35 |
+ } |
|
| 36 |
+ return "" |
|
| 37 |
+} |
|
| 38 |
+ |
|
| 39 |
+type spi struct {
|
|
| 40 |
+ forward int |
|
| 41 |
+ reverse int |
|
| 42 |
+} |
|
| 43 |
+ |
|
| 44 |
+func (s *spi) String() string {
|
|
| 45 |
+ return fmt.Sprintf("SPI(FWD: 0x%x, REV: 0x%x)", uint32(s.forward), uint32(s.reverse))
|
|
| 46 |
+} |
|
| 47 |
+ |
|
| 48 |
+type encrMap struct {
|
|
| 49 |
+ nodes map[string][]*spi |
|
| 50 |
+ sync.Mutex |
|
| 51 |
+} |
|
| 52 |
+ |
|
| 53 |
+func (e *encrMap) String() string {
|
|
| 54 |
+ e.Lock() |
|
| 55 |
+ defer e.Unlock() |
|
| 56 |
+ b := new(bytes.Buffer) |
|
| 57 |
+ for k, v := range e.nodes {
|
|
| 58 |
+ b.WriteString("\n")
|
|
| 59 |
+ b.WriteString(k) |
|
| 60 |
+ b.WriteString(":")
|
|
| 61 |
+ b.WriteString("[")
|
|
| 62 |
+ for _, s := range v {
|
|
| 63 |
+ b.WriteString(s.String()) |
|
| 64 |
+ b.WriteString(",")
|
|
| 65 |
+ } |
|
| 66 |
+ b.WriteString("]")
|
|
| 67 |
+ |
|
| 68 |
+ } |
|
| 69 |
+ return b.String() |
|
| 70 |
+} |
|
| 71 |
+ |
|
| 72 |
+func (d *driver) checkEncryption(nid string, rIP net.IP, vxlanID uint32, isLocal, add bool) error {
|
|
| 73 |
+ logrus.Debugf("checkEncryption(%s, %v, %d, %t)", nid[0:7], rIP, vxlanID, isLocal)
|
|
| 74 |
+ |
|
| 75 |
+ n := d.network(nid) |
|
| 76 |
+ if n == nil || !n.secure {
|
|
| 77 |
+ return nil |
|
| 78 |
+ } |
|
| 79 |
+ |
|
| 80 |
+ if len(d.keys) == 0 {
|
|
| 81 |
+ return types.ForbiddenErrorf("encryption key is not present")
|
|
| 82 |
+ } |
|
| 83 |
+ |
|
| 84 |
+ lIP := net.ParseIP(d.bindAddress) |
|
| 85 |
+ aIP := net.ParseIP(d.advertiseAddress) |
|
| 86 |
+ nodes := map[string]net.IP{}
|
|
| 87 |
+ |
|
| 88 |
+ switch {
|
|
| 89 |
+ case isLocal: |
|
| 90 |
+ if err := d.peerDbNetworkWalk(nid, func(pKey *peerKey, pEntry *peerEntry) bool {
|
|
| 91 |
+ if !aIP.Equal(pEntry.vtep) {
|
|
| 92 |
+ nodes[pEntry.vtep.String()] = pEntry.vtep |
|
| 93 |
+ } |
|
| 94 |
+ return false |
|
| 95 |
+ }); err != nil {
|
|
| 96 |
+ logrus.Warnf("Failed to retrieve list of participating nodes in overlay network %s: %v", nid[0:5], err)
|
|
| 97 |
+ } |
|
| 98 |
+ default: |
|
| 99 |
+ if len(d.network(nid).endpoints) > 0 {
|
|
| 100 |
+ nodes[rIP.String()] = rIP |
|
| 101 |
+ } |
|
| 102 |
+ } |
|
| 103 |
+ |
|
| 104 |
+ logrus.Debugf("List of nodes: %s", nodes)
|
|
| 105 |
+ |
|
| 106 |
+ if add {
|
|
| 107 |
+ for _, rIP := range nodes {
|
|
| 108 |
+ if err := setupEncryption(lIP, aIP, rIP, vxlanID, d.secMap, d.keys); err != nil {
|
|
| 109 |
+ logrus.Warnf("Failed to program network encryption between %s and %s: %v", lIP, rIP, err)
|
|
| 110 |
+ } |
|
| 111 |
+ } |
|
| 112 |
+ } else {
|
|
| 113 |
+ if len(nodes) == 0 {
|
|
| 114 |
+ if err := removeEncryption(lIP, rIP, d.secMap); err != nil {
|
|
| 115 |
+ logrus.Warnf("Failed to remove network encryption between %s and %s: %v", lIP, rIP, err)
|
|
| 116 |
+ } |
|
| 117 |
+ } |
|
| 118 |
+ } |
|
| 119 |
+ |
|
| 120 |
+ return nil |
|
| 121 |
+} |
|
| 122 |
+ |
|
| 123 |
+func setupEncryption(localIP, advIP, remoteIP net.IP, vni uint32, em *encrMap, keys []*key) error {
|
|
| 124 |
+ logrus.Debugf("Programming encryption for vxlan %d between %s and %s", vni, localIP, remoteIP)
|
|
| 125 |
+ rIPs := remoteIP.String() |
|
| 126 |
+ |
|
| 127 |
+ indices := make([]*spi, 0, len(keys)) |
|
| 128 |
+ |
|
| 129 |
+ err := programMangle(vni, true) |
|
| 130 |
+ if err != nil {
|
|
| 131 |
+ logrus.Warn(err) |
|
| 132 |
+ } |
|
| 133 |
+ |
|
| 134 |
+ em.Lock() |
|
| 135 |
+ em.nodes[rIPs] = indices |
|
| 136 |
+ em.Unlock() |
|
| 137 |
+ |
|
| 138 |
+ return nil |
|
| 139 |
+} |
|
| 140 |
+ |
|
| 141 |
+func removeEncryption(localIP, remoteIP net.IP, em *encrMap) error {
|
|
| 142 |
+ return nil |
|
| 143 |
+} |
|
| 144 |
+ |
|
| 145 |
+func programMangle(vni uint32, add bool) (err error) {
|
|
| 146 |
+ return |
|
| 147 |
+} |
|
| 148 |
+ |
|
| 149 |
+func buildSPI(src, dst net.IP, st uint32) int {
|
|
| 150 |
+ b := make([]byte, 4) |
|
| 151 |
+ binary.BigEndian.PutUint32(b, st) |
|
| 152 |
+ h := fnv.New32a() |
|
| 153 |
+ h.Write(src) |
|
| 154 |
+ h.Write(b) |
|
| 155 |
+ h.Write(dst) |
|
| 156 |
+ return int(binary.BigEndian.Uint32(h.Sum(nil))) |
|
| 157 |
+} |
|
| 158 |
+ |
|
| 159 |
+func (d *driver) secMapWalk(f func(string, []*spi) ([]*spi, bool)) error {
|
|
| 160 |
+ d.secMap.Lock() |
|
| 161 |
+ for node, indices := range d.secMap.nodes {
|
|
| 162 |
+ idxs, stop := f(node, indices) |
|
| 163 |
+ if idxs != nil {
|
|
| 164 |
+ d.secMap.nodes[node] = idxs |
|
| 165 |
+ } |
|
| 166 |
+ if stop {
|
|
| 167 |
+ break |
|
| 168 |
+ } |
|
| 169 |
+ } |
|
| 170 |
+ d.secMap.Unlock() |
|
| 171 |
+ return nil |
|
| 172 |
+} |
|
| 173 |
+ |
|
| 174 |
+func (d *driver) setKeys(keys []*key) error {
|
|
| 175 |
+ if d.keys != nil {
|
|
| 176 |
+ return types.ForbiddenErrorf("initial keys are already present")
|
|
| 177 |
+ } |
|
| 178 |
+ d.keys = keys |
|
| 179 |
+ logrus.Debugf("Initial encryption keys: %v", d.keys)
|
|
| 180 |
+ return nil |
|
| 181 |
+} |
|
| 182 |
+ |
|
| 183 |
+// updateKeys allows to add a new key and/or change the primary key and/or prune an existing key |
|
| 184 |
+// The primary key is the key used in transmission and will go in first position in the list. |
|
| 185 |
+func (d *driver) updateKeys(newKey, primary, pruneKey *key) error {
|
|
| 186 |
+ logrus.Debugf("Updating Keys. New: %v, Primary: %v, Pruned: %v", newKey, primary, pruneKey)
|
|
| 187 |
+ |
|
| 188 |
+ logrus.Debugf("Current: %v", d.keys)
|
|
| 189 |
+ |
|
| 190 |
+ var ( |
|
| 191 |
+ newIdx = -1 |
|
| 192 |
+ priIdx = -1 |
|
| 193 |
+ delIdx = -1 |
|
| 194 |
+ lIP = net.ParseIP(d.bindAddress) |
|
| 195 |
+ ) |
|
| 196 |
+ |
|
| 197 |
+ d.Lock() |
|
| 198 |
+ // add new |
|
| 199 |
+ if newKey != nil {
|
|
| 200 |
+ d.keys = append(d.keys, newKey) |
|
| 201 |
+ newIdx += len(d.keys) |
|
| 202 |
+ } |
|
| 203 |
+ for i, k := range d.keys {
|
|
| 204 |
+ if primary != nil && k.tag == primary.tag {
|
|
| 205 |
+ priIdx = i |
|
| 206 |
+ } |
|
| 207 |
+ if pruneKey != nil && k.tag == pruneKey.tag {
|
|
| 208 |
+ delIdx = i |
|
| 209 |
+ } |
|
| 210 |
+ } |
|
| 211 |
+ d.Unlock() |
|
| 212 |
+ |
|
| 213 |
+ if (newKey != nil && newIdx == -1) || |
|
| 214 |
+ (primary != nil && priIdx == -1) || |
|
| 215 |
+ (pruneKey != nil && delIdx == -1) {
|
|
| 216 |
+ err := types.BadRequestErrorf("cannot find proper key indices while processing key update:"+
|
|
| 217 |
+ "(newIdx,priIdx,delIdx):(%d, %d, %d)", newIdx, priIdx, delIdx) |
|
| 218 |
+ logrus.Warn(err) |
|
| 219 |
+ return err |
|
| 220 |
+ } |
|
| 221 |
+ |
|
| 222 |
+ d.secMapWalk(func(rIPs string, spis []*spi) ([]*spi, bool) {
|
|
| 223 |
+ rIP := net.ParseIP(rIPs) |
|
| 224 |
+ return updateNodeKey(lIP, rIP, spis, d.keys, newIdx, priIdx, delIdx), false |
|
| 225 |
+ }) |
|
| 226 |
+ |
|
| 227 |
+ d.Lock() |
|
| 228 |
+ // swap primary |
|
| 229 |
+ if priIdx != -1 {
|
|
| 230 |
+ swp := d.keys[0] |
|
| 231 |
+ d.keys[0] = d.keys[priIdx] |
|
| 232 |
+ d.keys[priIdx] = swp |
|
| 233 |
+ } |
|
| 234 |
+ // prune |
|
| 235 |
+ if delIdx != -1 {
|
|
| 236 |
+ if delIdx == 0 {
|
|
| 237 |
+ delIdx = priIdx |
|
| 238 |
+ } |
|
| 239 |
+ d.keys = append(d.keys[:delIdx], d.keys[delIdx+1:]...) |
|
| 240 |
+ } |
|
| 241 |
+ d.Unlock() |
|
| 242 |
+ |
|
| 243 |
+ logrus.Debugf("Updated: %v", d.keys)
|
|
| 244 |
+ |
|
| 245 |
+ return nil |
|
| 246 |
+} |
|
| 247 |
+ |
|
| 248 |
+/******************************************************** |
|
| 249 |
+ * Steady state: rSA0, rSA1, rSA2, fSA1, fSP1 |
|
| 250 |
+ * Rotation --> -rSA0, +rSA3, +fSA2, +fSP2/-fSP1, -fSA1 |
|
| 251 |
+ * Steady state: rSA1, rSA2, rSA3, fSA2, fSP2 |
|
| 252 |
+ *********************************************************/ |
|
| 253 |
+ |
|
| 254 |
+// Spis and keys are sorted in such away the one in position 0 is the primary |
|
| 255 |
+func updateNodeKey(lIP, rIP net.IP, idxs []*spi, curKeys []*key, newIdx, priIdx, delIdx int) []*spi {
|
|
| 256 |
+ logrus.Debugf("Updating keys for node: %s (%d,%d,%d)", rIP, newIdx, priIdx, delIdx)
|
|
| 257 |
+ return nil |
|
| 258 |
+} |
|
| 259 |
+ |
|
| 260 |
+func (n *network) maxMTU() int {
|
|
| 261 |
+ mtu := 1500 |
|
| 262 |
+ if n.mtu != 0 {
|
|
| 263 |
+ mtu = n.mtu |
|
| 264 |
+ } |
|
| 265 |
+ mtu -= vxlanEncap |
|
| 266 |
+ if n.secure {
|
|
| 267 |
+ // In case of encryption account for the |
|
| 268 |
+ // esp packet espansion and padding |
|
| 269 |
+ mtu -= pktExpansion |
|
| 270 |
+ mtu -= (mtu % 4) |
|
| 271 |
+ } |
|
| 272 |
+ return mtu |
|
| 273 |
+} |
| 0 | 274 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,184 @@ |
| 0 |
+package overlay |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "fmt" |
|
| 4 |
+ "net" |
|
| 5 |
+ |
|
| 6 |
+ "github.com/Sirupsen/logrus" |
|
| 7 |
+ "github.com/docker/libnetwork/driverapi" |
|
| 8 |
+ "github.com/docker/libnetwork/types" |
|
| 9 |
+ "github.com/gogo/protobuf/proto" |
|
| 10 |
+) |
|
| 11 |
+ |
|
| 12 |
+// Join method is invoked when a Sandbox is attached to an endpoint. |
|
| 13 |
+func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
|
| 14 |
+ if err := validateID(nid, eid); err != nil {
|
|
| 15 |
+ return err |
|
| 16 |
+ } |
|
| 17 |
+ |
|
| 18 |
+ n := d.network(nid) |
|
| 19 |
+ if n == nil {
|
|
| 20 |
+ return fmt.Errorf("could not find network with id %s", nid)
|
|
| 21 |
+ } |
|
| 22 |
+ |
|
| 23 |
+ ep := n.endpoint(eid) |
|
| 24 |
+ if ep == nil {
|
|
| 25 |
+ return fmt.Errorf("could not find endpoint with id %s", eid)
|
|
| 26 |
+ } |
|
| 27 |
+ |
|
| 28 |
+ if n.secure && len(d.keys) == 0 {
|
|
| 29 |
+ return fmt.Errorf("cannot join secure network: encryption keys not present")
|
|
| 30 |
+ } |
|
| 31 |
+ |
|
| 32 |
+ s := n.getSubnetforIP(ep.addr) |
|
| 33 |
+ if s == nil {
|
|
| 34 |
+ return fmt.Errorf("could not find subnet for endpoint %s", eid)
|
|
| 35 |
+ } |
|
| 36 |
+ |
|
| 37 |
+ if err := n.obtainVxlanID(s); err != nil {
|
|
| 38 |
+ return fmt.Errorf("couldn't get vxlan id for %q: %v", s.subnetIP.String(), err)
|
|
| 39 |
+ } |
|
| 40 |
+ |
|
| 41 |
+ if err := n.joinSandbox(false); err != nil {
|
|
| 42 |
+ return fmt.Errorf("network sandbox join failed: %v", err)
|
|
| 43 |
+ } |
|
| 44 |
+ |
|
| 45 |
+ if err := n.joinSubnetSandbox(s, false); err != nil {
|
|
| 46 |
+ return fmt.Errorf("subnet sandbox join failed for %q: %v", s.subnetIP.String(), err)
|
|
| 47 |
+ } |
|
| 48 |
+ |
|
| 49 |
+ // joinSubnetSandbox gets called when an endpoint comes up on a new subnet in the |
|
| 50 |
+ // overlay network. Hence the Endpoint count should be updated outside joinSubnetSandbox |
|
| 51 |
+ n.incEndpointCount() |
|
| 52 |
+ |
|
| 53 |
+ // Add creating a veth Pair for Solaris |
|
| 54 |
+ |
|
| 55 |
+ containerIfName := "solaris-if" |
|
| 56 |
+ ep.ifName = containerIfName |
|
| 57 |
+ |
|
| 58 |
+ if err := d.writeEndpointToStore(ep); err != nil {
|
|
| 59 |
+ return fmt.Errorf("failed to update overlay endpoint %s to local data store: %v", ep.id[0:7], err)
|
|
| 60 |
+ } |
|
| 61 |
+ |
|
| 62 |
+ // Add solaris plumbing to add veth (with ep mac addr) to sandbox |
|
| 63 |
+ |
|
| 64 |
+ for _, sub := range n.subnets {
|
|
| 65 |
+ if sub == s {
|
|
| 66 |
+ continue |
|
| 67 |
+ } |
|
| 68 |
+ if err := jinfo.AddStaticRoute(sub.subnetIP, types.NEXTHOP, s.gwIP.IP); err != nil {
|
|
| 69 |
+ logrus.Errorf("Adding subnet %s static route in network %q failed\n", s.subnetIP, n.id)
|
|
| 70 |
+ } |
|
| 71 |
+ } |
|
| 72 |
+ |
|
| 73 |
+ if iNames := jinfo.InterfaceName(); iNames != nil {
|
|
| 74 |
+ err := iNames.SetNames(containerIfName, "eth") |
|
| 75 |
+ if err != nil {
|
|
| 76 |
+ return err |
|
| 77 |
+ } |
|
| 78 |
+ } |
|
| 79 |
+ |
|
| 80 |
+ d.peerDbAdd(nid, eid, ep.addr.IP, ep.addr.Mask, ep.mac, |
|
| 81 |
+ net.ParseIP(d.advertiseAddress), true) |
|
| 82 |
+ |
|
| 83 |
+ if err := d.checkEncryption(nid, nil, n.vxlanID(s), true, true); err != nil {
|
|
| 84 |
+ logrus.Warn(err) |
|
| 85 |
+ } |
|
| 86 |
+ |
|
| 87 |
+ buf, err := proto.Marshal(&PeerRecord{
|
|
| 88 |
+ EndpointIP: ep.addr.String(), |
|
| 89 |
+ EndpointMAC: ep.mac.String(), |
|
| 90 |
+ TunnelEndpointIP: d.advertiseAddress, |
|
| 91 |
+ }) |
|
| 92 |
+ if err != nil {
|
|
| 93 |
+ return err |
|
| 94 |
+ } |
|
| 95 |
+ |
|
| 96 |
+ if err := jinfo.AddTableEntry(ovPeerTable, eid, buf); err != nil {
|
|
| 97 |
+ logrus.Errorf("overlay: Failed adding table entry to joininfo: %v", err)
|
|
| 98 |
+ } |
|
| 99 |
+ |
|
| 100 |
+ d.pushLocalEndpointEvent("join", nid, eid)
|
|
| 101 |
+ |
|
| 102 |
+ return nil |
|
| 103 |
+} |
|
| 104 |
+ |
|
| 105 |
+func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
|
|
| 106 |
+ if tableName != ovPeerTable {
|
|
| 107 |
+ logrus.Errorf("Unexpected table notification for table %s received", tableName)
|
|
| 108 |
+ return |
|
| 109 |
+ } |
|
| 110 |
+ |
|
| 111 |
+ eid := key |
|
| 112 |
+ |
|
| 113 |
+ var peer PeerRecord |
|
| 114 |
+ if err := proto.Unmarshal(value, &peer); err != nil {
|
|
| 115 |
+ logrus.Errorf("Failed to unmarshal peer record: %v", err)
|
|
| 116 |
+ return |
|
| 117 |
+ } |
|
| 118 |
+ |
|
| 119 |
+ // Ignore local peers. We already know about them and they |
|
| 120 |
+ // should not be added to vxlan fdb. |
|
| 121 |
+ if peer.TunnelEndpointIP == d.advertiseAddress {
|
|
| 122 |
+ return |
|
| 123 |
+ } |
|
| 124 |
+ |
|
| 125 |
+ addr, err := types.ParseCIDR(peer.EndpointIP) |
|
| 126 |
+ if err != nil {
|
|
| 127 |
+ logrus.Errorf("Invalid peer IP %s received in event notify", peer.EndpointIP)
|
|
| 128 |
+ return |
|
| 129 |
+ } |
|
| 130 |
+ |
|
| 131 |
+ mac, err := net.ParseMAC(peer.EndpointMAC) |
|
| 132 |
+ if err != nil {
|
|
| 133 |
+ logrus.Errorf("Invalid mac %s received in event notify", peer.EndpointMAC)
|
|
| 134 |
+ return |
|
| 135 |
+ } |
|
| 136 |
+ |
|
| 137 |
+ vtep := net.ParseIP(peer.TunnelEndpointIP) |
|
| 138 |
+ if vtep == nil {
|
|
| 139 |
+ logrus.Errorf("Invalid VTEP %s received in event notify", peer.TunnelEndpointIP)
|
|
| 140 |
+ return |
|
| 141 |
+ } |
|
| 142 |
+ |
|
| 143 |
+ if etype == driverapi.Delete {
|
|
| 144 |
+ d.peerDelete(nid, eid, addr.IP, addr.Mask, mac, vtep, true) |
|
| 145 |
+ return |
|
| 146 |
+ } |
|
| 147 |
+ |
|
| 148 |
+ d.peerAdd(nid, eid, addr.IP, addr.Mask, mac, vtep, true) |
|
| 149 |
+} |
|
| 150 |
+ |
|
| 151 |
+// Leave method is invoked when a Sandbox detaches from an endpoint. |
|
| 152 |
+func (d *driver) Leave(nid, eid string) error {
|
|
| 153 |
+ if err := validateID(nid, eid); err != nil {
|
|
| 154 |
+ return err |
|
| 155 |
+ } |
|
| 156 |
+ |
|
| 157 |
+ n := d.network(nid) |
|
| 158 |
+ if n == nil {
|
|
| 159 |
+ return fmt.Errorf("could not find network with id %s", nid)
|
|
| 160 |
+ } |
|
| 161 |
+ |
|
| 162 |
+ ep := n.endpoint(eid) |
|
| 163 |
+ |
|
| 164 |
+ if ep == nil {
|
|
| 165 |
+ return types.InternalMaskableErrorf("could not find endpoint with id %s", eid)
|
|
| 166 |
+ } |
|
| 167 |
+ |
|
| 168 |
+ if d.notifyCh != nil {
|
|
| 169 |
+ d.notifyCh <- ovNotify{
|
|
| 170 |
+ action: "leave", |
|
| 171 |
+ nw: n, |
|
| 172 |
+ ep: ep, |
|
| 173 |
+ } |
|
| 174 |
+ } |
|
| 175 |
+ |
|
| 176 |
+ n.leaveSandbox() |
|
| 177 |
+ |
|
| 178 |
+ if err := d.checkEncryption(nid, nil, 0, true, false); err != nil {
|
|
| 179 |
+ logrus.Warn(err) |
|
| 180 |
+ } |
|
| 181 |
+ |
|
| 182 |
+ return nil |
|
| 183 |
+} |
| 0 | 184 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,249 @@ |
| 0 |
+package overlay |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "encoding/json" |
|
| 4 |
+ "fmt" |
|
| 5 |
+ "net" |
|
| 6 |
+ |
|
| 7 |
+ "github.com/Sirupsen/logrus" |
|
| 8 |
+ "github.com/docker/libnetwork/datastore" |
|
| 9 |
+ "github.com/docker/libnetwork/driverapi" |
|
| 10 |
+ "github.com/docker/libnetwork/netutils" |
|
| 11 |
+ "github.com/docker/libnetwork/types" |
|
| 12 |
+) |
|
| 13 |
+ |
|
| 14 |
+type endpointTable map[string]*endpoint |
|
| 15 |
+ |
|
| 16 |
+const overlayEndpointPrefix = "overlay/endpoint" |
|
| 17 |
+ |
|
| 18 |
+type endpoint struct {
|
|
| 19 |
+ id string |
|
| 20 |
+ nid string |
|
| 21 |
+ ifName string |
|
| 22 |
+ mac net.HardwareAddr |
|
| 23 |
+ addr *net.IPNet |
|
| 24 |
+ dbExists bool |
|
| 25 |
+ dbIndex uint64 |
|
| 26 |
+} |
|
| 27 |
+ |
|
| 28 |
+func (n *network) endpoint(eid string) *endpoint {
|
|
| 29 |
+ n.Lock() |
|
| 30 |
+ defer n.Unlock() |
|
| 31 |
+ |
|
| 32 |
+ return n.endpoints[eid] |
|
| 33 |
+} |
|
| 34 |
+ |
|
| 35 |
+func (n *network) addEndpoint(ep *endpoint) {
|
|
| 36 |
+ n.Lock() |
|
| 37 |
+ n.endpoints[ep.id] = ep |
|
| 38 |
+ n.Unlock() |
|
| 39 |
+} |
|
| 40 |
+ |
|
| 41 |
+func (n *network) deleteEndpoint(eid string) {
|
|
| 42 |
+ n.Lock() |
|
| 43 |
+ delete(n.endpoints, eid) |
|
| 44 |
+ n.Unlock() |
|
| 45 |
+} |
|
| 46 |
+ |
|
| 47 |
+func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, |
|
| 48 |
+ epOptions map[string]interface{}) error {
|
|
| 49 |
+ var err error |
|
| 50 |
+ |
|
| 51 |
+ if err = validateID(nid, eid); err != nil {
|
|
| 52 |
+ return err |
|
| 53 |
+ } |
|
| 54 |
+ |
|
| 55 |
+ // Since we perform lazy configuration make sure we try |
|
| 56 |
+ // configuring the driver when we enter CreateEndpoint since |
|
| 57 |
+ // CreateNetwork may not be called in every node. |
|
| 58 |
+ if err := d.configure(); err != nil {
|
|
| 59 |
+ return err |
|
| 60 |
+ } |
|
| 61 |
+ |
|
| 62 |
+ n := d.network(nid) |
|
| 63 |
+ if n == nil {
|
|
| 64 |
+ return fmt.Errorf("network id %q not found", nid)
|
|
| 65 |
+ } |
|
| 66 |
+ |
|
| 67 |
+ ep := &endpoint{
|
|
| 68 |
+ id: eid, |
|
| 69 |
+ nid: n.id, |
|
| 70 |
+ addr: ifInfo.Address(), |
|
| 71 |
+ mac: ifInfo.MacAddress(), |
|
| 72 |
+ } |
|
| 73 |
+ if ep.addr == nil {
|
|
| 74 |
+ return fmt.Errorf("create endpoint was not passed interface IP address")
|
|
| 75 |
+ } |
|
| 76 |
+ |
|
| 77 |
+ if s := n.getSubnetforIP(ep.addr); s == nil {
|
|
| 78 |
+ return fmt.Errorf("no matching subnet for IP %q in network %q\n", ep.addr, nid)
|
|
| 79 |
+ } |
|
| 80 |
+ |
|
| 81 |
+ if ep.mac == nil {
|
|
| 82 |
+ ep.mac = netutils.GenerateMACFromIP(ep.addr.IP) |
|
| 83 |
+ if err := ifInfo.SetMacAddress(ep.mac); err != nil {
|
|
| 84 |
+ return err |
|
| 85 |
+ } |
|
| 86 |
+ } |
|
| 87 |
+ |
|
| 88 |
+ n.addEndpoint(ep) |
|
| 89 |
+ |
|
| 90 |
+ if err := d.writeEndpointToStore(ep); err != nil {
|
|
| 91 |
+ return fmt.Errorf("failed to update overlay endpoint %s to local store: %v", ep.id[0:7], err)
|
|
| 92 |
+ } |
|
| 93 |
+ |
|
| 94 |
+ return nil |
|
| 95 |
+} |
|
| 96 |
+ |
|
| 97 |
+func (d *driver) DeleteEndpoint(nid, eid string) error {
|
|
| 98 |
+ if err := validateID(nid, eid); err != nil {
|
|
| 99 |
+ return err |
|
| 100 |
+ } |
|
| 101 |
+ |
|
| 102 |
+ n := d.network(nid) |
|
| 103 |
+ if n == nil {
|
|
| 104 |
+ return fmt.Errorf("network id %q not found", nid)
|
|
| 105 |
+ } |
|
| 106 |
+ |
|
| 107 |
+ ep := n.endpoint(eid) |
|
| 108 |
+ if ep == nil {
|
|
| 109 |
+ return fmt.Errorf("endpoint id %q not found", eid)
|
|
| 110 |
+ } |
|
| 111 |
+ |
|
| 112 |
+ n.deleteEndpoint(eid) |
|
| 113 |
+ |
|
| 114 |
+ if err := d.deleteEndpointFromStore(ep); err != nil {
|
|
| 115 |
+ logrus.Warnf("Failed to delete overlay endpoint %s from local store: %v", ep.id[0:7], err)
|
|
| 116 |
+ } |
|
| 117 |
+ |
|
| 118 |
+ if ep.ifName == "" {
|
|
| 119 |
+ return nil |
|
| 120 |
+ } |
|
| 121 |
+ |
|
| 122 |
+ // OVERLAY_SOLARIS: Add Solaris unplumbing for removing the interface endpoint |
|
| 123 |
+ |
|
| 124 |
+ return nil |
|
| 125 |
+} |
|
| 126 |
+ |
|
| 127 |
+func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) {
|
|
| 128 |
+ return make(map[string]interface{}, 0), nil
|
|
| 129 |
+} |
|
| 130 |
+ |
|
| 131 |
+func (d *driver) deleteEndpointFromStore(e *endpoint) error {
|
|
| 132 |
+ if d.localStore == nil {
|
|
| 133 |
+ return fmt.Errorf("overlay local store not initialized, ep not deleted")
|
|
| 134 |
+ } |
|
| 135 |
+ |
|
| 136 |
+ if err := d.localStore.DeleteObjectAtomic(e); err != nil {
|
|
| 137 |
+ return err |
|
| 138 |
+ } |
|
| 139 |
+ |
|
| 140 |
+ return nil |
|
| 141 |
+} |
|
| 142 |
+ |
|
| 143 |
+func (d *driver) writeEndpointToStore(e *endpoint) error {
|
|
| 144 |
+ if d.localStore == nil {
|
|
| 145 |
+ return fmt.Errorf("overlay local store not initialized, ep not added")
|
|
| 146 |
+ } |
|
| 147 |
+ |
|
| 148 |
+ if err := d.localStore.PutObjectAtomic(e); err != nil {
|
|
| 149 |
+ return err |
|
| 150 |
+ } |
|
| 151 |
+ return nil |
|
| 152 |
+} |
|
| 153 |
+ |
|
| 154 |
+func (ep *endpoint) DataScope() string {
|
|
| 155 |
+ return datastore.LocalScope |
|
| 156 |
+} |
|
| 157 |
+ |
|
| 158 |
+func (ep *endpoint) New() datastore.KVObject {
|
|
| 159 |
+ return &endpoint{}
|
|
| 160 |
+} |
|
| 161 |
+ |
|
| 162 |
+func (ep *endpoint) CopyTo(o datastore.KVObject) error {
|
|
| 163 |
+ dstep := o.(*endpoint) |
|
| 164 |
+ *dstep = *ep |
|
| 165 |
+ return nil |
|
| 166 |
+} |
|
| 167 |
+ |
|
| 168 |
+func (ep *endpoint) Key() []string {
|
|
| 169 |
+ return []string{overlayEndpointPrefix, ep.id}
|
|
| 170 |
+} |
|
| 171 |
+ |
|
| 172 |
+func (ep *endpoint) KeyPrefix() []string {
|
|
| 173 |
+ return []string{overlayEndpointPrefix}
|
|
| 174 |
+} |
|
| 175 |
+ |
|
| 176 |
+func (ep *endpoint) Index() uint64 {
|
|
| 177 |
+ return ep.dbIndex |
|
| 178 |
+} |
|
| 179 |
+ |
|
| 180 |
+func (ep *endpoint) SetIndex(index uint64) {
|
|
| 181 |
+ ep.dbIndex = index |
|
| 182 |
+ ep.dbExists = true |
|
| 183 |
+} |
|
| 184 |
+ |
|
| 185 |
+func (ep *endpoint) Exists() bool {
|
|
| 186 |
+ return ep.dbExists |
|
| 187 |
+} |
|
| 188 |
+ |
|
| 189 |
+func (ep *endpoint) Skip() bool {
|
|
| 190 |
+ return false |
|
| 191 |
+} |
|
| 192 |
+ |
|
| 193 |
+func (ep *endpoint) Value() []byte {
|
|
| 194 |
+ b, err := json.Marshal(ep) |
|
| 195 |
+ if err != nil {
|
|
| 196 |
+ return nil |
|
| 197 |
+ } |
|
| 198 |
+ return b |
|
| 199 |
+} |
|
| 200 |
+ |
|
| 201 |
+func (ep *endpoint) SetValue(value []byte) error {
|
|
| 202 |
+ return json.Unmarshal(value, ep) |
|
| 203 |
+} |
|
| 204 |
+ |
|
| 205 |
+func (ep *endpoint) MarshalJSON() ([]byte, error) {
|
|
| 206 |
+ epMap := make(map[string]interface{})
|
|
| 207 |
+ |
|
| 208 |
+ epMap["id"] = ep.id |
|
| 209 |
+ epMap["nid"] = ep.nid |
|
| 210 |
+ if ep.ifName != "" {
|
|
| 211 |
+ epMap["ifName"] = ep.ifName |
|
| 212 |
+ } |
|
| 213 |
+ if ep.addr != nil {
|
|
| 214 |
+ epMap["addr"] = ep.addr.String() |
|
| 215 |
+ } |
|
| 216 |
+ if len(ep.mac) != 0 {
|
|
| 217 |
+ epMap["mac"] = ep.mac.String() |
|
| 218 |
+ } |
|
| 219 |
+ |
|
| 220 |
+ return json.Marshal(epMap) |
|
| 221 |
+} |
|
| 222 |
+ |
|
| 223 |
+func (ep *endpoint) UnmarshalJSON(value []byte) error {
|
|
| 224 |
+ var ( |
|
| 225 |
+ err error |
|
| 226 |
+ epMap map[string]interface{}
|
|
| 227 |
+ ) |
|
| 228 |
+ |
|
| 229 |
+ json.Unmarshal(value, &epMap) |
|
| 230 |
+ |
|
| 231 |
+ ep.id = epMap["id"].(string) |
|
| 232 |
+ ep.nid = epMap["nid"].(string) |
|
| 233 |
+ if v, ok := epMap["mac"]; ok {
|
|
| 234 |
+ if ep.mac, err = net.ParseMAC(v.(string)); err != nil {
|
|
| 235 |
+ return types.InternalErrorf("failed to decode endpoint interface mac address after json unmarshal: %s", v.(string))
|
|
| 236 |
+ } |
|
| 237 |
+ } |
|
| 238 |
+ if v, ok := epMap["addr"]; ok {
|
|
| 239 |
+ if ep.addr, err = types.ParseCIDR(v.(string)); err != nil {
|
|
| 240 |
+ return types.InternalErrorf("failed to decode endpoint interface ipv4 address after json unmarshal: %v", err)
|
|
| 241 |
+ } |
|
| 242 |
+ } |
|
| 243 |
+ if v, ok := epMap["ifName"]; ok {
|
|
| 244 |
+ ep.ifName = v.(string) |
|
| 245 |
+ } |
|
| 246 |
+ |
|
| 247 |
+ return nil |
|
| 248 |
+} |
| 0 | 249 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,791 @@ |
| 0 |
+package overlay |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "encoding/json" |
|
| 4 |
+ "fmt" |
|
| 5 |
+ "net" |
|
| 6 |
+ "os" |
|
| 7 |
+ "path/filepath" |
|
| 8 |
+ "strconv" |
|
| 9 |
+ "strings" |
|
| 10 |
+ "sync" |
|
| 11 |
+ |
|
| 12 |
+ "github.com/Sirupsen/logrus" |
|
| 13 |
+ "github.com/docker/libnetwork/datastore" |
|
| 14 |
+ "github.com/docker/libnetwork/driverapi" |
|
| 15 |
+ "github.com/docker/libnetwork/netlabel" |
|
| 16 |
+ "github.com/docker/libnetwork/netutils" |
|
| 17 |
+ "github.com/docker/libnetwork/osl" |
|
| 18 |
+ "github.com/docker/libnetwork/resolvconf" |
|
| 19 |
+ "github.com/docker/libnetwork/types" |
|
| 20 |
+) |
|
| 21 |
+ |
|
| 22 |
+var ( |
|
| 23 |
+ hostMode bool |
|
| 24 |
+ networkOnce sync.Once |
|
| 25 |
+ networkMu sync.Mutex |
|
| 26 |
+ vniTbl = make(map[uint32]string) |
|
| 27 |
+) |
|
| 28 |
+ |
|
| 29 |
+type networkTable map[string]*network |
|
| 30 |
+ |
|
| 31 |
+type subnet struct {
|
|
| 32 |
+ once *sync.Once |
|
| 33 |
+ vxlanName string |
|
| 34 |
+ brName string |
|
| 35 |
+ vni uint32 |
|
| 36 |
+ initErr error |
|
| 37 |
+ subnetIP *net.IPNet |
|
| 38 |
+ gwIP *net.IPNet |
|
| 39 |
+} |
|
| 40 |
+ |
|
| 41 |
+type subnetJSON struct {
|
|
| 42 |
+ SubnetIP string |
|
| 43 |
+ GwIP string |
|
| 44 |
+ Vni uint32 |
|
| 45 |
+} |
|
| 46 |
+ |
|
| 47 |
+type network struct {
|
|
| 48 |
+ id string |
|
| 49 |
+ dbIndex uint64 |
|
| 50 |
+ dbExists bool |
|
| 51 |
+ sbox osl.Sandbox |
|
| 52 |
+ endpoints endpointTable |
|
| 53 |
+ driver *driver |
|
| 54 |
+ joinCnt int |
|
| 55 |
+ once *sync.Once |
|
| 56 |
+ initEpoch int |
|
| 57 |
+ initErr error |
|
| 58 |
+ subnets []*subnet |
|
| 59 |
+ secure bool |
|
| 60 |
+ mtu int |
|
| 61 |
+ sync.Mutex |
|
| 62 |
+} |
|
| 63 |
+ |
|
| 64 |
+func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {
|
|
| 65 |
+ return nil, types.NotImplementedErrorf("not implemented")
|
|
| 66 |
+} |
|
| 67 |
+ |
|
| 68 |
+func (d *driver) NetworkFree(id string) error {
|
|
| 69 |
+ return types.NotImplementedErrorf("not implemented")
|
|
| 70 |
+} |
|
| 71 |
+ |
|
| 72 |
+func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
|
|
| 73 |
+ if id == "" {
|
|
| 74 |
+ return fmt.Errorf("invalid network id")
|
|
| 75 |
+ } |
|
| 76 |
+ if len(ipV4Data) == 0 || ipV4Data[0].Pool.String() == "0.0.0.0/0" {
|
|
| 77 |
+ return types.BadRequestErrorf("ipv4 pool is empty")
|
|
| 78 |
+ } |
|
| 79 |
+ |
|
| 80 |
+ // Since we perform lazy configuration make sure we try |
|
| 81 |
+ // configuring the driver when we enter CreateNetwork |
|
| 82 |
+ if err := d.configure(); err != nil {
|
|
| 83 |
+ return err |
|
| 84 |
+ } |
|
| 85 |
+ |
|
| 86 |
+ n := &network{
|
|
| 87 |
+ id: id, |
|
| 88 |
+ driver: d, |
|
| 89 |
+ endpoints: endpointTable{},
|
|
| 90 |
+ once: &sync.Once{},
|
|
| 91 |
+ subnets: []*subnet{},
|
|
| 92 |
+ } |
|
| 93 |
+ |
|
| 94 |
+ vnis := make([]uint32, 0, len(ipV4Data)) |
|
| 95 |
+ if gval, ok := option[netlabel.GenericData]; ok {
|
|
| 96 |
+ optMap := gval.(map[string]string) |
|
| 97 |
+ if val, ok := optMap[netlabel.OverlayVxlanIDList]; ok {
|
|
| 98 |
+ logrus.Debugf("overlay: Received vxlan IDs: %s", val)
|
|
| 99 |
+ vniStrings := strings.Split(val, ",") |
|
| 100 |
+ for _, vniStr := range vniStrings {
|
|
| 101 |
+ vni, err := strconv.Atoi(vniStr) |
|
| 102 |
+ if err != nil {
|
|
| 103 |
+ return fmt.Errorf("invalid vxlan id value %q passed", vniStr)
|
|
| 104 |
+ } |
|
| 105 |
+ |
|
| 106 |
+ vnis = append(vnis, uint32(vni)) |
|
| 107 |
+ } |
|
| 108 |
+ } |
|
| 109 |
+ if _, ok := optMap[secureOption]; ok {
|
|
| 110 |
+ n.secure = true |
|
| 111 |
+ } |
|
| 112 |
+ if val, ok := optMap[netlabel.DriverMTU]; ok {
|
|
| 113 |
+ var err error |
|
| 114 |
+ if n.mtu, err = strconv.Atoi(val); err != nil {
|
|
| 115 |
+ return fmt.Errorf("failed to parse %v: %v", val, err)
|
|
| 116 |
+ } |
|
| 117 |
+ if n.mtu < 0 {
|
|
| 118 |
+ return fmt.Errorf("invalid MTU value: %v", n.mtu)
|
|
| 119 |
+ } |
|
| 120 |
+ } |
|
| 121 |
+ } |
|
| 122 |
+ |
|
| 123 |
+ // If we are getting vnis from libnetwork, either we get for |
|
| 124 |
+ // all subnets or none. |
|
| 125 |
+ if len(vnis) != 0 && len(vnis) < len(ipV4Data) {
|
|
| 126 |
+ return fmt.Errorf("insufficient vnis(%d) passed to overlay", len(vnis))
|
|
| 127 |
+ } |
|
| 128 |
+ |
|
| 129 |
+ for i, ipd := range ipV4Data {
|
|
| 130 |
+ s := &subnet{
|
|
| 131 |
+ subnetIP: ipd.Pool, |
|
| 132 |
+ gwIP: ipd.Gateway, |
|
| 133 |
+ once: &sync.Once{},
|
|
| 134 |
+ } |
|
| 135 |
+ |
|
| 136 |
+ if len(vnis) != 0 {
|
|
| 137 |
+ s.vni = vnis[i] |
|
| 138 |
+ } |
|
| 139 |
+ |
|
| 140 |
+ n.subnets = append(n.subnets, s) |
|
| 141 |
+ } |
|
| 142 |
+ |
|
| 143 |
+ if err := n.writeToStore(); err != nil {
|
|
| 144 |
+ return fmt.Errorf("failed to update data store for network %v: %v", n.id, err)
|
|
| 145 |
+ } |
|
| 146 |
+ |
|
| 147 |
+ // Make sure no rule is on the way from any stale secure network |
|
| 148 |
+ if !n.secure {
|
|
| 149 |
+ for _, vni := range vnis {
|
|
| 150 |
+ programMangle(vni, false) |
|
| 151 |
+ } |
|
| 152 |
+ } |
|
| 153 |
+ |
|
| 154 |
+ if nInfo != nil {
|
|
| 155 |
+ if err := nInfo.TableEventRegister(ovPeerTable); err != nil {
|
|
| 156 |
+ return err |
|
| 157 |
+ } |
|
| 158 |
+ } |
|
| 159 |
+ |
|
| 160 |
+ d.addNetwork(n) |
|
| 161 |
+ return nil |
|
| 162 |
+} |
|
| 163 |
+ |
|
| 164 |
+func (d *driver) DeleteNetwork(nid string) error {
|
|
| 165 |
+ if nid == "" {
|
|
| 166 |
+ return fmt.Errorf("invalid network id")
|
|
| 167 |
+ } |
|
| 168 |
+ |
|
| 169 |
+ // Make sure driver resources are initialized before proceeding |
|
| 170 |
+ if err := d.configure(); err != nil {
|
|
| 171 |
+ return err |
|
| 172 |
+ } |
|
| 173 |
+ |
|
| 174 |
+ n := d.network(nid) |
|
| 175 |
+ if n == nil {
|
|
| 176 |
+ return fmt.Errorf("could not find network with id %s", nid)
|
|
| 177 |
+ } |
|
| 178 |
+ |
|
| 179 |
+ d.deleteNetwork(nid) |
|
| 180 |
+ |
|
| 181 |
+ vnis, err := n.releaseVxlanID() |
|
| 182 |
+ if err != nil {
|
|
| 183 |
+ return err |
|
| 184 |
+ } |
|
| 185 |
+ |
|
| 186 |
+ if n.secure {
|
|
| 187 |
+ for _, vni := range vnis {
|
|
| 188 |
+ programMangle(vni, false) |
|
| 189 |
+ } |
|
| 190 |
+ } |
|
| 191 |
+ |
|
| 192 |
+ return nil |
|
| 193 |
+} |
|
| 194 |
+ |
|
| 195 |
+func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
|
| 196 |
+ return nil |
|
| 197 |
+} |
|
| 198 |
+ |
|
| 199 |
+func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
|
| 200 |
+ return nil |
|
| 201 |
+} |
|
| 202 |
+ |
|
| 203 |
+func (n *network) incEndpointCount() {
|
|
| 204 |
+ n.Lock() |
|
| 205 |
+ defer n.Unlock() |
|
| 206 |
+ n.joinCnt++ |
|
| 207 |
+} |
|
| 208 |
+ |
|
| 209 |
+func (n *network) joinSandbox(restore bool) error {
|
|
| 210 |
+ // If there is a race between two go routines here only one will win |
|
| 211 |
+ // the other will wait. |
|
| 212 |
+ n.once.Do(func() {
|
|
| 213 |
+ // save the error status of initSandbox in n.initErr so that |
|
| 214 |
+ // all the racing go routines are able to know the status. |
|
| 215 |
+ n.initErr = n.initSandbox(restore) |
|
| 216 |
+ }) |
|
| 217 |
+ |
|
| 218 |
+ return n.initErr |
|
| 219 |
+} |
|
| 220 |
+ |
|
| 221 |
+func (n *network) joinSubnetSandbox(s *subnet, restore bool) error {
|
|
| 222 |
+ s.once.Do(func() {
|
|
| 223 |
+ s.initErr = n.initSubnetSandbox(s, restore) |
|
| 224 |
+ }) |
|
| 225 |
+ return s.initErr |
|
| 226 |
+} |
|
| 227 |
+ |
|
| 228 |
+func (n *network) leaveSandbox() {
|
|
| 229 |
+ n.Lock() |
|
| 230 |
+ defer n.Unlock() |
|
| 231 |
+ n.joinCnt-- |
|
| 232 |
+ if n.joinCnt != 0 {
|
|
| 233 |
+ return |
|
| 234 |
+ } |
|
| 235 |
+ |
|
| 236 |
+ // We are about to destroy sandbox since the container is leaving the network |
|
| 237 |
+ // Reinitialize the once variable so that we will be able to trigger one time |
|
| 238 |
+ // sandbox initialization(again) when another container joins subsequently. |
|
| 239 |
+ n.once = &sync.Once{}
|
|
| 240 |
+ for _, s := range n.subnets {
|
|
| 241 |
+ s.once = &sync.Once{}
|
|
| 242 |
+ } |
|
| 243 |
+ |
|
| 244 |
+ n.destroySandbox() |
|
| 245 |
+} |
|
| 246 |
+ |
|
| 247 |
+// to be called while holding network lock |
|
| 248 |
+func (n *network) destroySandbox() {
|
|
| 249 |
+ if n.sbox != nil {
|
|
| 250 |
+ for _, iface := range n.sbox.Info().Interfaces() {
|
|
| 251 |
+ if err := iface.Remove(); err != nil {
|
|
| 252 |
+ logrus.Debugf("Remove interface %s failed: %v", iface.SrcName(), err)
|
|
| 253 |
+ } |
|
| 254 |
+ } |
|
| 255 |
+ |
|
| 256 |
+ for _, s := range n.subnets {
|
|
| 257 |
+ if s.vxlanName != "" {
|
|
| 258 |
+ err := deleteInterface(s.vxlanName) |
|
| 259 |
+ if err != nil {
|
|
| 260 |
+ logrus.Warnf("could not cleanup sandbox properly: %v", err)
|
|
| 261 |
+ } |
|
| 262 |
+ } |
|
| 263 |
+ } |
|
| 264 |
+ |
|
| 265 |
+ n.sbox.Destroy() |
|
| 266 |
+ n.sbox = nil |
|
| 267 |
+ } |
|
| 268 |
+} |
|
| 269 |
+ |
|
| 270 |
+func networkOnceInit() {
|
|
| 271 |
+ if os.Getenv("_OVERLAY_HOST_MODE") != "" {
|
|
| 272 |
+ hostMode = true |
|
| 273 |
+ return |
|
| 274 |
+ } |
|
| 275 |
+ |
|
| 276 |
+ err := createVxlan("testvxlan1", 1, 0)
|
|
| 277 |
+ if err != nil {
|
|
| 278 |
+ logrus.Errorf("Failed to create testvxlan1 interface: %v", err)
|
|
| 279 |
+ return |
|
| 280 |
+ } |
|
| 281 |
+ |
|
| 282 |
+ defer deleteInterface("testvxlan1")
|
|
| 283 |
+} |
|
| 284 |
+ |
|
| 285 |
+func (n *network) generateVxlanName(s *subnet) string {
|
|
| 286 |
+ id := n.id |
|
| 287 |
+ if len(n.id) > 12 {
|
|
| 288 |
+ id = n.id[:12] |
|
| 289 |
+ } |
|
| 290 |
+ |
|
| 291 |
+ return "vx_" + id + "_0" |
|
| 292 |
+} |
|
| 293 |
+ |
|
| 294 |
+func (n *network) generateBridgeName(s *subnet) string {
|
|
| 295 |
+ id := n.id |
|
| 296 |
+ if len(n.id) > 5 {
|
|
| 297 |
+ id = n.id[:5] |
|
| 298 |
+ } |
|
| 299 |
+ |
|
| 300 |
+ return n.getBridgeNamePrefix(s) + "_" + id + "_0" |
|
| 301 |
+} |
|
| 302 |
+ |
|
| 303 |
+func (n *network) getBridgeNamePrefix(s *subnet) string {
|
|
| 304 |
+ return "ov_" + fmt.Sprintf("%06x", n.vxlanID(s))
|
|
| 305 |
+} |
|
| 306 |
+ |
|
| 307 |
+func isOverlap(nw *net.IPNet) bool {
|
|
| 308 |
+ var nameservers []string |
|
| 309 |
+ |
|
| 310 |
+ if rc, err := resolvconf.Get(); err == nil {
|
|
| 311 |
+ nameservers = resolvconf.GetNameserversAsCIDR(rc.Content) |
|
| 312 |
+ } |
|
| 313 |
+ |
|
| 314 |
+ if err := netutils.CheckNameserverOverlaps(nameservers, nw); err != nil {
|
|
| 315 |
+ return true |
|
| 316 |
+ } |
|
| 317 |
+ |
|
| 318 |
+ if err := netutils.CheckRouteOverlaps(nw); err != nil {
|
|
| 319 |
+ return true |
|
| 320 |
+ } |
|
| 321 |
+ |
|
| 322 |
+ return false |
|
| 323 |
+} |
|
| 324 |
+ |
|
| 325 |
+func (n *network) restoreSubnetSandbox(s *subnet, brName, vxlanName string) error {
|
|
| 326 |
+ sbox := n.sandbox() |
|
| 327 |
+ |
|
| 328 |
+ // restore overlay osl sandbox |
|
| 329 |
+ Ifaces := make(map[string][]osl.IfaceOption) |
|
| 330 |
+ brIfaceOption := make([]osl.IfaceOption, 2) |
|
| 331 |
+ brIfaceOption = append(brIfaceOption, sbox.InterfaceOptions().Address(s.gwIP)) |
|
| 332 |
+ brIfaceOption = append(brIfaceOption, sbox.InterfaceOptions().Bridge(true)) |
|
| 333 |
+ Ifaces[fmt.Sprintf("%s+%s", brName, "br")] = brIfaceOption
|
|
| 334 |
+ |
|
| 335 |
+ err := sbox.Restore(Ifaces, nil, nil, nil) |
|
| 336 |
+ if err != nil {
|
|
| 337 |
+ return err |
|
| 338 |
+ } |
|
| 339 |
+ |
|
| 340 |
+ Ifaces = make(map[string][]osl.IfaceOption) |
|
| 341 |
+ vxlanIfaceOption := make([]osl.IfaceOption, 1) |
|
| 342 |
+ vxlanIfaceOption = append(vxlanIfaceOption, sbox.InterfaceOptions().Master(brName)) |
|
| 343 |
+ Ifaces[fmt.Sprintf("%s+%s", vxlanName, "vxlan")] = vxlanIfaceOption
|
|
| 344 |
+ err = sbox.Restore(Ifaces, nil, nil, nil) |
|
| 345 |
+ if err != nil {
|
|
| 346 |
+ return err |
|
| 347 |
+ } |
|
| 348 |
+ return nil |
|
| 349 |
+} |
|
| 350 |
+ |
|
| 351 |
+func (n *network) addInterface(srcName, dstPrefix, name string, isBridge bool) error {
|
|
| 352 |
+ return nil |
|
| 353 |
+} |
|
| 354 |
+ |
|
| 355 |
+func (n *network) setupSubnetSandbox(s *subnet, brName, vxlanName string) error {
|
|
| 356 |
+ |
|
| 357 |
+ if hostMode {
|
|
| 358 |
+ // Try to delete stale bridge interface if it exists |
|
| 359 |
+ if err := deleteInterface(brName); err != nil {
|
|
| 360 |
+ deleteInterfaceBySubnet(n.getBridgeNamePrefix(s), s) |
|
| 361 |
+ } |
|
| 362 |
+ |
|
| 363 |
+ if isOverlap(s.subnetIP) {
|
|
| 364 |
+ return fmt.Errorf("overlay subnet %s has conflicts in the host while running in host mode", s.subnetIP.String())
|
|
| 365 |
+ } |
|
| 366 |
+ } |
|
| 367 |
+ |
|
| 368 |
+ if !hostMode {
|
|
| 369 |
+ // Try to find this subnet's vni is being used in some |
|
| 370 |
+ // other namespace by looking at vniTbl that we just |
|
| 371 |
+ // populated in the once init. If a hit is found then |
|
| 372 |
+ // it must a stale namespace from previous |
|
| 373 |
+ // life. Destroy it completely and reclaim resourced. |
|
| 374 |
+ networkMu.Lock() |
|
| 375 |
+ path, ok := vniTbl[n.vxlanID(s)] |
|
| 376 |
+ networkMu.Unlock() |
|
| 377 |
+ |
|
| 378 |
+ if ok {
|
|
| 379 |
+ os.Remove(path) |
|
| 380 |
+ |
|
| 381 |
+ networkMu.Lock() |
|
| 382 |
+ delete(vniTbl, n.vxlanID(s)) |
|
| 383 |
+ networkMu.Unlock() |
|
| 384 |
+ } |
|
| 385 |
+ } |
|
| 386 |
+ |
|
| 387 |
+ err := createVxlan(vxlanName, n.vxlanID(s), n.maxMTU()) |
|
| 388 |
+ if err != nil {
|
|
| 389 |
+ return err |
|
| 390 |
+ } |
|
| 391 |
+ |
|
| 392 |
+ return nil |
|
| 393 |
+} |
|
| 394 |
+ |
|
| 395 |
+func (n *network) initSubnetSandbox(s *subnet, restore bool) error {
|
|
| 396 |
+ brName := n.generateBridgeName(s) |
|
| 397 |
+ vxlanName := n.generateVxlanName(s) |
|
| 398 |
+ |
|
| 399 |
+ if restore {
|
|
| 400 |
+ n.restoreSubnetSandbox(s, brName, vxlanName) |
|
| 401 |
+ } else {
|
|
| 402 |
+ n.setupSubnetSandbox(s, brName, vxlanName) |
|
| 403 |
+ } |
|
| 404 |
+ |
|
| 405 |
+ n.Lock() |
|
| 406 |
+ s.vxlanName = vxlanName |
|
| 407 |
+ s.brName = brName |
|
| 408 |
+ n.Unlock() |
|
| 409 |
+ |
|
| 410 |
+ return nil |
|
| 411 |
+} |
|
| 412 |
+ |
|
| 413 |
+func (n *network) cleanupStaleSandboxes() {
|
|
| 414 |
+ filepath.Walk(filepath.Dir(osl.GenerateKey("walk")),
|
|
| 415 |
+ func(path string, info os.FileInfo, err error) error {
|
|
| 416 |
+ _, fname := filepath.Split(path) |
|
| 417 |
+ |
|
| 418 |
+ pList := strings.Split(fname, "-") |
|
| 419 |
+ if len(pList) <= 1 {
|
|
| 420 |
+ return nil |
|
| 421 |
+ } |
|
| 422 |
+ |
|
| 423 |
+ pattern := pList[1] |
|
| 424 |
+ if strings.Contains(n.id, pattern) {
|
|
| 425 |
+ // Now that we have destroyed this |
|
| 426 |
+ // sandbox, remove all references to |
|
| 427 |
+ // it in vniTbl so that we don't |
|
| 428 |
+ // inadvertently destroy the sandbox |
|
| 429 |
+ // created in this life. |
|
| 430 |
+ networkMu.Lock() |
|
| 431 |
+ for vni, tblPath := range vniTbl {
|
|
| 432 |
+ if tblPath == path {
|
|
| 433 |
+ delete(vniTbl, vni) |
|
| 434 |
+ } |
|
| 435 |
+ } |
|
| 436 |
+ networkMu.Unlock() |
|
| 437 |
+ } |
|
| 438 |
+ |
|
| 439 |
+ return nil |
|
| 440 |
+ }) |
|
| 441 |
+} |
|
| 442 |
+ |
|
| 443 |
+func (n *network) initSandbox(restore bool) error {
|
|
| 444 |
+ n.Lock() |
|
| 445 |
+ n.initEpoch++ |
|
| 446 |
+ n.Unlock() |
|
| 447 |
+ |
|
| 448 |
+ networkOnce.Do(networkOnceInit) |
|
| 449 |
+ |
|
| 450 |
+ if !restore {
|
|
| 451 |
+ // If there are any stale sandboxes related to this network |
|
| 452 |
+ // from previous daemon life clean it up here |
|
| 453 |
+ n.cleanupStaleSandboxes() |
|
| 454 |
+ } |
|
| 455 |
+ |
|
| 456 |
+ // In the restore case network sandbox already exist; but we don't know |
|
| 457 |
+ // what epoch number it was created with. It has to be retrieved by |
|
| 458 |
+ // searching the net namespaces. |
|
| 459 |
+ key := "" |
|
| 460 |
+ if restore {
|
|
| 461 |
+ key = osl.GenerateKey("-" + n.id)
|
|
| 462 |
+ } else {
|
|
| 463 |
+ key = osl.GenerateKey(fmt.Sprintf("%d-", n.initEpoch) + n.id)
|
|
| 464 |
+ } |
|
| 465 |
+ |
|
| 466 |
+ sbox, err := osl.NewSandbox(key, !hostMode, restore) |
|
| 467 |
+ if err != nil {
|
|
| 468 |
+ return fmt.Errorf("could not get network sandbox (oper %t): %v", restore, err)
|
|
| 469 |
+ } |
|
| 470 |
+ |
|
| 471 |
+ n.setSandbox(sbox) |
|
| 472 |
+ |
|
| 473 |
+ if !restore {
|
|
| 474 |
+ n.driver.peerDbUpdateSandbox(n.id) |
|
| 475 |
+ } |
|
| 476 |
+ |
|
| 477 |
+ return nil |
|
| 478 |
+} |
|
| 479 |
+ |
|
| 480 |
+func (d *driver) addNetwork(n *network) {
|
|
| 481 |
+ d.Lock() |
|
| 482 |
+ d.networks[n.id] = n |
|
| 483 |
+ d.Unlock() |
|
| 484 |
+} |
|
| 485 |
+ |
|
| 486 |
+func (d *driver) deleteNetwork(nid string) {
|
|
| 487 |
+ d.Lock() |
|
| 488 |
+ delete(d.networks, nid) |
|
| 489 |
+ d.Unlock() |
|
| 490 |
+} |
|
| 491 |
+ |
|
| 492 |
+func (d *driver) network(nid string) *network {
|
|
| 493 |
+ d.Lock() |
|
| 494 |
+ networks := d.networks |
|
| 495 |
+ d.Unlock() |
|
| 496 |
+ |
|
| 497 |
+ n, ok := networks[nid] |
|
| 498 |
+ if !ok {
|
|
| 499 |
+ n = d.getNetworkFromStore(nid) |
|
| 500 |
+ if n != nil {
|
|
| 501 |
+ n.driver = d |
|
| 502 |
+ n.endpoints = endpointTable{}
|
|
| 503 |
+ n.once = &sync.Once{}
|
|
| 504 |
+ networks[nid] = n |
|
| 505 |
+ } |
|
| 506 |
+ } |
|
| 507 |
+ |
|
| 508 |
+ return n |
|
| 509 |
+} |
|
| 510 |
+ |
|
| 511 |
+func (d *driver) getNetworkFromStore(nid string) *network {
|
|
| 512 |
+ if d.store == nil {
|
|
| 513 |
+ return nil |
|
| 514 |
+ } |
|
| 515 |
+ |
|
| 516 |
+ n := &network{id: nid}
|
|
| 517 |
+ if err := d.store.GetObject(datastore.Key(n.Key()...), n); err != nil {
|
|
| 518 |
+ return nil |
|
| 519 |
+ } |
|
| 520 |
+ |
|
| 521 |
+ return n |
|
| 522 |
+} |
|
| 523 |
+ |
|
| 524 |
+func (n *network) sandbox() osl.Sandbox {
|
|
| 525 |
+ n.Lock() |
|
| 526 |
+ defer n.Unlock() |
|
| 527 |
+ |
|
| 528 |
+ return n.sbox |
|
| 529 |
+} |
|
| 530 |
+ |
|
| 531 |
+func (n *network) setSandbox(sbox osl.Sandbox) {
|
|
| 532 |
+ n.Lock() |
|
| 533 |
+ n.sbox = sbox |
|
| 534 |
+ n.Unlock() |
|
| 535 |
+} |
|
| 536 |
+ |
|
| 537 |
+func (n *network) vxlanID(s *subnet) uint32 {
|
|
| 538 |
+ n.Lock() |
|
| 539 |
+ defer n.Unlock() |
|
| 540 |
+ |
|
| 541 |
+ return s.vni |
|
| 542 |
+} |
|
| 543 |
+ |
|
| 544 |
+func (n *network) setVxlanID(s *subnet, vni uint32) {
|
|
| 545 |
+ n.Lock() |
|
| 546 |
+ s.vni = vni |
|
| 547 |
+ n.Unlock() |
|
| 548 |
+} |
|
| 549 |
+ |
|
| 550 |
+func (n *network) Key() []string {
|
|
| 551 |
+ return []string{"overlay", "network", n.id}
|
|
| 552 |
+} |
|
| 553 |
+ |
|
| 554 |
+func (n *network) KeyPrefix() []string {
|
|
| 555 |
+ return []string{"overlay", "network"}
|
|
| 556 |
+} |
|
| 557 |
+ |
|
| 558 |
+func (n *network) Value() []byte {
|
|
| 559 |
+ m := map[string]interface{}{}
|
|
| 560 |
+ |
|
| 561 |
+ netJSON := []*subnetJSON{}
|
|
| 562 |
+ |
|
| 563 |
+ for _, s := range n.subnets {
|
|
| 564 |
+ sj := &subnetJSON{
|
|
| 565 |
+ SubnetIP: s.subnetIP.String(), |
|
| 566 |
+ GwIP: s.gwIP.String(), |
|
| 567 |
+ Vni: s.vni, |
|
| 568 |
+ } |
|
| 569 |
+ netJSON = append(netJSON, sj) |
|
| 570 |
+ } |
|
| 571 |
+ |
|
| 572 |
+ b, err := json.Marshal(netJSON) |
|
| 573 |
+ if err != nil {
|
|
| 574 |
+ return []byte{}
|
|
| 575 |
+ } |
|
| 576 |
+ |
|
| 577 |
+ m["secure"] = n.secure |
|
| 578 |
+ m["subnets"] = netJSON |
|
| 579 |
+ m["mtu"] = n.mtu |
|
| 580 |
+ b, err = json.Marshal(m) |
|
| 581 |
+ if err != nil {
|
|
| 582 |
+ return []byte{}
|
|
| 583 |
+ } |
|
| 584 |
+ |
|
| 585 |
+ return b |
|
| 586 |
+} |
|
| 587 |
+ |
|
| 588 |
+func (n *network) Index() uint64 {
|
|
| 589 |
+ return n.dbIndex |
|
| 590 |
+} |
|
| 591 |
+ |
|
| 592 |
+func (n *network) SetIndex(index uint64) {
|
|
| 593 |
+ n.dbIndex = index |
|
| 594 |
+ n.dbExists = true |
|
| 595 |
+} |
|
| 596 |
+ |
|
| 597 |
+func (n *network) Exists() bool {
|
|
| 598 |
+ return n.dbExists |
|
| 599 |
+} |
|
| 600 |
+ |
|
| 601 |
+func (n *network) Skip() bool {
|
|
| 602 |
+ return false |
|
| 603 |
+} |
|
| 604 |
+ |
|
| 605 |
+func (n *network) SetValue(value []byte) error {
|
|
| 606 |
+ var ( |
|
| 607 |
+ m map[string]interface{}
|
|
| 608 |
+ newNet bool |
|
| 609 |
+ isMap = true |
|
| 610 |
+ netJSON = []*subnetJSON{}
|
|
| 611 |
+ ) |
|
| 612 |
+ |
|
| 613 |
+ if err := json.Unmarshal(value, &m); err != nil {
|
|
| 614 |
+ err := json.Unmarshal(value, &netJSON) |
|
| 615 |
+ if err != nil {
|
|
| 616 |
+ return err |
|
| 617 |
+ } |
|
| 618 |
+ isMap = false |
|
| 619 |
+ } |
|
| 620 |
+ |
|
| 621 |
+ if len(n.subnets) == 0 {
|
|
| 622 |
+ newNet = true |
|
| 623 |
+ } |
|
| 624 |
+ |
|
| 625 |
+ if isMap {
|
|
| 626 |
+ if val, ok := m["secure"]; ok {
|
|
| 627 |
+ n.secure = val.(bool) |
|
| 628 |
+ } |
|
| 629 |
+ if val, ok := m["mtu"]; ok {
|
|
| 630 |
+ n.mtu = int(val.(float64)) |
|
| 631 |
+ } |
|
| 632 |
+ bytes, err := json.Marshal(m["subnets"]) |
|
| 633 |
+ if err != nil {
|
|
| 634 |
+ return err |
|
| 635 |
+ } |
|
| 636 |
+ if err := json.Unmarshal(bytes, &netJSON); err != nil {
|
|
| 637 |
+ return err |
|
| 638 |
+ } |
|
| 639 |
+ } |
|
| 640 |
+ |
|
| 641 |
+ for _, sj := range netJSON {
|
|
| 642 |
+ subnetIPstr := sj.SubnetIP |
|
| 643 |
+ gwIPstr := sj.GwIP |
|
| 644 |
+ vni := sj.Vni |
|
| 645 |
+ |
|
| 646 |
+ subnetIP, _ := types.ParseCIDR(subnetIPstr) |
|
| 647 |
+ gwIP, _ := types.ParseCIDR(gwIPstr) |
|
| 648 |
+ |
|
| 649 |
+ if newNet {
|
|
| 650 |
+ s := &subnet{
|
|
| 651 |
+ subnetIP: subnetIP, |
|
| 652 |
+ gwIP: gwIP, |
|
| 653 |
+ vni: vni, |
|
| 654 |
+ once: &sync.Once{},
|
|
| 655 |
+ } |
|
| 656 |
+ n.subnets = append(n.subnets, s) |
|
| 657 |
+ } else {
|
|
| 658 |
+ sNet := n.getMatchingSubnet(subnetIP) |
|
| 659 |
+ if sNet != nil {
|
|
| 660 |
+ sNet.vni = vni |
|
| 661 |
+ } |
|
| 662 |
+ } |
|
| 663 |
+ } |
|
| 664 |
+ return nil |
|
| 665 |
+} |
|
| 666 |
+ |
|
| 667 |
+func (n *network) DataScope() string {
|
|
| 668 |
+ return datastore.GlobalScope |
|
| 669 |
+} |
|
| 670 |
+ |
|
| 671 |
+func (n *network) writeToStore() error {
|
|
| 672 |
+ if n.driver.store == nil {
|
|
| 673 |
+ return nil |
|
| 674 |
+ } |
|
| 675 |
+ |
|
| 676 |
+ return n.driver.store.PutObjectAtomic(n) |
|
| 677 |
+} |
|
| 678 |
+ |
|
| 679 |
+func (n *network) releaseVxlanID() ([]uint32, error) {
|
|
| 680 |
+ if len(n.subnets) == 0 {
|
|
| 681 |
+ return nil, nil |
|
| 682 |
+ } |
|
| 683 |
+ |
|
| 684 |
+ if n.driver.store != nil {
|
|
| 685 |
+ if err := n.driver.store.DeleteObjectAtomic(n); err != nil {
|
|
| 686 |
+ if err == datastore.ErrKeyModified || err == datastore.ErrKeyNotFound {
|
|
| 687 |
+ // In both the above cases we can safely assume that the key has been removed by some other |
|
| 688 |
+ // instance and so simply get out of here |
|
| 689 |
+ return nil, nil |
|
| 690 |
+ } |
|
| 691 |
+ |
|
| 692 |
+ return nil, fmt.Errorf("failed to delete network to vxlan id map: %v", err)
|
|
| 693 |
+ } |
|
| 694 |
+ } |
|
| 695 |
+ var vnis []uint32 |
|
| 696 |
+ for _, s := range n.subnets {
|
|
| 697 |
+ if n.driver.vxlanIdm != nil {
|
|
| 698 |
+ vni := n.vxlanID(s) |
|
| 699 |
+ vnis = append(vnis, vni) |
|
| 700 |
+ n.driver.vxlanIdm.Release(uint64(vni)) |
|
| 701 |
+ } |
|
| 702 |
+ |
|
| 703 |
+ n.setVxlanID(s, 0) |
|
| 704 |
+ } |
|
| 705 |
+ |
|
| 706 |
+ return vnis, nil |
|
| 707 |
+} |
|
| 708 |
+ |
|
| 709 |
+func (n *network) obtainVxlanID(s *subnet) error {
|
|
| 710 |
+ //return if the subnet already has a vxlan id assigned |
|
| 711 |
+ if s.vni != 0 {
|
|
| 712 |
+ return nil |
|
| 713 |
+ } |
|
| 714 |
+ |
|
| 715 |
+ if n.driver.store == nil {
|
|
| 716 |
+ return fmt.Errorf("no valid vxlan id and no datastore configured, cannot obtain vxlan id")
|
|
| 717 |
+ } |
|
| 718 |
+ |
|
| 719 |
+ for {
|
|
| 720 |
+ if err := n.driver.store.GetObject(datastore.Key(n.Key()...), n); err != nil {
|
|
| 721 |
+ return fmt.Errorf("getting network %q from datastore failed %v", n.id, err)
|
|
| 722 |
+ } |
|
| 723 |
+ |
|
| 724 |
+ if s.vni == 0 {
|
|
| 725 |
+ vxlanID, err := n.driver.vxlanIdm.GetID() |
|
| 726 |
+ if err != nil {
|
|
| 727 |
+ return fmt.Errorf("failed to allocate vxlan id: %v", err)
|
|
| 728 |
+ } |
|
| 729 |
+ |
|
| 730 |
+ n.setVxlanID(s, uint32(vxlanID)) |
|
| 731 |
+ if err := n.writeToStore(); err != nil {
|
|
| 732 |
+ n.driver.vxlanIdm.Release(uint64(n.vxlanID(s))) |
|
| 733 |
+ n.setVxlanID(s, 0) |
|
| 734 |
+ if err == datastore.ErrKeyModified {
|
|
| 735 |
+ continue |
|
| 736 |
+ } |
|
| 737 |
+ return fmt.Errorf("network %q failed to update data store: %v", n.id, err)
|
|
| 738 |
+ } |
|
| 739 |
+ return nil |
|
| 740 |
+ } |
|
| 741 |
+ return nil |
|
| 742 |
+ } |
|
| 743 |
+} |
|
| 744 |
+ |
|
| 745 |
+// contains return true if the passed ip belongs to one the network's |
|
| 746 |
+// subnets |
|
| 747 |
+func (n *network) contains(ip net.IP) bool {
|
|
| 748 |
+ for _, s := range n.subnets {
|
|
| 749 |
+ if s.subnetIP.Contains(ip) {
|
|
| 750 |
+ return true |
|
| 751 |
+ } |
|
| 752 |
+ } |
|
| 753 |
+ |
|
| 754 |
+ return false |
|
| 755 |
+} |
|
| 756 |
+ |
|
| 757 |
+// getSubnetforIP returns the subnet to which the given IP belongs |
|
| 758 |
+func (n *network) getSubnetforIP(ip *net.IPNet) *subnet {
|
|
| 759 |
+ for _, s := range n.subnets {
|
|
| 760 |
+ // first check if the mask lengths are the same |
|
| 761 |
+ i, _ := s.subnetIP.Mask.Size() |
|
| 762 |
+ j, _ := ip.Mask.Size() |
|
| 763 |
+ if i != j {
|
|
| 764 |
+ continue |
|
| 765 |
+ } |
|
| 766 |
+ if s.subnetIP.Contains(ip.IP) {
|
|
| 767 |
+ return s |
|
| 768 |
+ } |
|
| 769 |
+ } |
|
| 770 |
+ return nil |
|
| 771 |
+} |
|
| 772 |
+ |
|
| 773 |
+// getMatchingSubnet return the network's subnet that matches the input |
|
| 774 |
+func (n *network) getMatchingSubnet(ip *net.IPNet) *subnet {
|
|
| 775 |
+ if ip == nil {
|
|
| 776 |
+ return nil |
|
| 777 |
+ } |
|
| 778 |
+ for _, s := range n.subnets {
|
|
| 779 |
+ // first check if the mask lengths are the same |
|
| 780 |
+ i, _ := s.subnetIP.Mask.Size() |
|
| 781 |
+ j, _ := ip.Mask.Size() |
|
| 782 |
+ if i != j {
|
|
| 783 |
+ continue |
|
| 784 |
+ } |
|
| 785 |
+ if s.subnetIP.IP.Equal(ip.IP) {
|
|
| 786 |
+ return s |
|
| 787 |
+ } |
|
| 788 |
+ } |
|
| 789 |
+ return nil |
|
| 790 |
+} |
| 0 | 791 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,233 @@ |
| 0 |
+package overlay |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "fmt" |
|
| 4 |
+ "net" |
|
| 5 |
+ "strings" |
|
| 6 |
+ "time" |
|
| 7 |
+ |
|
| 8 |
+ "github.com/Sirupsen/logrus" |
|
| 9 |
+ "github.com/hashicorp/serf/serf" |
|
| 10 |
+) |
|
| 11 |
+ |
|
| 12 |
+type ovNotify struct {
|
|
| 13 |
+ action string |
|
| 14 |
+ ep *endpoint |
|
| 15 |
+ nw *network |
|
| 16 |
+} |
|
| 17 |
+ |
|
| 18 |
+type logWriter struct{}
|
|
| 19 |
+ |
|
| 20 |
+func (l *logWriter) Write(p []byte) (int, error) {
|
|
| 21 |
+ str := string(p) |
|
| 22 |
+ |
|
| 23 |
+ switch {
|
|
| 24 |
+ case strings.Contains(str, "[WARN]"): |
|
| 25 |
+ logrus.Warn(str) |
|
| 26 |
+ case strings.Contains(str, "[DEBUG]"): |
|
| 27 |
+ logrus.Debug(str) |
|
| 28 |
+ case strings.Contains(str, "[INFO]"): |
|
| 29 |
+ logrus.Info(str) |
|
| 30 |
+ case strings.Contains(str, "[ERR]"): |
|
| 31 |
+ logrus.Error(str) |
|
| 32 |
+ } |
|
| 33 |
+ |
|
| 34 |
+ return len(p), nil |
|
| 35 |
+} |
|
| 36 |
+ |
|
| 37 |
+func (d *driver) serfInit() error {
|
|
| 38 |
+ var err error |
|
| 39 |
+ |
|
| 40 |
+ config := serf.DefaultConfig() |
|
| 41 |
+ config.Init() |
|
| 42 |
+ config.MemberlistConfig.BindAddr = d.advertiseAddress |
|
| 43 |
+ |
|
| 44 |
+ d.eventCh = make(chan serf.Event, 4) |
|
| 45 |
+ config.EventCh = d.eventCh |
|
| 46 |
+ config.UserCoalescePeriod = 1 * time.Second |
|
| 47 |
+ config.UserQuiescentPeriod = 50 * time.Millisecond |
|
| 48 |
+ |
|
| 49 |
+ config.LogOutput = &logWriter{}
|
|
| 50 |
+ config.MemberlistConfig.LogOutput = config.LogOutput |
|
| 51 |
+ |
|
| 52 |
+ s, err := serf.Create(config) |
|
| 53 |
+ if err != nil {
|
|
| 54 |
+ return fmt.Errorf("failed to create cluster node: %v", err)
|
|
| 55 |
+ } |
|
| 56 |
+ defer func() {
|
|
| 57 |
+ if err != nil {
|
|
| 58 |
+ s.Shutdown() |
|
| 59 |
+ } |
|
| 60 |
+ }() |
|
| 61 |
+ |
|
| 62 |
+ d.serfInstance = s |
|
| 63 |
+ |
|
| 64 |
+ d.notifyCh = make(chan ovNotify) |
|
| 65 |
+ d.exitCh = make(chan chan struct{})
|
|
| 66 |
+ |
|
| 67 |
+ go d.startSerfLoop(d.eventCh, d.notifyCh, d.exitCh) |
|
| 68 |
+ return nil |
|
| 69 |
+} |
|
| 70 |
+ |
|
| 71 |
+func (d *driver) serfJoin(neighIP string) error {
|
|
| 72 |
+ if neighIP == "" {
|
|
| 73 |
+ return fmt.Errorf("no neighbor to join")
|
|
| 74 |
+ } |
|
| 75 |
+ if _, err := d.serfInstance.Join([]string{neighIP}, false); err != nil {
|
|
| 76 |
+ return fmt.Errorf("Failed to join the cluster at neigh IP %s: %v",
|
|
| 77 |
+ neighIP, err) |
|
| 78 |
+ } |
|
| 79 |
+ return nil |
|
| 80 |
+} |
|
| 81 |
+ |
|
| 82 |
+func (d *driver) notifyEvent(event ovNotify) {
|
|
| 83 |
+ ep := event.ep |
|
| 84 |
+ |
|
| 85 |
+ ePayload := fmt.Sprintf("%s %s %s %s", event.action, ep.addr.IP.String(),
|
|
| 86 |
+ net.IP(ep.addr.Mask).String(), ep.mac.String()) |
|
| 87 |
+ eName := fmt.Sprintf("jl %s %s %s", d.serfInstance.LocalMember().Addr.String(),
|
|
| 88 |
+ event.nw.id, ep.id) |
|
| 89 |
+ |
|
| 90 |
+ if err := d.serfInstance.UserEvent(eName, []byte(ePayload), true); err != nil {
|
|
| 91 |
+ logrus.Errorf("Sending user event failed: %v\n", err)
|
|
| 92 |
+ } |
|
| 93 |
+} |
|
| 94 |
+ |
|
| 95 |
+func (d *driver) processEvent(u serf.UserEvent) {
|
|
| 96 |
+ logrus.Debugf("Received user event name:%s, payload:%s\n", u.Name,
|
|
| 97 |
+ string(u.Payload)) |
|
| 98 |
+ |
|
| 99 |
+ var dummy, action, vtepStr, nid, eid, ipStr, maskStr, macStr string |
|
| 100 |
+ if _, err := fmt.Sscan(u.Name, &dummy, &vtepStr, &nid, &eid); err != nil {
|
|
| 101 |
+ fmt.Printf("Failed to scan name string: %v\n", err)
|
|
| 102 |
+ } |
|
| 103 |
+ |
|
| 104 |
+ if _, err := fmt.Sscan(string(u.Payload), &action, |
|
| 105 |
+ &ipStr, &maskStr, &macStr); err != nil {
|
|
| 106 |
+ fmt.Printf("Failed to scan value string: %v\n", err)
|
|
| 107 |
+ } |
|
| 108 |
+ |
|
| 109 |
+ logrus.Debugf("Parsed data = %s/%s/%s/%s/%s/%s\n", nid, eid, vtepStr, ipStr, maskStr, macStr)
|
|
| 110 |
+ |
|
| 111 |
+ mac, err := net.ParseMAC(macStr) |
|
| 112 |
+ if err != nil {
|
|
| 113 |
+ logrus.Errorf("Failed to parse mac: %v\n", err)
|
|
| 114 |
+ } |
|
| 115 |
+ |
|
| 116 |
+ if d.serfInstance.LocalMember().Addr.String() == vtepStr {
|
|
| 117 |
+ return |
|
| 118 |
+ } |
|
| 119 |
+ |
|
| 120 |
+ switch action {
|
|
| 121 |
+ case "join": |
|
| 122 |
+ if err := d.peerAdd(nid, eid, net.ParseIP(ipStr), net.IPMask(net.ParseIP(maskStr).To4()), mac, |
|
| 123 |
+ net.ParseIP(vtepStr), true); err != nil {
|
|
| 124 |
+ logrus.Errorf("Peer add failed in the driver: %v\n", err)
|
|
| 125 |
+ } |
|
| 126 |
+ case "leave": |
|
| 127 |
+ if err := d.peerDelete(nid, eid, net.ParseIP(ipStr), net.IPMask(net.ParseIP(maskStr).To4()), mac, |
|
| 128 |
+ net.ParseIP(vtepStr), true); err != nil {
|
|
| 129 |
+ logrus.Errorf("Peer delete failed in the driver: %v\n", err)
|
|
| 130 |
+ } |
|
| 131 |
+ } |
|
| 132 |
+} |
|
| 133 |
+ |
|
| 134 |
+func (d *driver) processQuery(q *serf.Query) {
|
|
| 135 |
+ logrus.Debugf("Received query name:%s, payload:%s\n", q.Name,
|
|
| 136 |
+ string(q.Payload)) |
|
| 137 |
+ |
|
| 138 |
+ var nid, ipStr string |
|
| 139 |
+ if _, err := fmt.Sscan(string(q.Payload), &nid, &ipStr); err != nil {
|
|
| 140 |
+ fmt.Printf("Failed to scan query payload string: %v\n", err)
|
|
| 141 |
+ } |
|
| 142 |
+ |
|
| 143 |
+ peerMac, peerIPMask, vtep, err := d.peerDbSearch(nid, net.ParseIP(ipStr)) |
|
| 144 |
+ if err != nil {
|
|
| 145 |
+ return |
|
| 146 |
+ } |
|
| 147 |
+ |
|
| 148 |
+ q.Respond([]byte(fmt.Sprintf("%s %s %s", peerMac.String(), net.IP(peerIPMask).String(), vtep.String())))
|
|
| 149 |
+} |
|
| 150 |
+ |
|
| 151 |
+func (d *driver) resolvePeer(nid string, peerIP net.IP) (net.HardwareAddr, net.IPMask, net.IP, error) {
|
|
| 152 |
+ if d.serfInstance == nil {
|
|
| 153 |
+ return nil, nil, nil, fmt.Errorf("could not resolve peer: serf instance not initialized")
|
|
| 154 |
+ } |
|
| 155 |
+ |
|
| 156 |
+ qPayload := fmt.Sprintf("%s %s", string(nid), peerIP.String())
|
|
| 157 |
+ resp, err := d.serfInstance.Query("peerlookup", []byte(qPayload), nil)
|
|
| 158 |
+ if err != nil {
|
|
| 159 |
+ return nil, nil, nil, fmt.Errorf("resolving peer by querying the cluster failed: %v", err)
|
|
| 160 |
+ } |
|
| 161 |
+ |
|
| 162 |
+ respCh := resp.ResponseCh() |
|
| 163 |
+ select {
|
|
| 164 |
+ case r := <-respCh: |
|
| 165 |
+ var macStr, maskStr, vtepStr string |
|
| 166 |
+ if _, err := fmt.Sscan(string(r.Payload), &macStr, &maskStr, &vtepStr); err != nil {
|
|
| 167 |
+ return nil, nil, nil, fmt.Errorf("bad response %q for the resolve query: %v", string(r.Payload), err)
|
|
| 168 |
+ } |
|
| 169 |
+ |
|
| 170 |
+ mac, err := net.ParseMAC(macStr) |
|
| 171 |
+ if err != nil {
|
|
| 172 |
+ return nil, nil, nil, fmt.Errorf("failed to parse mac: %v", err)
|
|
| 173 |
+ } |
|
| 174 |
+ |
|
| 175 |
+ return mac, net.IPMask(net.ParseIP(maskStr).To4()), net.ParseIP(vtepStr), nil |
|
| 176 |
+ |
|
| 177 |
+ case <-time.After(time.Second): |
|
| 178 |
+ return nil, nil, nil, fmt.Errorf("timed out resolving peer by querying the cluster")
|
|
| 179 |
+ } |
|
| 180 |
+} |
|
| 181 |
+ |
|
| 182 |
+func (d *driver) startSerfLoop(eventCh chan serf.Event, notifyCh chan ovNotify, |
|
| 183 |
+ exitCh chan chan struct{}) {
|
|
| 184 |
+ |
|
| 185 |
+ for {
|
|
| 186 |
+ select {
|
|
| 187 |
+ case notify, ok := <-notifyCh: |
|
| 188 |
+ if !ok {
|
|
| 189 |
+ break |
|
| 190 |
+ } |
|
| 191 |
+ |
|
| 192 |
+ d.notifyEvent(notify) |
|
| 193 |
+ case ch, ok := <-exitCh: |
|
| 194 |
+ if !ok {
|
|
| 195 |
+ break |
|
| 196 |
+ } |
|
| 197 |
+ |
|
| 198 |
+ if err := d.serfInstance.Leave(); err != nil {
|
|
| 199 |
+ logrus.Errorf("failed leaving the cluster: %v\n", err)
|
|
| 200 |
+ } |
|
| 201 |
+ |
|
| 202 |
+ d.serfInstance.Shutdown() |
|
| 203 |
+ close(ch) |
|
| 204 |
+ return |
|
| 205 |
+ case e, ok := <-eventCh: |
|
| 206 |
+ if !ok {
|
|
| 207 |
+ break |
|
| 208 |
+ } |
|
| 209 |
+ |
|
| 210 |
+ if e.EventType() == serf.EventQuery {
|
|
| 211 |
+ d.processQuery(e.(*serf.Query)) |
|
| 212 |
+ break |
|
| 213 |
+ } |
|
| 214 |
+ |
|
| 215 |
+ u, ok := e.(serf.UserEvent) |
|
| 216 |
+ if !ok {
|
|
| 217 |
+ break |
|
| 218 |
+ } |
|
| 219 |
+ d.processEvent(u) |
|
| 220 |
+ } |
|
| 221 |
+ } |
|
| 222 |
+} |
|
| 223 |
+ |
|
| 224 |
+func (d *driver) isSerfAlive() bool {
|
|
| 225 |
+ d.Lock() |
|
| 226 |
+ serfInstance := d.serfInstance |
|
| 227 |
+ d.Unlock() |
|
| 228 |
+ if serfInstance == nil || serfInstance.State() != serf.SerfAlive {
|
|
| 229 |
+ return false |
|
| 230 |
+ } |
|
| 231 |
+ return true |
|
| 232 |
+} |
| 0 | 233 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,61 @@ |
| 0 |
+package overlay |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "fmt" |
|
| 4 |
+ "os/exec" |
|
| 5 |
+ "strings" |
|
| 6 |
+ |
|
| 7 |
+ "github.com/docker/libnetwork/osl" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+func validateID(nid, eid string) error {
|
|
| 11 |
+ if nid == "" {
|
|
| 12 |
+ return fmt.Errorf("invalid network id")
|
|
| 13 |
+ } |
|
| 14 |
+ |
|
| 15 |
+ if eid == "" {
|
|
| 16 |
+ return fmt.Errorf("invalid endpoint id")
|
|
| 17 |
+ } |
|
| 18 |
+ |
|
| 19 |
+ return nil |
|
| 20 |
+} |
|
| 21 |
+ |
|
| 22 |
+func createVxlan(name string, vni uint32, mtu int) error {
|
|
| 23 |
+ defer osl.InitOSContext()() |
|
| 24 |
+ |
|
| 25 |
+ // Get default interface to plumb the vxlan on |
|
| 26 |
+ routeCmd := "/usr/sbin/ipadm show-addr -p -o addrobj " + |
|
| 27 |
+ "`/usr/sbin/route get default | /usr/bin/grep interface | " + |
|
| 28 |
+ "/usr/bin/awk '{print $2}'`"
|
|
| 29 |
+ out, err := exec.Command("/usr/bin/bash", "-c", routeCmd).Output()
|
|
| 30 |
+ if err != nil {
|
|
| 31 |
+ return fmt.Errorf("cannot get default route: %v", err)
|
|
| 32 |
+ } |
|
| 33 |
+ |
|
| 34 |
+ defaultInterface := strings.SplitN(string(out), "/", 2) |
|
| 35 |
+ propList := fmt.Sprintf("interface=%s,vni=%d", defaultInterface[0], vni)
|
|
| 36 |
+ |
|
| 37 |
+ out, err = exec.Command("/usr/sbin/dladm", "create-vxlan", "-t", "-p", propList,
|
|
| 38 |
+ name).Output() |
|
| 39 |
+ if err != nil {
|
|
| 40 |
+ return fmt.Errorf("error creating vxlan interface: %v %s", err, out)
|
|
| 41 |
+ } |
|
| 42 |
+ |
|
| 43 |
+ return nil |
|
| 44 |
+} |
|
| 45 |
+ |
|
| 46 |
+func deleteInterfaceBySubnet(brPrefix string, s *subnet) error {
|
|
| 47 |
+ return nil |
|
| 48 |
+ |
|
| 49 |
+} |
|
| 50 |
+ |
|
| 51 |
+func deleteInterface(name string) error {
|
|
| 52 |
+ defer osl.InitOSContext()() |
|
| 53 |
+ |
|
| 54 |
+ out, err := exec.Command("/usr/sbin/dladm", "delete-vxlan", name).Output()
|
|
| 55 |
+ if err != nil {
|
|
| 56 |
+ return fmt.Errorf("error creating vxlan interface: %v %s", err, out)
|
|
| 57 |
+ } |
|
| 58 |
+ |
|
| 59 |
+ return nil |
|
| 60 |
+} |
| 0 | 61 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,362 @@ |
| 0 |
+package overlay |
|
| 1 |
+ |
|
| 2 |
+//go:generate protoc -I.:../../Godeps/_workspace/src/github.com/gogo/protobuf --gogo_out=import_path=github.com/docker/libnetwork/drivers/overlay,Mgogoproto/gogo.proto=github.com/gogo/protobuf/gogoproto:. overlay.proto |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "fmt" |
|
| 6 |
+ "net" |
|
| 7 |
+ "sync" |
|
| 8 |
+ |
|
| 9 |
+ "github.com/Sirupsen/logrus" |
|
| 10 |
+ "github.com/docker/libnetwork/datastore" |
|
| 11 |
+ "github.com/docker/libnetwork/discoverapi" |
|
| 12 |
+ "github.com/docker/libnetwork/driverapi" |
|
| 13 |
+ "github.com/docker/libnetwork/idm" |
|
| 14 |
+ "github.com/docker/libnetwork/netlabel" |
|
| 15 |
+ "github.com/docker/libnetwork/osl" |
|
| 16 |
+ "github.com/docker/libnetwork/types" |
|
| 17 |
+ "github.com/hashicorp/serf/serf" |
|
| 18 |
+) |
|
| 19 |
+ |
|
| 20 |
+// XXX OVERLAY_SOLARIS |
|
| 21 |
+// Might need changes for names/constant values in solaris |
|
| 22 |
+const ( |
|
| 23 |
+ networkType = "overlay" |
|
| 24 |
+ vethPrefix = "veth" |
|
| 25 |
+ vethLen = 7 |
|
| 26 |
+ vxlanIDStart = 256 |
|
| 27 |
+ vxlanIDEnd = (1 << 24) - 1 |
|
| 28 |
+ vxlanPort = 4789 |
|
| 29 |
+ vxlanEncap = 50 |
|
| 30 |
+ secureOption = "encrypted" |
|
| 31 |
+) |
|
| 32 |
+ |
|
| 33 |
+var initVxlanIdm = make(chan (bool), 1) |
|
| 34 |
+ |
|
| 35 |
+type driver struct {
|
|
| 36 |
+ eventCh chan serf.Event |
|
| 37 |
+ notifyCh chan ovNotify |
|
| 38 |
+ exitCh chan chan struct{}
|
|
| 39 |
+ bindAddress string |
|
| 40 |
+ advertiseAddress string |
|
| 41 |
+ neighIP string |
|
| 42 |
+ config map[string]interface{}
|
|
| 43 |
+ peerDb peerNetworkMap |
|
| 44 |
+ secMap *encrMap |
|
| 45 |
+ serfInstance *serf.Serf |
|
| 46 |
+ networks networkTable |
|
| 47 |
+ store datastore.DataStore |
|
| 48 |
+ localStore datastore.DataStore |
|
| 49 |
+ vxlanIdm *idm.Idm |
|
| 50 |
+ once sync.Once |
|
| 51 |
+ joinOnce sync.Once |
|
| 52 |
+ keys []*key |
|
| 53 |
+ sync.Mutex |
|
| 54 |
+} |
|
| 55 |
+ |
|
| 56 |
+// Init registers a new instance of overlay driver |
|
| 57 |
+func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
|
| 58 |
+ c := driverapi.Capability{
|
|
| 59 |
+ DataScope: datastore.GlobalScope, |
|
| 60 |
+ } |
|
| 61 |
+ d := &driver{
|
|
| 62 |
+ networks: networkTable{},
|
|
| 63 |
+ peerDb: peerNetworkMap{
|
|
| 64 |
+ mp: map[string]*peerMap{},
|
|
| 65 |
+ }, |
|
| 66 |
+ secMap: &encrMap{nodes: map[string][]*spi{}},
|
|
| 67 |
+ config: config, |
|
| 68 |
+ } |
|
| 69 |
+ |
|
| 70 |
+ if data, ok := config[netlabel.GlobalKVClient]; ok {
|
|
| 71 |
+ var err error |
|
| 72 |
+ dsc, ok := data.(discoverapi.DatastoreConfigData) |
|
| 73 |
+ if !ok {
|
|
| 74 |
+ return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
|
|
| 75 |
+ } |
|
| 76 |
+ d.store, err = datastore.NewDataStoreFromConfig(dsc) |
|
| 77 |
+ if err != nil {
|
|
| 78 |
+ return types.InternalErrorf("failed to initialize data store: %v", err)
|
|
| 79 |
+ } |
|
| 80 |
+ } |
|
| 81 |
+ |
|
| 82 |
+ if data, ok := config[netlabel.LocalKVClient]; ok {
|
|
| 83 |
+ var err error |
|
| 84 |
+ dsc, ok := data.(discoverapi.DatastoreConfigData) |
|
| 85 |
+ if !ok {
|
|
| 86 |
+ return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
|
|
| 87 |
+ } |
|
| 88 |
+ d.localStore, err = datastore.NewDataStoreFromConfig(dsc) |
|
| 89 |
+ if err != nil {
|
|
| 90 |
+ return types.InternalErrorf("failed to initialize local data store: %v", err)
|
|
| 91 |
+ } |
|
| 92 |
+ } |
|
| 93 |
+ |
|
| 94 |
+ d.restoreEndpoints() |
|
| 95 |
+ |
|
| 96 |
+ return dc.RegisterDriver(networkType, d, c) |
|
| 97 |
+} |
|
| 98 |
+ |
|
| 99 |
+// Endpoints are stored in the local store. Restore them and reconstruct the overlay sandbox |
|
| 100 |
+func (d *driver) restoreEndpoints() error {
|
|
| 101 |
+ if d.localStore == nil {
|
|
| 102 |
+ logrus.Warnf("Cannot restore overlay endpoints because local datastore is missing")
|
|
| 103 |
+ return nil |
|
| 104 |
+ } |
|
| 105 |
+ kvol, err := d.localStore.List(datastore.Key(overlayEndpointPrefix), &endpoint{})
|
|
| 106 |
+ if err != nil && err != datastore.ErrKeyNotFound {
|
|
| 107 |
+ return fmt.Errorf("failed to read overlay endpoint from store: %v", err)
|
|
| 108 |
+ } |
|
| 109 |
+ |
|
| 110 |
+ if err == datastore.ErrKeyNotFound {
|
|
| 111 |
+ return nil |
|
| 112 |
+ } |
|
| 113 |
+ for _, kvo := range kvol {
|
|
| 114 |
+ ep := kvo.(*endpoint) |
|
| 115 |
+ n := d.network(ep.nid) |
|
| 116 |
+ if n == nil {
|
|
| 117 |
+ logrus.Debugf("Network (%s) not found for restored endpoint (%s)", ep.nid[0:7], ep.id[0:7])
|
|
| 118 |
+ logrus.Debugf("Deleting stale overlay endpoint (%s) from store", ep.id[0:7])
|
|
| 119 |
+ if err := d.deleteEndpointFromStore(ep); err != nil {
|
|
| 120 |
+ logrus.Debugf("Failed to delete stale overlay endpoint (%s) from store", ep.id[0:7])
|
|
| 121 |
+ } |
|
| 122 |
+ continue |
|
| 123 |
+ } |
|
| 124 |
+ n.addEndpoint(ep) |
|
| 125 |
+ |
|
| 126 |
+ s := n.getSubnetforIP(ep.addr) |
|
| 127 |
+ if s == nil {
|
|
| 128 |
+ return fmt.Errorf("could not find subnet for endpoint %s", ep.id)
|
|
| 129 |
+ } |
|
| 130 |
+ |
|
| 131 |
+ if err := n.joinSandbox(true); err != nil {
|
|
| 132 |
+ return fmt.Errorf("restore network sandbox failed: %v", err)
|
|
| 133 |
+ } |
|
| 134 |
+ |
|
| 135 |
+ if err := n.joinSubnetSandbox(s, true); err != nil {
|
|
| 136 |
+ return fmt.Errorf("restore subnet sandbox failed for %q: %v", s.subnetIP.String(), err)
|
|
| 137 |
+ } |
|
| 138 |
+ |
|
| 139 |
+ Ifaces := make(map[string][]osl.IfaceOption) |
|
| 140 |
+ vethIfaceOption := make([]osl.IfaceOption, 1) |
|
| 141 |
+ vethIfaceOption = append(vethIfaceOption, n.sbox.InterfaceOptions().Master(s.brName)) |
|
| 142 |
+ Ifaces[fmt.Sprintf("%s+%s", "veth", "veth")] = vethIfaceOption
|
|
| 143 |
+ |
|
| 144 |
+ err := n.sbox.Restore(Ifaces, nil, nil, nil) |
|
| 145 |
+ if err != nil {
|
|
| 146 |
+ return fmt.Errorf("failed to restore overlay sandbox: %v", err)
|
|
| 147 |
+ } |
|
| 148 |
+ |
|
| 149 |
+ n.incEndpointCount() |
|
| 150 |
+ d.peerDbAdd(ep.nid, ep.id, ep.addr.IP, ep.addr.Mask, ep.mac, net.ParseIP(d.advertiseAddress), true) |
|
| 151 |
+ } |
|
| 152 |
+ return nil |
|
| 153 |
+} |
|
| 154 |
+ |
|
| 155 |
+// Fini cleans up the driver resources |
|
| 156 |
+func Fini(drv driverapi.Driver) {
|
|
| 157 |
+ d := drv.(*driver) |
|
| 158 |
+ |
|
| 159 |
+ if d.exitCh != nil {
|
|
| 160 |
+ waitCh := make(chan struct{})
|
|
| 161 |
+ |
|
| 162 |
+ d.exitCh <- waitCh |
|
| 163 |
+ |
|
| 164 |
+ <-waitCh |
|
| 165 |
+ } |
|
| 166 |
+} |
|
| 167 |
+ |
|
| 168 |
+func (d *driver) configure() error {
|
|
| 169 |
+ if d.store == nil {
|
|
| 170 |
+ return nil |
|
| 171 |
+ } |
|
| 172 |
+ |
|
| 173 |
+ if d.vxlanIdm == nil {
|
|
| 174 |
+ return d.initializeVxlanIdm() |
|
| 175 |
+ } |
|
| 176 |
+ |
|
| 177 |
+ return nil |
|
| 178 |
+} |
|
| 179 |
+ |
|
| 180 |
+func (d *driver) initializeVxlanIdm() error {
|
|
| 181 |
+ var err error |
|
| 182 |
+ |
|
| 183 |
+ initVxlanIdm <- true |
|
| 184 |
+ defer func() { <-initVxlanIdm }()
|
|
| 185 |
+ |
|
| 186 |
+ if d.vxlanIdm != nil {
|
|
| 187 |
+ return nil |
|
| 188 |
+ } |
|
| 189 |
+ |
|
| 190 |
+ d.vxlanIdm, err = idm.New(d.store, "vxlan-id", vxlanIDStart, vxlanIDEnd) |
|
| 191 |
+ if err != nil {
|
|
| 192 |
+ return fmt.Errorf("failed to initialize vxlan id manager: %v", err)
|
|
| 193 |
+ } |
|
| 194 |
+ |
|
| 195 |
+ return nil |
|
| 196 |
+} |
|
| 197 |
+ |
|
| 198 |
+func (d *driver) Type() string {
|
|
| 199 |
+ return networkType |
|
| 200 |
+} |
|
| 201 |
+ |
|
| 202 |
+func validateSelf(node string) error {
|
|
| 203 |
+ advIP := net.ParseIP(node) |
|
| 204 |
+ if advIP == nil {
|
|
| 205 |
+ return fmt.Errorf("invalid self address (%s)", node)
|
|
| 206 |
+ } |
|
| 207 |
+ |
|
| 208 |
+ addrs, err := net.InterfaceAddrs() |
|
| 209 |
+ if err != nil {
|
|
| 210 |
+ return fmt.Errorf("Unable to get interface addresses %v", err)
|
|
| 211 |
+ } |
|
| 212 |
+ for _, addr := range addrs {
|
|
| 213 |
+ ip, _, err := net.ParseCIDR(addr.String()) |
|
| 214 |
+ if err == nil && ip.Equal(advIP) {
|
|
| 215 |
+ return nil |
|
| 216 |
+ } |
|
| 217 |
+ } |
|
| 218 |
+ return fmt.Errorf("Multi-Host overlay networking requires cluster-advertise(%s) to be configured with a local ip-address that is reachable within the cluster", advIP.String())
|
|
| 219 |
+} |
|
| 220 |
+ |
|
| 221 |
+func (d *driver) nodeJoin(advertiseAddress, bindAddress string, self bool) {
|
|
| 222 |
+ if self && !d.isSerfAlive() {
|
|
| 223 |
+ d.Lock() |
|
| 224 |
+ d.advertiseAddress = advertiseAddress |
|
| 225 |
+ d.bindAddress = bindAddress |
|
| 226 |
+ d.Unlock() |
|
| 227 |
+ |
|
| 228 |
+ // If there is no cluster store there is no need to start serf. |
|
| 229 |
+ if d.store != nil {
|
|
| 230 |
+ if err := validateSelf(advertiseAddress); err != nil {
|
|
| 231 |
+ logrus.Warnf("%s", err.Error())
|
|
| 232 |
+ } |
|
| 233 |
+ err := d.serfInit() |
|
| 234 |
+ if err != nil {
|
|
| 235 |
+ logrus.Errorf("initializing serf instance failed: %v", err)
|
|
| 236 |
+ d.Lock() |
|
| 237 |
+ d.advertiseAddress = "" |
|
| 238 |
+ d.bindAddress = "" |
|
| 239 |
+ d.Unlock() |
|
| 240 |
+ return |
|
| 241 |
+ } |
|
| 242 |
+ } |
|
| 243 |
+ } |
|
| 244 |
+ |
|
| 245 |
+ d.Lock() |
|
| 246 |
+ if !self {
|
|
| 247 |
+ d.neighIP = advertiseAddress |
|
| 248 |
+ } |
|
| 249 |
+ neighIP := d.neighIP |
|
| 250 |
+ d.Unlock() |
|
| 251 |
+ |
|
| 252 |
+ if d.serfInstance != nil && neighIP != "" {
|
|
| 253 |
+ var err error |
|
| 254 |
+ d.joinOnce.Do(func() {
|
|
| 255 |
+ err = d.serfJoin(neighIP) |
|
| 256 |
+ if err == nil {
|
|
| 257 |
+ d.pushLocalDb() |
|
| 258 |
+ } |
|
| 259 |
+ }) |
|
| 260 |
+ if err != nil {
|
|
| 261 |
+ logrus.Errorf("joining serf neighbor %s failed: %v", advertiseAddress, err)
|
|
| 262 |
+ d.Lock() |
|
| 263 |
+ d.joinOnce = sync.Once{}
|
|
| 264 |
+ d.Unlock() |
|
| 265 |
+ return |
|
| 266 |
+ } |
|
| 267 |
+ } |
|
| 268 |
+} |
|
| 269 |
+ |
|
| 270 |
+func (d *driver) pushLocalEndpointEvent(action, nid, eid string) {
|
|
| 271 |
+ n := d.network(nid) |
|
| 272 |
+ if n == nil {
|
|
| 273 |
+ logrus.Debugf("Error pushing local endpoint event for network %s", nid)
|
|
| 274 |
+ return |
|
| 275 |
+ } |
|
| 276 |
+ ep := n.endpoint(eid) |
|
| 277 |
+ if ep == nil {
|
|
| 278 |
+ logrus.Debugf("Error pushing local endpoint event for ep %s / %s", nid, eid)
|
|
| 279 |
+ return |
|
| 280 |
+ } |
|
| 281 |
+ |
|
| 282 |
+ if !d.isSerfAlive() {
|
|
| 283 |
+ return |
|
| 284 |
+ } |
|
| 285 |
+ d.notifyCh <- ovNotify{
|
|
| 286 |
+ action: "join", |
|
| 287 |
+ nw: n, |
|
| 288 |
+ ep: ep, |
|
| 289 |
+ } |
|
| 290 |
+} |
|
| 291 |
+ |
|
| 292 |
+// DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster |
|
| 293 |
+func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
|
|
| 294 |
+ var err error |
|
| 295 |
+ switch dType {
|
|
| 296 |
+ case discoverapi.NodeDiscovery: |
|
| 297 |
+ nodeData, ok := data.(discoverapi.NodeDiscoveryData) |
|
| 298 |
+ if !ok || nodeData.Address == "" {
|
|
| 299 |
+ return fmt.Errorf("invalid discovery data")
|
|
| 300 |
+ } |
|
| 301 |
+ d.nodeJoin(nodeData.Address, nodeData.BindAddress, nodeData.Self) |
|
| 302 |
+ case discoverapi.DatastoreConfig: |
|
| 303 |
+ if d.store != nil {
|
|
| 304 |
+ return types.ForbiddenErrorf("cannot accept datastore configuration: Overlay driver has a datastore configured already")
|
|
| 305 |
+ } |
|
| 306 |
+ dsc, ok := data.(discoverapi.DatastoreConfigData) |
|
| 307 |
+ if !ok {
|
|
| 308 |
+ return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
|
|
| 309 |
+ } |
|
| 310 |
+ d.store, err = datastore.NewDataStoreFromConfig(dsc) |
|
| 311 |
+ if err != nil {
|
|
| 312 |
+ return types.InternalErrorf("failed to initialize data store: %v", err)
|
|
| 313 |
+ } |
|
| 314 |
+ case discoverapi.EncryptionKeysConfig: |
|
| 315 |
+ encrData, ok := data.(discoverapi.DriverEncryptionConfig) |
|
| 316 |
+ if !ok {
|
|
| 317 |
+ return fmt.Errorf("invalid encryption key notification data")
|
|
| 318 |
+ } |
|
| 319 |
+ keys := make([]*key, 0, len(encrData.Keys)) |
|
| 320 |
+ for i := 0; i < len(encrData.Keys); i++ {
|
|
| 321 |
+ k := &key{
|
|
| 322 |
+ value: encrData.Keys[i], |
|
| 323 |
+ tag: uint32(encrData.Tags[i]), |
|
| 324 |
+ } |
|
| 325 |
+ keys = append(keys, k) |
|
| 326 |
+ } |
|
| 327 |
+ d.setKeys(keys) |
|
| 328 |
+ case discoverapi.EncryptionKeysUpdate: |
|
| 329 |
+ var newKey, delKey, priKey *key |
|
| 330 |
+ encrData, ok := data.(discoverapi.DriverEncryptionUpdate) |
|
| 331 |
+ if !ok {
|
|
| 332 |
+ return fmt.Errorf("invalid encryption key notification data")
|
|
| 333 |
+ } |
|
| 334 |
+ if encrData.Key != nil {
|
|
| 335 |
+ newKey = &key{
|
|
| 336 |
+ value: encrData.Key, |
|
| 337 |
+ tag: uint32(encrData.Tag), |
|
| 338 |
+ } |
|
| 339 |
+ } |
|
| 340 |
+ if encrData.Primary != nil {
|
|
| 341 |
+ priKey = &key{
|
|
| 342 |
+ value: encrData.Primary, |
|
| 343 |
+ tag: uint32(encrData.PrimaryTag), |
|
| 344 |
+ } |
|
| 345 |
+ } |
|
| 346 |
+ if encrData.Prune != nil {
|
|
| 347 |
+ delKey = &key{
|
|
| 348 |
+ value: encrData.Prune, |
|
| 349 |
+ tag: uint32(encrData.PruneTag), |
|
| 350 |
+ } |
|
| 351 |
+ } |
|
| 352 |
+ d.updateKeys(newKey, priKey, delKey) |
|
| 353 |
+ default: |
|
| 354 |
+ } |
|
| 355 |
+ return nil |
|
| 356 |
+} |
|
| 357 |
+ |
|
| 358 |
+// DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster |
|
| 359 |
+func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
|
|
| 360 |
+ return nil |
|
| 361 |
+} |
| 0 | 362 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,468 @@ |
| 0 |
+// Code generated by protoc-gen-gogo. |
|
| 1 |
+// source: overlay.proto |
|
| 2 |
+// DO NOT EDIT! |
|
| 3 |
+ |
|
| 4 |
+/* |
|
| 5 |
+ Package overlay is a generated protocol buffer package. |
|
| 6 |
+ |
|
| 7 |
+ It is generated from these files: |
|
| 8 |
+ overlay.proto |
|
| 9 |
+ |
|
| 10 |
+ It has these top-level messages: |
|
| 11 |
+ PeerRecord |
|
| 12 |
+*/ |
|
| 13 |
+package overlay |
|
| 14 |
+ |
|
| 15 |
+import proto "github.com/gogo/protobuf/proto" |
|
| 16 |
+import fmt "fmt" |
|
| 17 |
+import math "math" |
|
| 18 |
+import _ "github.com/gogo/protobuf/gogoproto" |
|
| 19 |
+ |
|
| 20 |
+import strings "strings" |
|
| 21 |
+import github_com_gogo_protobuf_proto "github.com/gogo/protobuf/proto" |
|
| 22 |
+import sort "sort" |
|
| 23 |
+import strconv "strconv" |
|
| 24 |
+import reflect "reflect" |
|
| 25 |
+ |
|
| 26 |
+import io "io" |
|
| 27 |
+ |
|
| 28 |
+// Reference imports to suppress errors if they are not otherwise used. |
|
| 29 |
+var _ = proto.Marshal |
|
| 30 |
+var _ = fmt.Errorf |
|
| 31 |
+var _ = math.Inf |
|
| 32 |
+ |
|
| 33 |
+// This is a compile-time assertion to ensure that this generated file |
|
| 34 |
+// is compatible with the proto package it is being compiled against. |
|
| 35 |
+const _ = proto.GoGoProtoPackageIsVersion1 |
|
| 36 |
+ |
|
| 37 |
+// PeerRecord defines the information corresponding to a peer |
|
| 38 |
+// container in the overlay network. |
|
| 39 |
+type PeerRecord struct {
|
|
| 40 |
+ // Endpoint IP is the IP of the container attachment on the |
|
| 41 |
+ // given overlay network. |
|
| 42 |
+ EndpointIP string `protobuf:"bytes,1,opt,name=endpoint_ip,json=endpointIp,proto3" json:"endpoint_ip,omitempty"` |
|
| 43 |
+ // Endpoint MAC is the mac address of the container attachment |
|
| 44 |
+ // on the given overlay network. |
|
| 45 |
+ EndpointMAC string `protobuf:"bytes,2,opt,name=endpoint_mac,json=endpointMac,proto3" json:"endpoint_mac,omitempty"` |
|
| 46 |
+ // Tunnel Endpoint IP defines the host IP for the host in |
|
| 47 |
+ // which this container is running and can be reached by |
|
| 48 |
+ // building a tunnel to that host IP. |
|
| 49 |
+ TunnelEndpointIP string `protobuf:"bytes,3,opt,name=tunnel_endpoint_ip,json=tunnelEndpointIp,proto3" json:"tunnel_endpoint_ip,omitempty"` |
|
| 50 |
+} |
|
| 51 |
+ |
|
| 52 |
+func (m *PeerRecord) Reset() { *m = PeerRecord{} }
|
|
| 53 |
+func (*PeerRecord) ProtoMessage() {}
|
|
| 54 |
+func (*PeerRecord) Descriptor() ([]byte, []int) { return fileDescriptorOverlay, []int{0} }
|
|
| 55 |
+ |
|
| 56 |
+func init() {
|
|
| 57 |
+ proto.RegisterType((*PeerRecord)(nil), "overlay.PeerRecord") |
|
| 58 |
+} |
|
| 59 |
+func (this *PeerRecord) GoString() string {
|
|
| 60 |
+ if this == nil {
|
|
| 61 |
+ return "nil" |
|
| 62 |
+ } |
|
| 63 |
+ s := make([]string, 0, 7) |
|
| 64 |
+ s = append(s, "&overlay.PeerRecord{")
|
|
| 65 |
+ s = append(s, "EndpointIP: "+fmt.Sprintf("%#v", this.EndpointIP)+",\n")
|
|
| 66 |
+ s = append(s, "EndpointMAC: "+fmt.Sprintf("%#v", this.EndpointMAC)+",\n")
|
|
| 67 |
+ s = append(s, "TunnelEndpointIP: "+fmt.Sprintf("%#v", this.TunnelEndpointIP)+",\n")
|
|
| 68 |
+ s = append(s, "}") |
|
| 69 |
+ return strings.Join(s, "") |
|
| 70 |
+} |
|
| 71 |
+func valueToGoStringOverlay(v interface{}, typ string) string {
|
|
| 72 |
+ rv := reflect.ValueOf(v) |
|
| 73 |
+ if rv.IsNil() {
|
|
| 74 |
+ return "nil" |
|
| 75 |
+ } |
|
| 76 |
+ pv := reflect.Indirect(rv).Interface() |
|
| 77 |
+ return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
|
|
| 78 |
+} |
|
| 79 |
+func extensionToGoStringOverlay(e map[int32]github_com_gogo_protobuf_proto.Extension) string {
|
|
| 80 |
+ if e == nil {
|
|
| 81 |
+ return "nil" |
|
| 82 |
+ } |
|
| 83 |
+ s := "map[int32]proto.Extension{"
|
|
| 84 |
+ keys := make([]int, 0, len(e)) |
|
| 85 |
+ for k := range e {
|
|
| 86 |
+ keys = append(keys, int(k)) |
|
| 87 |
+ } |
|
| 88 |
+ sort.Ints(keys) |
|
| 89 |
+ ss := []string{}
|
|
| 90 |
+ for _, k := range keys {
|
|
| 91 |
+ ss = append(ss, strconv.Itoa(k)+": "+e[int32(k)].GoString()) |
|
| 92 |
+ } |
|
| 93 |
+ s += strings.Join(ss, ",") + "}" |
|
| 94 |
+ return s |
|
| 95 |
+} |
|
| 96 |
+func (m *PeerRecord) Marshal() (data []byte, err error) {
|
|
| 97 |
+ size := m.Size() |
|
| 98 |
+ data = make([]byte, size) |
|
| 99 |
+ n, err := m.MarshalTo(data) |
|
| 100 |
+ if err != nil {
|
|
| 101 |
+ return nil, err |
|
| 102 |
+ } |
|
| 103 |
+ return data[:n], nil |
|
| 104 |
+} |
|
| 105 |
+ |
|
| 106 |
+func (m *PeerRecord) MarshalTo(data []byte) (int, error) {
|
|
| 107 |
+ var i int |
|
| 108 |
+ _ = i |
|
| 109 |
+ var l int |
|
| 110 |
+ _ = l |
|
| 111 |
+ if len(m.EndpointIP) > 0 {
|
|
| 112 |
+ data[i] = 0xa |
|
| 113 |
+ i++ |
|
| 114 |
+ i = encodeVarintOverlay(data, i, uint64(len(m.EndpointIP))) |
|
| 115 |
+ i += copy(data[i:], m.EndpointIP) |
|
| 116 |
+ } |
|
| 117 |
+ if len(m.EndpointMAC) > 0 {
|
|
| 118 |
+ data[i] = 0x12 |
|
| 119 |
+ i++ |
|
| 120 |
+ i = encodeVarintOverlay(data, i, uint64(len(m.EndpointMAC))) |
|
| 121 |
+ i += copy(data[i:], m.EndpointMAC) |
|
| 122 |
+ } |
|
| 123 |
+ if len(m.TunnelEndpointIP) > 0 {
|
|
| 124 |
+ data[i] = 0x1a |
|
| 125 |
+ i++ |
|
| 126 |
+ i = encodeVarintOverlay(data, i, uint64(len(m.TunnelEndpointIP))) |
|
| 127 |
+ i += copy(data[i:], m.TunnelEndpointIP) |
|
| 128 |
+ } |
|
| 129 |
+ return i, nil |
|
| 130 |
+} |
|
| 131 |
+ |
|
| 132 |
+func encodeFixed64Overlay(data []byte, offset int, v uint64) int {
|
|
| 133 |
+ data[offset] = uint8(v) |
|
| 134 |
+ data[offset+1] = uint8(v >> 8) |
|
| 135 |
+ data[offset+2] = uint8(v >> 16) |
|
| 136 |
+ data[offset+3] = uint8(v >> 24) |
|
| 137 |
+ data[offset+4] = uint8(v >> 32) |
|
| 138 |
+ data[offset+5] = uint8(v >> 40) |
|
| 139 |
+ data[offset+6] = uint8(v >> 48) |
|
| 140 |
+ data[offset+7] = uint8(v >> 56) |
|
| 141 |
+ return offset + 8 |
|
| 142 |
+} |
|
| 143 |
+func encodeFixed32Overlay(data []byte, offset int, v uint32) int {
|
|
| 144 |
+ data[offset] = uint8(v) |
|
| 145 |
+ data[offset+1] = uint8(v >> 8) |
|
| 146 |
+ data[offset+2] = uint8(v >> 16) |
|
| 147 |
+ data[offset+3] = uint8(v >> 24) |
|
| 148 |
+ return offset + 4 |
|
| 149 |
+} |
|
| 150 |
+func encodeVarintOverlay(data []byte, offset int, v uint64) int {
|
|
| 151 |
+ for v >= 1<<7 {
|
|
| 152 |
+ data[offset] = uint8(v&0x7f | 0x80) |
|
| 153 |
+ v >>= 7 |
|
| 154 |
+ offset++ |
|
| 155 |
+ } |
|
| 156 |
+ data[offset] = uint8(v) |
|
| 157 |
+ return offset + 1 |
|
| 158 |
+} |
|
| 159 |
+func (m *PeerRecord) Size() (n int) {
|
|
| 160 |
+ var l int |
|
| 161 |
+ _ = l |
|
| 162 |
+ l = len(m.EndpointIP) |
|
| 163 |
+ if l > 0 {
|
|
| 164 |
+ n += 1 + l + sovOverlay(uint64(l)) |
|
| 165 |
+ } |
|
| 166 |
+ l = len(m.EndpointMAC) |
|
| 167 |
+ if l > 0 {
|
|
| 168 |
+ n += 1 + l + sovOverlay(uint64(l)) |
|
| 169 |
+ } |
|
| 170 |
+ l = len(m.TunnelEndpointIP) |
|
| 171 |
+ if l > 0 {
|
|
| 172 |
+ n += 1 + l + sovOverlay(uint64(l)) |
|
| 173 |
+ } |
|
| 174 |
+ return n |
|
| 175 |
+} |
|
| 176 |
+ |
|
| 177 |
+func sovOverlay(x uint64) (n int) {
|
|
| 178 |
+ for {
|
|
| 179 |
+ n++ |
|
| 180 |
+ x >>= 7 |
|
| 181 |
+ if x == 0 {
|
|
| 182 |
+ break |
|
| 183 |
+ } |
|
| 184 |
+ } |
|
| 185 |
+ return n |
|
| 186 |
+} |
|
| 187 |
+func sozOverlay(x uint64) (n int) {
|
|
| 188 |
+ return sovOverlay(uint64((x << 1) ^ uint64((int64(x) >> 63)))) |
|
| 189 |
+} |
|
| 190 |
+func (this *PeerRecord) String() string {
|
|
| 191 |
+ if this == nil {
|
|
| 192 |
+ return "nil" |
|
| 193 |
+ } |
|
| 194 |
+ s := strings.Join([]string{`&PeerRecord{`,
|
|
| 195 |
+ `EndpointIP:` + fmt.Sprintf("%v", this.EndpointIP) + `,`,
|
|
| 196 |
+ `EndpointMAC:` + fmt.Sprintf("%v", this.EndpointMAC) + `,`,
|
|
| 197 |
+ `TunnelEndpointIP:` + fmt.Sprintf("%v", this.TunnelEndpointIP) + `,`,
|
|
| 198 |
+ `}`, |
|
| 199 |
+ }, "") |
|
| 200 |
+ return s |
|
| 201 |
+} |
|
| 202 |
+func valueToStringOverlay(v interface{}) string {
|
|
| 203 |
+ rv := reflect.ValueOf(v) |
|
| 204 |
+ if rv.IsNil() {
|
|
| 205 |
+ return "nil" |
|
| 206 |
+ } |
|
| 207 |
+ pv := reflect.Indirect(rv).Interface() |
|
| 208 |
+ return fmt.Sprintf("*%v", pv)
|
|
| 209 |
+} |
|
| 210 |
+func (m *PeerRecord) Unmarshal(data []byte) error {
|
|
| 211 |
+ l := len(data) |
|
| 212 |
+ iNdEx := 0 |
|
| 213 |
+ for iNdEx < l {
|
|
| 214 |
+ preIndex := iNdEx |
|
| 215 |
+ var wire uint64 |
|
| 216 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 217 |
+ if shift >= 64 {
|
|
| 218 |
+ return ErrIntOverflowOverlay |
|
| 219 |
+ } |
|
| 220 |
+ if iNdEx >= l {
|
|
| 221 |
+ return io.ErrUnexpectedEOF |
|
| 222 |
+ } |
|
| 223 |
+ b := data[iNdEx] |
|
| 224 |
+ iNdEx++ |
|
| 225 |
+ wire |= (uint64(b) & 0x7F) << shift |
|
| 226 |
+ if b < 0x80 {
|
|
| 227 |
+ break |
|
| 228 |
+ } |
|
| 229 |
+ } |
|
| 230 |
+ fieldNum := int32(wire >> 3) |
|
| 231 |
+ wireType := int(wire & 0x7) |
|
| 232 |
+ if wireType == 4 {
|
|
| 233 |
+ return fmt.Errorf("proto: PeerRecord: wiretype end group for non-group")
|
|
| 234 |
+ } |
|
| 235 |
+ if fieldNum <= 0 {
|
|
| 236 |
+ return fmt.Errorf("proto: PeerRecord: illegal tag %d (wire type %d)", fieldNum, wire)
|
|
| 237 |
+ } |
|
| 238 |
+ switch fieldNum {
|
|
| 239 |
+ case 1: |
|
| 240 |
+ if wireType != 2 {
|
|
| 241 |
+ return fmt.Errorf("proto: wrong wireType = %d for field EndpointIP", wireType)
|
|
| 242 |
+ } |
|
| 243 |
+ var stringLen uint64 |
|
| 244 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 245 |
+ if shift >= 64 {
|
|
| 246 |
+ return ErrIntOverflowOverlay |
|
| 247 |
+ } |
|
| 248 |
+ if iNdEx >= l {
|
|
| 249 |
+ return io.ErrUnexpectedEOF |
|
| 250 |
+ } |
|
| 251 |
+ b := data[iNdEx] |
|
| 252 |
+ iNdEx++ |
|
| 253 |
+ stringLen |= (uint64(b) & 0x7F) << shift |
|
| 254 |
+ if b < 0x80 {
|
|
| 255 |
+ break |
|
| 256 |
+ } |
|
| 257 |
+ } |
|
| 258 |
+ intStringLen := int(stringLen) |
|
| 259 |
+ if intStringLen < 0 {
|
|
| 260 |
+ return ErrInvalidLengthOverlay |
|
| 261 |
+ } |
|
| 262 |
+ postIndex := iNdEx + intStringLen |
|
| 263 |
+ if postIndex > l {
|
|
| 264 |
+ return io.ErrUnexpectedEOF |
|
| 265 |
+ } |
|
| 266 |
+ m.EndpointIP = string(data[iNdEx:postIndex]) |
|
| 267 |
+ iNdEx = postIndex |
|
| 268 |
+ case 2: |
|
| 269 |
+ if wireType != 2 {
|
|
| 270 |
+ return fmt.Errorf("proto: wrong wireType = %d for field EndpointMAC", wireType)
|
|
| 271 |
+ } |
|
| 272 |
+ var stringLen uint64 |
|
| 273 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 274 |
+ if shift >= 64 {
|
|
| 275 |
+ return ErrIntOverflowOverlay |
|
| 276 |
+ } |
|
| 277 |
+ if iNdEx >= l {
|
|
| 278 |
+ return io.ErrUnexpectedEOF |
|
| 279 |
+ } |
|
| 280 |
+ b := data[iNdEx] |
|
| 281 |
+ iNdEx++ |
|
| 282 |
+ stringLen |= (uint64(b) & 0x7F) << shift |
|
| 283 |
+ if b < 0x80 {
|
|
| 284 |
+ break |
|
| 285 |
+ } |
|
| 286 |
+ } |
|
| 287 |
+ intStringLen := int(stringLen) |
|
| 288 |
+ if intStringLen < 0 {
|
|
| 289 |
+ return ErrInvalidLengthOverlay |
|
| 290 |
+ } |
|
| 291 |
+ postIndex := iNdEx + intStringLen |
|
| 292 |
+ if postIndex > l {
|
|
| 293 |
+ return io.ErrUnexpectedEOF |
|
| 294 |
+ } |
|
| 295 |
+ m.EndpointMAC = string(data[iNdEx:postIndex]) |
|
| 296 |
+ iNdEx = postIndex |
|
| 297 |
+ case 3: |
|
| 298 |
+ if wireType != 2 {
|
|
| 299 |
+ return fmt.Errorf("proto: wrong wireType = %d for field TunnelEndpointIP", wireType)
|
|
| 300 |
+ } |
|
| 301 |
+ var stringLen uint64 |
|
| 302 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 303 |
+ if shift >= 64 {
|
|
| 304 |
+ return ErrIntOverflowOverlay |
|
| 305 |
+ } |
|
| 306 |
+ if iNdEx >= l {
|
|
| 307 |
+ return io.ErrUnexpectedEOF |
|
| 308 |
+ } |
|
| 309 |
+ b := data[iNdEx] |
|
| 310 |
+ iNdEx++ |
|
| 311 |
+ stringLen |= (uint64(b) & 0x7F) << shift |
|
| 312 |
+ if b < 0x80 {
|
|
| 313 |
+ break |
|
| 314 |
+ } |
|
| 315 |
+ } |
|
| 316 |
+ intStringLen := int(stringLen) |
|
| 317 |
+ if intStringLen < 0 {
|
|
| 318 |
+ return ErrInvalidLengthOverlay |
|
| 319 |
+ } |
|
| 320 |
+ postIndex := iNdEx + intStringLen |
|
| 321 |
+ if postIndex > l {
|
|
| 322 |
+ return io.ErrUnexpectedEOF |
|
| 323 |
+ } |
|
| 324 |
+ m.TunnelEndpointIP = string(data[iNdEx:postIndex]) |
|
| 325 |
+ iNdEx = postIndex |
|
| 326 |
+ default: |
|
| 327 |
+ iNdEx = preIndex |
|
| 328 |
+ skippy, err := skipOverlay(data[iNdEx:]) |
|
| 329 |
+ if err != nil {
|
|
| 330 |
+ return err |
|
| 331 |
+ } |
|
| 332 |
+ if skippy < 0 {
|
|
| 333 |
+ return ErrInvalidLengthOverlay |
|
| 334 |
+ } |
|
| 335 |
+ if (iNdEx + skippy) > l {
|
|
| 336 |
+ return io.ErrUnexpectedEOF |
|
| 337 |
+ } |
|
| 338 |
+ iNdEx += skippy |
|
| 339 |
+ } |
|
| 340 |
+ } |
|
| 341 |
+ |
|
| 342 |
+ if iNdEx > l {
|
|
| 343 |
+ return io.ErrUnexpectedEOF |
|
| 344 |
+ } |
|
| 345 |
+ return nil |
|
| 346 |
+} |
|
| 347 |
+func skipOverlay(data []byte) (n int, err error) {
|
|
| 348 |
+ l := len(data) |
|
| 349 |
+ iNdEx := 0 |
|
| 350 |
+ for iNdEx < l {
|
|
| 351 |
+ var wire uint64 |
|
| 352 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 353 |
+ if shift >= 64 {
|
|
| 354 |
+ return 0, ErrIntOverflowOverlay |
|
| 355 |
+ } |
|
| 356 |
+ if iNdEx >= l {
|
|
| 357 |
+ return 0, io.ErrUnexpectedEOF |
|
| 358 |
+ } |
|
| 359 |
+ b := data[iNdEx] |
|
| 360 |
+ iNdEx++ |
|
| 361 |
+ wire |= (uint64(b) & 0x7F) << shift |
|
| 362 |
+ if b < 0x80 {
|
|
| 363 |
+ break |
|
| 364 |
+ } |
|
| 365 |
+ } |
|
| 366 |
+ wireType := int(wire & 0x7) |
|
| 367 |
+ switch wireType {
|
|
| 368 |
+ case 0: |
|
| 369 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 370 |
+ if shift >= 64 {
|
|
| 371 |
+ return 0, ErrIntOverflowOverlay |
|
| 372 |
+ } |
|
| 373 |
+ if iNdEx >= l {
|
|
| 374 |
+ return 0, io.ErrUnexpectedEOF |
|
| 375 |
+ } |
|
| 376 |
+ iNdEx++ |
|
| 377 |
+ if data[iNdEx-1] < 0x80 {
|
|
| 378 |
+ break |
|
| 379 |
+ } |
|
| 380 |
+ } |
|
| 381 |
+ return iNdEx, nil |
|
| 382 |
+ case 1: |
|
| 383 |
+ iNdEx += 8 |
|
| 384 |
+ return iNdEx, nil |
|
| 385 |
+ case 2: |
|
| 386 |
+ var length int |
|
| 387 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 388 |
+ if shift >= 64 {
|
|
| 389 |
+ return 0, ErrIntOverflowOverlay |
|
| 390 |
+ } |
|
| 391 |
+ if iNdEx >= l {
|
|
| 392 |
+ return 0, io.ErrUnexpectedEOF |
|
| 393 |
+ } |
|
| 394 |
+ b := data[iNdEx] |
|
| 395 |
+ iNdEx++ |
|
| 396 |
+ length |= (int(b) & 0x7F) << shift |
|
| 397 |
+ if b < 0x80 {
|
|
| 398 |
+ break |
|
| 399 |
+ } |
|
| 400 |
+ } |
|
| 401 |
+ iNdEx += length |
|
| 402 |
+ if length < 0 {
|
|
| 403 |
+ return 0, ErrInvalidLengthOverlay |
|
| 404 |
+ } |
|
| 405 |
+ return iNdEx, nil |
|
| 406 |
+ case 3: |
|
| 407 |
+ for {
|
|
| 408 |
+ var innerWire uint64 |
|
| 409 |
+ var start int = iNdEx |
|
| 410 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 411 |
+ if shift >= 64 {
|
|
| 412 |
+ return 0, ErrIntOverflowOverlay |
|
| 413 |
+ } |
|
| 414 |
+ if iNdEx >= l {
|
|
| 415 |
+ return 0, io.ErrUnexpectedEOF |
|
| 416 |
+ } |
|
| 417 |
+ b := data[iNdEx] |
|
| 418 |
+ iNdEx++ |
|
| 419 |
+ innerWire |= (uint64(b) & 0x7F) << shift |
|
| 420 |
+ if b < 0x80 {
|
|
| 421 |
+ break |
|
| 422 |
+ } |
|
| 423 |
+ } |
|
| 424 |
+ innerWireType := int(innerWire & 0x7) |
|
| 425 |
+ if innerWireType == 4 {
|
|
| 426 |
+ break |
|
| 427 |
+ } |
|
| 428 |
+ next, err := skipOverlay(data[start:]) |
|
| 429 |
+ if err != nil {
|
|
| 430 |
+ return 0, err |
|
| 431 |
+ } |
|
| 432 |
+ iNdEx = start + next |
|
| 433 |
+ } |
|
| 434 |
+ return iNdEx, nil |
|
| 435 |
+ case 4: |
|
| 436 |
+ return iNdEx, nil |
|
| 437 |
+ case 5: |
|
| 438 |
+ iNdEx += 4 |
|
| 439 |
+ return iNdEx, nil |
|
| 440 |
+ default: |
|
| 441 |
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
|
| 442 |
+ } |
|
| 443 |
+ } |
|
| 444 |
+ panic("unreachable")
|
|
| 445 |
+} |
|
| 446 |
+ |
|
| 447 |
+var ( |
|
| 448 |
+ ErrInvalidLengthOverlay = fmt.Errorf("proto: negative length found during unmarshaling")
|
|
| 449 |
+ ErrIntOverflowOverlay = fmt.Errorf("proto: integer overflow")
|
|
| 450 |
+) |
|
| 451 |
+ |
|
| 452 |
+var fileDescriptorOverlay = []byte{
|
|
| 453 |
+ // 195 bytes of a gzipped FileDescriptorProto |
|
| 454 |
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0xcd, 0x2f, 0x4b, 0x2d, |
|
| 455 |
+ 0xca, 0x49, 0xac, 0xd4, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x87, 0x72, 0xa5, 0x44, 0xd2, |
|
| 456 |
+ 0xf3, 0xd3, 0xf3, 0xc1, 0x62, 0xfa, 0x20, 0x16, 0x44, 0x5a, 0x69, 0x2b, 0x23, 0x17, 0x57, 0x40, |
|
| 457 |
+ 0x6a, 0x6a, 0x51, 0x50, 0x6a, 0x72, 0x7e, 0x51, 0x8a, 0x90, 0x3e, 0x17, 0x77, 0x6a, 0x5e, 0x4a, |
|
| 458 |
+ 0x41, 0x7e, 0x66, 0x5e, 0x49, 0x7c, 0x66, 0x81, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0xa7, 0x13, 0xdf, |
|
| 459 |
+ 0xa3, 0x7b, 0xf2, 0x5c, 0xae, 0x50, 0x61, 0xcf, 0x80, 0x20, 0x2e, 0x98, 0x12, 0xcf, 0x02, 0x21, |
|
| 460 |
+ 0x23, 0x2e, 0x1e, 0xb8, 0x86, 0xdc, 0xc4, 0x64, 0x09, 0x26, 0xb0, 0x0e, 0x7e, 0xa0, 0x0e, 0x6e, |
|
| 461 |
+ 0x98, 0x0e, 0x5f, 0x47, 0xe7, 0x20, 0xb8, 0xa9, 0xbe, 0x89, 0xc9, 0x42, 0x4e, 0x5c, 0x42, 0x25, |
|
| 462 |
+ 0xa5, 0x79, 0x79, 0xa9, 0x39, 0xf1, 0xc8, 0x76, 0x31, 0x83, 0x75, 0x8a, 0x00, 0x75, 0x0a, 0x84, |
|
| 463 |
+ 0x80, 0x65, 0x91, 0x6c, 0x14, 0x28, 0x41, 0x15, 0x29, 0x70, 0x92, 0xb8, 0xf1, 0x50, 0x8e, 0xe1, |
|
| 464 |
+ 0xc3, 0x43, 0x39, 0xc6, 0x86, 0x47, 0x72, 0x8c, 0x27, 0x80, 0xf8, 0x02, 0x10, 0x3f, 0x00, 0xe2, |
|
| 465 |
+ 0x24, 0x36, 0xb0, 0xc7, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xbf, 0xd7, 0x7d, 0x7d, 0x08, |
|
| 466 |
+ 0x01, 0x00, 0x00, |
|
| 467 |
+} |
| 0 | 468 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,27 @@ |
| 0 |
+syntax = "proto3"; |
|
| 1 |
+ |
|
| 2 |
+import "gogoproto/gogo.proto"; |
|
| 3 |
+ |
|
| 4 |
+package overlay; |
|
| 5 |
+ |
|
| 6 |
+option (gogoproto.marshaler_all) = true; |
|
| 7 |
+option (gogoproto.unmarshaler_all) = true; |
|
| 8 |
+option (gogoproto.stringer_all) = true; |
|
| 9 |
+option (gogoproto.gostring_all) = true; |
|
| 10 |
+option (gogoproto.sizer_all) = true; |
|
| 11 |
+option (gogoproto.goproto_stringer_all) = false; |
|
| 12 |
+ |
|
| 13 |
+// PeerRecord defines the information corresponding to a peer |
|
| 14 |
+// container in the overlay network. |
|
| 15 |
+message PeerRecord {
|
|
| 16 |
+ // Endpoint IP is the IP of the container attachment on the |
|
| 17 |
+ // given overlay network. |
|
| 18 |
+ string endpoint_ip = 1 [(gogoproto.customname) = "EndpointIP"]; |
|
| 19 |
+ // Endpoint MAC is the mac address of the container attachment |
|
| 20 |
+ // on the given overlay network. |
|
| 21 |
+ string endpoint_mac = 2 [(gogoproto.customname) = "EndpointMAC"]; |
|
| 22 |
+ // Tunnel Endpoint IP defines the host IP for the host in |
|
| 23 |
+ // which this container is running and can be reached by |
|
| 24 |
+ // building a tunnel to that host IP. |
|
| 25 |
+ string tunnel_endpoint_ip = 3 [(gogoproto.customname) = "TunnelEndpointIP"]; |
|
| 26 |
+} |
|
| 0 | 27 |
\ No newline at end of file |
| 1 | 28 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,336 @@ |
| 0 |
+package overlay |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "fmt" |
|
| 4 |
+ "net" |
|
| 5 |
+ "sync" |
|
| 6 |
+ |
|
| 7 |
+ "github.com/Sirupsen/logrus" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+const ovPeerTable = "overlay_peer_table" |
|
| 11 |
+ |
|
| 12 |
+type peerKey struct {
|
|
| 13 |
+ peerIP net.IP |
|
| 14 |
+ peerMac net.HardwareAddr |
|
| 15 |
+} |
|
| 16 |
+ |
|
| 17 |
+type peerEntry struct {
|
|
| 18 |
+ eid string |
|
| 19 |
+ vtep net.IP |
|
| 20 |
+ peerIPMask net.IPMask |
|
| 21 |
+ inSandbox bool |
|
| 22 |
+ isLocal bool |
|
| 23 |
+} |
|
| 24 |
+ |
|
| 25 |
+type peerMap struct {
|
|
| 26 |
+ mp map[string]peerEntry |
|
| 27 |
+ sync.Mutex |
|
| 28 |
+} |
|
| 29 |
+ |
|
| 30 |
+type peerNetworkMap struct {
|
|
| 31 |
+ mp map[string]*peerMap |
|
| 32 |
+ sync.Mutex |
|
| 33 |
+} |
|
| 34 |
+ |
|
| 35 |
+func (pKey peerKey) String() string {
|
|
| 36 |
+ return fmt.Sprintf("%s %s", pKey.peerIP, pKey.peerMac)
|
|
| 37 |
+} |
|
| 38 |
+ |
|
| 39 |
+func (pKey *peerKey) Scan(state fmt.ScanState, verb rune) error {
|
|
| 40 |
+ ipB, err := state.Token(true, nil) |
|
| 41 |
+ if err != nil {
|
|
| 42 |
+ return err |
|
| 43 |
+ } |
|
| 44 |
+ |
|
| 45 |
+ pKey.peerIP = net.ParseIP(string(ipB)) |
|
| 46 |
+ |
|
| 47 |
+ macB, err := state.Token(true, nil) |
|
| 48 |
+ if err != nil {
|
|
| 49 |
+ return err |
|
| 50 |
+ } |
|
| 51 |
+ |
|
| 52 |
+ pKey.peerMac, err = net.ParseMAC(string(macB)) |
|
| 53 |
+ if err != nil {
|
|
| 54 |
+ return err |
|
| 55 |
+ } |
|
| 56 |
+ |
|
| 57 |
+ return nil |
|
| 58 |
+} |
|
| 59 |
+ |
|
| 60 |
+var peerDbWg sync.WaitGroup |
|
| 61 |
+ |
|
| 62 |
+func (d *driver) peerDbWalk(f func(string, *peerKey, *peerEntry) bool) error {
|
|
| 63 |
+ d.peerDb.Lock() |
|
| 64 |
+ nids := []string{}
|
|
| 65 |
+ for nid := range d.peerDb.mp {
|
|
| 66 |
+ nids = append(nids, nid) |
|
| 67 |
+ } |
|
| 68 |
+ d.peerDb.Unlock() |
|
| 69 |
+ |
|
| 70 |
+ for _, nid := range nids {
|
|
| 71 |
+ d.peerDbNetworkWalk(nid, func(pKey *peerKey, pEntry *peerEntry) bool {
|
|
| 72 |
+ return f(nid, pKey, pEntry) |
|
| 73 |
+ }) |
|
| 74 |
+ } |
|
| 75 |
+ return nil |
|
| 76 |
+} |
|
| 77 |
+ |
|
| 78 |
+func (d *driver) peerDbNetworkWalk(nid string, f func(*peerKey, *peerEntry) bool) error {
|
|
| 79 |
+ d.peerDb.Lock() |
|
| 80 |
+ pMap, ok := d.peerDb.mp[nid] |
|
| 81 |
+ if !ok {
|
|
| 82 |
+ d.peerDb.Unlock() |
|
| 83 |
+ return nil |
|
| 84 |
+ } |
|
| 85 |
+ d.peerDb.Unlock() |
|
| 86 |
+ |
|
| 87 |
+ pMap.Lock() |
|
| 88 |
+ for pKeyStr, pEntry := range pMap.mp {
|
|
| 89 |
+ var pKey peerKey |
|
| 90 |
+ if _, err := fmt.Sscan(pKeyStr, &pKey); err != nil {
|
|
| 91 |
+ logrus.Warnf("Peer key scan on network %s failed: %v", nid, err)
|
|
| 92 |
+ } |
|
| 93 |
+ |
|
| 94 |
+ if f(&pKey, &pEntry) {
|
|
| 95 |
+ pMap.Unlock() |
|
| 96 |
+ return nil |
|
| 97 |
+ } |
|
| 98 |
+ } |
|
| 99 |
+ pMap.Unlock() |
|
| 100 |
+ |
|
| 101 |
+ return nil |
|
| 102 |
+} |
|
| 103 |
+ |
|
| 104 |
+func (d *driver) peerDbSearch(nid string, peerIP net.IP) (net.HardwareAddr, net.IPMask, net.IP, error) {
|
|
| 105 |
+ var ( |
|
| 106 |
+ peerMac net.HardwareAddr |
|
| 107 |
+ vtep net.IP |
|
| 108 |
+ peerIPMask net.IPMask |
|
| 109 |
+ found bool |
|
| 110 |
+ ) |
|
| 111 |
+ |
|
| 112 |
+ err := d.peerDbNetworkWalk(nid, func(pKey *peerKey, pEntry *peerEntry) bool {
|
|
| 113 |
+ if pKey.peerIP.Equal(peerIP) {
|
|
| 114 |
+ peerMac = pKey.peerMac |
|
| 115 |
+ peerIPMask = pEntry.peerIPMask |
|
| 116 |
+ vtep = pEntry.vtep |
|
| 117 |
+ found = true |
|
| 118 |
+ return found |
|
| 119 |
+ } |
|
| 120 |
+ |
|
| 121 |
+ return found |
|
| 122 |
+ }) |
|
| 123 |
+ |
|
| 124 |
+ if err != nil {
|
|
| 125 |
+ return nil, nil, nil, fmt.Errorf("peerdb search for peer ip %q failed: %v", peerIP, err)
|
|
| 126 |
+ } |
|
| 127 |
+ |
|
| 128 |
+ if !found {
|
|
| 129 |
+ return nil, nil, nil, fmt.Errorf("peer ip %q not found in peerdb", peerIP)
|
|
| 130 |
+ } |
|
| 131 |
+ |
|
| 132 |
+ return peerMac, peerIPMask, vtep, nil |
|
| 133 |
+} |
|
| 134 |
+ |
|
| 135 |
+func (d *driver) peerDbAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask, |
|
| 136 |
+ peerMac net.HardwareAddr, vtep net.IP, isLocal bool) {
|
|
| 137 |
+ |
|
| 138 |
+ peerDbWg.Wait() |
|
| 139 |
+ |
|
| 140 |
+ d.peerDb.Lock() |
|
| 141 |
+ pMap, ok := d.peerDb.mp[nid] |
|
| 142 |
+ if !ok {
|
|
| 143 |
+ d.peerDb.mp[nid] = &peerMap{
|
|
| 144 |
+ mp: make(map[string]peerEntry), |
|
| 145 |
+ } |
|
| 146 |
+ |
|
| 147 |
+ pMap = d.peerDb.mp[nid] |
|
| 148 |
+ } |
|
| 149 |
+ d.peerDb.Unlock() |
|
| 150 |
+ |
|
| 151 |
+ pKey := peerKey{
|
|
| 152 |
+ peerIP: peerIP, |
|
| 153 |
+ peerMac: peerMac, |
|
| 154 |
+ } |
|
| 155 |
+ |
|
| 156 |
+ pEntry := peerEntry{
|
|
| 157 |
+ eid: eid, |
|
| 158 |
+ vtep: vtep, |
|
| 159 |
+ peerIPMask: peerIPMask, |
|
| 160 |
+ isLocal: isLocal, |
|
| 161 |
+ } |
|
| 162 |
+ |
|
| 163 |
+ pMap.Lock() |
|
| 164 |
+ pMap.mp[pKey.String()] = pEntry |
|
| 165 |
+ pMap.Unlock() |
|
| 166 |
+} |
|
| 167 |
+ |
|
| 168 |
+func (d *driver) peerDbDelete(nid, eid string, peerIP net.IP, peerIPMask net.IPMask, |
|
| 169 |
+ peerMac net.HardwareAddr, vtep net.IP) {
|
|
| 170 |
+ peerDbWg.Wait() |
|
| 171 |
+ |
|
| 172 |
+ d.peerDb.Lock() |
|
| 173 |
+ pMap, ok := d.peerDb.mp[nid] |
|
| 174 |
+ if !ok {
|
|
| 175 |
+ d.peerDb.Unlock() |
|
| 176 |
+ return |
|
| 177 |
+ } |
|
| 178 |
+ d.peerDb.Unlock() |
|
| 179 |
+ |
|
| 180 |
+ pKey := peerKey{
|
|
| 181 |
+ peerIP: peerIP, |
|
| 182 |
+ peerMac: peerMac, |
|
| 183 |
+ } |
|
| 184 |
+ |
|
| 185 |
+ pMap.Lock() |
|
| 186 |
+ delete(pMap.mp, pKey.String()) |
|
| 187 |
+ pMap.Unlock() |
|
| 188 |
+} |
|
| 189 |
+ |
|
| 190 |
+func (d *driver) peerDbUpdateSandbox(nid string) {
|
|
| 191 |
+ d.peerDb.Lock() |
|
| 192 |
+ pMap, ok := d.peerDb.mp[nid] |
|
| 193 |
+ if !ok {
|
|
| 194 |
+ d.peerDb.Unlock() |
|
| 195 |
+ return |
|
| 196 |
+ } |
|
| 197 |
+ d.peerDb.Unlock() |
|
| 198 |
+ |
|
| 199 |
+ peerDbWg.Add(1) |
|
| 200 |
+ |
|
| 201 |
+ var peerOps []func() |
|
| 202 |
+ pMap.Lock() |
|
| 203 |
+ for pKeyStr, pEntry := range pMap.mp {
|
|
| 204 |
+ var pKey peerKey |
|
| 205 |
+ if _, err := fmt.Sscan(pKeyStr, &pKey); err != nil {
|
|
| 206 |
+ fmt.Printf("peer key scan failed: %v", err)
|
|
| 207 |
+ } |
|
| 208 |
+ |
|
| 209 |
+ if pEntry.isLocal {
|
|
| 210 |
+ continue |
|
| 211 |
+ } |
|
| 212 |
+ |
|
| 213 |
+ // Go captures variables by reference. The pEntry could be |
|
| 214 |
+ // pointing to the same memory location for every iteration. Make |
|
| 215 |
+ // a copy of pEntry before capturing it in the following closure. |
|
| 216 |
+ entry := pEntry |
|
| 217 |
+ op := func() {
|
|
| 218 |
+ if err := d.peerAdd(nid, entry.eid, pKey.peerIP, entry.peerIPMask, |
|
| 219 |
+ pKey.peerMac, entry.vtep, |
|
| 220 |
+ false); err != nil {
|
|
| 221 |
+ fmt.Printf("peerdbupdate in sandbox failed for ip %s and mac %s: %v",
|
|
| 222 |
+ pKey.peerIP, pKey.peerMac, err) |
|
| 223 |
+ } |
|
| 224 |
+ } |
|
| 225 |
+ |
|
| 226 |
+ peerOps = append(peerOps, op) |
|
| 227 |
+ } |
|
| 228 |
+ pMap.Unlock() |
|
| 229 |
+ |
|
| 230 |
+ for _, op := range peerOps {
|
|
| 231 |
+ op() |
|
| 232 |
+ } |
|
| 233 |
+ |
|
| 234 |
+ peerDbWg.Done() |
|
| 235 |
+} |
|
| 236 |
+ |
|
| 237 |
+func (d *driver) peerAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask, |
|
| 238 |
+ peerMac net.HardwareAddr, vtep net.IP, updateDb bool) error {
|
|
| 239 |
+ |
|
| 240 |
+ if err := validateID(nid, eid); err != nil {
|
|
| 241 |
+ return err |
|
| 242 |
+ } |
|
| 243 |
+ |
|
| 244 |
+ if updateDb {
|
|
| 245 |
+ d.peerDbAdd(nid, eid, peerIP, peerIPMask, peerMac, vtep, false) |
|
| 246 |
+ } |
|
| 247 |
+ |
|
| 248 |
+ n := d.network(nid) |
|
| 249 |
+ if n == nil {
|
|
| 250 |
+ return nil |
|
| 251 |
+ } |
|
| 252 |
+ |
|
| 253 |
+ sbox := n.sandbox() |
|
| 254 |
+ if sbox == nil {
|
|
| 255 |
+ return nil |
|
| 256 |
+ } |
|
| 257 |
+ |
|
| 258 |
+ IP := &net.IPNet{
|
|
| 259 |
+ IP: peerIP, |
|
| 260 |
+ Mask: peerIPMask, |
|
| 261 |
+ } |
|
| 262 |
+ |
|
| 263 |
+ s := n.getSubnetforIP(IP) |
|
| 264 |
+ if s == nil {
|
|
| 265 |
+ return fmt.Errorf("couldn't find the subnet %q in network %q\n", IP.String(), n.id)
|
|
| 266 |
+ } |
|
| 267 |
+ |
|
| 268 |
+ if err := n.obtainVxlanID(s); err != nil {
|
|
| 269 |
+ return fmt.Errorf("couldn't get vxlan id for %q: %v", s.subnetIP.String(), err)
|
|
| 270 |
+ } |
|
| 271 |
+ |
|
| 272 |
+ if err := n.joinSubnetSandbox(s, false); err != nil {
|
|
| 273 |
+ return fmt.Errorf("subnet sandbox join failed for %q: %v", s.subnetIP.String(), err)
|
|
| 274 |
+ } |
|
| 275 |
+ |
|
| 276 |
+ if err := d.checkEncryption(nid, vtep, n.vxlanID(s), false, true); err != nil {
|
|
| 277 |
+ logrus.Warn(err) |
|
| 278 |
+ } |
|
| 279 |
+ |
|
| 280 |
+ // Add neighbor entry for the peer IP |
|
| 281 |
+ if err := sbox.AddNeighbor(peerIP, peerMac, sbox.NeighborOptions().LinkName(s.vxlanName)); err != nil {
|
|
| 282 |
+ return fmt.Errorf("could not add neigbor entry into the sandbox: %v", err)
|
|
| 283 |
+ } |
|
| 284 |
+ |
|
| 285 |
+ // XXX Add fdb entry to the bridge for the peer mac |
|
| 286 |
+ |
|
| 287 |
+ return nil |
|
| 288 |
+} |
|
| 289 |
+ |
|
| 290 |
+func (d *driver) peerDelete(nid, eid string, peerIP net.IP, peerIPMask net.IPMask, |
|
| 291 |
+ peerMac net.HardwareAddr, vtep net.IP, updateDb bool) error {
|
|
| 292 |
+ |
|
| 293 |
+ if err := validateID(nid, eid); err != nil {
|
|
| 294 |
+ return err |
|
| 295 |
+ } |
|
| 296 |
+ |
|
| 297 |
+ if updateDb {
|
|
| 298 |
+ d.peerDbDelete(nid, eid, peerIP, peerIPMask, peerMac, vtep) |
|
| 299 |
+ } |
|
| 300 |
+ |
|
| 301 |
+ n := d.network(nid) |
|
| 302 |
+ if n == nil {
|
|
| 303 |
+ return nil |
|
| 304 |
+ } |
|
| 305 |
+ |
|
| 306 |
+ sbox := n.sandbox() |
|
| 307 |
+ if sbox == nil {
|
|
| 308 |
+ return nil |
|
| 309 |
+ } |
|
| 310 |
+ |
|
| 311 |
+ // Delete fdb entry to the bridge for the peer mac |
|
| 312 |
+ if err := sbox.DeleteNeighbor(vtep, peerMac, true); err != nil {
|
|
| 313 |
+ return fmt.Errorf("could not delete fdb entry into the sandbox: %v", err)
|
|
| 314 |
+ } |
|
| 315 |
+ |
|
| 316 |
+ // Delete neighbor entry for the peer IP |
|
| 317 |
+ if err := sbox.DeleteNeighbor(peerIP, peerMac, true); err != nil {
|
|
| 318 |
+ return fmt.Errorf("could not delete neigbor entry into the sandbox: %v", err)
|
|
| 319 |
+ } |
|
| 320 |
+ |
|
| 321 |
+ if err := d.checkEncryption(nid, vtep, 0, false, false); err != nil {
|
|
| 322 |
+ logrus.Warn(err) |
|
| 323 |
+ } |
|
| 324 |
+ |
|
| 325 |
+ return nil |
|
| 326 |
+} |
|
| 327 |
+ |
|
| 328 |
+func (d *driver) pushLocalDb() {
|
|
| 329 |
+ d.peerDbWalk(func(nid string, pKey *peerKey, pEntry *peerEntry) bool {
|
|
| 330 |
+ if pEntry.isLocal {
|
|
| 331 |
+ d.pushLocalEndpointEvent("join", nid, pEntry.eid)
|
|
| 332 |
+ } |
|
| 333 |
+ return false |
|
| 334 |
+ }) |
|
| 335 |
+} |
| ... | ... |
@@ -30,4 +30,10 @@ const ( |
| 30 | 30 |
|
| 31 | 31 |
// SourceMac of the network |
| 32 | 32 |
SourceMac = "com.docker.network.windowsshim.sourcemac" |
| 33 |
+ |
|
| 34 |
+ // DisableICC label |
|
| 35 |
+ DisableICC = "com.docker.network.windowsshim.disableicc" |
|
| 36 |
+ |
|
| 37 |
+ // DisableDNS label |
|
| 38 |
+ DisableDNS = "com.docker.network.windowsshim.disable_dns" |
|
| 33 | 39 |
) |
| 34 | 40 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,112 @@ |
| 0 |
+package overlay |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "fmt" |
|
| 4 |
+ "net" |
|
| 5 |
+ |
|
| 6 |
+ "github.com/Sirupsen/logrus" |
|
| 7 |
+ "github.com/docker/libnetwork/driverapi" |
|
| 8 |
+ "github.com/docker/libnetwork/types" |
|
| 9 |
+ "github.com/gogo/protobuf/proto" |
|
| 10 |
+) |
|
| 11 |
+ |
|
| 12 |
+// Join method is invoked when a Sandbox is attached to an endpoint. |
|
| 13 |
+func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
|
| 14 |
+ if err := validateID(nid, eid); err != nil {
|
|
| 15 |
+ return err |
|
| 16 |
+ } |
|
| 17 |
+ |
|
| 18 |
+ n := d.network(nid) |
|
| 19 |
+ if n == nil {
|
|
| 20 |
+ return fmt.Errorf("could not find network with id %s", nid)
|
|
| 21 |
+ } |
|
| 22 |
+ |
|
| 23 |
+ ep := n.endpoint(eid) |
|
| 24 |
+ if ep == nil {
|
|
| 25 |
+ return fmt.Errorf("could not find endpoint with id %s", eid)
|
|
| 26 |
+ } |
|
| 27 |
+ |
|
| 28 |
+ if err := d.writeEndpointToStore(ep); err != nil {
|
|
| 29 |
+ return fmt.Errorf("failed to update overlay endpoint %s to local data store: %v", ep.id[0:7], err)
|
|
| 30 |
+ } |
|
| 31 |
+ |
|
| 32 |
+ buf, err := proto.Marshal(&PeerRecord{
|
|
| 33 |
+ EndpointIP: ep.addr.String(), |
|
| 34 |
+ EndpointMAC: ep.mac.String(), |
|
| 35 |
+ TunnelEndpointIP: n.providerAddress, |
|
| 36 |
+ }) |
|
| 37 |
+ |
|
| 38 |
+ if err != nil {
|
|
| 39 |
+ return err |
|
| 40 |
+ } |
|
| 41 |
+ |
|
| 42 |
+ if err := jinfo.AddTableEntry(ovPeerTable, eid, buf); err != nil {
|
|
| 43 |
+ logrus.Errorf("overlay: Failed adding table entry to joininfo: %v", err)
|
|
| 44 |
+ } |
|
| 45 |
+ |
|
| 46 |
+ d.pushLocalEndpointEvent("join", nid, eid)
|
|
| 47 |
+ |
|
| 48 |
+ return nil |
|
| 49 |
+} |
|
| 50 |
+ |
|
| 51 |
+func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
|
|
| 52 |
+ if tableName != ovPeerTable {
|
|
| 53 |
+ logrus.Errorf("Unexpected table notification for table %s received", tableName)
|
|
| 54 |
+ return |
|
| 55 |
+ } |
|
| 56 |
+ |
|
| 57 |
+ eid := key |
|
| 58 |
+ |
|
| 59 |
+ var peer PeerRecord |
|
| 60 |
+ if err := proto.Unmarshal(value, &peer); err != nil {
|
|
| 61 |
+ logrus.Errorf("Failed to unmarshal peer record: %v", err)
|
|
| 62 |
+ return |
|
| 63 |
+ } |
|
| 64 |
+ |
|
| 65 |
+ n := d.network(nid) |
|
| 66 |
+ if n == nil {
|
|
| 67 |
+ return |
|
| 68 |
+ } |
|
| 69 |
+ |
|
| 70 |
+ // Ignore local peers. We already know about them and they |
|
| 71 |
+ // should not be added to vxlan fdb. |
|
| 72 |
+ if peer.TunnelEndpointIP == n.providerAddress {
|
|
| 73 |
+ return |
|
| 74 |
+ } |
|
| 75 |
+ |
|
| 76 |
+ addr, err := types.ParseCIDR(peer.EndpointIP) |
|
| 77 |
+ if err != nil {
|
|
| 78 |
+ logrus.Errorf("Invalid peer IP %s received in event notify", peer.EndpointIP)
|
|
| 79 |
+ return |
|
| 80 |
+ } |
|
| 81 |
+ |
|
| 82 |
+ mac, err := net.ParseMAC(peer.EndpointMAC) |
|
| 83 |
+ if err != nil {
|
|
| 84 |
+ logrus.Errorf("Invalid mac %s received in event notify", peer.EndpointMAC)
|
|
| 85 |
+ return |
|
| 86 |
+ } |
|
| 87 |
+ |
|
| 88 |
+ vtep := net.ParseIP(peer.TunnelEndpointIP) |
|
| 89 |
+ if vtep == nil {
|
|
| 90 |
+ logrus.Errorf("Invalid VTEP %s received in event notify", peer.TunnelEndpointIP)
|
|
| 91 |
+ return |
|
| 92 |
+ } |
|
| 93 |
+ |
|
| 94 |
+ if etype == driverapi.Delete {
|
|
| 95 |
+ d.peerDelete(nid, eid, addr.IP, addr.Mask, mac, vtep, true) |
|
| 96 |
+ return |
|
| 97 |
+ } |
|
| 98 |
+ |
|
| 99 |
+ d.peerAdd(nid, eid, addr.IP, addr.Mask, mac, vtep, true) |
|
| 100 |
+} |
|
| 101 |
+ |
|
| 102 |
+// Leave method is invoked when a Sandbox detaches from an endpoint. |
|
| 103 |
+func (d *driver) Leave(nid, eid string) error {
|
|
| 104 |
+ if err := validateID(nid, eid); err != nil {
|
|
| 105 |
+ return err |
|
| 106 |
+ } |
|
| 107 |
+ |
|
| 108 |
+ d.pushLocalEndpointEvent("leave", nid, eid)
|
|
| 109 |
+ |
|
| 110 |
+ return nil |
|
| 111 |
+} |
| 0 | 112 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,346 @@ |
| 0 |
+package overlay |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "encoding/json" |
|
| 4 |
+ "fmt" |
|
| 5 |
+ "net" |
|
| 6 |
+ |
|
| 7 |
+ "github.com/Microsoft/hcsshim" |
|
| 8 |
+ "github.com/Sirupsen/logrus" |
|
| 9 |
+ "github.com/docker/libnetwork/datastore" |
|
| 10 |
+ "github.com/docker/libnetwork/driverapi" |
|
| 11 |
+ "github.com/docker/libnetwork/types" |
|
| 12 |
+) |
|
| 13 |
+ |
|
| 14 |
+type endpointTable map[string]*endpoint |
|
| 15 |
+ |
|
| 16 |
+const overlayEndpointPrefix = "overlay/endpoint" |
|
| 17 |
+ |
|
| 18 |
+type endpoint struct {
|
|
| 19 |
+ id string |
|
| 20 |
+ nid string |
|
| 21 |
+ profileId string |
|
| 22 |
+ remote bool |
|
| 23 |
+ mac net.HardwareAddr |
|
| 24 |
+ addr *net.IPNet |
|
| 25 |
+ dbExists bool |
|
| 26 |
+ dbIndex uint64 |
|
| 27 |
+} |
|
| 28 |
+ |
|
| 29 |
+func validateID(nid, eid string) error {
|
|
| 30 |
+ if nid == "" {
|
|
| 31 |
+ return fmt.Errorf("invalid network id")
|
|
| 32 |
+ } |
|
| 33 |
+ |
|
| 34 |
+ if eid == "" {
|
|
| 35 |
+ return fmt.Errorf("invalid endpoint id")
|
|
| 36 |
+ } |
|
| 37 |
+ |
|
| 38 |
+ return nil |
|
| 39 |
+} |
|
| 40 |
+ |
|
| 41 |
+func (n *network) endpoint(eid string) *endpoint {
|
|
| 42 |
+ n.Lock() |
|
| 43 |
+ defer n.Unlock() |
|
| 44 |
+ |
|
| 45 |
+ return n.endpoints[eid] |
|
| 46 |
+} |
|
| 47 |
+ |
|
| 48 |
+func (n *network) addEndpoint(ep *endpoint) {
|
|
| 49 |
+ n.Lock() |
|
| 50 |
+ n.endpoints[ep.id] = ep |
|
| 51 |
+ n.Unlock() |
|
| 52 |
+} |
|
| 53 |
+ |
|
| 54 |
+func (n *network) deleteEndpoint(eid string) {
|
|
| 55 |
+ n.Lock() |
|
| 56 |
+ delete(n.endpoints, eid) |
|
| 57 |
+ n.Unlock() |
|
| 58 |
+} |
|
| 59 |
+ |
|
| 60 |
+func (n *network) removeEndpointWithAddress(addr *net.IPNet) {
|
|
| 61 |
+ var networkEndpoint *endpoint |
|
| 62 |
+ n.Lock() |
|
| 63 |
+ for _, ep := range n.endpoints {
|
|
| 64 |
+ if ep.addr.IP.Equal(addr.IP) {
|
|
| 65 |
+ networkEndpoint = ep |
|
| 66 |
+ break |
|
| 67 |
+ } |
|
| 68 |
+ } |
|
| 69 |
+ if networkEndpoint != nil {
|
|
| 70 |
+ delete(n.endpoints, networkEndpoint.id) |
|
| 71 |
+ } |
|
| 72 |
+ n.Unlock() |
|
| 73 |
+ |
|
| 74 |
+ if networkEndpoint != nil {
|
|
| 75 |
+ logrus.Debugf("Removing stale endpoint from HNS")
|
|
| 76 |
+ _, err := hcsshim.HNSEndpointRequest("DELETE", networkEndpoint.profileId, "")
|
|
| 77 |
+ |
|
| 78 |
+ if err != nil {
|
|
| 79 |
+ logrus.Debugf("Failed to delete stale overlay endpoint (%s) from hns", networkEndpoint.id[0:7])
|
|
| 80 |
+ } |
|
| 81 |
+ |
|
| 82 |
+ if err := n.driver.deleteEndpointFromStore(networkEndpoint); err != nil {
|
|
| 83 |
+ logrus.Debugf("Failed to delete stale overlay endpoint (%s) from store", networkEndpoint.id[0:7])
|
|
| 84 |
+ } |
|
| 85 |
+ } |
|
| 86 |
+} |
|
| 87 |
+ |
|
| 88 |
+func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, |
|
| 89 |
+ epOptions map[string]interface{}) error {
|
|
| 90 |
+ var err error |
|
| 91 |
+ if err = validateID(nid, eid); err != nil {
|
|
| 92 |
+ return err |
|
| 93 |
+ } |
|
| 94 |
+ |
|
| 95 |
+ // Since we perform lazy configuration make sure we try |
|
| 96 |
+ // configuring the driver when we enter CreateEndpoint since |
|
| 97 |
+ // CreateNetwork may not be called in every node. |
|
| 98 |
+ if err := d.configure(); err != nil {
|
|
| 99 |
+ return err |
|
| 100 |
+ } |
|
| 101 |
+ |
|
| 102 |
+ n := d.network(nid) |
|
| 103 |
+ if n == nil {
|
|
| 104 |
+ return fmt.Errorf("network id %q not found", nid)
|
|
| 105 |
+ } |
|
| 106 |
+ |
|
| 107 |
+ ep := &endpoint{
|
|
| 108 |
+ id: eid, |
|
| 109 |
+ nid: n.id, |
|
| 110 |
+ addr: ifInfo.Address(), |
|
| 111 |
+ mac: ifInfo.MacAddress(), |
|
| 112 |
+ } |
|
| 113 |
+ |
|
| 114 |
+ if ep.addr == nil {
|
|
| 115 |
+ return fmt.Errorf("create endpoint was not passed interface IP address")
|
|
| 116 |
+ } |
|
| 117 |
+ |
|
| 118 |
+ if s := n.getSubnetforIP(ep.addr); s == nil {
|
|
| 119 |
+ return fmt.Errorf("no matching subnet for IP %q in network %q\n", ep.addr, nid)
|
|
| 120 |
+ } |
|
| 121 |
+ |
|
| 122 |
+ // Todo: Add port bindings and qos policies here |
|
| 123 |
+ |
|
| 124 |
+ hnsEndpoint := &hcsshim.HNSEndpoint{
|
|
| 125 |
+ VirtualNetwork: n.hnsId, |
|
| 126 |
+ IPAddress: ep.addr.IP, |
|
| 127 |
+ EnableInternalDNS: true, |
|
| 128 |
+ } |
|
| 129 |
+ |
|
| 130 |
+ if ep.mac != nil {
|
|
| 131 |
+ hnsEndpoint.MacAddress = ep.mac.String() |
|
| 132 |
+ } |
|
| 133 |
+ |
|
| 134 |
+ paPolicy, err := json.Marshal(hcsshim.PaPolicy{
|
|
| 135 |
+ Type: "PA", |
|
| 136 |
+ PA: n.providerAddress, |
|
| 137 |
+ }) |
|
| 138 |
+ |
|
| 139 |
+ if err != nil {
|
|
| 140 |
+ return err |
|
| 141 |
+ } |
|
| 142 |
+ |
|
| 143 |
+ hnsEndpoint.Policies = append(hnsEndpoint.Policies, paPolicy) |
|
| 144 |
+ |
|
| 145 |
+ configurationb, err := json.Marshal(hnsEndpoint) |
|
| 146 |
+ if err != nil {
|
|
| 147 |
+ return err |
|
| 148 |
+ } |
|
| 149 |
+ |
|
| 150 |
+ hnsresponse, err := hcsshim.HNSEndpointRequest("POST", "", string(configurationb))
|
|
| 151 |
+ if err != nil {
|
|
| 152 |
+ return err |
|
| 153 |
+ } |
|
| 154 |
+ |
|
| 155 |
+ ep.profileId = hnsresponse.Id |
|
| 156 |
+ |
|
| 157 |
+ if ep.mac == nil {
|
|
| 158 |
+ ep.mac, err = net.ParseMAC(hnsresponse.MacAddress) |
|
| 159 |
+ if err != nil {
|
|
| 160 |
+ return err |
|
| 161 |
+ } |
|
| 162 |
+ |
|
| 163 |
+ if err := ifInfo.SetMacAddress(ep.mac); err != nil {
|
|
| 164 |
+ return err |
|
| 165 |
+ } |
|
| 166 |
+ } |
|
| 167 |
+ |
|
| 168 |
+ n.addEndpoint(ep) |
|
| 169 |
+ if err := d.writeEndpointToStore(ep); err != nil {
|
|
| 170 |
+ return fmt.Errorf("failed to update overlay endpoint %s to local store: %v", ep.id[0:7], err)
|
|
| 171 |
+ } |
|
| 172 |
+ |
|
| 173 |
+ return nil |
|
| 174 |
+} |
|
| 175 |
+ |
|
| 176 |
+func (d *driver) DeleteEndpoint(nid, eid string) error {
|
|
| 177 |
+ if err := validateID(nid, eid); err != nil {
|
|
| 178 |
+ return err |
|
| 179 |
+ } |
|
| 180 |
+ |
|
| 181 |
+ n := d.network(nid) |
|
| 182 |
+ if n == nil {
|
|
| 183 |
+ return fmt.Errorf("network id %q not found", nid)
|
|
| 184 |
+ } |
|
| 185 |
+ |
|
| 186 |
+ ep := n.endpoint(eid) |
|
| 187 |
+ if ep == nil {
|
|
| 188 |
+ return fmt.Errorf("endpoint id %q not found", eid)
|
|
| 189 |
+ } |
|
| 190 |
+ |
|
| 191 |
+ n.deleteEndpoint(eid) |
|
| 192 |
+ |
|
| 193 |
+ if err := d.deleteEndpointFromStore(ep); err != nil {
|
|
| 194 |
+ logrus.Warnf("Failed to delete overlay endpoint %s from local store: %v", ep.id[0:7], err)
|
|
| 195 |
+ } |
|
| 196 |
+ |
|
| 197 |
+ _, err := hcsshim.HNSEndpointRequest("DELETE", ep.profileId, "")
|
|
| 198 |
+ if err != nil {
|
|
| 199 |
+ return err |
|
| 200 |
+ } |
|
| 201 |
+ |
|
| 202 |
+ return nil |
|
| 203 |
+} |
|
| 204 |
+ |
|
| 205 |
+func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) {
|
|
| 206 |
+ if err := validateID(nid, eid); err != nil {
|
|
| 207 |
+ return nil, err |
|
| 208 |
+ } |
|
| 209 |
+ |
|
| 210 |
+ n := d.network(nid) |
|
| 211 |
+ if n == nil {
|
|
| 212 |
+ return nil, fmt.Errorf("network id %q not found", nid)
|
|
| 213 |
+ } |
|
| 214 |
+ |
|
| 215 |
+ ep := n.endpoint(eid) |
|
| 216 |
+ if ep == nil {
|
|
| 217 |
+ return nil, fmt.Errorf("endpoint id %q not found", eid)
|
|
| 218 |
+ } |
|
| 219 |
+ |
|
| 220 |
+ data := make(map[string]interface{}, 1)
|
|
| 221 |
+ data["hnsid"] = ep.profileId |
|
| 222 |
+ data["AllowUnqualifiedDNSQuery"] = true |
|
| 223 |
+ return data, nil |
|
| 224 |
+} |
|
| 225 |
+ |
|
| 226 |
+func (d *driver) deleteEndpointFromStore(e *endpoint) error {
|
|
| 227 |
+ if d.localStore == nil {
|
|
| 228 |
+ return fmt.Errorf("overlay local store not initialized, ep not deleted")
|
|
| 229 |
+ } |
|
| 230 |
+ |
|
| 231 |
+ if err := d.localStore.DeleteObjectAtomic(e); err != nil {
|
|
| 232 |
+ return err |
|
| 233 |
+ } |
|
| 234 |
+ |
|
| 235 |
+ return nil |
|
| 236 |
+} |
|
| 237 |
+ |
|
| 238 |
+func (d *driver) writeEndpointToStore(e *endpoint) error {
|
|
| 239 |
+ if d.localStore == nil {
|
|
| 240 |
+ return fmt.Errorf("overlay local store not initialized, ep not added")
|
|
| 241 |
+ } |
|
| 242 |
+ |
|
| 243 |
+ if err := d.localStore.PutObjectAtomic(e); err != nil {
|
|
| 244 |
+ return err |
|
| 245 |
+ } |
|
| 246 |
+ return nil |
|
| 247 |
+} |
|
| 248 |
+ |
|
| 249 |
+func (ep *endpoint) DataScope() string {
|
|
| 250 |
+ return datastore.LocalScope |
|
| 251 |
+} |
|
| 252 |
+ |
|
| 253 |
+func (ep *endpoint) New() datastore.KVObject {
|
|
| 254 |
+ return &endpoint{}
|
|
| 255 |
+} |
|
| 256 |
+ |
|
| 257 |
+func (ep *endpoint) CopyTo(o datastore.KVObject) error {
|
|
| 258 |
+ dstep := o.(*endpoint) |
|
| 259 |
+ *dstep = *ep |
|
| 260 |
+ return nil |
|
| 261 |
+} |
|
| 262 |
+ |
|
| 263 |
+func (ep *endpoint) Key() []string {
|
|
| 264 |
+ return []string{overlayEndpointPrefix, ep.id}
|
|
| 265 |
+} |
|
| 266 |
+ |
|
| 267 |
+func (ep *endpoint) KeyPrefix() []string {
|
|
| 268 |
+ return []string{overlayEndpointPrefix}
|
|
| 269 |
+} |
|
| 270 |
+ |
|
| 271 |
+func (ep *endpoint) Index() uint64 {
|
|
| 272 |
+ return ep.dbIndex |
|
| 273 |
+} |
|
| 274 |
+ |
|
| 275 |
+func (ep *endpoint) SetIndex(index uint64) {
|
|
| 276 |
+ ep.dbIndex = index |
|
| 277 |
+ ep.dbExists = true |
|
| 278 |
+} |
|
| 279 |
+ |
|
| 280 |
+func (ep *endpoint) Exists() bool {
|
|
| 281 |
+ return ep.dbExists |
|
| 282 |
+} |
|
| 283 |
+ |
|
| 284 |
+func (ep *endpoint) Skip() bool {
|
|
| 285 |
+ return false |
|
| 286 |
+} |
|
| 287 |
+ |
|
| 288 |
+func (ep *endpoint) Value() []byte {
|
|
| 289 |
+ b, err := json.Marshal(ep) |
|
| 290 |
+ if err != nil {
|
|
| 291 |
+ return nil |
|
| 292 |
+ } |
|
| 293 |
+ return b |
|
| 294 |
+} |
|
| 295 |
+ |
|
| 296 |
+func (ep *endpoint) SetValue(value []byte) error {
|
|
| 297 |
+ return json.Unmarshal(value, ep) |
|
| 298 |
+} |
|
| 299 |
+ |
|
| 300 |
+func (ep *endpoint) MarshalJSON() ([]byte, error) {
|
|
| 301 |
+ epMap := make(map[string]interface{})
|
|
| 302 |
+ |
|
| 303 |
+ epMap["id"] = ep.id |
|
| 304 |
+ epMap["nid"] = ep.nid |
|
| 305 |
+ epMap["remote"] = ep.remote |
|
| 306 |
+ if ep.profileId != "" {
|
|
| 307 |
+ epMap["profileId"] = ep.profileId |
|
| 308 |
+ } |
|
| 309 |
+ |
|
| 310 |
+ if ep.addr != nil {
|
|
| 311 |
+ epMap["addr"] = ep.addr.String() |
|
| 312 |
+ } |
|
| 313 |
+ if len(ep.mac) != 0 {
|
|
| 314 |
+ epMap["mac"] = ep.mac.String() |
|
| 315 |
+ } |
|
| 316 |
+ |
|
| 317 |
+ return json.Marshal(epMap) |
|
| 318 |
+} |
|
| 319 |
+ |
|
| 320 |
+func (ep *endpoint) UnmarshalJSON(value []byte) error {
|
|
| 321 |
+ var ( |
|
| 322 |
+ err error |
|
| 323 |
+ epMap map[string]interface{}
|
|
| 324 |
+ ) |
|
| 325 |
+ |
|
| 326 |
+ json.Unmarshal(value, &epMap) |
|
| 327 |
+ |
|
| 328 |
+ ep.id = epMap["id"].(string) |
|
| 329 |
+ ep.nid = epMap["nid"].(string) |
|
| 330 |
+ ep.remote = epMap["remote"].(bool) |
|
| 331 |
+ if v, ok := epMap["profileId"]; ok {
|
|
| 332 |
+ ep.profileId = v.(string) |
|
| 333 |
+ } |
|
| 334 |
+ if v, ok := epMap["mac"]; ok {
|
|
| 335 |
+ if ep.mac, err = net.ParseMAC(v.(string)); err != nil {
|
|
| 336 |
+ return types.InternalErrorf("failed to decode endpoint interface mac address after json unmarshal: %s", v.(string))
|
|
| 337 |
+ } |
|
| 338 |
+ } |
|
| 339 |
+ if v, ok := epMap["addr"]; ok {
|
|
| 340 |
+ if ep.addr, err = types.ParseCIDR(v.(string)); err != nil {
|
|
| 341 |
+ return types.InternalErrorf("failed to decode endpoint interface ipv4 address after json unmarshal: %v", err)
|
|
| 342 |
+ } |
|
| 343 |
+ } |
|
| 344 |
+ return nil |
|
| 345 |
+} |
| 0 | 346 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,209 @@ |
| 0 |
+package overlay |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "encoding/json" |
|
| 4 |
+ "fmt" |
|
| 5 |
+ "sync" |
|
| 6 |
+ |
|
| 7 |
+ "github.com/Microsoft/hcsshim" |
|
| 8 |
+ "github.com/Sirupsen/logrus" |
|
| 9 |
+ "github.com/docker/libnetwork/datastore" |
|
| 10 |
+) |
|
| 11 |
+ |
|
| 12 |
+const overlayNetworkPrefix = "overlay/network" |
|
| 13 |
+ |
|
| 14 |
+type localNetwork struct {
|
|
| 15 |
+ id string |
|
| 16 |
+ hnsID string |
|
| 17 |
+ providerAddress string |
|
| 18 |
+ dbIndex uint64 |
|
| 19 |
+ dbExists bool |
|
| 20 |
+ sync.Mutex |
|
| 21 |
+} |
|
| 22 |
+ |
|
| 23 |
+func (d *driver) findHnsNetwork(n *network) error {
|
|
| 24 |
+ ln, err := d.getLocalNetworkFromStore(n.id) |
|
| 25 |
+ |
|
| 26 |
+ if err != nil {
|
|
| 27 |
+ return err |
|
| 28 |
+ } |
|
| 29 |
+ |
|
| 30 |
+ if ln == nil {
|
|
| 31 |
+ subnets := []hcsshim.Subnet{}
|
|
| 32 |
+ |
|
| 33 |
+ for _, s := range n.subnets {
|
|
| 34 |
+ subnet := hcsshim.Subnet{
|
|
| 35 |
+ AddressPrefix: s.subnetIP.String(), |
|
| 36 |
+ } |
|
| 37 |
+ |
|
| 38 |
+ if s.gwIP != nil {
|
|
| 39 |
+ subnet.GatewayAddress = s.gwIP.IP.String() |
|
| 40 |
+ } |
|
| 41 |
+ |
|
| 42 |
+ vsidPolicy, err := json.Marshal(hcsshim.VsidPolicy{
|
|
| 43 |
+ Type: "VSID", |
|
| 44 |
+ VSID: uint(s.vni), |
|
| 45 |
+ }) |
|
| 46 |
+ |
|
| 47 |
+ if err != nil {
|
|
| 48 |
+ return err |
|
| 49 |
+ } |
|
| 50 |
+ |
|
| 51 |
+ subnet.Policies = append(subnet.Policies, vsidPolicy) |
|
| 52 |
+ subnets = append(subnets, subnet) |
|
| 53 |
+ } |
|
| 54 |
+ |
|
| 55 |
+ network := &hcsshim.HNSNetwork{
|
|
| 56 |
+ Name: n.name, |
|
| 57 |
+ Type: d.Type(), |
|
| 58 |
+ Subnets: subnets, |
|
| 59 |
+ NetworkAdapterName: n.interfaceName, |
|
| 60 |
+ } |
|
| 61 |
+ |
|
| 62 |
+ configurationb, err := json.Marshal(network) |
|
| 63 |
+ if err != nil {
|
|
| 64 |
+ return err |
|
| 65 |
+ } |
|
| 66 |
+ |
|
| 67 |
+ configuration := string(configurationb) |
|
| 68 |
+ logrus.Infof("HNSNetwork Request =%v", configuration)
|
|
| 69 |
+ |
|
| 70 |
+ hnsresponse, err := hcsshim.HNSNetworkRequest("POST", "", configuration)
|
|
| 71 |
+ if err != nil {
|
|
| 72 |
+ return err |
|
| 73 |
+ } |
|
| 74 |
+ |
|
| 75 |
+ n.hnsId = hnsresponse.Id |
|
| 76 |
+ n.providerAddress = hnsresponse.ManagementIP |
|
| 77 |
+ |
|
| 78 |
+ // Save local host specific info |
|
| 79 |
+ if err := d.writeLocalNetworkToStore(n); err != nil {
|
|
| 80 |
+ return fmt.Errorf("failed to update data store for network %v: %v", n.id, err)
|
|
| 81 |
+ } |
|
| 82 |
+ } else {
|
|
| 83 |
+ n.hnsId = ln.hnsID |
|
| 84 |
+ n.providerAddress = ln.providerAddress |
|
| 85 |
+ } |
|
| 86 |
+ |
|
| 87 |
+ return nil |
|
| 88 |
+} |
|
| 89 |
+ |
|
| 90 |
+func (d *driver) getLocalNetworkFromStore(nid string) (*localNetwork, error) {
|
|
| 91 |
+ |
|
| 92 |
+ if d.localStore == nil {
|
|
| 93 |
+ return nil, fmt.Errorf("overlay local store not initialized, network not found")
|
|
| 94 |
+ } |
|
| 95 |
+ |
|
| 96 |
+ n := &localNetwork{id: nid}
|
|
| 97 |
+ if err := d.localStore.GetObject(datastore.Key(n.Key()...), n); err != nil {
|
|
| 98 |
+ return nil, nil |
|
| 99 |
+ } |
|
| 100 |
+ |
|
| 101 |
+ return n, nil |
|
| 102 |
+} |
|
| 103 |
+ |
|
| 104 |
+func (d *driver) deleteLocalNetworkFromStore(n *network) error {
|
|
| 105 |
+ if d.localStore == nil {
|
|
| 106 |
+ return fmt.Errorf("overlay local store not initialized, network not deleted")
|
|
| 107 |
+ } |
|
| 108 |
+ |
|
| 109 |
+ ln, err := d.getLocalNetworkFromStore(n.id) |
|
| 110 |
+ |
|
| 111 |
+ if err != nil {
|
|
| 112 |
+ return err |
|
| 113 |
+ } |
|
| 114 |
+ |
|
| 115 |
+ if err = d.localStore.DeleteObjectAtomic(ln); err != nil {
|
|
| 116 |
+ return err |
|
| 117 |
+ } |
|
| 118 |
+ |
|
| 119 |
+ return nil |
|
| 120 |
+} |
|
| 121 |
+ |
|
| 122 |
+func (d *driver) writeLocalNetworkToStore(n *network) error {
|
|
| 123 |
+ if d.localStore == nil {
|
|
| 124 |
+ return fmt.Errorf("overlay local store not initialized, network not added")
|
|
| 125 |
+ } |
|
| 126 |
+ |
|
| 127 |
+ ln := &localNetwork{
|
|
| 128 |
+ id: n.id, |
|
| 129 |
+ hnsID: n.hnsId, |
|
| 130 |
+ providerAddress: n.providerAddress, |
|
| 131 |
+ } |
|
| 132 |
+ |
|
| 133 |
+ if err := d.localStore.PutObjectAtomic(ln); err != nil {
|
|
| 134 |
+ return err |
|
| 135 |
+ } |
|
| 136 |
+ return nil |
|
| 137 |
+} |
|
| 138 |
+ |
|
| 139 |
+func (n *localNetwork) DataScope() string {
|
|
| 140 |
+ return datastore.LocalScope |
|
| 141 |
+} |
|
| 142 |
+ |
|
| 143 |
+func (n *localNetwork) New() datastore.KVObject {
|
|
| 144 |
+ return &localNetwork{}
|
|
| 145 |
+} |
|
| 146 |
+ |
|
| 147 |
+func (n *localNetwork) CopyTo(o datastore.KVObject) error {
|
|
| 148 |
+ dstep := o.(*localNetwork) |
|
| 149 |
+ *dstep = *n |
|
| 150 |
+ return nil |
|
| 151 |
+} |
|
| 152 |
+ |
|
| 153 |
+func (n *localNetwork) Key() []string {
|
|
| 154 |
+ return []string{overlayNetworkPrefix, n.id}
|
|
| 155 |
+} |
|
| 156 |
+ |
|
| 157 |
+func (n *localNetwork) KeyPrefix() []string {
|
|
| 158 |
+ return []string{overlayNetworkPrefix}
|
|
| 159 |
+} |
|
| 160 |
+ |
|
| 161 |
+func (n *localNetwork) Index() uint64 {
|
|
| 162 |
+ return n.dbIndex |
|
| 163 |
+} |
|
| 164 |
+ |
|
| 165 |
+func (n *localNetwork) SetIndex(index uint64) {
|
|
| 166 |
+ n.dbIndex = index |
|
| 167 |
+ n.dbExists = true |
|
| 168 |
+} |
|
| 169 |
+ |
|
| 170 |
+func (n *localNetwork) Exists() bool {
|
|
| 171 |
+ return n.dbExists |
|
| 172 |
+} |
|
| 173 |
+ |
|
| 174 |
+func (n *localNetwork) Skip() bool {
|
|
| 175 |
+ return false |
|
| 176 |
+} |
|
| 177 |
+ |
|
| 178 |
+func (n *localNetwork) Value() []byte {
|
|
| 179 |
+ b, err := json.Marshal(n) |
|
| 180 |
+ if err != nil {
|
|
| 181 |
+ return nil |
|
| 182 |
+ } |
|
| 183 |
+ return b |
|
| 184 |
+} |
|
| 185 |
+ |
|
| 186 |
+func (n *localNetwork) SetValue(value []byte) error {
|
|
| 187 |
+ return json.Unmarshal(value, n) |
|
| 188 |
+} |
|
| 189 |
+ |
|
| 190 |
+func (n *localNetwork) MarshalJSON() ([]byte, error) {
|
|
| 191 |
+ networkMap := make(map[string]interface{})
|
|
| 192 |
+ |
|
| 193 |
+ networkMap["id"] = n.id |
|
| 194 |
+ networkMap["hnsID"] = n.hnsID |
|
| 195 |
+ networkMap["providerAddress"] = n.providerAddress |
|
| 196 |
+ return json.Marshal(networkMap) |
|
| 197 |
+} |
|
| 198 |
+ |
|
| 199 |
+func (n *localNetwork) UnmarshalJSON(value []byte) error {
|
|
| 200 |
+ var networkMap map[string]interface{}
|
|
| 201 |
+ |
|
| 202 |
+ json.Unmarshal(value, &networkMap) |
|
| 203 |
+ |
|
| 204 |
+ n.id = networkMap["id"].(string) |
|
| 205 |
+ n.hnsID = networkMap["hnsID"].(string) |
|
| 206 |
+ n.providerAddress = networkMap["providerAddress"].(string) |
|
| 207 |
+ return nil |
|
| 208 |
+} |
| 0 | 209 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,512 @@ |
| 0 |
+package overlay |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "encoding/json" |
|
| 4 |
+ "fmt" |
|
| 5 |
+ "net" |
|
| 6 |
+ "strconv" |
|
| 7 |
+ "strings" |
|
| 8 |
+ "sync" |
|
| 9 |
+ |
|
| 10 |
+ "github.com/Microsoft/hcsshim" |
|
| 11 |
+ "github.com/Sirupsen/logrus" |
|
| 12 |
+ "github.com/docker/libnetwork/datastore" |
|
| 13 |
+ "github.com/docker/libnetwork/driverapi" |
|
| 14 |
+ "github.com/docker/libnetwork/netlabel" |
|
| 15 |
+ "github.com/docker/libnetwork/types" |
|
| 16 |
+) |
|
| 17 |
+ |
|
| 18 |
+var ( |
|
| 19 |
+ hostMode bool |
|
| 20 |
+ networkMu sync.Mutex |
|
| 21 |
+) |
|
| 22 |
+ |
|
| 23 |
+type networkTable map[string]*network |
|
| 24 |
+ |
|
| 25 |
+type subnet struct {
|
|
| 26 |
+ vni uint32 |
|
| 27 |
+ initErr error |
|
| 28 |
+ subnetIP *net.IPNet |
|
| 29 |
+ gwIP *net.IPNet |
|
| 30 |
+} |
|
| 31 |
+ |
|
| 32 |
+type subnetJSON struct {
|
|
| 33 |
+ SubnetIP string |
|
| 34 |
+ GwIP string |
|
| 35 |
+ Vni uint32 |
|
| 36 |
+} |
|
| 37 |
+ |
|
| 38 |
+type network struct {
|
|
| 39 |
+ id string |
|
| 40 |
+ name string |
|
| 41 |
+ hnsId string |
|
| 42 |
+ dbIndex uint64 |
|
| 43 |
+ dbExists bool |
|
| 44 |
+ providerAddress string |
|
| 45 |
+ interfaceName string |
|
| 46 |
+ endpoints endpointTable |
|
| 47 |
+ driver *driver |
|
| 48 |
+ initEpoch int |
|
| 49 |
+ initErr error |
|
| 50 |
+ subnets []*subnet |
|
| 51 |
+ secure bool |
|
| 52 |
+ sync.Mutex |
|
| 53 |
+} |
|
| 54 |
+ |
|
| 55 |
+func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {
|
|
| 56 |
+ return nil, types.NotImplementedErrorf("not implemented")
|
|
| 57 |
+} |
|
| 58 |
+ |
|
| 59 |
+func (d *driver) NetworkFree(id string) error {
|
|
| 60 |
+ return types.NotImplementedErrorf("not implemented")
|
|
| 61 |
+} |
|
| 62 |
+ |
|
| 63 |
+func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
|
|
| 64 |
+ var ( |
|
| 65 |
+ networkName string |
|
| 66 |
+ interfaceName string |
|
| 67 |
+ ) |
|
| 68 |
+ |
|
| 69 |
+ if id == "" {
|
|
| 70 |
+ return fmt.Errorf("invalid network id")
|
|
| 71 |
+ } |
|
| 72 |
+ |
|
| 73 |
+ if len(ipV4Data) == 0 || ipV4Data[0].Pool.String() == "0.0.0.0/0" {
|
|
| 74 |
+ return types.BadRequestErrorf("ipv4 pool is empty")
|
|
| 75 |
+ } |
|
| 76 |
+ |
|
| 77 |
+ vnis := make([]uint32, 0, len(ipV4Data)) |
|
| 78 |
+ |
|
| 79 |
+ // Since we perform lazy configuration make sure we try |
|
| 80 |
+ // configuring the driver when we enter CreateNetwork |
|
| 81 |
+ if err := d.configure(); err != nil {
|
|
| 82 |
+ return err |
|
| 83 |
+ } |
|
| 84 |
+ |
|
| 85 |
+ n := &network{
|
|
| 86 |
+ id: id, |
|
| 87 |
+ driver: d, |
|
| 88 |
+ endpoints: endpointTable{},
|
|
| 89 |
+ subnets: []*subnet{},
|
|
| 90 |
+ } |
|
| 91 |
+ |
|
| 92 |
+ genData, ok := option[netlabel.GenericData].(map[string]string) |
|
| 93 |
+ |
|
| 94 |
+ if !ok {
|
|
| 95 |
+ return fmt.Errorf("Unknown generic data option")
|
|
| 96 |
+ } |
|
| 97 |
+ |
|
| 98 |
+ for label, value := range genData {
|
|
| 99 |
+ switch label {
|
|
| 100 |
+ case "com.docker.network.windowsshim.networkname": |
|
| 101 |
+ networkName = value |
|
| 102 |
+ case "com.docker.network.windowsshim.interface": |
|
| 103 |
+ interfaceName = value |
|
| 104 |
+ case "com.docker.network.windowsshim.hnsid": |
|
| 105 |
+ n.hnsId = value |
|
| 106 |
+ case netlabel.OverlayVxlanIDList: |
|
| 107 |
+ vniStrings := strings.Split(value, ",") |
|
| 108 |
+ for _, vniStr := range vniStrings {
|
|
| 109 |
+ vni, err := strconv.Atoi(vniStr) |
|
| 110 |
+ if err != nil {
|
|
| 111 |
+ return fmt.Errorf("invalid vxlan id value %q passed", vniStr)
|
|
| 112 |
+ } |
|
| 113 |
+ |
|
| 114 |
+ vnis = append(vnis, uint32(vni)) |
|
| 115 |
+ } |
|
| 116 |
+ } |
|
| 117 |
+ } |
|
| 118 |
+ |
|
| 119 |
+ // If we are getting vnis from libnetwork, either we get for |
|
| 120 |
+ // all subnets or none. |
|
| 121 |
+ if len(vnis) != 0 && len(vnis) < len(ipV4Data) {
|
|
| 122 |
+ return fmt.Errorf("insufficient vnis(%d) passed to overlay", len(vnis))
|
|
| 123 |
+ } |
|
| 124 |
+ |
|
| 125 |
+ for i, ipd := range ipV4Data {
|
|
| 126 |
+ s := &subnet{
|
|
| 127 |
+ subnetIP: ipd.Pool, |
|
| 128 |
+ gwIP: ipd.Gateway, |
|
| 129 |
+ } |
|
| 130 |
+ |
|
| 131 |
+ if len(vnis) != 0 {
|
|
| 132 |
+ s.vni = vnis[i] |
|
| 133 |
+ } |
|
| 134 |
+ |
|
| 135 |
+ n.subnets = append(n.subnets, s) |
|
| 136 |
+ } |
|
| 137 |
+ |
|
| 138 |
+ n.name = networkName |
|
| 139 |
+ if n.name == "" {
|
|
| 140 |
+ n.name = id |
|
| 141 |
+ } |
|
| 142 |
+ |
|
| 143 |
+ n.interfaceName = interfaceName |
|
| 144 |
+ |
|
| 145 |
+ if err := n.writeToStore(); err != nil {
|
|
| 146 |
+ return fmt.Errorf("failed to update data store for network %v: %v", n.id, err)
|
|
| 147 |
+ } |
|
| 148 |
+ |
|
| 149 |
+ if nInfo != nil {
|
|
| 150 |
+ if err := nInfo.TableEventRegister(ovPeerTable); err != nil {
|
|
| 151 |
+ return err |
|
| 152 |
+ } |
|
| 153 |
+ } |
|
| 154 |
+ |
|
| 155 |
+ d.addNetwork(n) |
|
| 156 |
+ |
|
| 157 |
+ err := d.findHnsNetwork(n) |
|
| 158 |
+ genData["com.docker.network.windowsshim.hnsid"] = n.hnsId |
|
| 159 |
+ |
|
| 160 |
+ return err |
|
| 161 |
+} |
|
| 162 |
+ |
|
| 163 |
+func (d *driver) DeleteNetwork(nid string) error {
|
|
| 164 |
+ if nid == "" {
|
|
| 165 |
+ return fmt.Errorf("invalid network id")
|
|
| 166 |
+ } |
|
| 167 |
+ |
|
| 168 |
+ // Make sure driver resources are initialized before proceeding |
|
| 169 |
+ if err := d.configure(); err != nil {
|
|
| 170 |
+ return err |
|
| 171 |
+ } |
|
| 172 |
+ |
|
| 173 |
+ n := d.network(nid) |
|
| 174 |
+ if n == nil {
|
|
| 175 |
+ return fmt.Errorf("could not find network with id %s", nid)
|
|
| 176 |
+ } |
|
| 177 |
+ |
|
| 178 |
+ _, err := hcsshim.HNSNetworkRequest("DELETE", n.hnsId, "")
|
|
| 179 |
+ if err != nil {
|
|
| 180 |
+ return err |
|
| 181 |
+ } |
|
| 182 |
+ |
|
| 183 |
+ d.deleteNetwork(nid) |
|
| 184 |
+ d.deleteLocalNetworkFromStore(n) |
|
| 185 |
+ |
|
| 186 |
+ return nil |
|
| 187 |
+} |
|
| 188 |
+ |
|
| 189 |
+func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
|
| 190 |
+ return nil |
|
| 191 |
+} |
|
| 192 |
+ |
|
| 193 |
+func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
|
| 194 |
+ return nil |
|
| 195 |
+} |
|
| 196 |
+ |
|
| 197 |
+func (d *driver) addNetwork(n *network) {
|
|
| 198 |
+ d.Lock() |
|
| 199 |
+ d.networks[n.id] = n |
|
| 200 |
+ d.Unlock() |
|
| 201 |
+} |
|
| 202 |
+ |
|
| 203 |
+func (d *driver) deleteNetwork(nid string) {
|
|
| 204 |
+ d.Lock() |
|
| 205 |
+ delete(d.networks, nid) |
|
| 206 |
+ d.Unlock() |
|
| 207 |
+} |
|
| 208 |
+ |
|
| 209 |
+func (d *driver) network(nid string) *network {
|
|
| 210 |
+ d.Lock() |
|
| 211 |
+ networks := d.networks |
|
| 212 |
+ d.Unlock() |
|
| 213 |
+ |
|
| 214 |
+ n, ok := networks[nid] |
|
| 215 |
+ if !ok {
|
|
| 216 |
+ n = d.getNetworkFromStore(nid) |
|
| 217 |
+ if n != nil {
|
|
| 218 |
+ n.driver = d |
|
| 219 |
+ n.endpoints = endpointTable{}
|
|
| 220 |
+ networks[nid] = n |
|
| 221 |
+ } |
|
| 222 |
+ } |
|
| 223 |
+ |
|
| 224 |
+ return n |
|
| 225 |
+} |
|
| 226 |
+ |
|
| 227 |
+func (d *driver) getNetworkFromStore(nid string) *network {
|
|
| 228 |
+ if d.store == nil {
|
|
| 229 |
+ return nil |
|
| 230 |
+ } |
|
| 231 |
+ |
|
| 232 |
+ n := &network{id: nid}
|
|
| 233 |
+ if err := d.store.GetObject(datastore.Key(n.Key()...), n); err != nil {
|
|
| 234 |
+ return nil |
|
| 235 |
+ } |
|
| 236 |
+ |
|
| 237 |
+ // As the network is being discovered from the global store, HNS may not be aware of it yet |
|
| 238 |
+ err := d.findHnsNetwork(n) |
|
| 239 |
+ if err != nil {
|
|
| 240 |
+ logrus.Errorf("Failed to find hns network: %v", err)
|
|
| 241 |
+ return nil |
|
| 242 |
+ } |
|
| 243 |
+ |
|
| 244 |
+ return n |
|
| 245 |
+} |
|
| 246 |
+ |
|
| 247 |
+func (n *network) vxlanID(s *subnet) uint32 {
|
|
| 248 |
+ n.Lock() |
|
| 249 |
+ defer n.Unlock() |
|
| 250 |
+ |
|
| 251 |
+ return s.vni |
|
| 252 |
+} |
|
| 253 |
+ |
|
| 254 |
+func (n *network) setVxlanID(s *subnet, vni uint32) {
|
|
| 255 |
+ n.Lock() |
|
| 256 |
+ s.vni = vni |
|
| 257 |
+ n.Unlock() |
|
| 258 |
+} |
|
| 259 |
+ |
|
| 260 |
+func (n *network) Key() []string {
|
|
| 261 |
+ return []string{"overlay", "network", n.id}
|
|
| 262 |
+} |
|
| 263 |
+ |
|
| 264 |
+func (n *network) KeyPrefix() []string {
|
|
| 265 |
+ return []string{"overlay", "network"}
|
|
| 266 |
+} |
|
| 267 |
+ |
|
| 268 |
+func (n *network) Value() []byte {
|
|
| 269 |
+ m := map[string]interface{}{}
|
|
| 270 |
+ |
|
| 271 |
+ netJSON := []*subnetJSON{}
|
|
| 272 |
+ |
|
| 273 |
+ for _, s := range n.subnets {
|
|
| 274 |
+ sj := &subnetJSON{
|
|
| 275 |
+ SubnetIP: s.subnetIP.String(), |
|
| 276 |
+ GwIP: s.gwIP.String(), |
|
| 277 |
+ Vni: s.vni, |
|
| 278 |
+ } |
|
| 279 |
+ netJSON = append(netJSON, sj) |
|
| 280 |
+ } |
|
| 281 |
+ |
|
| 282 |
+ b, err := json.Marshal(netJSON) |
|
| 283 |
+ if err != nil {
|
|
| 284 |
+ return []byte{}
|
|
| 285 |
+ } |
|
| 286 |
+ |
|
| 287 |
+ m["secure"] = n.secure |
|
| 288 |
+ m["subnets"] = netJSON |
|
| 289 |
+ m["interfaceName"] = n.interfaceName |
|
| 290 |
+ m["providerAddress"] = n.providerAddress |
|
| 291 |
+ m["hnsId"] = n.hnsId |
|
| 292 |
+ m["name"] = n.name |
|
| 293 |
+ b, err = json.Marshal(m) |
|
| 294 |
+ if err != nil {
|
|
| 295 |
+ return []byte{}
|
|
| 296 |
+ } |
|
| 297 |
+ |
|
| 298 |
+ return b |
|
| 299 |
+} |
|
| 300 |
+ |
|
| 301 |
+func (n *network) Index() uint64 {
|
|
| 302 |
+ return n.dbIndex |
|
| 303 |
+} |
|
| 304 |
+ |
|
| 305 |
+func (n *network) SetIndex(index uint64) {
|
|
| 306 |
+ n.dbIndex = index |
|
| 307 |
+ n.dbExists = true |
|
| 308 |
+} |
|
| 309 |
+ |
|
| 310 |
+func (n *network) Exists() bool {
|
|
| 311 |
+ return n.dbExists |
|
| 312 |
+} |
|
| 313 |
+ |
|
| 314 |
+func (n *network) Skip() bool {
|
|
| 315 |
+ return false |
|
| 316 |
+} |
|
| 317 |
+ |
|
| 318 |
+func (n *network) SetValue(value []byte) error {
|
|
| 319 |
+ var ( |
|
| 320 |
+ m map[string]interface{}
|
|
| 321 |
+ newNet bool |
|
| 322 |
+ isMap = true |
|
| 323 |
+ netJSON = []*subnetJSON{}
|
|
| 324 |
+ ) |
|
| 325 |
+ |
|
| 326 |
+ if err := json.Unmarshal(value, &m); err != nil {
|
|
| 327 |
+ err := json.Unmarshal(value, &netJSON) |
|
| 328 |
+ if err != nil {
|
|
| 329 |
+ return err |
|
| 330 |
+ } |
|
| 331 |
+ isMap = false |
|
| 332 |
+ } |
|
| 333 |
+ |
|
| 334 |
+ if len(n.subnets) == 0 {
|
|
| 335 |
+ newNet = true |
|
| 336 |
+ } |
|
| 337 |
+ |
|
| 338 |
+ if isMap {
|
|
| 339 |
+ if val, ok := m["secure"]; ok {
|
|
| 340 |
+ n.secure = val.(bool) |
|
| 341 |
+ } |
|
| 342 |
+ if val, ok := m["providerAddress"]; ok {
|
|
| 343 |
+ n.providerAddress = val.(string) |
|
| 344 |
+ } |
|
| 345 |
+ if val, ok := m["interfaceName"]; ok {
|
|
| 346 |
+ n.interfaceName = val.(string) |
|
| 347 |
+ } |
|
| 348 |
+ if val, ok := m["hnsId"]; ok {
|
|
| 349 |
+ n.hnsId = val.(string) |
|
| 350 |
+ } |
|
| 351 |
+ if val, ok := m["name"]; ok {
|
|
| 352 |
+ n.name = val.(string) |
|
| 353 |
+ } |
|
| 354 |
+ bytes, err := json.Marshal(m["subnets"]) |
|
| 355 |
+ if err != nil {
|
|
| 356 |
+ return err |
|
| 357 |
+ } |
|
| 358 |
+ if err := json.Unmarshal(bytes, &netJSON); err != nil {
|
|
| 359 |
+ return err |
|
| 360 |
+ } |
|
| 361 |
+ } |
|
| 362 |
+ |
|
| 363 |
+ for _, sj := range netJSON {
|
|
| 364 |
+ subnetIPstr := sj.SubnetIP |
|
| 365 |
+ gwIPstr := sj.GwIP |
|
| 366 |
+ vni := sj.Vni |
|
| 367 |
+ |
|
| 368 |
+ subnetIP, _ := types.ParseCIDR(subnetIPstr) |
|
| 369 |
+ gwIP, _ := types.ParseCIDR(gwIPstr) |
|
| 370 |
+ |
|
| 371 |
+ if newNet {
|
|
| 372 |
+ s := &subnet{
|
|
| 373 |
+ subnetIP: subnetIP, |
|
| 374 |
+ gwIP: gwIP, |
|
| 375 |
+ vni: vni, |
|
| 376 |
+ } |
|
| 377 |
+ n.subnets = append(n.subnets, s) |
|
| 378 |
+ } else {
|
|
| 379 |
+ sNet := n.getMatchingSubnet(subnetIP) |
|
| 380 |
+ if sNet != nil {
|
|
| 381 |
+ sNet.vni = vni |
|
| 382 |
+ } |
|
| 383 |
+ } |
|
| 384 |
+ } |
|
| 385 |
+ return nil |
|
| 386 |
+} |
|
| 387 |
+ |
|
| 388 |
+func (n *network) DataScope() string {
|
|
| 389 |
+ return datastore.GlobalScope |
|
| 390 |
+} |
|
| 391 |
+ |
|
| 392 |
+func (n *network) writeToStore() error {
|
|
| 393 |
+ if n.driver.store == nil {
|
|
| 394 |
+ return nil |
|
| 395 |
+ } |
|
| 396 |
+ |
|
| 397 |
+ return n.driver.store.PutObjectAtomic(n) |
|
| 398 |
+} |
|
| 399 |
+ |
|
| 400 |
+func (n *network) releaseVxlanID() ([]uint32, error) {
|
|
| 401 |
+ if len(n.subnets) == 0 {
|
|
| 402 |
+ return nil, nil |
|
| 403 |
+ } |
|
| 404 |
+ |
|
| 405 |
+ if n.driver.store != nil {
|
|
| 406 |
+ if err := n.driver.store.DeleteObjectAtomic(n); err != nil {
|
|
| 407 |
+ if err == datastore.ErrKeyModified || err == datastore.ErrKeyNotFound {
|
|
| 408 |
+ // In both the above cases we can safely assume that the key has been removed by some other |
|
| 409 |
+ // instance and so simply get out of here |
|
| 410 |
+ return nil, nil |
|
| 411 |
+ } |
|
| 412 |
+ |
|
| 413 |
+ return nil, fmt.Errorf("failed to delete network to vxlan id map: %v", err)
|
|
| 414 |
+ } |
|
| 415 |
+ } |
|
| 416 |
+ var vnis []uint32 |
|
| 417 |
+ for _, s := range n.subnets {
|
|
| 418 |
+ if n.driver.vxlanIdm != nil {
|
|
| 419 |
+ vni := n.vxlanID(s) |
|
| 420 |
+ vnis = append(vnis, vni) |
|
| 421 |
+ n.driver.vxlanIdm.Release(uint64(vni)) |
|
| 422 |
+ } |
|
| 423 |
+ |
|
| 424 |
+ n.setVxlanID(s, 0) |
|
| 425 |
+ } |
|
| 426 |
+ |
|
| 427 |
+ return vnis, nil |
|
| 428 |
+} |
|
| 429 |
+ |
|
| 430 |
+func (n *network) obtainVxlanID(s *subnet) error {
|
|
| 431 |
+ //return if the subnet already has a vxlan id assigned |
|
| 432 |
+ if s.vni != 0 {
|
|
| 433 |
+ return nil |
|
| 434 |
+ } |
|
| 435 |
+ |
|
| 436 |
+ if n.driver.store == nil {
|
|
| 437 |
+ return fmt.Errorf("no valid vxlan id and no datastore configured, cannot obtain vxlan id")
|
|
| 438 |
+ } |
|
| 439 |
+ |
|
| 440 |
+ for {
|
|
| 441 |
+ if err := n.driver.store.GetObject(datastore.Key(n.Key()...), n); err != nil {
|
|
| 442 |
+ return fmt.Errorf("getting network %q from datastore failed %v", n.id, err)
|
|
| 443 |
+ } |
|
| 444 |
+ |
|
| 445 |
+ if s.vni == 0 {
|
|
| 446 |
+ vxlanID, err := n.driver.vxlanIdm.GetID() |
|
| 447 |
+ if err != nil {
|
|
| 448 |
+ return fmt.Errorf("failed to allocate vxlan id: %v", err)
|
|
| 449 |
+ } |
|
| 450 |
+ |
|
| 451 |
+ n.setVxlanID(s, uint32(vxlanID)) |
|
| 452 |
+ if err := n.writeToStore(); err != nil {
|
|
| 453 |
+ n.driver.vxlanIdm.Release(uint64(n.vxlanID(s))) |
|
| 454 |
+ n.setVxlanID(s, 0) |
|
| 455 |
+ if err == datastore.ErrKeyModified {
|
|
| 456 |
+ continue |
|
| 457 |
+ } |
|
| 458 |
+ return fmt.Errorf("network %q failed to update data store: %v", n.id, err)
|
|
| 459 |
+ } |
|
| 460 |
+ return nil |
|
| 461 |
+ } |
|
| 462 |
+ return nil |
|
| 463 |
+ } |
|
| 464 |
+} |
|
| 465 |
+ |
|
| 466 |
+// contains return true if the passed ip belongs to one the network's |
|
| 467 |
+// subnets |
|
| 468 |
+func (n *network) contains(ip net.IP) bool {
|
|
| 469 |
+ for _, s := range n.subnets {
|
|
| 470 |
+ if s.subnetIP.Contains(ip) {
|
|
| 471 |
+ return true |
|
| 472 |
+ } |
|
| 473 |
+ } |
|
| 474 |
+ |
|
| 475 |
+ return false |
|
| 476 |
+} |
|
| 477 |
+ |
|
| 478 |
+// getSubnetforIP returns the subnet to which the given IP belongs |
|
| 479 |
+func (n *network) getSubnetforIP(ip *net.IPNet) *subnet {
|
|
| 480 |
+ for _, s := range n.subnets {
|
|
| 481 |
+ // first check if the mask lengths are the same |
|
| 482 |
+ i, _ := s.subnetIP.Mask.Size() |
|
| 483 |
+ j, _ := ip.Mask.Size() |
|
| 484 |
+ if i != j {
|
|
| 485 |
+ continue |
|
| 486 |
+ } |
|
| 487 |
+ if s.subnetIP.Contains(ip.IP) {
|
|
| 488 |
+ return s |
|
| 489 |
+ } |
|
| 490 |
+ } |
|
| 491 |
+ return nil |
|
| 492 |
+} |
|
| 493 |
+ |
|
| 494 |
+// getMatchingSubnet return the network's subnet that matches the input |
|
| 495 |
+func (n *network) getMatchingSubnet(ip *net.IPNet) *subnet {
|
|
| 496 |
+ if ip == nil {
|
|
| 497 |
+ return nil |
|
| 498 |
+ } |
|
| 499 |
+ for _, s := range n.subnets {
|
|
| 500 |
+ // first check if the mask lengths are the same |
|
| 501 |
+ i, _ := s.subnetIP.Mask.Size() |
|
| 502 |
+ j, _ := ip.Mask.Size() |
|
| 503 |
+ if i != j {
|
|
| 504 |
+ continue |
|
| 505 |
+ } |
|
| 506 |
+ if s.subnetIP.IP.Equal(ip.IP) {
|
|
| 507 |
+ return s |
|
| 508 |
+ } |
|
| 509 |
+ } |
|
| 510 |
+ return nil |
|
| 511 |
+} |
| 0 | 512 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,179 @@ |
| 0 |
+package overlay |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "fmt" |
|
| 4 |
+ "net" |
|
| 5 |
+ "strings" |
|
| 6 |
+ "time" |
|
| 7 |
+ |
|
| 8 |
+ "github.com/Sirupsen/logrus" |
|
| 9 |
+ "github.com/hashicorp/serf/serf" |
|
| 10 |
+) |
|
| 11 |
+ |
|
| 12 |
+type ovNotify struct {
|
|
| 13 |
+ action string |
|
| 14 |
+ ep *endpoint |
|
| 15 |
+ nw *network |
|
| 16 |
+} |
|
| 17 |
+ |
|
| 18 |
+type logWriter struct{}
|
|
| 19 |
+ |
|
| 20 |
+func (l *logWriter) Write(p []byte) (int, error) {
|
|
| 21 |
+ str := string(p) |
|
| 22 |
+ |
|
| 23 |
+ switch {
|
|
| 24 |
+ case strings.Contains(str, "[WARN]"): |
|
| 25 |
+ logrus.Warn(str) |
|
| 26 |
+ case strings.Contains(str, "[DEBUG]"): |
|
| 27 |
+ logrus.Debug(str) |
|
| 28 |
+ case strings.Contains(str, "[INFO]"): |
|
| 29 |
+ logrus.Info(str) |
|
| 30 |
+ case strings.Contains(str, "[ERR]"): |
|
| 31 |
+ logrus.Error(str) |
|
| 32 |
+ } |
|
| 33 |
+ |
|
| 34 |
+ return len(p), nil |
|
| 35 |
+} |
|
| 36 |
+ |
|
| 37 |
+func (d *driver) serfInit() error {
|
|
| 38 |
+ var err error |
|
| 39 |
+ |
|
| 40 |
+ config := serf.DefaultConfig() |
|
| 41 |
+ config.Init() |
|
| 42 |
+ config.MemberlistConfig.BindAddr = d.bindAddress |
|
| 43 |
+ |
|
| 44 |
+ d.eventCh = make(chan serf.Event, 4) |
|
| 45 |
+ config.EventCh = d.eventCh |
|
| 46 |
+ config.UserCoalescePeriod = 1 * time.Second |
|
| 47 |
+ config.UserQuiescentPeriod = 50 * time.Millisecond |
|
| 48 |
+ |
|
| 49 |
+ config.LogOutput = &logWriter{}
|
|
| 50 |
+ config.MemberlistConfig.LogOutput = config.LogOutput |
|
| 51 |
+ |
|
| 52 |
+ s, err := serf.Create(config) |
|
| 53 |
+ if err != nil {
|
|
| 54 |
+ return fmt.Errorf("failed to create cluster node: %v", err)
|
|
| 55 |
+ } |
|
| 56 |
+ defer func() {
|
|
| 57 |
+ if err != nil {
|
|
| 58 |
+ s.Shutdown() |
|
| 59 |
+ } |
|
| 60 |
+ }() |
|
| 61 |
+ |
|
| 62 |
+ d.serfInstance = s |
|
| 63 |
+ |
|
| 64 |
+ d.notifyCh = make(chan ovNotify) |
|
| 65 |
+ d.exitCh = make(chan chan struct{})
|
|
| 66 |
+ |
|
| 67 |
+ go d.startSerfLoop(d.eventCh, d.notifyCh, d.exitCh) |
|
| 68 |
+ return nil |
|
| 69 |
+} |
|
| 70 |
+ |
|
| 71 |
+func (d *driver) serfJoin(neighIP string) error {
|
|
| 72 |
+ if neighIP == "" {
|
|
| 73 |
+ return fmt.Errorf("no neighbor to join")
|
|
| 74 |
+ } |
|
| 75 |
+ if _, err := d.serfInstance.Join([]string{neighIP}, false); err != nil {
|
|
| 76 |
+ return fmt.Errorf("Failed to join the cluster at neigh IP %s: %v",
|
|
| 77 |
+ neighIP, err) |
|
| 78 |
+ } |
|
| 79 |
+ return nil |
|
| 80 |
+} |
|
| 81 |
+ |
|
| 82 |
+func (d *driver) notifyEvent(event ovNotify) {
|
|
| 83 |
+ ep := event.ep |
|
| 84 |
+ |
|
| 85 |
+ ePayload := fmt.Sprintf("%s %s %s %s", event.action, ep.addr.IP.String(),
|
|
| 86 |
+ net.IP(ep.addr.Mask).String(), ep.mac.String()) |
|
| 87 |
+ eName := fmt.Sprintf("jl %s %s %s", d.serfInstance.LocalMember().Addr.String(),
|
|
| 88 |
+ event.nw.id, ep.id) |
|
| 89 |
+ |
|
| 90 |
+ if err := d.serfInstance.UserEvent(eName, []byte(ePayload), true); err != nil {
|
|
| 91 |
+ logrus.Errorf("Sending user event failed: %v\n", err)
|
|
| 92 |
+ } |
|
| 93 |
+} |
|
| 94 |
+ |
|
| 95 |
+func (d *driver) processEvent(u serf.UserEvent) {
|
|
| 96 |
+ logrus.Debugf("Received user event name:%s, payload:%s\n", u.Name,
|
|
| 97 |
+ string(u.Payload)) |
|
| 98 |
+ |
|
| 99 |
+ var dummy, action, vtepStr, nid, eid, ipStr, maskStr, macStr string |
|
| 100 |
+ if _, err := fmt.Sscan(u.Name, &dummy, &vtepStr, &nid, &eid); err != nil {
|
|
| 101 |
+ fmt.Printf("Failed to scan name string: %v\n", err)
|
|
| 102 |
+ } |
|
| 103 |
+ |
|
| 104 |
+ if _, err := fmt.Sscan(string(u.Payload), &action, |
|
| 105 |
+ &ipStr, &maskStr, &macStr); err != nil {
|
|
| 106 |
+ fmt.Printf("Failed to scan value string: %v\n", err)
|
|
| 107 |
+ } |
|
| 108 |
+ |
|
| 109 |
+ logrus.Debugf("Parsed data = %s/%s/%s/%s/%s/%s\n", nid, eid, vtepStr, ipStr, maskStr, macStr)
|
|
| 110 |
+ |
|
| 111 |
+ mac, err := net.ParseMAC(macStr) |
|
| 112 |
+ if err != nil {
|
|
| 113 |
+ logrus.Errorf("Failed to parse mac: %v\n", err)
|
|
| 114 |
+ } |
|
| 115 |
+ |
|
| 116 |
+ if d.serfInstance.LocalMember().Addr.String() == vtepStr {
|
|
| 117 |
+ return |
|
| 118 |
+ } |
|
| 119 |
+ |
|
| 120 |
+ switch action {
|
|
| 121 |
+ case "join": |
|
| 122 |
+ if err := d.peerAdd(nid, eid, net.ParseIP(ipStr), net.IPMask(net.ParseIP(maskStr).To4()), mac, |
|
| 123 |
+ net.ParseIP(vtepStr), true); err != nil {
|
|
| 124 |
+ logrus.Errorf("Peer add failed in the driver: %v\n", err)
|
|
| 125 |
+ } |
|
| 126 |
+ case "leave": |
|
| 127 |
+ if err := d.peerDelete(nid, eid, net.ParseIP(ipStr), net.IPMask(net.ParseIP(maskStr).To4()), mac, |
|
| 128 |
+ net.ParseIP(vtepStr), true); err != nil {
|
|
| 129 |
+ logrus.Errorf("Peer delete failed in the driver: %v\n", err)
|
|
| 130 |
+ } |
|
| 131 |
+ } |
|
| 132 |
+} |
|
| 133 |
+ |
|
| 134 |
+func (d *driver) startSerfLoop(eventCh chan serf.Event, notifyCh chan ovNotify, |
|
| 135 |
+ exitCh chan chan struct{}) {
|
|
| 136 |
+ |
|
| 137 |
+ for {
|
|
| 138 |
+ select {
|
|
| 139 |
+ case notify, ok := <-notifyCh: |
|
| 140 |
+ if !ok {
|
|
| 141 |
+ break |
|
| 142 |
+ } |
|
| 143 |
+ |
|
| 144 |
+ d.notifyEvent(notify) |
|
| 145 |
+ case ch, ok := <-exitCh: |
|
| 146 |
+ if !ok {
|
|
| 147 |
+ break |
|
| 148 |
+ } |
|
| 149 |
+ |
|
| 150 |
+ if err := d.serfInstance.Leave(); err != nil {
|
|
| 151 |
+ logrus.Errorf("failed leaving the cluster: %v\n", err)
|
|
| 152 |
+ } |
|
| 153 |
+ |
|
| 154 |
+ d.serfInstance.Shutdown() |
|
| 155 |
+ close(ch) |
|
| 156 |
+ return |
|
| 157 |
+ case e, ok := <-eventCh: |
|
| 158 |
+ if !ok {
|
|
| 159 |
+ break |
|
| 160 |
+ } |
|
| 161 |
+ u, ok := e.(serf.UserEvent) |
|
| 162 |
+ if !ok {
|
|
| 163 |
+ break |
|
| 164 |
+ } |
|
| 165 |
+ d.processEvent(u) |
|
| 166 |
+ } |
|
| 167 |
+ } |
|
| 168 |
+} |
|
| 169 |
+ |
|
| 170 |
+func (d *driver) isSerfAlive() bool {
|
|
| 171 |
+ d.Lock() |
|
| 172 |
+ serfInstance := d.serfInstance |
|
| 173 |
+ d.Unlock() |
|
| 174 |
+ if serfInstance == nil || serfInstance.State() != serf.SerfAlive {
|
|
| 175 |
+ return false |
|
| 176 |
+ } |
|
| 177 |
+ return true |
|
| 178 |
+} |
| 0 | 179 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,468 @@ |
| 0 |
+// Code generated by protoc-gen-gogo. |
|
| 1 |
+// source: overlay.proto |
|
| 2 |
+// DO NOT EDIT! |
|
| 3 |
+ |
|
| 4 |
+/* |
|
| 5 |
+ Package overlay is a generated protocol buffer package. |
|
| 6 |
+ |
|
| 7 |
+ It is generated from these files: |
|
| 8 |
+ overlay.proto |
|
| 9 |
+ |
|
| 10 |
+ It has these top-level messages: |
|
| 11 |
+ PeerRecord |
|
| 12 |
+*/ |
|
| 13 |
+package overlay |
|
| 14 |
+ |
|
| 15 |
+import proto "github.com/gogo/protobuf/proto" |
|
| 16 |
+import fmt "fmt" |
|
| 17 |
+import math "math" |
|
| 18 |
+import _ "github.com/gogo/protobuf/gogoproto" |
|
| 19 |
+ |
|
| 20 |
+import strings "strings" |
|
| 21 |
+import github_com_gogo_protobuf_proto "github.com/gogo/protobuf/proto" |
|
| 22 |
+import sort "sort" |
|
| 23 |
+import strconv "strconv" |
|
| 24 |
+import reflect "reflect" |
|
| 25 |
+ |
|
| 26 |
+import io "io" |
|
| 27 |
+ |
|
| 28 |
+// Reference imports to suppress errors if they are not otherwise used. |
|
| 29 |
+var _ = proto.Marshal |
|
| 30 |
+var _ = fmt.Errorf |
|
| 31 |
+var _ = math.Inf |
|
| 32 |
+ |
|
| 33 |
+// This is a compile-time assertion to ensure that this generated file |
|
| 34 |
+// is compatible with the proto package it is being compiled against. |
|
| 35 |
+const _ = proto.GoGoProtoPackageIsVersion1 |
|
| 36 |
+ |
|
| 37 |
+// PeerRecord defines the information corresponding to a peer |
|
| 38 |
+// container in the overlay network. |
|
| 39 |
+type PeerRecord struct {
|
|
| 40 |
+ // Endpoint IP is the IP of the container attachment on the |
|
| 41 |
+ // given overlay network. |
|
| 42 |
+ EndpointIP string `protobuf:"bytes,1,opt,name=endpoint_ip,json=endpointIp,proto3" json:"endpoint_ip,omitempty"` |
|
| 43 |
+ // Endpoint MAC is the mac address of the container attachment |
|
| 44 |
+ // on the given overlay network. |
|
| 45 |
+ EndpointMAC string `protobuf:"bytes,2,opt,name=endpoint_mac,json=endpointMac,proto3" json:"endpoint_mac,omitempty"` |
|
| 46 |
+ // Tunnel Endpoint IP defines the host IP for the host in |
|
| 47 |
+ // which this container is running and can be reached by |
|
| 48 |
+ // building a tunnel to that host IP. |
|
| 49 |
+ TunnelEndpointIP string `protobuf:"bytes,3,opt,name=tunnel_endpoint_ip,json=tunnelEndpointIp,proto3" json:"tunnel_endpoint_ip,omitempty"` |
|
| 50 |
+} |
|
| 51 |
+ |
|
| 52 |
+func (m *PeerRecord) Reset() { *m = PeerRecord{} }
|
|
| 53 |
+func (*PeerRecord) ProtoMessage() {}
|
|
| 54 |
+func (*PeerRecord) Descriptor() ([]byte, []int) { return fileDescriptorOverlay, []int{0} }
|
|
| 55 |
+ |
|
| 56 |
+func init() {
|
|
| 57 |
+ proto.RegisterType((*PeerRecord)(nil), "overlay.PeerRecord") |
|
| 58 |
+} |
|
| 59 |
+func (this *PeerRecord) GoString() string {
|
|
| 60 |
+ if this == nil {
|
|
| 61 |
+ return "nil" |
|
| 62 |
+ } |
|
| 63 |
+ s := make([]string, 0, 7) |
|
| 64 |
+ s = append(s, "&overlay.PeerRecord{")
|
|
| 65 |
+ s = append(s, "EndpointIP: "+fmt.Sprintf("%#v", this.EndpointIP)+",\n")
|
|
| 66 |
+ s = append(s, "EndpointMAC: "+fmt.Sprintf("%#v", this.EndpointMAC)+",\n")
|
|
| 67 |
+ s = append(s, "TunnelEndpointIP: "+fmt.Sprintf("%#v", this.TunnelEndpointIP)+",\n")
|
|
| 68 |
+ s = append(s, "}") |
|
| 69 |
+ return strings.Join(s, "") |
|
| 70 |
+} |
|
| 71 |
+func valueToGoStringOverlay(v interface{}, typ string) string {
|
|
| 72 |
+ rv := reflect.ValueOf(v) |
|
| 73 |
+ if rv.IsNil() {
|
|
| 74 |
+ return "nil" |
|
| 75 |
+ } |
|
| 76 |
+ pv := reflect.Indirect(rv).Interface() |
|
| 77 |
+ return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
|
|
| 78 |
+} |
|
| 79 |
+func extensionToGoStringOverlay(e map[int32]github_com_gogo_protobuf_proto.Extension) string {
|
|
| 80 |
+ if e == nil {
|
|
| 81 |
+ return "nil" |
|
| 82 |
+ } |
|
| 83 |
+ s := "map[int32]proto.Extension{"
|
|
| 84 |
+ keys := make([]int, 0, len(e)) |
|
| 85 |
+ for k := range e {
|
|
| 86 |
+ keys = append(keys, int(k)) |
|
| 87 |
+ } |
|
| 88 |
+ sort.Ints(keys) |
|
| 89 |
+ ss := []string{}
|
|
| 90 |
+ for _, k := range keys {
|
|
| 91 |
+ ss = append(ss, strconv.Itoa(k)+": "+e[int32(k)].GoString()) |
|
| 92 |
+ } |
|
| 93 |
+ s += strings.Join(ss, ",") + "}" |
|
| 94 |
+ return s |
|
| 95 |
+} |
|
| 96 |
+func (m *PeerRecord) Marshal() (data []byte, err error) {
|
|
| 97 |
+ size := m.Size() |
|
| 98 |
+ data = make([]byte, size) |
|
| 99 |
+ n, err := m.MarshalTo(data) |
|
| 100 |
+ if err != nil {
|
|
| 101 |
+ return nil, err |
|
| 102 |
+ } |
|
| 103 |
+ return data[:n], nil |
|
| 104 |
+} |
|
| 105 |
+ |
|
| 106 |
+func (m *PeerRecord) MarshalTo(data []byte) (int, error) {
|
|
| 107 |
+ var i int |
|
| 108 |
+ _ = i |
|
| 109 |
+ var l int |
|
| 110 |
+ _ = l |
|
| 111 |
+ if len(m.EndpointIP) > 0 {
|
|
| 112 |
+ data[i] = 0xa |
|
| 113 |
+ i++ |
|
| 114 |
+ i = encodeVarintOverlay(data, i, uint64(len(m.EndpointIP))) |
|
| 115 |
+ i += copy(data[i:], m.EndpointIP) |
|
| 116 |
+ } |
|
| 117 |
+ if len(m.EndpointMAC) > 0 {
|
|
| 118 |
+ data[i] = 0x12 |
|
| 119 |
+ i++ |
|
| 120 |
+ i = encodeVarintOverlay(data, i, uint64(len(m.EndpointMAC))) |
|
| 121 |
+ i += copy(data[i:], m.EndpointMAC) |
|
| 122 |
+ } |
|
| 123 |
+ if len(m.TunnelEndpointIP) > 0 {
|
|
| 124 |
+ data[i] = 0x1a |
|
| 125 |
+ i++ |
|
| 126 |
+ i = encodeVarintOverlay(data, i, uint64(len(m.TunnelEndpointIP))) |
|
| 127 |
+ i += copy(data[i:], m.TunnelEndpointIP) |
|
| 128 |
+ } |
|
| 129 |
+ return i, nil |
|
| 130 |
+} |
|
| 131 |
+ |
|
| 132 |
+func encodeFixed64Overlay(data []byte, offset int, v uint64) int {
|
|
| 133 |
+ data[offset] = uint8(v) |
|
| 134 |
+ data[offset+1] = uint8(v >> 8) |
|
| 135 |
+ data[offset+2] = uint8(v >> 16) |
|
| 136 |
+ data[offset+3] = uint8(v >> 24) |
|
| 137 |
+ data[offset+4] = uint8(v >> 32) |
|
| 138 |
+ data[offset+5] = uint8(v >> 40) |
|
| 139 |
+ data[offset+6] = uint8(v >> 48) |
|
| 140 |
+ data[offset+7] = uint8(v >> 56) |
|
| 141 |
+ return offset + 8 |
|
| 142 |
+} |
|
| 143 |
+func encodeFixed32Overlay(data []byte, offset int, v uint32) int {
|
|
| 144 |
+ data[offset] = uint8(v) |
|
| 145 |
+ data[offset+1] = uint8(v >> 8) |
|
| 146 |
+ data[offset+2] = uint8(v >> 16) |
|
| 147 |
+ data[offset+3] = uint8(v >> 24) |
|
| 148 |
+ return offset + 4 |
|
| 149 |
+} |
|
| 150 |
+func encodeVarintOverlay(data []byte, offset int, v uint64) int {
|
|
| 151 |
+ for v >= 1<<7 {
|
|
| 152 |
+ data[offset] = uint8(v&0x7f | 0x80) |
|
| 153 |
+ v >>= 7 |
|
| 154 |
+ offset++ |
|
| 155 |
+ } |
|
| 156 |
+ data[offset] = uint8(v) |
|
| 157 |
+ return offset + 1 |
|
| 158 |
+} |
|
| 159 |
+func (m *PeerRecord) Size() (n int) {
|
|
| 160 |
+ var l int |
|
| 161 |
+ _ = l |
|
| 162 |
+ l = len(m.EndpointIP) |
|
| 163 |
+ if l > 0 {
|
|
| 164 |
+ n += 1 + l + sovOverlay(uint64(l)) |
|
| 165 |
+ } |
|
| 166 |
+ l = len(m.EndpointMAC) |
|
| 167 |
+ if l > 0 {
|
|
| 168 |
+ n += 1 + l + sovOverlay(uint64(l)) |
|
| 169 |
+ } |
|
| 170 |
+ l = len(m.TunnelEndpointIP) |
|
| 171 |
+ if l > 0 {
|
|
| 172 |
+ n += 1 + l + sovOverlay(uint64(l)) |
|
| 173 |
+ } |
|
| 174 |
+ return n |
|
| 175 |
+} |
|
| 176 |
+ |
|
| 177 |
+func sovOverlay(x uint64) (n int) {
|
|
| 178 |
+ for {
|
|
| 179 |
+ n++ |
|
| 180 |
+ x >>= 7 |
|
| 181 |
+ if x == 0 {
|
|
| 182 |
+ break |
|
| 183 |
+ } |
|
| 184 |
+ } |
|
| 185 |
+ return n |
|
| 186 |
+} |
|
| 187 |
+func sozOverlay(x uint64) (n int) {
|
|
| 188 |
+ return sovOverlay(uint64((x << 1) ^ uint64((int64(x) >> 63)))) |
|
| 189 |
+} |
|
| 190 |
+func (this *PeerRecord) String() string {
|
|
| 191 |
+ if this == nil {
|
|
| 192 |
+ return "nil" |
|
| 193 |
+ } |
|
| 194 |
+ s := strings.Join([]string{`&PeerRecord{`,
|
|
| 195 |
+ `EndpointIP:` + fmt.Sprintf("%v", this.EndpointIP) + `,`,
|
|
| 196 |
+ `EndpointMAC:` + fmt.Sprintf("%v", this.EndpointMAC) + `,`,
|
|
| 197 |
+ `TunnelEndpointIP:` + fmt.Sprintf("%v", this.TunnelEndpointIP) + `,`,
|
|
| 198 |
+ `}`, |
|
| 199 |
+ }, "") |
|
| 200 |
+ return s |
|
| 201 |
+} |
|
| 202 |
+func valueToStringOverlay(v interface{}) string {
|
|
| 203 |
+ rv := reflect.ValueOf(v) |
|
| 204 |
+ if rv.IsNil() {
|
|
| 205 |
+ return "nil" |
|
| 206 |
+ } |
|
| 207 |
+ pv := reflect.Indirect(rv).Interface() |
|
| 208 |
+ return fmt.Sprintf("*%v", pv)
|
|
| 209 |
+} |
|
| 210 |
+func (m *PeerRecord) Unmarshal(data []byte) error {
|
|
| 211 |
+ l := len(data) |
|
| 212 |
+ iNdEx := 0 |
|
| 213 |
+ for iNdEx < l {
|
|
| 214 |
+ preIndex := iNdEx |
|
| 215 |
+ var wire uint64 |
|
| 216 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 217 |
+ if shift >= 64 {
|
|
| 218 |
+ return ErrIntOverflowOverlay |
|
| 219 |
+ } |
|
| 220 |
+ if iNdEx >= l {
|
|
| 221 |
+ return io.ErrUnexpectedEOF |
|
| 222 |
+ } |
|
| 223 |
+ b := data[iNdEx] |
|
| 224 |
+ iNdEx++ |
|
| 225 |
+ wire |= (uint64(b) & 0x7F) << shift |
|
| 226 |
+ if b < 0x80 {
|
|
| 227 |
+ break |
|
| 228 |
+ } |
|
| 229 |
+ } |
|
| 230 |
+ fieldNum := int32(wire >> 3) |
|
| 231 |
+ wireType := int(wire & 0x7) |
|
| 232 |
+ if wireType == 4 {
|
|
| 233 |
+ return fmt.Errorf("proto: PeerRecord: wiretype end group for non-group")
|
|
| 234 |
+ } |
|
| 235 |
+ if fieldNum <= 0 {
|
|
| 236 |
+ return fmt.Errorf("proto: PeerRecord: illegal tag %d (wire type %d)", fieldNum, wire)
|
|
| 237 |
+ } |
|
| 238 |
+ switch fieldNum {
|
|
| 239 |
+ case 1: |
|
| 240 |
+ if wireType != 2 {
|
|
| 241 |
+ return fmt.Errorf("proto: wrong wireType = %d for field EndpointIP", wireType)
|
|
| 242 |
+ } |
|
| 243 |
+ var stringLen uint64 |
|
| 244 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 245 |
+ if shift >= 64 {
|
|
| 246 |
+ return ErrIntOverflowOverlay |
|
| 247 |
+ } |
|
| 248 |
+ if iNdEx >= l {
|
|
| 249 |
+ return io.ErrUnexpectedEOF |
|
| 250 |
+ } |
|
| 251 |
+ b := data[iNdEx] |
|
| 252 |
+ iNdEx++ |
|
| 253 |
+ stringLen |= (uint64(b) & 0x7F) << shift |
|
| 254 |
+ if b < 0x80 {
|
|
| 255 |
+ break |
|
| 256 |
+ } |
|
| 257 |
+ } |
|
| 258 |
+ intStringLen := int(stringLen) |
|
| 259 |
+ if intStringLen < 0 {
|
|
| 260 |
+ return ErrInvalidLengthOverlay |
|
| 261 |
+ } |
|
| 262 |
+ postIndex := iNdEx + intStringLen |
|
| 263 |
+ if postIndex > l {
|
|
| 264 |
+ return io.ErrUnexpectedEOF |
|
| 265 |
+ } |
|
| 266 |
+ m.EndpointIP = string(data[iNdEx:postIndex]) |
|
| 267 |
+ iNdEx = postIndex |
|
| 268 |
+ case 2: |
|
| 269 |
+ if wireType != 2 {
|
|
| 270 |
+ return fmt.Errorf("proto: wrong wireType = %d for field EndpointMAC", wireType)
|
|
| 271 |
+ } |
|
| 272 |
+ var stringLen uint64 |
|
| 273 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 274 |
+ if shift >= 64 {
|
|
| 275 |
+ return ErrIntOverflowOverlay |
|
| 276 |
+ } |
|
| 277 |
+ if iNdEx >= l {
|
|
| 278 |
+ return io.ErrUnexpectedEOF |
|
| 279 |
+ } |
|
| 280 |
+ b := data[iNdEx] |
|
| 281 |
+ iNdEx++ |
|
| 282 |
+ stringLen |= (uint64(b) & 0x7F) << shift |
|
| 283 |
+ if b < 0x80 {
|
|
| 284 |
+ break |
|
| 285 |
+ } |
|
| 286 |
+ } |
|
| 287 |
+ intStringLen := int(stringLen) |
|
| 288 |
+ if intStringLen < 0 {
|
|
| 289 |
+ return ErrInvalidLengthOverlay |
|
| 290 |
+ } |
|
| 291 |
+ postIndex := iNdEx + intStringLen |
|
| 292 |
+ if postIndex > l {
|
|
| 293 |
+ return io.ErrUnexpectedEOF |
|
| 294 |
+ } |
|
| 295 |
+ m.EndpointMAC = string(data[iNdEx:postIndex]) |
|
| 296 |
+ iNdEx = postIndex |
|
| 297 |
+ case 3: |
|
| 298 |
+ if wireType != 2 {
|
|
| 299 |
+ return fmt.Errorf("proto: wrong wireType = %d for field TunnelEndpointIP", wireType)
|
|
| 300 |
+ } |
|
| 301 |
+ var stringLen uint64 |
|
| 302 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 303 |
+ if shift >= 64 {
|
|
| 304 |
+ return ErrIntOverflowOverlay |
|
| 305 |
+ } |
|
| 306 |
+ if iNdEx >= l {
|
|
| 307 |
+ return io.ErrUnexpectedEOF |
|
| 308 |
+ } |
|
| 309 |
+ b := data[iNdEx] |
|
| 310 |
+ iNdEx++ |
|
| 311 |
+ stringLen |= (uint64(b) & 0x7F) << shift |
|
| 312 |
+ if b < 0x80 {
|
|
| 313 |
+ break |
|
| 314 |
+ } |
|
| 315 |
+ } |
|
| 316 |
+ intStringLen := int(stringLen) |
|
| 317 |
+ if intStringLen < 0 {
|
|
| 318 |
+ return ErrInvalidLengthOverlay |
|
| 319 |
+ } |
|
| 320 |
+ postIndex := iNdEx + intStringLen |
|
| 321 |
+ if postIndex > l {
|
|
| 322 |
+ return io.ErrUnexpectedEOF |
|
| 323 |
+ } |
|
| 324 |
+ m.TunnelEndpointIP = string(data[iNdEx:postIndex]) |
|
| 325 |
+ iNdEx = postIndex |
|
| 326 |
+ default: |
|
| 327 |
+ iNdEx = preIndex |
|
| 328 |
+ skippy, err := skipOverlay(data[iNdEx:]) |
|
| 329 |
+ if err != nil {
|
|
| 330 |
+ return err |
|
| 331 |
+ } |
|
| 332 |
+ if skippy < 0 {
|
|
| 333 |
+ return ErrInvalidLengthOverlay |
|
| 334 |
+ } |
|
| 335 |
+ if (iNdEx + skippy) > l {
|
|
| 336 |
+ return io.ErrUnexpectedEOF |
|
| 337 |
+ } |
|
| 338 |
+ iNdEx += skippy |
|
| 339 |
+ } |
|
| 340 |
+ } |
|
| 341 |
+ |
|
| 342 |
+ if iNdEx > l {
|
|
| 343 |
+ return io.ErrUnexpectedEOF |
|
| 344 |
+ } |
|
| 345 |
+ return nil |
|
| 346 |
+} |
|
| 347 |
+func skipOverlay(data []byte) (n int, err error) {
|
|
| 348 |
+ l := len(data) |
|
| 349 |
+ iNdEx := 0 |
|
| 350 |
+ for iNdEx < l {
|
|
| 351 |
+ var wire uint64 |
|
| 352 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 353 |
+ if shift >= 64 {
|
|
| 354 |
+ return 0, ErrIntOverflowOverlay |
|
| 355 |
+ } |
|
| 356 |
+ if iNdEx >= l {
|
|
| 357 |
+ return 0, io.ErrUnexpectedEOF |
|
| 358 |
+ } |
|
| 359 |
+ b := data[iNdEx] |
|
| 360 |
+ iNdEx++ |
|
| 361 |
+ wire |= (uint64(b) & 0x7F) << shift |
|
| 362 |
+ if b < 0x80 {
|
|
| 363 |
+ break |
|
| 364 |
+ } |
|
| 365 |
+ } |
|
| 366 |
+ wireType := int(wire & 0x7) |
|
| 367 |
+ switch wireType {
|
|
| 368 |
+ case 0: |
|
| 369 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 370 |
+ if shift >= 64 {
|
|
| 371 |
+ return 0, ErrIntOverflowOverlay |
|
| 372 |
+ } |
|
| 373 |
+ if iNdEx >= l {
|
|
| 374 |
+ return 0, io.ErrUnexpectedEOF |
|
| 375 |
+ } |
|
| 376 |
+ iNdEx++ |
|
| 377 |
+ if data[iNdEx-1] < 0x80 {
|
|
| 378 |
+ break |
|
| 379 |
+ } |
|
| 380 |
+ } |
|
| 381 |
+ return iNdEx, nil |
|
| 382 |
+ case 1: |
|
| 383 |
+ iNdEx += 8 |
|
| 384 |
+ return iNdEx, nil |
|
| 385 |
+ case 2: |
|
| 386 |
+ var length int |
|
| 387 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 388 |
+ if shift >= 64 {
|
|
| 389 |
+ return 0, ErrIntOverflowOverlay |
|
| 390 |
+ } |
|
| 391 |
+ if iNdEx >= l {
|
|
| 392 |
+ return 0, io.ErrUnexpectedEOF |
|
| 393 |
+ } |
|
| 394 |
+ b := data[iNdEx] |
|
| 395 |
+ iNdEx++ |
|
| 396 |
+ length |= (int(b) & 0x7F) << shift |
|
| 397 |
+ if b < 0x80 {
|
|
| 398 |
+ break |
|
| 399 |
+ } |
|
| 400 |
+ } |
|
| 401 |
+ iNdEx += length |
|
| 402 |
+ if length < 0 {
|
|
| 403 |
+ return 0, ErrInvalidLengthOverlay |
|
| 404 |
+ } |
|
| 405 |
+ return iNdEx, nil |
|
| 406 |
+ case 3: |
|
| 407 |
+ for {
|
|
| 408 |
+ var innerWire uint64 |
|
| 409 |
+ var start int = iNdEx |
|
| 410 |
+ for shift := uint(0); ; shift += 7 {
|
|
| 411 |
+ if shift >= 64 {
|
|
| 412 |
+ return 0, ErrIntOverflowOverlay |
|
| 413 |
+ } |
|
| 414 |
+ if iNdEx >= l {
|
|
| 415 |
+ return 0, io.ErrUnexpectedEOF |
|
| 416 |
+ } |
|
| 417 |
+ b := data[iNdEx] |
|
| 418 |
+ iNdEx++ |
|
| 419 |
+ innerWire |= (uint64(b) & 0x7F) << shift |
|
| 420 |
+ if b < 0x80 {
|
|
| 421 |
+ break |
|
| 422 |
+ } |
|
| 423 |
+ } |
|
| 424 |
+ innerWireType := int(innerWire & 0x7) |
|
| 425 |
+ if innerWireType == 4 {
|
|
| 426 |
+ break |
|
| 427 |
+ } |
|
| 428 |
+ next, err := skipOverlay(data[start:]) |
|
| 429 |
+ if err != nil {
|
|
| 430 |
+ return 0, err |
|
| 431 |
+ } |
|
| 432 |
+ iNdEx = start + next |
|
| 433 |
+ } |
|
| 434 |
+ return iNdEx, nil |
|
| 435 |
+ case 4: |
|
| 436 |
+ return iNdEx, nil |
|
| 437 |
+ case 5: |
|
| 438 |
+ iNdEx += 4 |
|
| 439 |
+ return iNdEx, nil |
|
| 440 |
+ default: |
|
| 441 |
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
|
| 442 |
+ } |
|
| 443 |
+ } |
|
| 444 |
+ panic("unreachable")
|
|
| 445 |
+} |
|
| 446 |
+ |
|
| 447 |
+var ( |
|
| 448 |
+ ErrInvalidLengthOverlay = fmt.Errorf("proto: negative length found during unmarshaling")
|
|
| 449 |
+ ErrIntOverflowOverlay = fmt.Errorf("proto: integer overflow")
|
|
| 450 |
+) |
|
| 451 |
+ |
|
| 452 |
+var fileDescriptorOverlay = []byte{
|
|
| 453 |
+ // 195 bytes of a gzipped FileDescriptorProto |
|
| 454 |
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0xcd, 0x2f, 0x4b, 0x2d, |
|
| 455 |
+ 0xca, 0x49, 0xac, 0xd4, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x87, 0x72, 0xa5, 0x44, 0xd2, |
|
| 456 |
+ 0xf3, 0xd3, 0xf3, 0xc1, 0x62, 0xfa, 0x20, 0x16, 0x44, 0x5a, 0x69, 0x2b, 0x23, 0x17, 0x57, 0x40, |
|
| 457 |
+ 0x6a, 0x6a, 0x51, 0x50, 0x6a, 0x72, 0x7e, 0x51, 0x8a, 0x90, 0x3e, 0x17, 0x77, 0x6a, 0x5e, 0x4a, |
|
| 458 |
+ 0x41, 0x7e, 0x66, 0x5e, 0x49, 0x7c, 0x66, 0x81, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0xa7, 0x13, 0xdf, |
|
| 459 |
+ 0xa3, 0x7b, 0xf2, 0x5c, 0xae, 0x50, 0x61, 0xcf, 0x80, 0x20, 0x2e, 0x98, 0x12, 0xcf, 0x02, 0x21, |
|
| 460 |
+ 0x23, 0x2e, 0x1e, 0xb8, 0x86, 0xdc, 0xc4, 0x64, 0x09, 0x26, 0xb0, 0x0e, 0x7e, 0xa0, 0x0e, 0x6e, |
|
| 461 |
+ 0x98, 0x0e, 0x5f, 0x47, 0xe7, 0x20, 0xb8, 0xa9, 0xbe, 0x89, 0xc9, 0x42, 0x4e, 0x5c, 0x42, 0x25, |
|
| 462 |
+ 0xa5, 0x79, 0x79, 0xa9, 0x39, 0xf1, 0xc8, 0x76, 0x31, 0x83, 0x75, 0x8a, 0x00, 0x75, 0x0a, 0x84, |
|
| 463 |
+ 0x80, 0x65, 0x91, 0x6c, 0x14, 0x28, 0x41, 0x15, 0x29, 0x70, 0x92, 0xb8, 0xf1, 0x50, 0x8e, 0xe1, |
|
| 464 |
+ 0xc3, 0x43, 0x39, 0xc6, 0x86, 0x47, 0x72, 0x8c, 0x27, 0x80, 0xf8, 0x02, 0x10, 0x3f, 0x00, 0xe2, |
|
| 465 |
+ 0x24, 0x36, 0xb0, 0xc7, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xbf, 0xd7, 0x7d, 0x7d, 0x08, |
|
| 466 |
+ 0x01, 0x00, 0x00, |
|
| 467 |
+} |
| 0 | 468 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,27 @@ |
| 0 |
+syntax = "proto3"; |
|
| 1 |
+ |
|
| 2 |
+import "gogoproto/gogo.proto"; |
|
| 3 |
+ |
|
| 4 |
+package overlay; |
|
| 5 |
+ |
|
| 6 |
+option (gogoproto.marshaler_all) = true; |
|
| 7 |
+option (gogoproto.unmarshaler_all) = true; |
|
| 8 |
+option (gogoproto.stringer_all) = true; |
|
| 9 |
+option (gogoproto.gostring_all) = true; |
|
| 10 |
+option (gogoproto.sizer_all) = true; |
|
| 11 |
+option (gogoproto.goproto_stringer_all) = false; |
|
| 12 |
+ |
|
| 13 |
+// PeerRecord defines the information corresponding to a peer |
|
| 14 |
+// container in the overlay network. |
|
| 15 |
+message PeerRecord {
|
|
| 16 |
+ // Endpoint IP is the IP of the container attachment on the |
|
| 17 |
+ // given overlay network. |
|
| 18 |
+ string endpoint_ip = 1 [(gogoproto.customname) = "EndpointIP"]; |
|
| 19 |
+ // Endpoint MAC is the mac address of the container attachment |
|
| 20 |
+ // on the given overlay network. |
|
| 21 |
+ string endpoint_mac = 2 [(gogoproto.customname) = "EndpointMAC"]; |
|
| 22 |
+ // Tunnel Endpoint IP defines the host IP for the host in |
|
| 23 |
+ // which this container is running and can be reached by |
|
| 24 |
+ // building a tunnel to that host IP. |
|
| 25 |
+ string tunnel_endpoint_ip = 3 [(gogoproto.customname) = "TunnelEndpointIP"]; |
|
| 26 |
+} |
|
| 0 | 27 |
\ No newline at end of file |
| 1 | 28 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,297 @@ |
| 0 |
+package overlay |
|
| 1 |
+ |
|
| 2 |
+//go:generate protoc -I.:../../Godeps/_workspace/src/github.com/gogo/protobuf --gogo_out=import_path=github.com/docker/libnetwork/drivers/overlay,Mgogoproto/gogo.proto=github.com/gogo/protobuf/gogoproto:. overlay.proto |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "fmt" |
|
| 6 |
+ "net" |
|
| 7 |
+ "sync" |
|
| 8 |
+ |
|
| 9 |
+ "github.com/Microsoft/hcsshim" |
|
| 10 |
+ "github.com/Sirupsen/logrus" |
|
| 11 |
+ "github.com/docker/libnetwork/datastore" |
|
| 12 |
+ "github.com/docker/libnetwork/discoverapi" |
|
| 13 |
+ "github.com/docker/libnetwork/driverapi" |
|
| 14 |
+ "github.com/docker/libnetwork/idm" |
|
| 15 |
+ "github.com/docker/libnetwork/netlabel" |
|
| 16 |
+ "github.com/docker/libnetwork/types" |
|
| 17 |
+ "github.com/hashicorp/serf/serf" |
|
| 18 |
+) |
|
| 19 |
+ |
|
| 20 |
+const ( |
|
| 21 |
+ networkType = "overlay" |
|
| 22 |
+ vethPrefix = "veth" |
|
| 23 |
+ vethLen = 7 |
|
| 24 |
+ vxlanIDStart = 4096 |
|
| 25 |
+ vxlanIDEnd = (1 << 24) - 1 |
|
| 26 |
+ vxlanPort = 4789 |
|
| 27 |
+ vxlanEncap = 50 |
|
| 28 |
+ secureOption = "encrypted" |
|
| 29 |
+) |
|
| 30 |
+ |
|
| 31 |
+var initVxlanIdm = make(chan (bool), 1) |
|
| 32 |
+ |
|
| 33 |
+type driver struct {
|
|
| 34 |
+ eventCh chan serf.Event |
|
| 35 |
+ notifyCh chan ovNotify |
|
| 36 |
+ exitCh chan chan struct{}
|
|
| 37 |
+ bindAddress string |
|
| 38 |
+ advertiseAddress string |
|
| 39 |
+ neighIP string |
|
| 40 |
+ config map[string]interface{}
|
|
| 41 |
+ serfInstance *serf.Serf |
|
| 42 |
+ networks networkTable |
|
| 43 |
+ store datastore.DataStore |
|
| 44 |
+ localStore datastore.DataStore |
|
| 45 |
+ vxlanIdm *idm.Idm |
|
| 46 |
+ once sync.Once |
|
| 47 |
+ joinOnce sync.Once |
|
| 48 |
+ sync.Mutex |
|
| 49 |
+} |
|
| 50 |
+ |
|
| 51 |
+// Init registers a new instance of overlay driver |
|
| 52 |
+func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
|
| 53 |
+ c := driverapi.Capability{
|
|
| 54 |
+ DataScope: datastore.GlobalScope, |
|
| 55 |
+ } |
|
| 56 |
+ |
|
| 57 |
+ d := &driver{
|
|
| 58 |
+ networks: networkTable{},
|
|
| 59 |
+ config: config, |
|
| 60 |
+ } |
|
| 61 |
+ |
|
| 62 |
+ if data, ok := config[netlabel.GlobalKVClient]; ok {
|
|
| 63 |
+ var err error |
|
| 64 |
+ dsc, ok := data.(discoverapi.DatastoreConfigData) |
|
| 65 |
+ if !ok {
|
|
| 66 |
+ return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
|
|
| 67 |
+ } |
|
| 68 |
+ d.store, err = datastore.NewDataStoreFromConfig(dsc) |
|
| 69 |
+ if err != nil {
|
|
| 70 |
+ return types.InternalErrorf("failed to initialize data store: %v", err)
|
|
| 71 |
+ } |
|
| 72 |
+ } |
|
| 73 |
+ |
|
| 74 |
+ if data, ok := config[netlabel.LocalKVClient]; ok {
|
|
| 75 |
+ var err error |
|
| 76 |
+ dsc, ok := data.(discoverapi.DatastoreConfigData) |
|
| 77 |
+ if !ok {
|
|
| 78 |
+ return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
|
|
| 79 |
+ } |
|
| 80 |
+ d.localStore, err = datastore.NewDataStoreFromConfig(dsc) |
|
| 81 |
+ if err != nil {
|
|
| 82 |
+ return types.InternalErrorf("failed to initialize local data store: %v", err)
|
|
| 83 |
+ } |
|
| 84 |
+ } |
|
| 85 |
+ |
|
| 86 |
+ d.restoreEndpoints() |
|
| 87 |
+ |
|
| 88 |
+ return dc.RegisterDriver(networkType, d, c) |
|
| 89 |
+} |
|
| 90 |
+ |
|
| 91 |
+// Endpoints are stored in the local store. Restore them and reconstruct the overlay sandbox |
|
| 92 |
+func (d *driver) restoreEndpoints() error {
|
|
| 93 |
+ if d.localStore == nil {
|
|
| 94 |
+ logrus.Warnf("Cannot restore overlay endpoints because local datastore is missing")
|
|
| 95 |
+ return nil |
|
| 96 |
+ } |
|
| 97 |
+ kvol, err := d.localStore.List(datastore.Key(overlayEndpointPrefix), &endpoint{})
|
|
| 98 |
+ if err != nil && err != datastore.ErrKeyNotFound {
|
|
| 99 |
+ return fmt.Errorf("failed to read overlay endpoint from store: %v", err)
|
|
| 100 |
+ } |
|
| 101 |
+ |
|
| 102 |
+ if err == datastore.ErrKeyNotFound {
|
|
| 103 |
+ return nil |
|
| 104 |
+ } |
|
| 105 |
+ |
|
| 106 |
+ for _, kvo := range kvol {
|
|
| 107 |
+ ep := kvo.(*endpoint) |
|
| 108 |
+ |
|
| 109 |
+ n := d.network(ep.nid) |
|
| 110 |
+ if n == nil || ep.remote {
|
|
| 111 |
+ if !ep.remote {
|
|
| 112 |
+ logrus.Debugf("Network (%s) not found for restored endpoint (%s)", ep.nid[0:7], ep.id[0:7])
|
|
| 113 |
+ logrus.Debugf("Deleting stale overlay endpoint (%s) from store", ep.id[0:7])
|
|
| 114 |
+ } |
|
| 115 |
+ |
|
| 116 |
+ hcsshim.HNSEndpointRequest("DELETE", ep.profileId, "")
|
|
| 117 |
+ |
|
| 118 |
+ if err := d.deleteEndpointFromStore(ep); err != nil {
|
|
| 119 |
+ logrus.Debugf("Failed to delete stale overlay endpoint (%s) from store", ep.id[0:7])
|
|
| 120 |
+ } |
|
| 121 |
+ |
|
| 122 |
+ continue |
|
| 123 |
+ } |
|
| 124 |
+ |
|
| 125 |
+ n.addEndpoint(ep) |
|
| 126 |
+ } |
|
| 127 |
+ |
|
| 128 |
+ return nil |
|
| 129 |
+} |
|
| 130 |
+ |
|
| 131 |
+// Fini cleans up the driver resources |
|
| 132 |
+func Fini(drv driverapi.Driver) {
|
|
| 133 |
+ d := drv.(*driver) |
|
| 134 |
+ |
|
| 135 |
+ if d.exitCh != nil {
|
|
| 136 |
+ waitCh := make(chan struct{})
|
|
| 137 |
+ |
|
| 138 |
+ d.exitCh <- waitCh |
|
| 139 |
+ |
|
| 140 |
+ <-waitCh |
|
| 141 |
+ } |
|
| 142 |
+} |
|
| 143 |
+ |
|
| 144 |
+func (d *driver) configure() error {
|
|
| 145 |
+ if d.store == nil {
|
|
| 146 |
+ return nil |
|
| 147 |
+ } |
|
| 148 |
+ |
|
| 149 |
+ if d.vxlanIdm == nil {
|
|
| 150 |
+ return d.initializeVxlanIdm() |
|
| 151 |
+ } |
|
| 152 |
+ |
|
| 153 |
+ return nil |
|
| 154 |
+} |
|
| 155 |
+ |
|
| 156 |
+func (d *driver) initializeVxlanIdm() error {
|
|
| 157 |
+ var err error |
|
| 158 |
+ |
|
| 159 |
+ initVxlanIdm <- true |
|
| 160 |
+ defer func() { <-initVxlanIdm }()
|
|
| 161 |
+ |
|
| 162 |
+ if d.vxlanIdm != nil {
|
|
| 163 |
+ return nil |
|
| 164 |
+ } |
|
| 165 |
+ |
|
| 166 |
+ d.vxlanIdm, err = idm.New(d.store, "vxlan-id", vxlanIDStart, vxlanIDEnd) |
|
| 167 |
+ if err != nil {
|
|
| 168 |
+ return fmt.Errorf("failed to initialize vxlan id manager: %v", err)
|
|
| 169 |
+ } |
|
| 170 |
+ |
|
| 171 |
+ return nil |
|
| 172 |
+} |
|
| 173 |
+ |
|
| 174 |
+func (d *driver) Type() string {
|
|
| 175 |
+ return networkType |
|
| 176 |
+} |
|
| 177 |
+ |
|
| 178 |
+func validateSelf(node string) error {
|
|
| 179 |
+ advIP := net.ParseIP(node) |
|
| 180 |
+ if advIP == nil {
|
|
| 181 |
+ return fmt.Errorf("invalid self address (%s)", node)
|
|
| 182 |
+ } |
|
| 183 |
+ |
|
| 184 |
+ addrs, err := net.InterfaceAddrs() |
|
| 185 |
+ if err != nil {
|
|
| 186 |
+ return fmt.Errorf("Unable to get interface addresses %v", err)
|
|
| 187 |
+ } |
|
| 188 |
+ for _, addr := range addrs {
|
|
| 189 |
+ ip, _, err := net.ParseCIDR(addr.String()) |
|
| 190 |
+ if err == nil && ip.Equal(advIP) {
|
|
| 191 |
+ return nil |
|
| 192 |
+ } |
|
| 193 |
+ } |
|
| 194 |
+ return fmt.Errorf("Multi-Host overlay networking requires cluster-advertise(%s) to be configured with a local ip-address that is reachable within the cluster", advIP.String())
|
|
| 195 |
+} |
|
| 196 |
+ |
|
| 197 |
+func (d *driver) nodeJoin(advertiseAddress, bindAddress string, self bool) {
|
|
| 198 |
+ if self && !d.isSerfAlive() {
|
|
| 199 |
+ if err := validateSelf(advertiseAddress); err != nil {
|
|
| 200 |
+ logrus.Errorf("%s", err.Error())
|
|
| 201 |
+ } |
|
| 202 |
+ |
|
| 203 |
+ d.Lock() |
|
| 204 |
+ d.advertiseAddress = advertiseAddress |
|
| 205 |
+ d.bindAddress = bindAddress |
|
| 206 |
+ d.Unlock() |
|
| 207 |
+ |
|
| 208 |
+ // If there is no cluster store there is no need to start serf. |
|
| 209 |
+ if d.store != nil {
|
|
| 210 |
+ err := d.serfInit() |
|
| 211 |
+ if err != nil {
|
|
| 212 |
+ logrus.Errorf("initializing serf instance failed: %v", err)
|
|
| 213 |
+ return |
|
| 214 |
+ } |
|
| 215 |
+ } |
|
| 216 |
+ } |
|
| 217 |
+ |
|
| 218 |
+ d.Lock() |
|
| 219 |
+ if !self {
|
|
| 220 |
+ d.neighIP = advertiseAddress |
|
| 221 |
+ } |
|
| 222 |
+ neighIP := d.neighIP |
|
| 223 |
+ d.Unlock() |
|
| 224 |
+ |
|
| 225 |
+ if d.serfInstance != nil && neighIP != "" {
|
|
| 226 |
+ var err error |
|
| 227 |
+ d.joinOnce.Do(func() {
|
|
| 228 |
+ err = d.serfJoin(neighIP) |
|
| 229 |
+ if err == nil {
|
|
| 230 |
+ d.pushLocalDb() |
|
| 231 |
+ } |
|
| 232 |
+ }) |
|
| 233 |
+ if err != nil {
|
|
| 234 |
+ logrus.Errorf("joining serf neighbor %s failed: %v", advertiseAddress, err)
|
|
| 235 |
+ d.Lock() |
|
| 236 |
+ d.joinOnce = sync.Once{}
|
|
| 237 |
+ d.Unlock() |
|
| 238 |
+ return |
|
| 239 |
+ } |
|
| 240 |
+ } |
|
| 241 |
+} |
|
| 242 |
+ |
|
| 243 |
+func (d *driver) pushLocalEndpointEvent(action, nid, eid string) {
|
|
| 244 |
+ n := d.network(nid) |
|
| 245 |
+ if n == nil {
|
|
| 246 |
+ logrus.Debugf("Error pushing local endpoint event for network %s", nid)
|
|
| 247 |
+ return |
|
| 248 |
+ } |
|
| 249 |
+ ep := n.endpoint(eid) |
|
| 250 |
+ if ep == nil {
|
|
| 251 |
+ logrus.Debugf("Error pushing local endpoint event for ep %s / %s", nid, eid)
|
|
| 252 |
+ return |
|
| 253 |
+ } |
|
| 254 |
+ |
|
| 255 |
+ if !d.isSerfAlive() {
|
|
| 256 |
+ return |
|
| 257 |
+ } |
|
| 258 |
+ d.notifyCh <- ovNotify{
|
|
| 259 |
+ action: action, |
|
| 260 |
+ nw: n, |
|
| 261 |
+ ep: ep, |
|
| 262 |
+ } |
|
| 263 |
+} |
|
| 264 |
+ |
|
| 265 |
+// DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster |
|
| 266 |
+func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
|
|
| 267 |
+ |
|
| 268 |
+ var err error |
|
| 269 |
+ switch dType {
|
|
| 270 |
+ case discoverapi.NodeDiscovery: |
|
| 271 |
+ nodeData, ok := data.(discoverapi.NodeDiscoveryData) |
|
| 272 |
+ if !ok || nodeData.Address == "" {
|
|
| 273 |
+ return fmt.Errorf("invalid discovery data")
|
|
| 274 |
+ } |
|
| 275 |
+ d.nodeJoin(nodeData.Address, nodeData.BindAddress, nodeData.Self) |
|
| 276 |
+ case discoverapi.DatastoreConfig: |
|
| 277 |
+ if d.store != nil {
|
|
| 278 |
+ return types.ForbiddenErrorf("cannot accept datastore configuration: Overlay driver has a datastore configured already")
|
|
| 279 |
+ } |
|
| 280 |
+ dsc, ok := data.(discoverapi.DatastoreConfigData) |
|
| 281 |
+ if !ok {
|
|
| 282 |
+ return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
|
|
| 283 |
+ } |
|
| 284 |
+ d.store, err = datastore.NewDataStoreFromConfig(dsc) |
|
| 285 |
+ if err != nil {
|
|
| 286 |
+ return types.InternalErrorf("failed to initialize data store: %v", err)
|
|
| 287 |
+ } |
|
| 288 |
+ default: |
|
| 289 |
+ } |
|
| 290 |
+ return nil |
|
| 291 |
+} |
|
| 292 |
+ |
|
| 293 |
+// DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster |
|
| 294 |
+func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
|
|
| 295 |
+ return nil |
|
| 296 |
+} |
| 0 | 297 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,154 @@ |
| 0 |
+package overlay |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "fmt" |
|
| 4 |
+ "net" |
|
| 5 |
+ |
|
| 6 |
+ "encoding/json" |
|
| 7 |
+ |
|
| 8 |
+ "github.com/Sirupsen/logrus" |
|
| 9 |
+ |
|
| 10 |
+ "github.com/Microsoft/hcsshim" |
|
| 11 |
+ "github.com/docker/libnetwork/types" |
|
| 12 |
+) |
|
| 13 |
+ |
|
| 14 |
+const ovPeerTable = "overlay_peer_table" |
|
| 15 |
+ |
|
| 16 |
+func (d *driver) pushLocalDb() {
|
|
| 17 |
+ if !d.isSerfAlive() {
|
|
| 18 |
+ return |
|
| 19 |
+ } |
|
| 20 |
+ |
|
| 21 |
+ d.Lock() |
|
| 22 |
+ networks := d.networks |
|
| 23 |
+ d.Unlock() |
|
| 24 |
+ |
|
| 25 |
+ for _, n := range networks {
|
|
| 26 |
+ n.Lock() |
|
| 27 |
+ endpoints := n.endpoints |
|
| 28 |
+ n.Unlock() |
|
| 29 |
+ |
|
| 30 |
+ for _, ep := range endpoints {
|
|
| 31 |
+ if !ep.remote {
|
|
| 32 |
+ d.notifyCh <- ovNotify{
|
|
| 33 |
+ action: "join", |
|
| 34 |
+ nw: n, |
|
| 35 |
+ ep: ep, |
|
| 36 |
+ } |
|
| 37 |
+ |
|
| 38 |
+ } |
|
| 39 |
+ } |
|
| 40 |
+ } |
|
| 41 |
+} |
|
| 42 |
+ |
|
| 43 |
+func (d *driver) peerAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask, |
|
| 44 |
+ peerMac net.HardwareAddr, vtep net.IP, updateDb bool) error {
|
|
| 45 |
+ |
|
| 46 |
+ logrus.Debugf("WINOVERLAY: Enter peerAdd for ca ip %s with ca mac %s", peerIP.String(), peerMac.String())
|
|
| 47 |
+ |
|
| 48 |
+ if err := validateID(nid, eid); err != nil {
|
|
| 49 |
+ return err |
|
| 50 |
+ } |
|
| 51 |
+ |
|
| 52 |
+ n := d.network(nid) |
|
| 53 |
+ if n == nil {
|
|
| 54 |
+ return nil |
|
| 55 |
+ } |
|
| 56 |
+ |
|
| 57 |
+ if updateDb {
|
|
| 58 |
+ logrus.Info("WINOVERLAY: peerAdd: notifying HNS of the REMOTE endpoint")
|
|
| 59 |
+ |
|
| 60 |
+ hnsEndpoint := &hcsshim.HNSEndpoint{
|
|
| 61 |
+ VirtualNetwork: n.hnsId, |
|
| 62 |
+ MacAddress: peerMac.String(), |
|
| 63 |
+ IPAddress: peerIP, |
|
| 64 |
+ IsRemoteEndpoint: true, |
|
| 65 |
+ } |
|
| 66 |
+ |
|
| 67 |
+ paPolicy, err := json.Marshal(hcsshim.PaPolicy{
|
|
| 68 |
+ Type: "PA", |
|
| 69 |
+ PA: vtep.String(), |
|
| 70 |
+ }) |
|
| 71 |
+ |
|
| 72 |
+ if err != nil {
|
|
| 73 |
+ return err |
|
| 74 |
+ } |
|
| 75 |
+ |
|
| 76 |
+ hnsEndpoint.Policies = append(hnsEndpoint.Policies, paPolicy) |
|
| 77 |
+ |
|
| 78 |
+ configurationb, err := json.Marshal(hnsEndpoint) |
|
| 79 |
+ if err != nil {
|
|
| 80 |
+ return err |
|
| 81 |
+ } |
|
| 82 |
+ |
|
| 83 |
+ // Temp: We have to create a endpoint object to keep track of the HNS ID for |
|
| 84 |
+ // this endpoint so that we can retrieve it later when the endpoint is deleted. |
|
| 85 |
+ // This seems unnecessary when we already have dockers EID. See if we can pass |
|
| 86 |
+ // the global EID to HNS to use as it's ID, rather than having each HNS assign |
|
| 87 |
+ // it's own local ID for the endpoint |
|
| 88 |
+ |
|
| 89 |
+ addr, err := types.ParseCIDR(peerIP.String() + "/32") |
|
| 90 |
+ if err != nil {
|
|
| 91 |
+ return err |
|
| 92 |
+ } |
|
| 93 |
+ |
|
| 94 |
+ n.removeEndpointWithAddress(addr) |
|
| 95 |
+ |
|
| 96 |
+ hnsresponse, err := hcsshim.HNSEndpointRequest("POST", "", string(configurationb))
|
|
| 97 |
+ if err != nil {
|
|
| 98 |
+ return err |
|
| 99 |
+ } |
|
| 100 |
+ |
|
| 101 |
+ ep := &endpoint{
|
|
| 102 |
+ id: eid, |
|
| 103 |
+ nid: nid, |
|
| 104 |
+ addr: addr, |
|
| 105 |
+ mac: peerMac, |
|
| 106 |
+ profileId: hnsresponse.Id, |
|
| 107 |
+ remote: true, |
|
| 108 |
+ } |
|
| 109 |
+ |
|
| 110 |
+ n.addEndpoint(ep) |
|
| 111 |
+ |
|
| 112 |
+ if err := d.writeEndpointToStore(ep); err != nil {
|
|
| 113 |
+ return fmt.Errorf("failed to update overlay endpoint %s to local store: %v", ep.id[0:7], err)
|
|
| 114 |
+ } |
|
| 115 |
+ } |
|
| 116 |
+ |
|
| 117 |
+ return nil |
|
| 118 |
+} |
|
| 119 |
+ |
|
| 120 |
+func (d *driver) peerDelete(nid, eid string, peerIP net.IP, peerIPMask net.IPMask, |
|
| 121 |
+ peerMac net.HardwareAddr, vtep net.IP, updateDb bool) error {
|
|
| 122 |
+ |
|
| 123 |
+ logrus.Infof("WINOVERLAY: Enter peerDelete for endpoint %s and peer ip %s", eid, peerIP.String())
|
|
| 124 |
+ |
|
| 125 |
+ if err := validateID(nid, eid); err != nil {
|
|
| 126 |
+ return err |
|
| 127 |
+ } |
|
| 128 |
+ |
|
| 129 |
+ n := d.network(nid) |
|
| 130 |
+ if n == nil {
|
|
| 131 |
+ return nil |
|
| 132 |
+ } |
|
| 133 |
+ |
|
| 134 |
+ ep := n.endpoint(eid) |
|
| 135 |
+ if ep == nil {
|
|
| 136 |
+ return fmt.Errorf("could not find endpoint with id %s", eid)
|
|
| 137 |
+ } |
|
| 138 |
+ |
|
| 139 |
+ if updateDb {
|
|
| 140 |
+ _, err := hcsshim.HNSEndpointRequest("DELETE", ep.profileId, "")
|
|
| 141 |
+ if err != nil {
|
|
| 142 |
+ return err |
|
| 143 |
+ } |
|
| 144 |
+ |
|
| 145 |
+ n.deleteEndpoint(eid) |
|
| 146 |
+ |
|
| 147 |
+ if err := d.deleteEndpointFromStore(ep); err != nil {
|
|
| 148 |
+ logrus.Debugf("Failed to delete stale overlay endpoint (%s) from store", ep.id[0:7])
|
|
| 149 |
+ } |
|
| 150 |
+ } |
|
| 151 |
+ |
|
| 152 |
+ return nil |
|
| 153 |
+} |
| ... | ... |
@@ -20,7 +20,7 @@ import ( |
| 20 | 20 |
"sync" |
| 21 | 21 |
|
| 22 | 22 |
"github.com/Microsoft/hcsshim" |
| 23 |
- log "github.com/Sirupsen/logrus" |
|
| 23 |
+ "github.com/Sirupsen/logrus" |
|
| 24 | 24 |
"github.com/docker/libnetwork/datastore" |
| 25 | 25 |
"github.com/docker/libnetwork/discoverapi" |
| 26 | 26 |
"github.com/docker/libnetwork/driverapi" |
| ... | ... |
@@ -44,21 +44,28 @@ type networkConfiguration struct {
|
| 44 | 44 |
} |
| 45 | 45 |
|
| 46 | 46 |
// endpointConfiguration represents the user specified configuration for the sandbox endpoint |
| 47 |
-type endpointConfiguration struct {
|
|
| 48 |
- MacAddress net.HardwareAddr |
|
| 47 |
+type endpointOption struct {
|
|
| 48 |
+ MacAddress net.HardwareAddr |
|
| 49 |
+ QosPolicies []types.QosPolicy |
|
| 50 |
+ DNSServers []string |
|
| 51 |
+ DisableDNS bool |
|
| 52 |
+ DisableICC bool |
|
| 53 |
+} |
|
| 54 |
+ |
|
| 55 |
+type endpointConnectivity struct {
|
|
| 49 | 56 |
PortBindings []types.PortBinding |
| 50 | 57 |
ExposedPorts []types.TransportPort |
| 51 |
- QosPolicies []types.QosPolicy |
|
| 52 |
- DNSServers []string |
|
| 53 | 58 |
} |
| 54 | 59 |
|
| 55 | 60 |
type hnsEndpoint struct {
|
| 56 |
- id string |
|
| 57 |
- profileID string |
|
| 58 |
- macAddress net.HardwareAddr |
|
| 59 |
- config *endpointConfiguration // User specified parameters |
|
| 60 |
- portMapping []types.PortBinding // Operation port bindings |
|
| 61 |
- addr *net.IPNet |
|
| 61 |
+ id string |
|
| 62 |
+ profileID string |
|
| 63 |
+ macAddress net.HardwareAddr |
|
| 64 |
+ epOption *endpointOption // User specified parameters |
|
| 65 |
+ epConnectivity *endpointConnectivity // User specified parameters |
|
| 66 |
+ portMapping []types.PortBinding // Operation port bindings |
|
| 67 |
+ addr *net.IPNet |
|
| 68 |
+ gateway net.IP |
|
| 62 | 69 |
} |
| 63 | 70 |
|
| 64 | 71 |
type hnsNetwork struct {
|
| ... | ... |
@@ -75,7 +82,8 @@ type driver struct {
|
| 75 | 75 |
sync.Mutex |
| 76 | 76 |
} |
| 77 | 77 |
|
| 78 |
-func isValidNetworkType(networkType string) bool {
|
|
| 78 |
+// IsBuiltinWindowsDriver vaidates if network-type is a builtin local-scoped driver |
|
| 79 |
+func IsBuiltinLocalDriver(networkType string) bool {
|
|
| 79 | 80 |
if "l2bridge" == networkType || "l2tunnel" == networkType || "nat" == networkType || "ics" == networkType || "transparent" == networkType {
|
| 80 | 81 |
return true |
| 81 | 82 |
} |
| ... | ... |
@@ -91,7 +99,7 @@ func newDriver(networkType string) *driver {
|
| 91 | 91 |
// GetInit returns an initializer for the given network type |
| 92 | 92 |
func GetInit(networkType string) func(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
| 93 | 93 |
return func(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
| 94 |
- if !isValidNetworkType(networkType) {
|
|
| 94 |
+ if !IsBuiltinLocalDriver(networkType) {
|
|
| 95 | 95 |
return types.BadRequestErrorf("Network type not supported: %s", networkType)
|
| 96 | 96 |
} |
| 97 | 97 |
|
| ... | ... |
@@ -270,7 +278,7 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo d
|
| 270 | 270 |
} |
| 271 | 271 |
|
| 272 | 272 |
configuration := string(configurationb) |
| 273 |
- log.Debugf("HNSNetwork Request =%v Address Space=%v", configuration, subnets)
|
|
| 273 |
+ logrus.Debugf("HNSNetwork Request =%v Address Space=%v", configuration, subnets)
|
|
| 274 | 274 |
|
| 275 | 275 |
hnsresponse, err := hcsshim.HNSNetworkRequest("POST", "", configuration)
|
| 276 | 276 |
if err != nil {
|
| ... | ... |
@@ -390,12 +398,12 @@ func parsePortBindingPolicies(policies []json.RawMessage) ([]types.PortBinding, |
| 390 | 390 |
return bindings, nil |
| 391 | 391 |
} |
| 392 | 392 |
|
| 393 |
-func parseEndpointOptions(epOptions map[string]interface{}) (*endpointConfiguration, error) {
|
|
| 393 |
+func parseEndpointOptions(epOptions map[string]interface{}) (*endpointOption, error) {
|
|
| 394 | 394 |
if epOptions == nil {
|
| 395 | 395 |
return nil, nil |
| 396 | 396 |
} |
| 397 | 397 |
|
| 398 |
- ec := &endpointConfiguration{}
|
|
| 398 |
+ ec := &endpointOption{}
|
|
| 399 | 399 |
|
| 400 | 400 |
if opt, ok := epOptions[netlabel.MacAddress]; ok {
|
| 401 | 401 |
if mac, ok := opt.(net.HardwareAddr); ok {
|
| ... | ... |
@@ -405,33 +413,33 @@ func parseEndpointOptions(epOptions map[string]interface{}) (*endpointConfigurat
|
| 405 | 405 |
} |
| 406 | 406 |
} |
| 407 | 407 |
|
| 408 |
- if opt, ok := epOptions[netlabel.PortMap]; ok {
|
|
| 409 |
- if bs, ok := opt.([]types.PortBinding); ok {
|
|
| 410 |
- ec.PortBindings = bs |
|
| 408 |
+ if opt, ok := epOptions[QosPolicies]; ok {
|
|
| 409 |
+ if policies, ok := opt.([]types.QosPolicy); ok {
|
|
| 410 |
+ ec.QosPolicies = policies |
|
| 411 | 411 |
} else {
|
| 412 | 412 |
return nil, fmt.Errorf("Invalid endpoint configuration")
|
| 413 | 413 |
} |
| 414 | 414 |
} |
| 415 | 415 |
|
| 416 |
- if opt, ok := epOptions[netlabel.ExposedPorts]; ok {
|
|
| 417 |
- if ports, ok := opt.([]types.TransportPort); ok {
|
|
| 418 |
- ec.ExposedPorts = ports |
|
| 416 |
+ if opt, ok := epOptions[netlabel.DNSServers]; ok {
|
|
| 417 |
+ if dns, ok := opt.([]string); ok {
|
|
| 418 |
+ ec.DNSServers = dns |
|
| 419 | 419 |
} else {
|
| 420 | 420 |
return nil, fmt.Errorf("Invalid endpoint configuration")
|
| 421 | 421 |
} |
| 422 | 422 |
} |
| 423 | 423 |
|
| 424 |
- if opt, ok := epOptions[QosPolicies]; ok {
|
|
| 425 |
- if policies, ok := opt.([]types.QosPolicy); ok {
|
|
| 426 |
- ec.QosPolicies = policies |
|
| 424 |
+ if opt, ok := epOptions[DisableICC]; ok {
|
|
| 425 |
+ if disableICC, ok := opt.(bool); ok {
|
|
| 426 |
+ ec.DisableICC = disableICC |
|
| 427 | 427 |
} else {
|
| 428 | 428 |
return nil, fmt.Errorf("Invalid endpoint configuration")
|
| 429 | 429 |
} |
| 430 | 430 |
} |
| 431 | 431 |
|
| 432 |
- if opt, ok := epOptions[netlabel.DNSServers]; ok {
|
|
| 433 |
- if dns, ok := opt.([]string); ok {
|
|
| 434 |
- ec.DNSServers = dns |
|
| 432 |
+ if opt, ok := epOptions[DisableDNS]; ok {
|
|
| 433 |
+ if disableDNS, ok := opt.(bool); ok {
|
|
| 434 |
+ ec.DisableDNS = disableDNS |
|
| 435 | 435 |
} else {
|
| 436 | 436 |
return nil, fmt.Errorf("Invalid endpoint configuration")
|
| 437 | 437 |
} |
| ... | ... |
@@ -440,6 +448,31 @@ func parseEndpointOptions(epOptions map[string]interface{}) (*endpointConfigurat
|
| 440 | 440 |
return ec, nil |
| 441 | 441 |
} |
| 442 | 442 |
|
| 443 |
+func parseEndpointConnectivity(epOptions map[string]interface{}) (*endpointConnectivity, error) {
|
|
| 444 |
+ if epOptions == nil {
|
|
| 445 |
+ return nil, nil |
|
| 446 |
+ } |
|
| 447 |
+ |
|
| 448 |
+ ec := &endpointConnectivity{}
|
|
| 449 |
+ |
|
| 450 |
+ if opt, ok := epOptions[netlabel.PortMap]; ok {
|
|
| 451 |
+ if bs, ok := opt.([]types.PortBinding); ok {
|
|
| 452 |
+ ec.PortBindings = bs |
|
| 453 |
+ } else {
|
|
| 454 |
+ return nil, fmt.Errorf("Invalid endpoint configuration")
|
|
| 455 |
+ } |
|
| 456 |
+ } |
|
| 457 |
+ |
|
| 458 |
+ if opt, ok := epOptions[netlabel.ExposedPorts]; ok {
|
|
| 459 |
+ if ports, ok := opt.([]types.TransportPort); ok {
|
|
| 460 |
+ ec.ExposedPorts = ports |
|
| 461 |
+ } else {
|
|
| 462 |
+ return nil, fmt.Errorf("Invalid endpoint configuration")
|
|
| 463 |
+ } |
|
| 464 |
+ } |
|
| 465 |
+ return ec, nil |
|
| 466 |
+} |
|
| 467 |
+ |
|
| 443 | 468 |
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error {
|
| 444 | 469 |
n, err := d.getNetwork(nid) |
| 445 | 470 |
if err != nil {
|
| ... | ... |
@@ -456,7 +489,8 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, |
| 456 | 456 |
VirtualNetwork: n.config.HnsID, |
| 457 | 457 |
} |
| 458 | 458 |
|
| 459 |
- ec, err := parseEndpointOptions(epOptions) |
|
| 459 |
+ epOption, err := parseEndpointOptions(epOptions) |
|
| 460 |
+ epConnectivity, err := parseEndpointConnectivity(epOptions) |
|
| 460 | 461 |
|
| 461 | 462 |
macAddress := ifInfo.MacAddress() |
| 462 | 463 |
// Use the macaddress if it was provided |
| ... | ... |
@@ -464,12 +498,12 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, |
| 464 | 464 |
endpointStruct.MacAddress = strings.Replace(macAddress.String(), ":", "-", -1) |
| 465 | 465 |
} |
| 466 | 466 |
|
| 467 |
- endpointStruct.Policies, err = convertPortBindings(ec.PortBindings) |
|
| 467 |
+ endpointStruct.Policies, err = convertPortBindings(epConnectivity.PortBindings) |
|
| 468 | 468 |
if err != nil {
|
| 469 | 469 |
return err |
| 470 | 470 |
} |
| 471 | 471 |
|
| 472 |
- qosPolicies, err := convertQosPolicies(ec.QosPolicies) |
|
| 472 |
+ qosPolicies, err := convertQosPolicies(epOption.QosPolicies) |
|
| 473 | 473 |
if err != nil {
|
| 474 | 474 |
return err |
| 475 | 475 |
} |
| ... | ... |
@@ -479,12 +513,14 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, |
| 479 | 479 |
endpointStruct.IPAddress = ifInfo.Address().IP |
| 480 | 480 |
} |
| 481 | 481 |
|
| 482 |
- endpointStruct.DNSServerList = strings.Join(ec.DNSServers, ",") |
|
| 482 |
+ endpointStruct.DNSServerList = strings.Join(epOption.DNSServers, ",") |
|
| 483 | 483 |
|
| 484 |
- if n.driver.name == "nat" {
|
|
| 484 |
+ if n.driver.name == "nat" && !epOption.DisableDNS {
|
|
| 485 | 485 |
endpointStruct.EnableInternalDNS = true |
| 486 | 486 |
} |
| 487 | 487 |
|
| 488 |
+ endpointStruct.DisableICC = epOption.DisableICC |
|
| 489 |
+ |
|
| 488 | 490 |
configurationb, err := json.Marshal(endpointStruct) |
| 489 | 491 |
if err != nil {
|
| 490 | 492 |
return err |
| ... | ... |
@@ -507,8 +543,13 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, |
| 507 | 507 |
macAddress: mac, |
| 508 | 508 |
} |
| 509 | 509 |
|
| 510 |
+ if hnsresponse.GatewayAddress != "" {
|
|
| 511 |
+ endpoint.gateway = net.ParseIP(hnsresponse.GatewayAddress) |
|
| 512 |
+ } |
|
| 513 |
+ |
|
| 510 | 514 |
endpoint.profileID = hnsresponse.Id |
| 511 |
- endpoint.config = ec |
|
| 515 |
+ endpoint.epConnectivity = epConnectivity |
|
| 516 |
+ endpoint.epOption = epOption |
|
| 512 | 517 |
endpoint.portMapping, err = parsePortBindingPolicies(hnsresponse.Policies) |
| 513 | 518 |
|
| 514 | 519 |
if err != nil {
|
| ... | ... |
@@ -571,10 +612,10 @@ func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, erro
|
| 571 | 571 |
} |
| 572 | 572 |
|
| 573 | 573 |
data["hnsid"] = ep.profileID |
| 574 |
- if ep.config.ExposedPorts != nil {
|
|
| 574 |
+ if ep.epConnectivity.ExposedPorts != nil {
|
|
| 575 | 575 |
// Return a copy of the config data |
| 576 |
- epc := make([]types.TransportPort, 0, len(ep.config.ExposedPorts)) |
|
| 577 |
- for _, tp := range ep.config.ExposedPorts {
|
|
| 576 |
+ epc := make([]types.TransportPort, 0, len(ep.epConnectivity.ExposedPorts)) |
|
| 577 |
+ for _, tp := range ep.epConnectivity.ExposedPorts {
|
|
| 578 | 578 |
epc = append(epc, tp.GetCopy()) |
| 579 | 579 |
} |
| 580 | 580 |
data[netlabel.ExposedPorts] = epc |
| ... | ... |
@@ -603,7 +644,12 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, |
| 603 | 603 |
} |
| 604 | 604 |
|
| 605 | 605 |
// Ensure that the endpoint exists |
| 606 |
- _, err = network.getEndpoint(eid) |
|
| 606 |
+ endpoint, err := network.getEndpoint(eid) |
|
| 607 |
+ if err != nil {
|
|
| 608 |
+ return err |
|
| 609 |
+ } |
|
| 610 |
+ |
|
| 611 |
+ err = jinfo.SetGateway(endpoint.gateway) |
|
| 607 | 612 |
if err != nil {
|
| 608 | 613 |
return err |
| 609 | 614 |
} |
| ... | ... |
@@ -3,10 +3,12 @@ package libnetwork |
| 3 | 3 |
import ( |
| 4 | 4 |
"github.com/docker/libnetwork/drivers/null" |
| 5 | 5 |
"github.com/docker/libnetwork/drivers/solaris/bridge" |
| 6 |
+ "github.com/docker/libnetwork/drivers/solaris/overlay" |
|
| 6 | 7 |
) |
| 7 | 8 |
|
| 8 | 9 |
func getInitializers() []initializer {
|
| 9 | 10 |
return []initializer{
|
| 11 |
+ {overlay.Init, "overlay"},
|
|
| 10 | 12 |
{bridge.Init, "bridge"},
|
| 11 | 13 |
{null.Init, "null"},
|
| 12 | 14 |
} |
| ... | ... |
@@ -2,12 +2,16 @@ package libnetwork |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 | 4 |
"github.com/docker/libnetwork/drivers/null" |
| 5 |
+ "github.com/docker/libnetwork/drivers/remote" |
|
| 5 | 6 |
"github.com/docker/libnetwork/drivers/windows" |
| 7 |
+ "github.com/docker/libnetwork/drivers/windows/overlay" |
|
| 6 | 8 |
) |
| 7 | 9 |
|
| 8 | 10 |
func getInitializers() []initializer {
|
| 9 | 11 |
return []initializer{
|
| 10 | 12 |
{null.Init, "null"},
|
| 13 |
+ {overlay.Init, "overlay"},
|
|
| 14 |
+ {remote.Init, "remote"},
|
|
| 11 | 15 |
{windows.GetInit("transparent"), "transparent"},
|
| 12 | 16 |
{windows.GetInit("l2bridge"), "l2bridge"},
|
| 13 | 17 |
{windows.GetInit("l2tunnel"), "l2tunnel"},
|
| ... | ... |
@@ -8,7 +8,7 @@ import ( |
| 8 | 8 |
"strings" |
| 9 | 9 |
"sync" |
| 10 | 10 |
|
| 11 |
- log "github.com/Sirupsen/logrus" |
|
| 11 |
+ "github.com/Sirupsen/logrus" |
|
| 12 | 12 |
"github.com/docker/libnetwork/datastore" |
| 13 | 13 |
"github.com/docker/libnetwork/ipamapi" |
| 14 | 14 |
"github.com/docker/libnetwork/netlabel" |
| ... | ... |
@@ -142,12 +142,12 @@ func (ep *endpoint) UnmarshalJSON(b []byte) (err error) {
|
| 142 | 142 |
|
| 143 | 143 |
bytes, err := json.Marshal(tmp) |
| 144 | 144 |
if err != nil {
|
| 145 |
- log.Error(err) |
|
| 145 |
+ logrus.Error(err) |
|
| 146 | 146 |
break |
| 147 | 147 |
} |
| 148 | 148 |
err = json.Unmarshal(bytes, &pb) |
| 149 | 149 |
if err != nil {
|
| 150 |
- log.Error(err) |
|
| 150 |
+ logrus.Error(err) |
|
| 151 | 151 |
break |
| 152 | 152 |
} |
| 153 | 153 |
pblist = append(pblist, pb) |
| ... | ... |
@@ -164,12 +164,12 @@ func (ep *endpoint) UnmarshalJSON(b []byte) (err error) {
|
| 164 | 164 |
|
| 165 | 165 |
bytes, err := json.Marshal(tmp) |
| 166 | 166 |
if err != nil {
|
| 167 |
- log.Error(err) |
|
| 167 |
+ logrus.Error(err) |
|
| 168 | 168 |
break |
| 169 | 169 |
} |
| 170 | 170 |
err = json.Unmarshal(bytes, &tp) |
| 171 | 171 |
if err != nil {
|
| 172 |
- log.Error(err) |
|
| 172 |
+ logrus.Error(err) |
|
| 173 | 173 |
break |
| 174 | 174 |
} |
| 175 | 175 |
tplist = append(tplist, tp) |
| ... | ... |
@@ -472,7 +472,7 @@ func (ep *endpoint) sbJoin(sb *sandbox, options ...EndpointOption) error {
|
| 472 | 472 |
defer func() {
|
| 473 | 473 |
if err != nil {
|
| 474 | 474 |
if err := d.Leave(nid, epid); err != nil {
|
| 475 |
- log.Warnf("driver leave failed while rolling back join: %v", err)
|
|
| 475 |
+ logrus.Warnf("driver leave failed while rolling back join: %v", err)
|
|
| 476 | 476 |
} |
| 477 | 477 |
} |
| 478 | 478 |
}() |
| ... | ... |
@@ -495,10 +495,6 @@ func (ep *endpoint) sbJoin(sb *sandbox, options ...EndpointOption) error {
|
| 495 | 495 |
return err |
| 496 | 496 |
} |
| 497 | 497 |
|
| 498 |
- if err = n.getController().updateToStore(ep); err != nil {
|
|
| 499 |
- return err |
|
| 500 |
- } |
|
| 501 |
- |
|
| 502 | 498 |
// Current endpoint providing external connectivity for the sandbox |
| 503 | 499 |
extEp := sb.getGatewayEndpoint() |
| 504 | 500 |
|
| ... | ... |
@@ -515,6 +511,10 @@ func (ep *endpoint) sbJoin(sb *sandbox, options ...EndpointOption) error {
|
| 515 | 515 |
return err |
| 516 | 516 |
} |
| 517 | 517 |
|
| 518 |
+ if err = n.getController().updateToStore(ep); err != nil {
|
|
| 519 |
+ return err |
|
| 520 |
+ } |
|
| 521 |
+ |
|
| 518 | 522 |
if sb.needDefaultGW() && sb.getEndpointInGWNetwork() == nil {
|
| 519 | 523 |
return sb.setupDefaultGW() |
| 520 | 524 |
} |
| ... | ... |
@@ -523,7 +523,7 @@ func (ep *endpoint) sbJoin(sb *sandbox, options ...EndpointOption) error {
|
| 523 | 523 |
|
| 524 | 524 |
if moveExtConn {
|
| 525 | 525 |
if extEp != nil {
|
| 526 |
- log.Debugf("Revoking external connectivity on endpoint %s (%s)", extEp.Name(), extEp.ID())
|
|
| 526 |
+ logrus.Debugf("Revoking external connectivity on endpoint %s (%s)", extEp.Name(), extEp.ID())
|
|
| 527 | 527 |
extN, err := extEp.getNetworkFromStore() |
| 528 | 528 |
if err != nil {
|
| 529 | 529 |
return fmt.Errorf("failed to get network from store during join: %v", err)
|
| ... | ... |
@@ -540,14 +540,14 @@ func (ep *endpoint) sbJoin(sb *sandbox, options ...EndpointOption) error {
|
| 540 | 540 |
defer func() {
|
| 541 | 541 |
if err != nil {
|
| 542 | 542 |
if e := extD.ProgramExternalConnectivity(extEp.network.ID(), extEp.ID(), sb.Labels()); e != nil {
|
| 543 |
- log.Warnf("Failed to roll-back external connectivity on endpoint %s (%s): %v",
|
|
| 543 |
+ logrus.Warnf("Failed to roll-back external connectivity on endpoint %s (%s): %v",
|
|
| 544 | 544 |
extEp.Name(), extEp.ID(), e) |
| 545 | 545 |
} |
| 546 | 546 |
} |
| 547 | 547 |
}() |
| 548 | 548 |
} |
| 549 | 549 |
if !n.internal {
|
| 550 |
- log.Debugf("Programming external connectivity on endpoint %s (%s)", ep.Name(), ep.ID())
|
|
| 550 |
+ logrus.Debugf("Programming external connectivity on endpoint %s (%s)", ep.Name(), ep.ID())
|
|
| 551 | 551 |
if err = d.ProgramExternalConnectivity(n.ID(), ep.ID(), sb.Labels()); err != nil {
|
| 552 | 552 |
return types.InternalErrorf( |
| 553 | 553 |
"driver failed programming external connectivity on endpoint %s (%s): %v", |
| ... | ... |
@@ -559,7 +559,7 @@ func (ep *endpoint) sbJoin(sb *sandbox, options ...EndpointOption) error {
|
| 559 | 559 |
|
| 560 | 560 |
if !sb.needDefaultGW() {
|
| 561 | 561 |
if err := sb.clearDefaultGW(); err != nil {
|
| 562 |
- log.Warnf("Failure while disconnecting sandbox %s (%s) from gateway network: %v",
|
|
| 562 |
+ logrus.Warnf("Failure while disconnecting sandbox %s (%s) from gateway network: %v",
|
|
| 563 | 563 |
sb.ID(), sb.ContainerID(), err) |
| 564 | 564 |
} |
| 565 | 565 |
} |
| ... | ... |
@@ -682,22 +682,22 @@ func (ep *endpoint) sbLeave(sb *sandbox, force bool, options ...EndpointOption) |
| 682 | 682 |
|
| 683 | 683 |
if d != nil {
|
| 684 | 684 |
if moveExtConn {
|
| 685 |
- log.Debugf("Revoking external connectivity on endpoint %s (%s)", ep.Name(), ep.ID())
|
|
| 685 |
+ logrus.Debugf("Revoking external connectivity on endpoint %s (%s)", ep.Name(), ep.ID())
|
|
| 686 | 686 |
if err := d.RevokeExternalConnectivity(n.id, ep.id); err != nil {
|
| 687 |
- log.Warnf("driver failed revoking external connectivity on endpoint %s (%s): %v",
|
|
| 687 |
+ logrus.Warnf("driver failed revoking external connectivity on endpoint %s (%s): %v",
|
|
| 688 | 688 |
ep.Name(), ep.ID(), err) |
| 689 | 689 |
} |
| 690 | 690 |
} |
| 691 | 691 |
|
| 692 | 692 |
if err := d.Leave(n.id, ep.id); err != nil {
|
| 693 | 693 |
if _, ok := err.(types.MaskableError); !ok {
|
| 694 |
- log.Warnf("driver error disconnecting container %s : %v", ep.name, err)
|
|
| 694 |
+ logrus.Warnf("driver error disconnecting container %s : %v", ep.name, err)
|
|
| 695 | 695 |
} |
| 696 | 696 |
} |
| 697 | 697 |
} |
| 698 | 698 |
|
| 699 | 699 |
if err := sb.clearNetworkResources(ep); err != nil {
|
| 700 |
- log.Warnf("Could not cleanup network resources on container %s disconnect: %v", ep.name, err)
|
|
| 700 |
+ logrus.Warnf("Could not cleanup network resources on container %s disconnect: %v", ep.name, err)
|
|
| 701 | 701 |
} |
| 702 | 702 |
|
| 703 | 703 |
// Update the store about the sandbox detach only after we |
| ... | ... |
@@ -710,7 +710,7 @@ func (ep *endpoint) sbLeave(sb *sandbox, force bool, options ...EndpointOption) |
| 710 | 710 |
} |
| 711 | 711 |
|
| 712 | 712 |
if e := ep.deleteFromCluster(); e != nil {
|
| 713 |
- log.Errorf("Could not delete state for endpoint %s from cluster: %v", ep.Name(), e)
|
|
| 713 |
+ logrus.Errorf("Could not delete state for endpoint %s from cluster: %v", ep.Name(), e)
|
|
| 714 | 714 |
} |
| 715 | 715 |
|
| 716 | 716 |
sb.deleteHostsEntries(n.getSvcRecords(ep)) |
| ... | ... |
@@ -721,7 +721,7 @@ func (ep *endpoint) sbLeave(sb *sandbox, force bool, options ...EndpointOption) |
| 721 | 721 |
// New endpoint providing external connectivity for the sandbox |
| 722 | 722 |
extEp = sb.getGatewayEndpoint() |
| 723 | 723 |
if moveExtConn && extEp != nil {
|
| 724 |
- log.Debugf("Programming external connectivity on endpoint %s (%s)", extEp.Name(), extEp.ID())
|
|
| 724 |
+ logrus.Debugf("Programming external connectivity on endpoint %s (%s)", extEp.Name(), extEp.ID())
|
|
| 725 | 725 |
extN, err := extEp.getNetworkFromStore() |
| 726 | 726 |
if err != nil {
|
| 727 | 727 |
return fmt.Errorf("failed to get network from store during leave: %v", err)
|
| ... | ... |
@@ -731,14 +731,14 @@ func (ep *endpoint) sbLeave(sb *sandbox, force bool, options ...EndpointOption) |
| 731 | 731 |
return fmt.Errorf("failed to leave endpoint: %v", err)
|
| 732 | 732 |
} |
| 733 | 733 |
if err := extD.ProgramExternalConnectivity(extEp.network.ID(), extEp.ID(), sb.Labels()); err != nil {
|
| 734 |
- log.Warnf("driver failed programming external connectivity on endpoint %s: (%s) %v",
|
|
| 734 |
+ logrus.Warnf("driver failed programming external connectivity on endpoint %s: (%s) %v",
|
|
| 735 | 735 |
extEp.Name(), extEp.ID(), err) |
| 736 | 736 |
} |
| 737 | 737 |
} |
| 738 | 738 |
|
| 739 | 739 |
if !sb.needDefaultGW() {
|
| 740 | 740 |
if err := sb.clearDefaultGW(); err != nil {
|
| 741 |
- log.Warnf("Failure while disconnecting sandbox %s (%s) from gateway network: %v",
|
|
| 741 |
+ logrus.Warnf("Failure while disconnecting sandbox %s (%s) from gateway network: %v",
|
|
| 742 | 742 |
sb.ID(), sb.ContainerID(), err) |
| 743 | 743 |
} |
| 744 | 744 |
} |
| ... | ... |
@@ -771,7 +771,7 @@ func (ep *endpoint) Delete(force bool) error {
|
| 771 | 771 |
|
| 772 | 772 |
if sb != nil {
|
| 773 | 773 |
if e := ep.sbLeave(sb.(*sandbox), force); e != nil {
|
| 774 |
- log.Warnf("failed to leave sandbox for endpoint %s : %v", name, e)
|
|
| 774 |
+ logrus.Warnf("failed to leave sandbox for endpoint %s : %v", name, e)
|
|
| 775 | 775 |
} |
| 776 | 776 |
} |
| 777 | 777 |
|
| ... | ... |
@@ -783,7 +783,7 @@ func (ep *endpoint) Delete(force bool) error {
|
| 783 | 783 |
if err != nil && !force {
|
| 784 | 784 |
ep.dbExists = false |
| 785 | 785 |
if e := n.getController().updateToStore(ep); e != nil {
|
| 786 |
- log.Warnf("failed to recreate endpoint in store %s : %v", name, e)
|
|
| 786 |
+ logrus.Warnf("failed to recreate endpoint in store %s : %v", name, e)
|
|
| 787 | 787 |
} |
| 788 | 788 |
} |
| 789 | 789 |
}() |
| ... | ... |
@@ -798,7 +798,7 @@ func (ep *endpoint) Delete(force bool) error {
|
| 798 | 798 |
ep.releaseAddress() |
| 799 | 799 |
|
| 800 | 800 |
if err := n.getEpCnt().DecEndpointCnt(); err != nil {
|
| 801 |
- log.Warnf("failed to decrement endpoint count for ep %s: %v", ep.ID(), err)
|
|
| 801 |
+ logrus.Warnf("failed to decrement endpoint count for ep %s: %v", ep.ID(), err)
|
|
| 802 | 802 |
} |
| 803 | 803 |
|
| 804 | 804 |
return nil |
| ... | ... |
@@ -826,7 +826,7 @@ func (ep *endpoint) deleteEndpoint(force bool) error {
|
| 826 | 826 |
} |
| 827 | 827 |
|
| 828 | 828 |
if _, ok := err.(types.MaskableError); !ok {
|
| 829 |
- log.Warnf("driver error deleting endpoint %s : %v", name, err)
|
|
| 829 |
+ logrus.Warnf("driver error deleting endpoint %s : %v", name, err)
|
|
| 830 | 830 |
} |
| 831 | 831 |
} |
| 832 | 832 |
|
| ... | ... |
@@ -976,7 +976,7 @@ func JoinOptionPriority(ep Endpoint, prio int) EndpointOption {
|
| 976 | 976 |
sb, ok := c.sandboxes[ep.sandboxID] |
| 977 | 977 |
c.Unlock() |
| 978 | 978 |
if !ok {
|
| 979 |
- log.Errorf("Could not set endpoint priority value during Join to endpoint %s: No sandbox id present in endpoint", ep.id)
|
|
| 979 |
+ logrus.Errorf("Could not set endpoint priority value during Join to endpoint %s: No sandbox id present in endpoint", ep.id)
|
|
| 980 | 980 |
return |
| 981 | 981 |
} |
| 982 | 982 |
sb.epPriority[ep.id] = prio |
| ... | ... |
@@ -995,7 +995,7 @@ func (ep *endpoint) assignAddress(ipam ipamapi.Ipam, assignIPv4, assignIPv6 bool |
| 995 | 995 |
return nil |
| 996 | 996 |
} |
| 997 | 997 |
|
| 998 |
- log.Debugf("Assigning addresses for endpoint %s's interface on network %s", ep.Name(), n.Name())
|
|
| 998 |
+ logrus.Debugf("Assigning addresses for endpoint %s's interface on network %s", ep.Name(), n.Name())
|
|
| 999 | 999 |
|
| 1000 | 1000 |
if assignIPv4 {
|
| 1001 | 1001 |
if err = ep.assignAddressVersion(4, ipam); err != nil {
|
| ... | ... |
@@ -1075,23 +1075,23 @@ func (ep *endpoint) releaseAddress() {
|
| 1075 | 1075 |
return |
| 1076 | 1076 |
} |
| 1077 | 1077 |
|
| 1078 |
- log.Debugf("Releasing addresses for endpoint %s's interface on network %s", ep.Name(), n.Name())
|
|
| 1078 |
+ logrus.Debugf("Releasing addresses for endpoint %s's interface on network %s", ep.Name(), n.Name())
|
|
| 1079 | 1079 |
|
| 1080 | 1080 |
ipam, _, err := n.getController().getIPAMDriver(n.ipamType) |
| 1081 | 1081 |
if err != nil {
|
| 1082 |
- log.Warnf("Failed to retrieve ipam driver to release interface address on delete of endpoint %s (%s): %v", ep.Name(), ep.ID(), err)
|
|
| 1082 |
+ logrus.Warnf("Failed to retrieve ipam driver to release interface address on delete of endpoint %s (%s): %v", ep.Name(), ep.ID(), err)
|
|
| 1083 | 1083 |
return |
| 1084 | 1084 |
} |
| 1085 | 1085 |
|
| 1086 | 1086 |
if ep.iface.addr != nil {
|
| 1087 | 1087 |
if err := ipam.ReleaseAddress(ep.iface.v4PoolID, ep.iface.addr.IP); err != nil {
|
| 1088 |
- log.Warnf("Failed to release ip address %s on delete of endpoint %s (%s): %v", ep.iface.addr.IP, ep.Name(), ep.ID(), err)
|
|
| 1088 |
+ logrus.Warnf("Failed to release ip address %s on delete of endpoint %s (%s): %v", ep.iface.addr.IP, ep.Name(), ep.ID(), err)
|
|
| 1089 | 1089 |
} |
| 1090 | 1090 |
} |
| 1091 | 1091 |
|
| 1092 | 1092 |
if ep.iface.addrv6 != nil && ep.iface.addrv6.IP.IsGlobalUnicast() {
|
| 1093 | 1093 |
if err := ipam.ReleaseAddress(ep.iface.v6PoolID, ep.iface.addrv6.IP); err != nil {
|
| 1094 |
- log.Warnf("Failed to release ip address %s on delete of endpoint %s (%s): %v", ep.iface.addrv6.IP, ep.Name(), ep.ID(), err)
|
|
| 1094 |
+ logrus.Warnf("Failed to release ip address %s on delete of endpoint %s (%s): %v", ep.iface.addrv6.IP, ep.Name(), ep.ID(), err)
|
|
| 1095 | 1095 |
} |
| 1096 | 1096 |
} |
| 1097 | 1097 |
} |
| ... | ... |
@@ -1106,14 +1106,14 @@ func (c *controller) cleanupLocalEndpoints() {
|
| 1106 | 1106 |
} |
| 1107 | 1107 |
nl, err := c.getNetworksForScope(datastore.LocalScope) |
| 1108 | 1108 |
if err != nil {
|
| 1109 |
- log.Warnf("Could not get list of networks during endpoint cleanup: %v", err)
|
|
| 1109 |
+ logrus.Warnf("Could not get list of networks during endpoint cleanup: %v", err)
|
|
| 1110 | 1110 |
return |
| 1111 | 1111 |
} |
| 1112 | 1112 |
|
| 1113 | 1113 |
for _, n := range nl {
|
| 1114 | 1114 |
epl, err := n.getEndpointsFromStore() |
| 1115 | 1115 |
if err != nil {
|
| 1116 |
- log.Warnf("Could not get list of endpoints in network %s during endpoint cleanup: %v", n.name, err)
|
|
| 1116 |
+ logrus.Warnf("Could not get list of endpoints in network %s during endpoint cleanup: %v", n.name, err)
|
|
| 1117 | 1117 |
continue |
| 1118 | 1118 |
} |
| 1119 | 1119 |
|
| ... | ... |
@@ -1121,21 +1121,21 @@ func (c *controller) cleanupLocalEndpoints() {
|
| 1121 | 1121 |
if _, ok := eps[ep.id]; ok {
|
| 1122 | 1122 |
continue |
| 1123 | 1123 |
} |
| 1124 |
- log.Infof("Removing stale endpoint %s (%s)", ep.name, ep.id)
|
|
| 1124 |
+ logrus.Infof("Removing stale endpoint %s (%s)", ep.name, ep.id)
|
|
| 1125 | 1125 |
if err := ep.Delete(true); err != nil {
|
| 1126 |
- log.Warnf("Could not delete local endpoint %s during endpoint cleanup: %v", ep.name, err)
|
|
| 1126 |
+ logrus.Warnf("Could not delete local endpoint %s during endpoint cleanup: %v", ep.name, err)
|
|
| 1127 | 1127 |
} |
| 1128 | 1128 |
} |
| 1129 | 1129 |
|
| 1130 | 1130 |
epl, err = n.getEndpointsFromStore() |
| 1131 | 1131 |
if err != nil {
|
| 1132 |
- log.Warnf("Could not get list of endpoints in network %s for count update: %v", n.name, err)
|
|
| 1132 |
+ logrus.Warnf("Could not get list of endpoints in network %s for count update: %v", n.name, err)
|
|
| 1133 | 1133 |
continue |
| 1134 | 1134 |
} |
| 1135 | 1135 |
|
| 1136 | 1136 |
epCnt := n.getEpCnt().EndpointCnt() |
| 1137 | 1137 |
if epCnt != uint64(len(epl)) {
|
| 1138 |
- log.Infof("Fixing inconsistent endpoint_cnt for network %s. Expected=%d, Actual=%d", n.name, len(epl), epCnt)
|
|
| 1138 |
+ logrus.Infof("Fixing inconsistent endpoint_cnt for network %s. Expected=%d, Actual=%d", n.name, len(epl), epCnt)
|
|
| 1139 | 1139 |
n.getEpCnt().setCnt(uint64(len(epl))) |
| 1140 | 1140 |
} |
| 1141 | 1141 |
} |
| ... | ... |
@@ -205,31 +205,6 @@ func (ep *endpoint) Info() EndpointInfo {
|
| 205 | 205 |
return nil |
| 206 | 206 |
} |
| 207 | 207 |
|
| 208 |
-func (ep *endpoint) DriverInfo() (map[string]interface{}, error) {
|
|
| 209 |
- ep, err := ep.retrieveFromStore() |
|
| 210 |
- if err != nil {
|
|
| 211 |
- return nil, err |
|
| 212 |
- } |
|
| 213 |
- |
|
| 214 |
- if sb, ok := ep.getSandbox(); ok {
|
|
| 215 |
- if gwep := sb.getEndpointInGWNetwork(); gwep != nil && gwep.ID() != ep.ID() {
|
|
| 216 |
- return gwep.DriverInfo() |
|
| 217 |
- } |
|
| 218 |
- } |
|
| 219 |
- |
|
| 220 |
- n, err := ep.getNetworkFromStore() |
|
| 221 |
- if err != nil {
|
|
| 222 |
- return nil, fmt.Errorf("could not find network in store for driver info: %v", err)
|
|
| 223 |
- } |
|
| 224 |
- |
|
| 225 |
- driver, err := n.driver(true) |
|
| 226 |
- if err != nil {
|
|
| 227 |
- return nil, fmt.Errorf("failed to get driver info: %v", err)
|
|
| 228 |
- } |
|
| 229 |
- |
|
| 230 |
- return driver.EndpointOperInfo(n.ID(), ep.ID()) |
|
| 231 |
-} |
|
| 232 |
- |
|
| 233 | 208 |
func (ep *endpoint) Iface() InterfaceInfo {
|
| 234 | 209 |
ep.Lock() |
| 235 | 210 |
defer ep.Unlock() |
| 236 | 211 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,30 @@ |
| 0 |
+// +build !windows |
|
| 1 |
+ |
|
| 2 |
+package libnetwork |
|
| 3 |
+ |
|
| 4 |
+import "fmt" |
|
| 5 |
+ |
|
| 6 |
+func (ep *endpoint) DriverInfo() (map[string]interface{}, error) {
|
|
| 7 |
+ ep, err := ep.retrieveFromStore() |
|
| 8 |
+ if err != nil {
|
|
| 9 |
+ return nil, err |
|
| 10 |
+ } |
|
| 11 |
+ |
|
| 12 |
+ if sb, ok := ep.getSandbox(); ok {
|
|
| 13 |
+ if gwep := sb.getEndpointInGWNetwork(); gwep != nil && gwep.ID() != ep.ID() {
|
|
| 14 |
+ return gwep.DriverInfo() |
|
| 15 |
+ } |
|
| 16 |
+ } |
|
| 17 |
+ |
|
| 18 |
+ n, err := ep.getNetworkFromStore() |
|
| 19 |
+ if err != nil {
|
|
| 20 |
+ return nil, fmt.Errorf("could not find network in store for driver info: %v", err)
|
|
| 21 |
+ } |
|
| 22 |
+ |
|
| 23 |
+ driver, err := n.driver(true) |
|
| 24 |
+ if err != nil {
|
|
| 25 |
+ return nil, fmt.Errorf("failed to get driver info: %v", err)
|
|
| 26 |
+ } |
|
| 27 |
+ |
|
| 28 |
+ return driver.EndpointOperInfo(n.ID(), ep.ID()) |
|
| 29 |
+} |
| 0 | 30 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,45 @@ |
| 0 |
+// +build windows |
|
| 1 |
+ |
|
| 2 |
+package libnetwork |
|
| 3 |
+ |
|
| 4 |
+import "fmt" |
|
| 5 |
+ |
|
| 6 |
+func (ep *endpoint) DriverInfo() (map[string]interface{}, error) {
|
|
| 7 |
+ ep, err := ep.retrieveFromStore() |
|
| 8 |
+ if err != nil {
|
|
| 9 |
+ return nil, err |
|
| 10 |
+ } |
|
| 11 |
+ |
|
| 12 |
+ var gwDriverInfo map[string]interface{}
|
|
| 13 |
+ if sb, ok := ep.getSandbox(); ok {
|
|
| 14 |
+ if gwep := sb.getEndpointInGWNetwork(); gwep != nil && gwep.ID() != ep.ID() {
|
|
| 15 |
+ |
|
| 16 |
+ gwDriverInfo, err = gwep.DriverInfo() |
|
| 17 |
+ if err != nil {
|
|
| 18 |
+ return nil, err |
|
| 19 |
+ } |
|
| 20 |
+ } |
|
| 21 |
+ } |
|
| 22 |
+ |
|
| 23 |
+ n, err := ep.getNetworkFromStore() |
|
| 24 |
+ if err != nil {
|
|
| 25 |
+ return nil, fmt.Errorf("could not find network in store for driver info: %v", err)
|
|
| 26 |
+ } |
|
| 27 |
+ |
|
| 28 |
+ driver, err := n.driver(true) |
|
| 29 |
+ if err != nil {
|
|
| 30 |
+ return nil, fmt.Errorf("failed to get driver info: %v", err)
|
|
| 31 |
+ } |
|
| 32 |
+ |
|
| 33 |
+ epInfo, err := driver.EndpointOperInfo(n.ID(), ep.ID()) |
|
| 34 |
+ if err != nil {
|
|
| 35 |
+ return nil, err |
|
| 36 |
+ } |
|
| 37 |
+ |
|
| 38 |
+ if epInfo != nil {
|
|
| 39 |
+ epInfo["GW_INFO"] = gwDriverInfo |
|
| 40 |
+ return epInfo, nil |
|
| 41 |
+ } |
|
| 42 |
+ |
|
| 43 |
+ return gwDriverInfo, nil |
|
| 44 |
+} |
| ... | ... |
@@ -4,7 +4,7 @@ import ( |
| 4 | 4 |
"net" |
| 5 | 5 |
"sync" |
| 6 | 6 |
|
| 7 |
- log "github.com/Sirupsen/logrus" |
|
| 7 |
+ "github.com/Sirupsen/logrus" |
|
| 8 | 8 |
|
| 9 | 9 |
mapset "github.com/deckarep/golang-set" |
| 10 | 10 |
"github.com/docker/docker/pkg/discovery" |
| ... | ... |
@@ -54,7 +54,7 @@ func (h *hostDiscovery) monitorDiscovery(ch <-chan discovery.Entries, errCh <-ch |
| 54 | 54 |
h.processCallback(entries, activeCallback, joinCallback, leaveCallback) |
| 55 | 55 |
case err := <-errCh: |
| 56 | 56 |
if err != nil {
|
| 57 |
- log.Errorf("discovery error: %v", err)
|
|
| 57 |
+ logrus.Errorf("discovery error: %v", err)
|
|
| 58 | 58 |
} |
| 59 | 59 |
case <-h.stopChan: |
| 60 | 60 |
return |
| ... | ... |
@@ -54,6 +54,19 @@ func (i *Idm) GetSpecificID(id uint64) error {
|
| 54 | 54 |
return i.handle.Set(id - i.start) |
| 55 | 55 |
} |
| 56 | 56 |
|
| 57 |
+// GetIDInRange returns the first available id in the set within a range |
|
| 58 |
+func (i *Idm) GetIDInRange(start, end uint64) (uint64, error) {
|
|
| 59 |
+ if i.handle == nil {
|
|
| 60 |
+ return 0, fmt.Errorf("ID set is not initialized")
|
|
| 61 |
+ } |
|
| 62 |
+ |
|
| 63 |
+ if start < i.start || end > i.end {
|
|
| 64 |
+ return 0, fmt.Errorf("Requested range does not belong to the set")
|
|
| 65 |
+ } |
|
| 66 |
+ |
|
| 67 |
+ return i.handle.SetAnyInRange(start, end-start) |
|
| 68 |
+} |
|
| 69 |
+ |
|
| 57 | 70 |
// Release releases the specified id |
| 58 | 71 |
func (i *Idm) Release(id uint64) {
|
| 59 | 72 |
i.handle.Unset(id - i.start) |
| ... | ... |
@@ -6,7 +6,7 @@ import ( |
| 6 | 6 |
"sort" |
| 7 | 7 |
"sync" |
| 8 | 8 |
|
| 9 |
- log "github.com/Sirupsen/logrus" |
|
| 9 |
+ "github.com/Sirupsen/logrus" |
|
| 10 | 10 |
"github.com/docker/libnetwork/bitseq" |
| 11 | 11 |
"github.com/docker/libnetwork/datastore" |
| 12 | 12 |
"github.com/docker/libnetwork/discoverapi" |
| ... | ... |
@@ -135,7 +135,7 @@ func (a *Allocator) checkConsistency(as string) {
|
| 135 | 135 |
bm := a.addresses[sk] |
| 136 | 136 |
a.Unlock() |
| 137 | 137 |
if err := bm.CheckConsistency(); err != nil {
|
| 138 |
- log.Warnf("Error while running consistency check for %s: %v", sk, err)
|
|
| 138 |
+ logrus.Warnf("Error while running consistency check for %s: %v", sk, err)
|
|
| 139 | 139 |
} |
| 140 | 140 |
} |
| 141 | 141 |
} |
| ... | ... |
@@ -198,7 +198,7 @@ func (a *Allocator) GetDefaultAddressSpaces() (string, string, error) {
|
| 198 | 198 |
|
| 199 | 199 |
// RequestPool returns an address pool along with its unique id. |
| 200 | 200 |
func (a *Allocator) RequestPool(addressSpace, pool, subPool string, options map[string]string, v6 bool) (string, *net.IPNet, map[string]string, error) {
|
| 201 |
- log.Debugf("RequestPool(%s, %s, %s, %v, %t)", addressSpace, pool, subPool, options, v6)
|
|
| 201 |
+ logrus.Debugf("RequestPool(%s, %s, %s, %v, %t)", addressSpace, pool, subPool, options, v6)
|
|
| 202 | 202 |
|
| 203 | 203 |
k, nw, ipr, err := a.parsePoolRequest(addressSpace, pool, subPool, v6) |
| 204 | 204 |
if err != nil {
|
| ... | ... |
@@ -227,7 +227,7 @@ retry: |
| 227 | 227 |
insert, err := aSpace.updatePoolDBOnAdd(*k, nw, ipr, pdf) |
| 228 | 228 |
if err != nil {
|
| 229 | 229 |
if _, ok := err.(types.MaskableError); ok {
|
| 230 |
- log.Debugf("Retrying predefined pool search: %v", err)
|
|
| 230 |
+ logrus.Debugf("Retrying predefined pool search: %v", err)
|
|
| 231 | 231 |
goto retry |
| 232 | 232 |
} |
| 233 | 233 |
return "", nil, nil, err |
| ... | ... |
@@ -246,7 +246,7 @@ retry: |
| 246 | 246 |
|
| 247 | 247 |
// ReleasePool releases the address pool identified by the passed id |
| 248 | 248 |
func (a *Allocator) ReleasePool(poolID string) error {
|
| 249 |
- log.Debugf("ReleasePool(%s)", poolID)
|
|
| 249 |
+ logrus.Debugf("ReleasePool(%s)", poolID)
|
|
| 250 | 250 |
k := SubnetKey{}
|
| 251 | 251 |
if err := k.FromString(poolID); err != nil {
|
| 252 | 252 |
return types.BadRequestErrorf("invalid pool id: %s", poolID)
|
| ... | ... |
@@ -322,7 +322,7 @@ func (a *Allocator) parsePoolRequest(addressSpace, pool, subPool string, v6 bool |
| 322 | 322 |
} |
| 323 | 323 |
|
| 324 | 324 |
func (a *Allocator) insertBitMask(key SubnetKey, pool *net.IPNet) error {
|
| 325 |
- //log.Debugf("Inserting bitmask (%s, %s)", key.String(), pool.String())
|
|
| 325 |
+ //logrus.Debugf("Inserting bitmask (%s, %s)", key.String(), pool.String())
|
|
| 326 | 326 |
|
| 327 | 327 |
store := a.getStore(key.AddressSpace) |
| 328 | 328 |
ipVer := getAddressVersion(pool.IP) |
| ... | ... |
@@ -360,7 +360,7 @@ func (a *Allocator) retrieveBitmask(k SubnetKey, n *net.IPNet) (*bitseq.Handle, |
| 360 | 360 |
bm, ok := a.addresses[k] |
| 361 | 361 |
a.Unlock() |
| 362 | 362 |
if !ok {
|
| 363 |
- log.Debugf("Retrieving bitmask (%s, %s)", k.String(), n.String())
|
|
| 363 |
+ logrus.Debugf("Retrieving bitmask (%s, %s)", k.String(), n.String())
|
|
| 364 | 364 |
if err := a.insertBitMask(k, n); err != nil {
|
| 365 | 365 |
return nil, types.InternalErrorf("could not find bitmask in datastore for %s", k.String())
|
| 366 | 366 |
} |
| ... | ... |
@@ -418,7 +418,7 @@ func (a *Allocator) getPredefinedPool(as string, ipV6 bool) (*net.IPNet, error) |
| 418 | 418 |
|
| 419 | 419 |
// RequestAddress returns an address from the specified pool ID |
| 420 | 420 |
func (a *Allocator) RequestAddress(poolID string, prefAddress net.IP, opts map[string]string) (*net.IPNet, map[string]string, error) {
|
| 421 |
- log.Debugf("RequestAddress(%s, %v, %v)", poolID, prefAddress, opts)
|
|
| 421 |
+ logrus.Debugf("RequestAddress(%s, %v, %v)", poolID, prefAddress, opts)
|
|
| 422 | 422 |
k := SubnetKey{}
|
| 423 | 423 |
if err := k.FromString(poolID); err != nil {
|
| 424 | 424 |
return nil, nil, types.BadRequestErrorf("invalid pool id: %s", poolID)
|
| ... | ... |
@@ -467,7 +467,7 @@ func (a *Allocator) RequestAddress(poolID string, prefAddress net.IP, opts map[s |
| 467 | 467 |
|
| 468 | 468 |
// ReleaseAddress releases the address from the specified pool ID |
| 469 | 469 |
func (a *Allocator) ReleaseAddress(poolID string, address net.IP) error {
|
| 470 |
- log.Debugf("ReleaseAddress(%s, %v)", poolID, address)
|
|
| 470 |
+ logrus.Debugf("ReleaseAddress(%s, %v)", poolID, address)
|
|
| 471 | 471 |
k := SubnetKey{}
|
| 472 | 472 |
if err := k.FromString(poolID); err != nil {
|
| 473 | 473 |
return types.BadRequestErrorf("invalid pool id: %s", poolID)
|
| ... | ... |
@@ -3,7 +3,7 @@ package ipam |
| 3 | 3 |
import ( |
| 4 | 4 |
"encoding/json" |
| 5 | 5 |
|
| 6 |
- log "github.com/Sirupsen/logrus" |
|
| 6 |
+ "github.com/Sirupsen/logrus" |
|
| 7 | 7 |
"github.com/docker/libnetwork/datastore" |
| 8 | 8 |
"github.com/docker/libnetwork/types" |
| 9 | 9 |
) |
| ... | ... |
@@ -26,7 +26,7 @@ func (aSpace *addrSpace) KeyPrefix() []string {
|
| 26 | 26 |
func (aSpace *addrSpace) Value() []byte {
|
| 27 | 27 |
b, err := json.Marshal(aSpace) |
| 28 | 28 |
if err != nil {
|
| 29 |
- log.Warnf("Failed to marshal ipam configured pools: %v", err)
|
|
| 29 |
+ logrus.Warnf("Failed to marshal ipam configured pools: %v", err)
|
|
| 30 | 30 |
return nil |
| 31 | 31 |
} |
| 32 | 32 |
return b |
| ... | ... |
@@ -3,14 +3,55 @@ |
| 3 | 3 |
package builtin |
| 4 | 4 |
|
| 5 | 5 |
import ( |
| 6 |
+ "fmt" |
|
| 7 |
+ |
|
| 8 |
+ "github.com/docker/libnetwork/datastore" |
|
| 9 |
+ "github.com/docker/libnetwork/ipam" |
|
| 6 | 10 |
"github.com/docker/libnetwork/ipamapi" |
| 11 |
+ "github.com/docker/libnetwork/ipamutils" |
|
| 7 | 12 |
|
| 8 | 13 |
windowsipam "github.com/docker/libnetwork/ipams/windowsipam" |
| 9 | 14 |
) |
| 10 | 15 |
|
| 16 |
+// InitDockerDefault registers the built-in ipam service with libnetwork |
|
| 17 |
+func InitDockerDefault(ic ipamapi.Callback, l, g interface{}) error {
|
|
| 18 |
+ var ( |
|
| 19 |
+ ok bool |
|
| 20 |
+ localDs, globalDs datastore.DataStore |
|
| 21 |
+ ) |
|
| 22 |
+ |
|
| 23 |
+ if l != nil {
|
|
| 24 |
+ if localDs, ok = l.(datastore.DataStore); !ok {
|
|
| 25 |
+ return fmt.Errorf("incorrect local datastore passed to built-in ipam init")
|
|
| 26 |
+ } |
|
| 27 |
+ } |
|
| 28 |
+ |
|
| 29 |
+ if g != nil {
|
|
| 30 |
+ if globalDs, ok = g.(datastore.DataStore); !ok {
|
|
| 31 |
+ return fmt.Errorf("incorrect global datastore passed to built-in ipam init")
|
|
| 32 |
+ } |
|
| 33 |
+ } |
|
| 34 |
+ |
|
| 35 |
+ ipamutils.InitNetworks() |
|
| 36 |
+ |
|
| 37 |
+ a, err := ipam.NewAllocator(localDs, globalDs) |
|
| 38 |
+ if err != nil {
|
|
| 39 |
+ return err |
|
| 40 |
+ } |
|
| 41 |
+ |
|
| 42 |
+ cps := &ipamapi.Capability{RequiresRequestReplay: true}
|
|
| 43 |
+ |
|
| 44 |
+ return ic.RegisterIpamDriverWithCapabilities(ipamapi.DefaultIPAM, a, cps) |
|
| 45 |
+} |
|
| 46 |
+ |
|
| 11 | 47 |
// Init registers the built-in ipam service with libnetwork |
| 12 | 48 |
func Init(ic ipamapi.Callback, l, g interface{}) error {
|
| 13 |
- initFunc := windowsipam.GetInit(ipamapi.DefaultIPAM) |
|
| 49 |
+ initFunc := windowsipam.GetInit(windowsipam.DefaultIPAM) |
|
| 50 |
+ |
|
| 51 |
+ err := InitDockerDefault(ic, l, g) |
|
| 52 |
+ if err != nil {
|
|
| 53 |
+ return err |
|
| 54 |
+ } |
|
| 14 | 55 |
|
| 15 | 56 |
return initFunc(ic, l, g) |
| 16 | 57 |
} |
| ... | ... |
@@ -4,7 +4,7 @@ import ( |
| 4 | 4 |
"fmt" |
| 5 | 5 |
"net" |
| 6 | 6 |
|
| 7 |
- log "github.com/Sirupsen/logrus" |
|
| 7 |
+ "github.com/Sirupsen/logrus" |
|
| 8 | 8 |
"github.com/docker/docker/pkg/plugins" |
| 9 | 9 |
"github.com/docker/libnetwork/discoverapi" |
| 10 | 10 |
"github.com/docker/libnetwork/ipamapi" |
| ... | ... |
@@ -40,13 +40,13 @@ func Init(cb ipamapi.Callback, l, g interface{}) error {
|
| 40 | 40 |
a := newAllocator(name, client) |
| 41 | 41 |
if cps, err := a.(*allocator).getCapabilities(); err == nil {
|
| 42 | 42 |
if err := cb.RegisterIpamDriverWithCapabilities(name, a, cps); err != nil {
|
| 43 |
- log.Errorf("error registering remote ipam driver %s due to %v", name, err)
|
|
| 43 |
+ logrus.Errorf("error registering remote ipam driver %s due to %v", name, err)
|
|
| 44 | 44 |
} |
| 45 | 45 |
} else {
|
| 46 |
- log.Infof("remote ipam driver %s does not support capabilities", name)
|
|
| 47 |
- log.Debug(err) |
|
| 46 |
+ logrus.Infof("remote ipam driver %s does not support capabilities", name)
|
|
| 47 |
+ logrus.Debug(err) |
|
| 48 | 48 |
if err := cb.RegisterIpamDriver(name, a); err != nil {
|
| 49 |
- log.Errorf("error registering remote ipam driver %s due to %v", name, err)
|
|
| 49 |
+ logrus.Errorf("error registering remote ipam driver %s due to %v", name, err)
|
|
| 50 | 50 |
} |
| 51 | 51 |
} |
| 52 | 52 |
}) |
| ... | ... |
@@ -3,7 +3,7 @@ package windowsipam |
| 3 | 3 |
import ( |
| 4 | 4 |
"net" |
| 5 | 5 |
|
| 6 |
- log "github.com/Sirupsen/logrus" |
|
| 6 |
+ "github.com/Sirupsen/logrus" |
|
| 7 | 7 |
"github.com/docker/libnetwork/discoverapi" |
| 8 | 8 |
"github.com/docker/libnetwork/ipamapi" |
| 9 | 9 |
"github.com/docker/libnetwork/netlabel" |
| ... | ... |
@@ -15,6 +15,9 @@ const ( |
| 15 | 15 |
globalAddressSpace = "GlobalDefault" |
| 16 | 16 |
) |
| 17 | 17 |
|
| 18 |
+// DefaultIPAM defines the default ipam-driver for local-scoped windows networks |
|
| 19 |
+const DefaultIPAM = "windows" |
|
| 20 |
+ |
|
| 18 | 21 |
var ( |
| 19 | 22 |
defaultPool, _ = types.ParseCIDR("0.0.0.0/0")
|
| 20 | 23 |
) |
| ... | ... |
@@ -36,7 +39,7 @@ func (a *allocator) GetDefaultAddressSpaces() (string, string, error) {
|
| 36 | 36 |
// RequestPool returns an address pool along with its unique id. This is a null ipam driver. It allocates the |
| 37 | 37 |
// subnet user asked and does not validate anything. Doesn't support subpool allocation |
| 38 | 38 |
func (a *allocator) RequestPool(addressSpace, pool, subPool string, options map[string]string, v6 bool) (string, *net.IPNet, map[string]string, error) {
|
| 39 |
- log.Debugf("RequestPool(%s, %s, %s, %v, %t)", addressSpace, pool, subPool, options, v6)
|
|
| 39 |
+ logrus.Debugf("RequestPool(%s, %s, %s, %v, %t)", addressSpace, pool, subPool, options, v6)
|
|
| 40 | 40 |
if subPool != "" || v6 {
|
| 41 | 41 |
return "", nil, nil, types.InternalErrorf("This request is not supported by null ipam driver")
|
| 42 | 42 |
} |
| ... | ... |
@@ -58,14 +61,14 @@ func (a *allocator) RequestPool(addressSpace, pool, subPool string, options map[ |
| 58 | 58 |
|
| 59 | 59 |
// ReleasePool releases the address pool - always succeeds |
| 60 | 60 |
func (a *allocator) ReleasePool(poolID string) error {
|
| 61 |
- log.Debugf("ReleasePool(%s)", poolID)
|
|
| 61 |
+ logrus.Debugf("ReleasePool(%s)", poolID)
|
|
| 62 | 62 |
return nil |
| 63 | 63 |
} |
| 64 | 64 |
|
| 65 | 65 |
// RequestAddress returns an address from the specified pool ID. |
| 66 | 66 |
// Always allocate the 0.0.0.0/32 ip if no preferred address was specified |
| 67 | 67 |
func (a *allocator) RequestAddress(poolID string, prefAddress net.IP, opts map[string]string) (*net.IPNet, map[string]string, error) {
|
| 68 |
- log.Debugf("RequestAddress(%s, %v, %v)", poolID, prefAddress, opts)
|
|
| 68 |
+ logrus.Debugf("RequestAddress(%s, %v, %v)", poolID, prefAddress, opts)
|
|
| 69 | 69 |
_, ipNet, err := net.ParseCIDR(poolID) |
| 70 | 70 |
|
| 71 | 71 |
if err != nil {
|
| ... | ... |
@@ -85,7 +88,7 @@ func (a *allocator) RequestAddress(poolID string, prefAddress net.IP, opts map[s |
| 85 | 85 |
|
| 86 | 86 |
// ReleaseAddress releases the address - always succeeds |
| 87 | 87 |
func (a *allocator) ReleaseAddress(poolID string, address net.IP) error {
|
| 88 |
- log.Debugf("ReleaseAddress(%s, %v)", poolID, address)
|
|
| 88 |
+ logrus.Debugf("ReleaseAddress(%s, %v)", poolID, address)
|
|
| 89 | 89 |
return nil |
| 90 | 90 |
} |
| 91 | 91 |
|
| ... | ... |
@@ -64,7 +64,7 @@ func setup() {
|
| 64 | 64 |
|
| 65 | 65 |
ipvsFamily, err = getIPVSFamily() |
| 66 | 66 |
if err != nil {
|
| 67 |
- logrus.Errorf("Could not get ipvs family information from the kernel. It is possible that ipvs is not enabled in your kernel. Native loadbalancing will not work until this is fixed.")
|
|
| 67 |
+ logrus.Error("Could not get ipvs family information from the kernel. It is possible that ipvs is not enabled in your kernel. Native loadbalancing will not work until this is fixed.")
|
|
| 68 | 68 |
} |
| 69 | 69 |
}) |
| 70 | 70 |
} |
| ... | ... |
@@ -18,6 +18,8 @@ func ElectInterfaceAddresses(name string) ([]*net.IPNet, []*net.IPNet, error) {
|
| 18 | 18 |
|
| 19 | 19 |
// FindAvailableNetwork returns a network from the passed list which does not |
| 20 | 20 |
// overlap with existing interfaces in the system |
| 21 |
+ |
|
| 22 |
+// TODO : Use appropriate windows APIs to identify non-overlapping subnets |
|
| 21 | 23 |
func FindAvailableNetwork(list []*net.IPNet) (*net.IPNet, error) {
|
| 22 |
- return nil, types.NotImplementedErrorf("not supported on windows")
|
|
| 24 |
+ return nil, nil |
|
| 23 | 25 |
} |
| ... | ... |
@@ -8,7 +8,7 @@ import ( |
| 8 | 8 |
"sync" |
| 9 | 9 |
"time" |
| 10 | 10 |
|
| 11 |
- log "github.com/Sirupsen/logrus" |
|
| 11 |
+ "github.com/Sirupsen/logrus" |
|
| 12 | 12 |
"github.com/docker/docker/pkg/stringid" |
| 13 | 13 |
"github.com/docker/libnetwork/config" |
| 14 | 14 |
"github.com/docker/libnetwork/datastore" |
| ... | ... |
@@ -473,7 +473,7 @@ func (n *network) UnmarshalJSON(b []byte) (err error) {
|
| 473 | 473 |
if v, ok := netMap["created"]; ok {
|
| 474 | 474 |
// n.created is time.Time but marshalled as string |
| 475 | 475 |
if err = n.created.UnmarshalText([]byte(v.(string))); err != nil {
|
| 476 |
- log.Warnf("failed to unmarshal creation time %v: %v", v, err)
|
|
| 476 |
+ logrus.Warnf("failed to unmarshal creation time %v: %v", v, err)
|
|
| 477 | 477 |
n.created = time.Time{}
|
| 478 | 478 |
} |
| 479 | 479 |
} |
| ... | ... |
@@ -633,6 +633,9 @@ func NetworkOptionIpam(ipamDriver string, addrSpace string, ipV4 []*IpamConf, ip |
| 633 | 633 |
return func(n *network) {
|
| 634 | 634 |
if ipamDriver != "" {
|
| 635 | 635 |
n.ipamType = ipamDriver |
| 636 |
+ if ipamDriver == ipamapi.DefaultIPAM {
|
|
| 637 |
+ n.ipamType = defaultIpamForNetworkType(n.Type()) |
|
| 638 |
+ } |
|
| 636 | 639 |
} |
| 637 | 640 |
n.ipamOptions = opts |
| 638 | 641 |
n.addrSpace = addrSpace |
| ... | ... |
@@ -776,12 +779,12 @@ func (n *network) delete(force bool) error {
|
| 776 | 776 |
if !force {
|
| 777 | 777 |
return err |
| 778 | 778 |
} |
| 779 |
- log.Debugf("driver failed to delete stale network %s (%s): %v", n.Name(), n.ID(), err)
|
|
| 779 |
+ logrus.Debugf("driver failed to delete stale network %s (%s): %v", n.Name(), n.ID(), err)
|
|
| 780 | 780 |
} |
| 781 | 781 |
|
| 782 | 782 |
n.ipamRelease() |
| 783 | 783 |
if err = c.updateToStore(n); err != nil {
|
| 784 |
- log.Warnf("Failed to update store after ipam release for network %s (%s): %v", n.Name(), n.ID(), err)
|
|
| 784 |
+ logrus.Warnf("Failed to update store after ipam release for network %s (%s): %v", n.Name(), n.ID(), err)
|
|
| 785 | 785 |
} |
| 786 | 786 |
|
| 787 | 787 |
// We are about to delete the network. Leave the gossip |
| ... | ... |
@@ -792,7 +795,7 @@ func (n *network) delete(force bool) error {
|
| 792 | 792 |
// bindings cleanup requires the network in the store. |
| 793 | 793 |
n.cancelDriverWatches() |
| 794 | 794 |
if err = n.leaveCluster(); err != nil {
|
| 795 |
- log.Errorf("Failed leaving network %s from the agent cluster: %v", n.Name(), err)
|
|
| 795 |
+ logrus.Errorf("Failed leaving network %s from the agent cluster: %v", n.Name(), err)
|
|
| 796 | 796 |
} |
| 797 | 797 |
|
| 798 | 798 |
c.cleanupServiceBindings(n.ID()) |
| ... | ... |
@@ -804,7 +807,7 @@ func (n *network) delete(force bool) error {
|
| 804 | 804 |
if !force {
|
| 805 | 805 |
return fmt.Errorf("error deleting network endpoint count from store: %v", err)
|
| 806 | 806 |
} |
| 807 |
- log.Debugf("Error deleting endpoint count from store for stale network %s (%s) for deletion: %v", n.Name(), n.ID(), err)
|
|
| 807 |
+ logrus.Debugf("Error deleting endpoint count from store for stale network %s (%s) for deletion: %v", n.Name(), n.ID(), err)
|
|
| 808 | 808 |
} |
| 809 | 809 |
|
| 810 | 810 |
if err = c.deleteFromStore(n); err != nil {
|
| ... | ... |
@@ -827,7 +830,7 @@ func (n *network) deleteNetwork() error {
|
| 827 | 827 |
} |
| 828 | 828 |
|
| 829 | 829 |
if _, ok := err.(types.MaskableError); !ok {
|
| 830 |
- log.Warnf("driver error deleting network %s : %v", n.name, err)
|
|
| 830 |
+ logrus.Warnf("driver error deleting network %s : %v", n.name, err)
|
|
| 831 | 831 |
} |
| 832 | 832 |
} |
| 833 | 833 |
|
| ... | ... |
@@ -920,7 +923,7 @@ func (n *network) CreateEndpoint(name string, options ...EndpointOption) (Endpoi |
| 920 | 920 |
defer func() {
|
| 921 | 921 |
if err != nil {
|
| 922 | 922 |
if e := ep.deleteEndpoint(false); e != nil {
|
| 923 |
- log.Warnf("cleaning up endpoint failed %s : %v", name, e)
|
|
| 923 |
+ logrus.Warnf("cleaning up endpoint failed %s : %v", name, e)
|
|
| 924 | 924 |
} |
| 925 | 925 |
} |
| 926 | 926 |
}() |
| ... | ... |
@@ -935,7 +938,7 @@ func (n *network) CreateEndpoint(name string, options ...EndpointOption) (Endpoi |
| 935 | 935 |
defer func() {
|
| 936 | 936 |
if err != nil {
|
| 937 | 937 |
if e := n.getController().deleteFromStore(ep); e != nil {
|
| 938 |
- log.Warnf("error rolling back endpoint %s from store: %v", name, e)
|
|
| 938 |
+ logrus.Warnf("error rolling back endpoint %s from store: %v", name, e)
|
|
| 939 | 939 |
} |
| 940 | 940 |
} |
| 941 | 941 |
}() |
| ... | ... |
@@ -961,7 +964,7 @@ func (n *network) Endpoints() []Endpoint {
|
| 961 | 961 |
|
| 962 | 962 |
endpoints, err := n.getEndpointsFromStore() |
| 963 | 963 |
if err != nil {
|
| 964 |
- log.Error(err) |
|
| 964 |
+ logrus.Error(err) |
|
| 965 | 965 |
} |
| 966 | 966 |
|
| 967 | 967 |
for _, ep := range endpoints {
|
| ... | ... |
@@ -1169,7 +1172,7 @@ func (n *network) getSvcRecords(ep *endpoint) []etchosts.Record {
|
| 1169 | 1169 |
continue |
| 1170 | 1170 |
} |
| 1171 | 1171 |
if len(ip) == 0 {
|
| 1172 |
- log.Warnf("Found empty list of IP addresses for service %s on network %s (%s)", h, n.name, n.id)
|
|
| 1172 |
+ logrus.Warnf("Found empty list of IP addresses for service %s on network %s (%s)", h, n.name, n.id)
|
|
| 1173 | 1173 |
continue |
| 1174 | 1174 |
} |
| 1175 | 1175 |
recs = append(recs, etchosts.Record{
|
| ... | ... |
@@ -1253,7 +1256,7 @@ func (n *network) requestPoolHelper(ipam ipamapi.Ipam, addressSpace, preferredPo |
| 1253 | 1253 |
// pools. |
| 1254 | 1254 |
defer func() {
|
| 1255 | 1255 |
if err := ipam.ReleasePool(poolID); err != nil {
|
| 1256 |
- log.Warnf("Failed to release overlapping pool %s while returning from pool request helper for network %s", pool, n.Name())
|
|
| 1256 |
+ logrus.Warnf("Failed to release overlapping pool %s while returning from pool request helper for network %s", pool, n.Name())
|
|
| 1257 | 1257 |
} |
| 1258 | 1258 |
}() |
| 1259 | 1259 |
|
| ... | ... |
@@ -1294,7 +1297,7 @@ func (n *network) ipamAllocateVersion(ipVer int, ipam ipamapi.Ipam) error {
|
| 1294 | 1294 |
|
| 1295 | 1295 |
*infoList = make([]*IpamInfo, len(*cfgList)) |
| 1296 | 1296 |
|
| 1297 |
- log.Debugf("Allocating IPv%d pools for network %s (%s)", ipVer, n.Name(), n.ID())
|
|
| 1297 |
+ logrus.Debugf("Allocating IPv%d pools for network %s (%s)", ipVer, n.Name(), n.ID())
|
|
| 1298 | 1298 |
|
| 1299 | 1299 |
for i, cfg := range *cfgList {
|
| 1300 | 1300 |
if err = cfg.Validate(); err != nil {
|
| ... | ... |
@@ -1312,7 +1315,7 @@ func (n *network) ipamAllocateVersion(ipVer int, ipam ipamapi.Ipam) error {
|
| 1312 | 1312 |
defer func() {
|
| 1313 | 1313 |
if err != nil {
|
| 1314 | 1314 |
if err := ipam.ReleasePool(d.PoolID); err != nil {
|
| 1315 |
- log.Warnf("Failed to release address pool %s after failure to create network %s (%s)", d.PoolID, n.Name(), n.ID())
|
|
| 1315 |
+ logrus.Warnf("Failed to release address pool %s after failure to create network %s (%s)", d.PoolID, n.Name(), n.ID())
|
|
| 1316 | 1316 |
} |
| 1317 | 1317 |
} |
| 1318 | 1318 |
}() |
| ... | ... |
@@ -1364,7 +1367,7 @@ func (n *network) ipamRelease() {
|
| 1364 | 1364 |
} |
| 1365 | 1365 |
ipam, _, err := n.getController().getIPAMDriver(n.ipamType) |
| 1366 | 1366 |
if err != nil {
|
| 1367 |
- log.Warnf("Failed to retrieve ipam driver to release address pool(s) on delete of network %s (%s): %v", n.Name(), n.ID(), err)
|
|
| 1367 |
+ logrus.Warnf("Failed to retrieve ipam driver to release address pool(s) on delete of network %s (%s): %v", n.Name(), n.ID(), err)
|
|
| 1368 | 1368 |
return |
| 1369 | 1369 |
} |
| 1370 | 1370 |
n.ipamReleaseVersion(4, ipam) |
| ... | ... |
@@ -1380,7 +1383,7 @@ func (n *network) ipamReleaseVersion(ipVer int, ipam ipamapi.Ipam) {
|
| 1380 | 1380 |
case 6: |
| 1381 | 1381 |
infoList = &n.ipamV6Info |
| 1382 | 1382 |
default: |
| 1383 |
- log.Warnf("incorrect ip version passed to ipam release: %d", ipVer)
|
|
| 1383 |
+ logrus.Warnf("incorrect ip version passed to ipam release: %d", ipVer)
|
|
| 1384 | 1384 |
return |
| 1385 | 1385 |
} |
| 1386 | 1386 |
|
| ... | ... |
@@ -1388,25 +1391,25 @@ func (n *network) ipamReleaseVersion(ipVer int, ipam ipamapi.Ipam) {
|
| 1388 | 1388 |
return |
| 1389 | 1389 |
} |
| 1390 | 1390 |
|
| 1391 |
- log.Debugf("releasing IPv%d pools from network %s (%s)", ipVer, n.Name(), n.ID())
|
|
| 1391 |
+ logrus.Debugf("releasing IPv%d pools from network %s (%s)", ipVer, n.Name(), n.ID())
|
|
| 1392 | 1392 |
|
| 1393 | 1393 |
for _, d := range *infoList {
|
| 1394 | 1394 |
if d.Gateway != nil {
|
| 1395 | 1395 |
if err := ipam.ReleaseAddress(d.PoolID, d.Gateway.IP); err != nil {
|
| 1396 |
- log.Warnf("Failed to release gateway ip address %s on delete of network %s (%s): %v", d.Gateway.IP, n.Name(), n.ID(), err)
|
|
| 1396 |
+ logrus.Warnf("Failed to release gateway ip address %s on delete of network %s (%s): %v", d.Gateway.IP, n.Name(), n.ID(), err)
|
|
| 1397 | 1397 |
} |
| 1398 | 1398 |
} |
| 1399 | 1399 |
if d.IPAMData.AuxAddresses != nil {
|
| 1400 | 1400 |
for k, nw := range d.IPAMData.AuxAddresses {
|
| 1401 | 1401 |
if d.Pool.Contains(nw.IP) {
|
| 1402 | 1402 |
if err := ipam.ReleaseAddress(d.PoolID, nw.IP); err != nil && err != ipamapi.ErrIPOutOfRange {
|
| 1403 |
- log.Warnf("Failed to release secondary ip address %s (%v) on delete of network %s (%s): %v", k, nw.IP, n.Name(), n.ID(), err)
|
|
| 1403 |
+ logrus.Warnf("Failed to release secondary ip address %s (%v) on delete of network %s (%s): %v", k, nw.IP, n.Name(), n.ID(), err)
|
|
| 1404 | 1404 |
} |
| 1405 | 1405 |
} |
| 1406 | 1406 |
} |
| 1407 | 1407 |
} |
| 1408 | 1408 |
if err := ipam.ReleasePool(d.PoolID); err != nil {
|
| 1409 |
- log.Warnf("Failed to release address pool %s on delete of network %s (%s): %v", d.PoolID, n.Name(), n.ID(), err)
|
|
| 1409 |
+ logrus.Warnf("Failed to release address pool %s on delete of network %s (%s): %v", d.PoolID, n.Name(), n.ID(), err)
|
|
| 1410 | 1410 |
} |
| 1411 | 1411 |
} |
| 1412 | 1412 |
|
| ... | ... |
@@ -1658,7 +1661,7 @@ func (n *network) ResolveService(name string) ([]*net.SRV, []net.IP) {
|
| 1658 | 1658 |
srv := []*net.SRV{}
|
| 1659 | 1659 |
ip := []net.IP{}
|
| 1660 | 1660 |
|
| 1661 |
- log.Debugf("Service name To resolve: %v", name)
|
|
| 1661 |
+ logrus.Debugf("Service name To resolve: %v", name)
|
|
| 1662 | 1662 |
|
| 1663 | 1663 |
// There are DNS implementaions that allow SRV queries for names not in |
| 1664 | 1664 |
// the format defined by RFC 2782. Hence specific validations checks are |
| ... | ... |
@@ -2,7 +2,13 @@ |
| 2 | 2 |
|
| 3 | 3 |
package libnetwork |
| 4 | 4 |
|
| 5 |
+import "github.com/docker/libnetwork/ipamapi" |
|
| 6 |
+ |
|
| 5 | 7 |
// Stub implementations for DNS related functions |
| 6 | 8 |
|
| 7 | 9 |
func (n *network) startResolver() {
|
| 8 | 10 |
} |
| 11 |
+ |
|
| 12 |
+func defaultIpamForNetworkType(networkType string) string {
|
|
| 13 |
+ return ipamapi.DefaultIPAM |
|
| 14 |
+} |
| ... | ... |
@@ -4,17 +4,20 @@ package libnetwork |
| 4 | 4 |
|
| 5 | 5 |
import ( |
| 6 | 6 |
"runtime" |
| 7 |
+ "time" |
|
| 7 | 8 |
|
| 8 | 9 |
"github.com/Microsoft/hcsshim" |
| 9 |
- log "github.com/Sirupsen/logrus" |
|
| 10 |
+ "github.com/Sirupsen/logrus" |
|
| 10 | 11 |
"github.com/docker/libnetwork/drivers/windows" |
| 12 |
+ "github.com/docker/libnetwork/ipamapi" |
|
| 13 |
+ "github.com/docker/libnetwork/ipams/windowsipam" |
|
| 11 | 14 |
) |
| 12 | 15 |
|
| 13 | 16 |
func executeInCompartment(compartmentID uint32, x func()) {
|
| 14 | 17 |
runtime.LockOSThread() |
| 15 | 18 |
|
| 16 | 19 |
if err := hcsshim.SetCurrentThreadCompartmentId(compartmentID); err != nil {
|
| 17 |
- log.Error(err) |
|
| 20 |
+ logrus.Error(err) |
|
| 18 | 21 |
} |
| 19 | 22 |
defer func() {
|
| 20 | 23 |
hcsshim.SetCurrentThreadCompartmentId(0) |
| ... | ... |
@@ -26,7 +29,7 @@ func executeInCompartment(compartmentID uint32, x func()) {
|
| 26 | 26 |
|
| 27 | 27 |
func (n *network) startResolver() {
|
| 28 | 28 |
n.resolverOnce.Do(func() {
|
| 29 |
- log.Debugf("Launching DNS server for network", n.Name())
|
|
| 29 |
+ logrus.Debugf("Launching DNS server for network", n.Name())
|
|
| 30 | 30 |
options := n.Info().DriverOptions() |
| 31 | 31 |
hnsid := options[windows.HNSID] |
| 32 | 32 |
|
| ... | ... |
@@ -36,21 +39,34 @@ func (n *network) startResolver() {
|
| 36 | 36 |
|
| 37 | 37 |
hnsresponse, err := hcsshim.HNSNetworkRequest("GET", hnsid, "")
|
| 38 | 38 |
if err != nil {
|
| 39 |
- log.Errorf("Resolver Setup/Start failed for container %s, %q", n.Name(), err)
|
|
| 39 |
+ logrus.Errorf("Resolver Setup/Start failed for container %s, %q", n.Name(), err)
|
|
| 40 | 40 |
return |
| 41 | 41 |
} |
| 42 | 42 |
|
| 43 | 43 |
for _, subnet := range hnsresponse.Subnets {
|
| 44 | 44 |
if subnet.GatewayAddress != "" {
|
| 45 |
- resolver := NewResolver(subnet.GatewayAddress, false, "", n) |
|
| 46 |
- log.Debugf("Binding a resolver on network %s gateway %s", n.Name(), subnet.GatewayAddress)
|
|
| 47 |
- executeInCompartment(hnsresponse.DNSServerCompartment, resolver.SetupFunc(53)) |
|
| 48 |
- if err = resolver.Start(); err != nil {
|
|
| 49 |
- log.Errorf("Resolver Setup/Start failed for container %s, %q", n.Name(), err)
|
|
| 50 |
- } else {
|
|
| 51 |
- n.resolver = append(n.resolver, resolver) |
|
| 45 |
+ for i := 0; i < 3; i++ {
|
|
| 46 |
+ resolver := NewResolver(subnet.GatewayAddress, false, "", n) |
|
| 47 |
+ logrus.Debugf("Binding a resolver on network %s gateway %s", n.Name(), subnet.GatewayAddress)
|
|
| 48 |
+ executeInCompartment(hnsresponse.DNSServerCompartment, resolver.SetupFunc(53)) |
|
| 49 |
+ |
|
| 50 |
+ if err = resolver.Start(); err != nil {
|
|
| 51 |
+ logrus.Errorf("Resolver Setup/Start failed for container %s, %q", n.Name(), err)
|
|
| 52 |
+ time.Sleep(1 * time.Second) |
|
| 53 |
+ } else {
|
|
| 54 |
+ logrus.Debugf("Resolver bound successfuly for network %s", n.Name())
|
|
| 55 |
+ n.resolver = append(n.resolver, resolver) |
|
| 56 |
+ break |
|
| 57 |
+ } |
|
| 52 | 58 |
} |
| 53 | 59 |
} |
| 54 | 60 |
} |
| 55 | 61 |
}) |
| 56 | 62 |
} |
| 63 |
+ |
|
| 64 |
+func defaultIpamForNetworkType(networkType string) string {
|
|
| 65 |
+ if windows.IsBuiltinLocalDriver(networkType) {
|
|
| 66 |
+ return windowsipam.DefaultIPAM |
|
| 67 |
+ } |
|
| 68 |
+ return ipamapi.DefaultIPAM |
|
| 69 |
+} |
| ... | ... |
@@ -139,7 +139,6 @@ func (nDB *NetworkDB) clusterInit() error {
|
| 139 | 139 |
|
| 140 | 140 |
nDB.stopCh = make(chan struct{})
|
| 141 | 141 |
nDB.memberlist = mlist |
| 142 |
- nDB.mConfig = config |
|
| 143 | 142 |
|
| 144 | 143 |
for _, trigger := range []struct {
|
| 145 | 144 |
interval time.Duration |
| ... | ... |
@@ -242,7 +241,7 @@ func (nDB *NetworkDB) reapDeadNode() {
|
| 242 | 242 |
defer nDB.Unlock() |
| 243 | 243 |
for id, n := range nDB.failedNodes {
|
| 244 | 244 |
if n.reapTime > 0 {
|
| 245 |
- n.reapTime -= reapPeriod |
|
| 245 |
+ n.reapTime -= nodeReapPeriod |
|
| 246 | 246 |
continue |
| 247 | 247 |
} |
| 248 | 248 |
logrus.Debugf("Removing failed node %v from gossip cluster", n.Name)
|
| ... | ... |
@@ -29,10 +29,6 @@ type NetworkDB struct {
|
| 29 | 29 |
// NetworkDB configuration. |
| 30 | 30 |
config *Config |
| 31 | 31 |
|
| 32 |
- // local copy of memberlist config that we use to driver |
|
| 33 |
- // network scoped gossip and bulk sync. |
|
| 34 |
- mConfig *memberlist.Config |
|
| 35 |
- |
|
| 36 | 32 |
// All the tree index (byTable, byNetwork) that we maintain |
| 37 | 33 |
// the db. |
| 38 | 34 |
indexes map[int]*radix.Tree |
| ... | ... |
@@ -57,7 +53,6 @@ type NetworkDB struct {
|
| 57 | 57 |
|
| 58 | 58 |
// A map of nodes which are participating in a given |
| 59 | 59 |
// network. The key is a network ID. |
| 60 |
- |
|
| 61 | 60 |
networkNodes map[string][]string |
| 62 | 61 |
|
| 63 | 62 |
// A table of ack channels for every node from which we are |
| ... | ... |
@@ -8,7 +8,7 @@ import ( |
| 8 | 8 |
"sync" |
| 9 | 9 |
"syscall" |
| 10 | 10 |
|
| 11 |
- log "github.com/Sirupsen/logrus" |
|
| 11 |
+ "github.com/Sirupsen/logrus" |
|
| 12 | 12 |
"github.com/vishvananda/netlink" |
| 13 | 13 |
"github.com/vishvananda/netns" |
| 14 | 14 |
) |
| ... | ... |
@@ -24,11 +24,11 @@ func Init() {
|
| 24 | 24 |
var err error |
| 25 | 25 |
initNs, err = netns.Get() |
| 26 | 26 |
if err != nil {
|
| 27 |
- log.Errorf("could not get initial namespace: %v", err)
|
|
| 27 |
+ logrus.Errorf("could not get initial namespace: %v", err)
|
|
| 28 | 28 |
} |
| 29 | 29 |
initNl, err = netlink.NewHandle(getSupportedNlFamilies()...) |
| 30 | 30 |
if err != nil {
|
| 31 |
- log.Errorf("could not create netlink handle on initial namespace: %v", err)
|
|
| 31 |
+ logrus.Errorf("could not create netlink handle on initial namespace: %v", err)
|
|
| 32 | 32 |
} |
| 33 | 33 |
} |
| 34 | 34 |
|
| ... | ... |
@@ -70,7 +70,7 @@ func getSupportedNlFamilies() []int {
|
| 70 | 70 |
fams := []int{syscall.NETLINK_ROUTE}
|
| 71 | 71 |
if err := loadXfrmModules(); err != nil {
|
| 72 | 72 |
if checkXfrmSocket() != nil {
|
| 73 |
- log.Warnf("Could not load necessary modules for IPSEC rules: %v", err)
|
|
| 73 |
+ logrus.Warnf("Could not load necessary modules for IPSEC rules: %v", err)
|
|
| 74 | 74 |
return fams |
| 75 | 75 |
} |
| 76 | 76 |
} |
| ... | ... |
@@ -8,7 +8,7 @@ import ( |
| 8 | 8 |
"syscall" |
| 9 | 9 |
"time" |
| 10 | 10 |
|
| 11 |
- log "github.com/Sirupsen/logrus" |
|
| 11 |
+ "github.com/Sirupsen/logrus" |
|
| 12 | 12 |
"github.com/docker/libnetwork/ns" |
| 13 | 13 |
"github.com/docker/libnetwork/types" |
| 14 | 14 |
"github.com/vishvananda/netlink" |
| ... | ... |
@@ -167,7 +167,7 @@ func (i *nwIface) Remove() error {
|
| 167 | 167 |
|
| 168 | 168 |
err = nlh.LinkSetName(iface, i.SrcName()) |
| 169 | 169 |
if err != nil {
|
| 170 |
- log.Debugf("LinkSetName failed for interface %s: %v", i.SrcName(), err)
|
|
| 170 |
+ logrus.Debugf("LinkSetName failed for interface %s: %v", i.SrcName(), err)
|
|
| 171 | 171 |
return err |
| 172 | 172 |
} |
| 173 | 173 |
|
| ... | ... |
@@ -179,7 +179,7 @@ func (i *nwIface) Remove() error {
|
| 179 | 179 |
} else if !isDefault {
|
| 180 | 180 |
// Move the network interface to caller namespace. |
| 181 | 181 |
if err := nlh.LinkSetNsFd(iface, ns.ParseHandlerInt()); err != nil {
|
| 182 |
- log.Debugf("LinkSetNsPid failed for interface %s: %v", i.SrcName(), err)
|
|
| 182 |
+ logrus.Debugf("LinkSetNsPid failed for interface %s: %v", i.SrcName(), err)
|
|
| 183 | 183 |
return err |
| 184 | 184 |
} |
| 185 | 185 |
} |
| ... | ... |
@@ -315,7 +315,7 @@ func (n *networkNamespace) AddInterface(srcName, dstPrefix string, options ...If |
| 315 | 315 |
// Up the interface. |
| 316 | 316 |
cnt := 0 |
| 317 | 317 |
for err = nlh.LinkSetUp(iface); err != nil && cnt < 3; cnt++ {
|
| 318 |
- log.Debugf("retrying link setup because of: %v", err)
|
|
| 318 |
+ logrus.Debugf("retrying link setup because of: %v", err)
|
|
| 319 | 319 |
time.Sleep(10 * time.Millisecond) |
| 320 | 320 |
err = nlh.LinkSetUp(iface) |
| 321 | 321 |
} |
| ... | ... |
@@ -377,7 +377,9 @@ func setInterfaceIP(nlh *netlink.Handle, iface netlink.Link, i *nwIface) error {
|
| 377 | 377 |
if i.Address() == nil {
|
| 378 | 378 |
return nil |
| 379 | 379 |
} |
| 380 |
- |
|
| 380 |
+ if err := checkRouteConflict(nlh, i.Address(), netlink.FAMILY_V4); err != nil {
|
|
| 381 |
+ return err |
|
| 382 |
+ } |
|
| 381 | 383 |
ipAddr := &netlink.Addr{IPNet: i.Address(), Label: ""}
|
| 382 | 384 |
return nlh.AddrAdd(iface, ipAddr) |
| 383 | 385 |
} |
| ... | ... |
@@ -386,6 +388,9 @@ func setInterfaceIPv6(nlh *netlink.Handle, iface netlink.Link, i *nwIface) error |
| 386 | 386 |
if i.AddressIPv6() == nil {
|
| 387 | 387 |
return nil |
| 388 | 388 |
} |
| 389 |
+ if err := checkRouteConflict(nlh, i.AddressIPv6(), netlink.FAMILY_V6); err != nil {
|
|
| 390 |
+ return err |
|
| 391 |
+ } |
|
| 389 | 392 |
ipAddr := &netlink.Addr{IPNet: i.AddressIPv6(), Label: "", Flags: syscall.IFA_F_NODAD}
|
| 390 | 393 |
return nlh.AddrAdd(iface, ipAddr) |
| 391 | 394 |
} |
| ... | ... |
@@ -442,3 +447,19 @@ func scanInterfaceStats(data, ifName string, i *types.InterfaceStatistics) error |
| 442 | 442 |
|
| 443 | 443 |
return err |
| 444 | 444 |
} |
| 445 |
+ |
|
| 446 |
+func checkRouteConflict(nlh *netlink.Handle, address *net.IPNet, family int) error {
|
|
| 447 |
+ routes, err := nlh.RouteList(nil, family) |
|
| 448 |
+ if err != nil {
|
|
| 449 |
+ return err |
|
| 450 |
+ } |
|
| 451 |
+ for _, route := range routes {
|
|
| 452 |
+ if route.Dst != nil {
|
|
| 453 |
+ if route.Dst.Contains(address.IP) || address.Contains(route.Dst.IP) {
|
|
| 454 |
+ return fmt.Errorf("cannot program address %v in sandbox interface because it conflicts with existing route %s",
|
|
| 455 |
+ address, route) |
|
| 456 |
+ } |
|
| 457 |
+ } |
|
| 458 |
+ } |
|
| 459 |
+ return nil |
|
| 460 |
+} |
| ... | ... |
@@ -14,7 +14,7 @@ import ( |
| 14 | 14 |
"syscall" |
| 15 | 15 |
"time" |
| 16 | 16 |
|
| 17 |
- log "github.com/Sirupsen/logrus" |
|
| 17 |
+ "github.com/Sirupsen/logrus" |
|
| 18 | 18 |
"github.com/docker/docker/pkg/reexec" |
| 19 | 19 |
"github.com/docker/libnetwork/ns" |
| 20 | 20 |
"github.com/docker/libnetwork/types" |
| ... | ... |
@@ -263,10 +263,10 @@ func GetSandboxForExternalKey(basePath string, key string) (Sandbox, error) {
|
| 263 | 263 |
|
| 264 | 264 |
func reexecCreateNamespace() {
|
| 265 | 265 |
if len(os.Args) < 2 {
|
| 266 |
- log.Fatal("no namespace path provided")
|
|
| 266 |
+ logrus.Fatal("no namespace path provided")
|
|
| 267 | 267 |
} |
| 268 | 268 |
if err := mountNetworkNamespace("/proc/self/ns/net", os.Args[1]); err != nil {
|
| 269 |
- log.Fatal(err) |
|
| 269 |
+ logrus.Fatal(err) |
|
| 270 | 270 |
} |
| 271 | 271 |
} |
| 272 | 272 |
|
| ... | ... |
@@ -338,7 +338,7 @@ func (n *networkNamespace) InvokeFunc(f func()) error {
|
| 338 | 338 |
func InitOSContext() func() {
|
| 339 | 339 |
runtime.LockOSThread() |
| 340 | 340 |
if err := ns.SetNamespace(); err != nil {
|
| 341 |
- log.Error(err) |
|
| 341 |
+ logrus.Error(err) |
|
| 342 | 342 |
} |
| 343 | 343 |
return runtime.UnlockOSThread |
| 344 | 344 |
} |
| ... | ... |
@@ -8,7 +8,7 @@ import ( |
| 8 | 8 |
"sync" |
| 9 | 9 |
"time" |
| 10 | 10 |
|
| 11 |
- log "github.com/Sirupsen/logrus" |
|
| 11 |
+ "github.com/Sirupsen/logrus" |
|
| 12 | 12 |
"github.com/docker/libnetwork/types" |
| 13 | 13 |
"github.com/miekg/dns" |
| 14 | 14 |
) |
| ... | ... |
@@ -219,7 +219,7 @@ func (r *resolver) handleIPQuery(name string, query *dns.Msg, ipType int) (*dns. |
| 219 | 219 |
|
| 220 | 220 |
if addr == nil && ipv6Miss {
|
| 221 | 221 |
// Send a reply without any Answer sections |
| 222 |
- log.Debugf("Lookup name %s present without IPv6 address", name)
|
|
| 222 |
+ logrus.Debugf("Lookup name %s present without IPv6 address", name)
|
|
| 223 | 223 |
resp := createRespMsg(query) |
| 224 | 224 |
return resp, nil |
| 225 | 225 |
} |
| ... | ... |
@@ -227,7 +227,7 @@ func (r *resolver) handleIPQuery(name string, query *dns.Msg, ipType int) (*dns. |
| 227 | 227 |
return nil, nil |
| 228 | 228 |
} |
| 229 | 229 |
|
| 230 |
- log.Debugf("Lookup for %s: IP %v", name, addr)
|
|
| 230 |
+ logrus.Debugf("Lookup for %s: IP %v", name, addr)
|
|
| 231 | 231 |
|
| 232 | 232 |
resp := createRespMsg(query) |
| 233 | 233 |
if len(addr) > 1 {
|
| ... | ... |
@@ -268,7 +268,7 @@ func (r *resolver) handlePTRQuery(ptr string, query *dns.Msg) (*dns.Msg, error) |
| 268 | 268 |
return nil, nil |
| 269 | 269 |
} |
| 270 | 270 |
|
| 271 |
- log.Debugf("Lookup for IP %s: name %s", parts[0], host)
|
|
| 271 |
+ logrus.Debugf("Lookup for IP %s: name %s", parts[0], host)
|
|
| 272 | 272 |
fqdn := dns.Fqdn(host) |
| 273 | 273 |
|
| 274 | 274 |
resp := new(dns.Msg) |
| ... | ... |
@@ -352,7 +352,7 @@ func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) {
|
| 352 | 352 |
} |
| 353 | 353 |
|
| 354 | 354 |
if err != nil {
|
| 355 |
- log.Error(err) |
|
| 355 |
+ logrus.Error(err) |
|
| 356 | 356 |
return |
| 357 | 357 |
} |
| 358 | 358 |
|
| ... | ... |
@@ -411,10 +411,10 @@ func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) {
|
| 411 | 411 |
|
| 412 | 412 |
execErr := r.backend.ExecFunc(extConnect) |
| 413 | 413 |
if execErr != nil || err != nil {
|
| 414 |
- log.Debugf("Connect failed, %s", err)
|
|
| 414 |
+ logrus.Debugf("Connect failed, %s", err)
|
|
| 415 | 415 |
continue |
| 416 | 416 |
} |
| 417 |
- log.Debugf("Query %s[%d] from %s, forwarding to %s:%s", name, query.Question[0].Qtype,
|
|
| 417 |
+ logrus.Debugf("Query %s[%d] from %s, forwarding to %s:%s", name, query.Question[0].Qtype,
|
|
| 418 | 418 |
extConn.LocalAddr().String(), proto, extDNS.ipStr) |
| 419 | 419 |
|
| 420 | 420 |
// Timeout has to be set for every IO operation. |
| ... | ... |
@@ -430,7 +430,7 @@ func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) {
|
| 430 | 430 |
old := r.tStamp |
| 431 | 431 |
r.tStamp = time.Now() |
| 432 | 432 |
if r.tStamp.Sub(old) > logInterval {
|
| 433 |
- log.Errorf("More than %v concurrent queries from %s", maxConcurrent, extConn.LocalAddr().String())
|
|
| 433 |
+ logrus.Errorf("More than %v concurrent queries from %s", maxConcurrent, extConn.LocalAddr().String())
|
|
| 434 | 434 |
} |
| 435 | 435 |
continue |
| 436 | 436 |
} |
| ... | ... |
@@ -438,7 +438,7 @@ func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) {
|
| 438 | 438 |
err = co.WriteMsg(query) |
| 439 | 439 |
if err != nil {
|
| 440 | 440 |
r.forwardQueryEnd() |
| 441 |
- log.Debugf("Send to DNS server failed, %s", err)
|
|
| 441 |
+ logrus.Debugf("Send to DNS server failed, %s", err)
|
|
| 442 | 442 |
continue |
| 443 | 443 |
} |
| 444 | 444 |
|
| ... | ... |
@@ -447,7 +447,7 @@ func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) {
|
| 447 | 447 |
// client can retry over TCP |
| 448 | 448 |
if err != nil && err != dns.ErrTruncated {
|
| 449 | 449 |
r.forwardQueryEnd() |
| 450 |
- log.Debugf("Read from DNS server failed, %s", err)
|
|
| 450 |
+ logrus.Debugf("Read from DNS server failed, %s", err)
|
|
| 451 | 451 |
continue |
| 452 | 452 |
} |
| 453 | 453 |
|
| ... | ... |
@@ -462,7 +462,7 @@ func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) {
|
| 462 | 462 |
} |
| 463 | 463 |
|
| 464 | 464 |
if err = w.WriteMsg(resp); err != nil {
|
| 465 |
- log.Errorf("error writing resolver resp, %s", err)
|
|
| 465 |
+ logrus.Errorf("error writing resolver resp, %s", err)
|
|
| 466 | 466 |
} |
| 467 | 467 |
} |
| 468 | 468 |
|
| ... | ... |
@@ -483,7 +483,7 @@ func (r *resolver) forwardQueryEnd() {
|
| 483 | 483 |
defer r.queryLock.Unlock() |
| 484 | 484 |
|
| 485 | 485 |
if r.count == 0 {
|
| 486 |
- log.Errorf("Invalid concurrent query count")
|
|
| 486 |
+ logrus.Error("Invalid concurrent query count")
|
|
| 487 | 487 |
} else {
|
| 488 | 488 |
r.count-- |
| 489 | 489 |
} |
| ... | ... |
@@ -9,7 +9,7 @@ import ( |
| 9 | 9 |
"os/exec" |
| 10 | 10 |
"runtime" |
| 11 | 11 |
|
| 12 |
- log "github.com/Sirupsen/logrus" |
|
| 12 |
+ "github.com/Sirupsen/logrus" |
|
| 13 | 13 |
"github.com/docker/docker/pkg/reexec" |
| 14 | 14 |
"github.com/docker/libnetwork/iptables" |
| 15 | 15 |
"github.com/vishvananda/netns" |
| ... | ... |
@@ -31,7 +31,7 @@ func reexecSetupResolver() {
|
| 31 | 31 |
defer runtime.UnlockOSThread() |
| 32 | 32 |
|
| 33 | 33 |
if len(os.Args) < 4 {
|
| 34 |
- log.Error("invalid number of arguments..")
|
|
| 34 |
+ logrus.Error("invalid number of arguments..")
|
|
| 35 | 35 |
os.Exit(1) |
| 36 | 36 |
} |
| 37 | 37 |
|
| ... | ... |
@@ -46,14 +46,14 @@ func reexecSetupResolver() {
|
| 46 | 46 |
|
| 47 | 47 |
f, err := os.OpenFile(os.Args[1], os.O_RDONLY, 0) |
| 48 | 48 |
if err != nil {
|
| 49 |
- log.Errorf("failed get network namespace %q: %v", os.Args[1], err)
|
|
| 49 |
+ logrus.Errorf("failed get network namespace %q: %v", os.Args[1], err)
|
|
| 50 | 50 |
os.Exit(2) |
| 51 | 51 |
} |
| 52 | 52 |
defer f.Close() |
| 53 | 53 |
|
| 54 | 54 |
nsFD := f.Fd() |
| 55 | 55 |
if err = netns.Set(netns.NsHandle(nsFD)); err != nil {
|
| 56 |
- log.Errorf("setting into container net ns %v failed, %v", os.Args[1], err)
|
|
| 56 |
+ logrus.Errorf("setting into container net ns %v failed, %v", os.Args[1], err)
|
|
| 57 | 57 |
os.Exit(3) |
| 58 | 58 |
} |
| 59 | 59 |
|
| ... | ... |
@@ -76,7 +76,7 @@ func reexecSetupResolver() {
|
| 76 | 76 |
|
| 77 | 77 |
for _, rule := range rules {
|
| 78 | 78 |
if iptables.RawCombinedOutputNative(rule...) != nil {
|
| 79 |
- log.Errorf("setting up rule failed, %v", rule)
|
|
| 79 |
+ logrus.Errorf("setting up rule failed, %v", rule)
|
|
| 80 | 80 |
} |
| 81 | 81 |
} |
| 82 | 82 |
} |
| ... | ... |
@@ -9,7 +9,7 @@ import ( |
| 9 | 9 |
"sync" |
| 10 | 10 |
"time" |
| 11 | 11 |
|
| 12 |
- log "github.com/Sirupsen/logrus" |
|
| 12 |
+ "github.com/Sirupsen/logrus" |
|
| 13 | 13 |
"github.com/docker/libnetwork/etchosts" |
| 14 | 14 |
"github.com/docker/libnetwork/netlabel" |
| 15 | 15 |
"github.com/docker/libnetwork/osl" |
| ... | ... |
@@ -213,18 +213,18 @@ func (sb *sandbox) delete(force bool) error {
|
| 213 | 213 |
if c.isDistributedControl() {
|
| 214 | 214 |
retain = true |
| 215 | 215 |
} |
| 216 |
- log.Warnf("Failed getting network for ep %s during sandbox %s delete: %v", ep.ID(), sb.ID(), err)
|
|
| 216 |
+ logrus.Warnf("Failed getting network for ep %s during sandbox %s delete: %v", ep.ID(), sb.ID(), err)
|
|
| 217 | 217 |
continue |
| 218 | 218 |
} |
| 219 | 219 |
|
| 220 | 220 |
if !force {
|
| 221 | 221 |
if err := ep.Leave(sb); err != nil {
|
| 222 |
- log.Warnf("Failed detaching sandbox %s from endpoint %s: %v\n", sb.ID(), ep.ID(), err)
|
|
| 222 |
+ logrus.Warnf("Failed detaching sandbox %s from endpoint %s: %v\n", sb.ID(), ep.ID(), err)
|
|
| 223 | 223 |
} |
| 224 | 224 |
} |
| 225 | 225 |
|
| 226 | 226 |
if err := ep.Delete(force); err != nil {
|
| 227 |
- log.Warnf("Failed deleting endpoint %s: %v\n", ep.ID(), err)
|
|
| 227 |
+ logrus.Warnf("Failed deleting endpoint %s: %v\n", ep.ID(), err)
|
|
| 228 | 228 |
} |
| 229 | 229 |
} |
| 230 | 230 |
|
| ... | ... |
@@ -247,7 +247,7 @@ func (sb *sandbox) delete(force bool) error {
|
| 247 | 247 |
} |
| 248 | 248 |
|
| 249 | 249 |
if err := sb.storeDelete(); err != nil {
|
| 250 |
- log.Warnf("Failed to delete sandbox %s from store: %v", sb.ID(), err)
|
|
| 250 |
+ logrus.Warnf("Failed to delete sandbox %s from store: %v", sb.ID(), err)
|
|
| 251 | 251 |
} |
| 252 | 252 |
|
| 253 | 253 |
c.Lock() |
| ... | ... |
@@ -291,7 +291,7 @@ func (sb *sandbox) Refresh(options ...SandboxOption) error {
|
| 291 | 291 |
// Detach from all endpoints |
| 292 | 292 |
for _, ep := range epList {
|
| 293 | 293 |
if err := ep.Leave(sb); err != nil {
|
| 294 |
- log.Warnf("Failed detaching sandbox %s from endpoint %s: %v\n", sb.ID(), ep.ID(), err)
|
|
| 294 |
+ logrus.Warnf("Failed detaching sandbox %s from endpoint %s: %v\n", sb.ID(), ep.ID(), err)
|
|
| 295 | 295 |
} |
| 296 | 296 |
} |
| 297 | 297 |
|
| ... | ... |
@@ -307,7 +307,7 @@ func (sb *sandbox) Refresh(options ...SandboxOption) error {
|
| 307 | 307 |
// Re-connect to all endpoints |
| 308 | 308 |
for _, ep := range epList {
|
| 309 | 309 |
if err := ep.Join(sb); err != nil {
|
| 310 |
- log.Warnf("Failed attach sandbox %s to endpoint %s: %v\n", sb.ID(), ep.ID(), err)
|
|
| 310 |
+ logrus.Warnf("Failed attach sandbox %s to endpoint %s: %v\n", sb.ID(), ep.ID(), err)
|
|
| 311 | 311 |
} |
| 312 | 312 |
} |
| 313 | 313 |
|
| ... | ... |
@@ -413,7 +413,7 @@ func (sb *sandbox) updateGateway(ep *endpoint) error {
|
| 413 | 413 |
|
| 414 | 414 |
func (sb *sandbox) ResolveIP(ip string) string {
|
| 415 | 415 |
var svc string |
| 416 |
- log.Debugf("IP To resolve %v", ip)
|
|
| 416 |
+ logrus.Debugf("IP To resolve %v", ip)
|
|
| 417 | 417 |
|
| 418 | 418 |
for _, ep := range sb.getConnectedEndpoints() {
|
| 419 | 419 |
n := ep.getNetwork() |
| ... | ... |
@@ -434,7 +434,7 @@ func (sb *sandbox) ResolveService(name string) ([]*net.SRV, []net.IP) {
|
| 434 | 434 |
srv := []*net.SRV{}
|
| 435 | 435 |
ip := []net.IP{}
|
| 436 | 436 |
|
| 437 |
- log.Debugf("Service name To resolve: %v", name)
|
|
| 437 |
+ logrus.Debugf("Service name To resolve: %v", name)
|
|
| 438 | 438 |
|
| 439 | 439 |
// There are DNS implementaions that allow SRV queries for names not in |
| 440 | 440 |
// the format defined by RFC 2782. Hence specific validations checks are |
| ... | ... |
@@ -497,7 +497,7 @@ func (sb *sandbox) ResolveName(name string, ipType int) ([]net.IP, bool) {
|
| 497 | 497 |
// {a.b in network c.d},
|
| 498 | 498 |
// {a in network b.c.d},
|
| 499 | 499 |
|
| 500 |
- log.Debugf("Name To resolve: %v", name)
|
|
| 500 |
+ logrus.Debugf("Name To resolve: %v", name)
|
|
| 501 | 501 |
name = strings.TrimSuffix(name, ".") |
| 502 | 502 |
reqName := []string{name}
|
| 503 | 503 |
networkName := []string{""}
|
| ... | ... |
@@ -605,7 +605,7 @@ func (sb *sandbox) resolveName(req string, networkName string, epList []*endpoin |
| 605 | 605 |
func (sb *sandbox) SetKey(basePath string) error {
|
| 606 | 606 |
start := time.Now() |
| 607 | 607 |
defer func() {
|
| 608 |
- log.Debugf("sandbox set key processing took %s for container %s", time.Now().Sub(start), sb.ContainerID())
|
|
| 608 |
+ logrus.Debugf("sandbox set key processing took %s for container %s", time.Now().Sub(start), sb.ContainerID())
|
|
| 609 | 609 |
}() |
| 610 | 610 |
|
| 611 | 611 |
if basePath == "" {
|
| ... | ... |
@@ -646,10 +646,10 @@ func (sb *sandbox) SetKey(basePath string) error {
|
| 646 | 646 |
|
| 647 | 647 |
if err := sb.osSbox.InvokeFunc(sb.resolver.SetupFunc(0)); err == nil {
|
| 648 | 648 |
if err := sb.resolver.Start(); err != nil {
|
| 649 |
- log.Errorf("Resolver Start failed for container %s, %q", sb.ContainerID(), err)
|
|
| 649 |
+ logrus.Errorf("Resolver Start failed for container %s, %q", sb.ContainerID(), err)
|
|
| 650 | 650 |
} |
| 651 | 651 |
} else {
|
| 652 |
- log.Errorf("Resolver Setup Function failed for container %s, %q", sb.ContainerID(), err)
|
|
| 652 |
+ logrus.Errorf("Resolver Setup Function failed for container %s, %q", sb.ContainerID(), err)
|
|
| 653 | 653 |
} |
| 654 | 654 |
} |
| 655 | 655 |
|
| ... | ... |
@@ -690,7 +690,7 @@ func releaseOSSboxResources(osSbox osl.Sandbox, ep *endpoint) {
|
| 690 | 690 |
// Only remove the interfaces owned by this endpoint from the sandbox. |
| 691 | 691 |
if ep.hasInterface(i.SrcName()) {
|
| 692 | 692 |
if err := i.Remove(); err != nil {
|
| 693 |
- log.Debugf("Remove interface %s failed: %v", i.SrcName(), err)
|
|
| 693 |
+ logrus.Debugf("Remove interface %s failed: %v", i.SrcName(), err)
|
|
| 694 | 694 |
} |
| 695 | 695 |
} |
| 696 | 696 |
} |
| ... | ... |
@@ -706,7 +706,7 @@ func releaseOSSboxResources(osSbox osl.Sandbox, ep *endpoint) {
|
| 706 | 706 |
// Remove non-interface routes. |
| 707 | 707 |
for _, r := range joinInfo.StaticRoutes {
|
| 708 | 708 |
if err := osSbox.RemoveStaticRoute(r); err != nil {
|
| 709 |
- log.Debugf("Remove route failed: %v", err)
|
|
| 709 |
+ logrus.Debugf("Remove route failed: %v", err)
|
|
| 710 | 710 |
} |
| 711 | 711 |
} |
| 712 | 712 |
} |
| ... | ... |
@@ -741,7 +741,7 @@ func (sb *sandbox) restoreOslSandbox() error {
|
| 741 | 741 |
ep.Unlock() |
| 742 | 742 |
|
| 743 | 743 |
if i == nil {
|
| 744 |
- log.Errorf("error restoring endpoint %s for container %s", ep.Name(), sb.ContainerID())
|
|
| 744 |
+ logrus.Errorf("error restoring endpoint %s for container %s", ep.Name(), sb.ContainerID())
|
|
| 745 | 745 |
continue |
| 746 | 746 |
} |
| 747 | 747 |
|
| ... | ... |
@@ -876,7 +876,7 @@ func (sb *sandbox) clearNetworkResources(origEp *endpoint) error {
|
| 876 | 876 |
if len(sb.endpoints) == 0 {
|
| 877 | 877 |
// sb.endpoints should never be empty and this is unexpected error condition |
| 878 | 878 |
// We log an error message to note this down for debugging purposes. |
| 879 |
- log.Errorf("No endpoints in sandbox while trying to remove endpoint %s", ep.Name())
|
|
| 879 |
+ logrus.Errorf("No endpoints in sandbox while trying to remove endpoint %s", ep.Name())
|
|
| 880 | 880 |
sb.Unlock() |
| 881 | 881 |
return nil |
| 882 | 882 |
} |
| ... | ... |
@@ -11,7 +11,7 @@ import ( |
| 11 | 11 |
"strconv" |
| 12 | 12 |
"strings" |
| 13 | 13 |
|
| 14 |
- log "github.com/Sirupsen/logrus" |
|
| 14 |
+ "github.com/Sirupsen/logrus" |
|
| 15 | 15 |
"github.com/docker/libnetwork/etchosts" |
| 16 | 16 |
"github.com/docker/libnetwork/resolvconf" |
| 17 | 17 |
"github.com/docker/libnetwork/types" |
| ... | ... |
@@ -40,19 +40,19 @@ func (sb *sandbox) startResolver(restore bool) {
|
| 40 | 40 |
if !restore {
|
| 41 | 41 |
err = sb.rebuildDNS() |
| 42 | 42 |
if err != nil {
|
| 43 |
- log.Errorf("Updating resolv.conf failed for container %s, %q", sb.ContainerID(), err)
|
|
| 43 |
+ logrus.Errorf("Updating resolv.conf failed for container %s, %q", sb.ContainerID(), err)
|
|
| 44 | 44 |
return |
| 45 | 45 |
} |
| 46 | 46 |
} |
| 47 | 47 |
sb.resolver.SetExtServers(sb.extDNS) |
| 48 | 48 |
|
| 49 | 49 |
if err = sb.osSbox.InvokeFunc(sb.resolver.SetupFunc(0)); err != nil {
|
| 50 |
- log.Errorf("Resolver Setup function failed for container %s, %q", sb.ContainerID(), err)
|
|
| 50 |
+ logrus.Errorf("Resolver Setup function failed for container %s, %q", sb.ContainerID(), err)
|
|
| 51 | 51 |
return |
| 52 | 52 |
} |
| 53 | 53 |
|
| 54 | 54 |
if err = sb.resolver.Start(); err != nil {
|
| 55 |
- log.Errorf("Resolver Start failed for container %s, %q", sb.ContainerID(), err)
|
|
| 55 |
+ logrus.Errorf("Resolver Start failed for container %s, %q", sb.ContainerID(), err)
|
|
| 56 | 56 |
} |
| 57 | 57 |
}) |
| 58 | 58 |
} |
| ... | ... |
@@ -125,13 +125,13 @@ func (sb *sandbox) updateHostsFile(ifaceIP string) error {
|
| 125 | 125 |
|
| 126 | 126 |
func (sb *sandbox) addHostsEntries(recs []etchosts.Record) {
|
| 127 | 127 |
if err := etchosts.Add(sb.config.hostsPath, recs); err != nil {
|
| 128 |
- log.Warnf("Failed adding service host entries to the running container: %v", err)
|
|
| 128 |
+ logrus.Warnf("Failed adding service host entries to the running container: %v", err)
|
|
| 129 | 129 |
} |
| 130 | 130 |
} |
| 131 | 131 |
|
| 132 | 132 |
func (sb *sandbox) deleteHostsEntries(recs []etchosts.Record) {
|
| 133 | 133 |
if err := etchosts.Delete(sb.config.hostsPath, recs); err != nil {
|
| 134 |
- log.Warnf("Failed deleting service host entries to the running container: %v", err)
|
|
| 134 |
+ logrus.Warnf("Failed deleting service host entries to the running container: %v", err)
|
|
| 135 | 135 |
} |
| 136 | 136 |
} |
| 137 | 137 |
|
| ... | ... |
@@ -261,7 +261,7 @@ func (sb *sandbox) updateDNS(ipv6Enabled bool) error {
|
| 261 | 261 |
if currHash != "" && currHash != currRC.Hash {
|
| 262 | 262 |
// Seems the user has changed the container resolv.conf since the last time |
| 263 | 263 |
// we checked so return without doing anything. |
| 264 |
- //log.Infof("Skipping update of resolv.conf file with ipv6Enabled: %t because file was touched by user", ipv6Enabled)
|
|
| 264 |
+ //logrus.Infof("Skipping update of resolv.conf file with ipv6Enabled: %t because file was touched by user", ipv6Enabled)
|
|
| 265 | 265 |
return nil |
| 266 | 266 |
} |
| 267 | 267 |
|
| ... | ... |
@@ -178,7 +178,7 @@ func (sb *sandbox) storeDelete() error {
|
| 178 | 178 |
func (c *controller) sandboxCleanup(activeSandboxes map[string]interface{}) {
|
| 179 | 179 |
store := c.getStore(datastore.LocalScope) |
| 180 | 180 |
if store == nil {
|
| 181 |
- logrus.Errorf("Could not find local scope store while trying to cleanup sandboxes")
|
|
| 181 |
+ logrus.Error("Could not find local scope store while trying to cleanup sandboxes")
|
|
| 182 | 182 |
return |
| 183 | 183 |
} |
| 184 | 184 |
|
| 185 | 185 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,225 @@ |
| 0 |
+// +build linux windows |
|
| 1 |
+ |
|
| 2 |
+package libnetwork |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "net" |
|
| 6 |
+ |
|
| 7 |
+ "github.com/Sirupsen/logrus" |
|
| 8 |
+) |
|
| 9 |
+ |
|
| 10 |
+func newService(name string, id string, ingressPorts []*PortConfig, aliases []string) *service {
|
|
| 11 |
+ return &service{
|
|
| 12 |
+ name: name, |
|
| 13 |
+ id: id, |
|
| 14 |
+ ingressPorts: ingressPorts, |
|
| 15 |
+ loadBalancers: make(map[string]*loadBalancer), |
|
| 16 |
+ aliases: aliases, |
|
| 17 |
+ } |
|
| 18 |
+} |
|
| 19 |
+ |
|
| 20 |
+func (c *controller) cleanupServiceBindings(cleanupNID string) {
|
|
| 21 |
+ var cleanupFuncs []func() |
|
| 22 |
+ |
|
| 23 |
+ c.Lock() |
|
| 24 |
+ services := make([]*service, 0, len(c.serviceBindings)) |
|
| 25 |
+ for _, s := range c.serviceBindings {
|
|
| 26 |
+ services = append(services, s) |
|
| 27 |
+ } |
|
| 28 |
+ c.Unlock() |
|
| 29 |
+ |
|
| 30 |
+ for _, s := range services {
|
|
| 31 |
+ s.Lock() |
|
| 32 |
+ for nid, lb := range s.loadBalancers {
|
|
| 33 |
+ if cleanupNID != "" && nid != cleanupNID {
|
|
| 34 |
+ continue |
|
| 35 |
+ } |
|
| 36 |
+ |
|
| 37 |
+ for eid, ip := range lb.backEnds {
|
|
| 38 |
+ service := s |
|
| 39 |
+ loadBalancer := lb |
|
| 40 |
+ networkID := nid |
|
| 41 |
+ epID := eid |
|
| 42 |
+ epIP := ip |
|
| 43 |
+ |
|
| 44 |
+ cleanupFuncs = append(cleanupFuncs, func() {
|
|
| 45 |
+ if err := c.rmServiceBinding(service.name, service.id, networkID, epID, loadBalancer.vip, |
|
| 46 |
+ service.ingressPorts, service.aliases, epIP); err != nil {
|
|
| 47 |
+ logrus.Errorf("Failed to remove service bindings for service %s network %s endpoint %s while cleanup: %v",
|
|
| 48 |
+ service.id, networkID, epID, err) |
|
| 49 |
+ } |
|
| 50 |
+ }) |
|
| 51 |
+ } |
|
| 52 |
+ } |
|
| 53 |
+ s.Unlock() |
|
| 54 |
+ } |
|
| 55 |
+ |
|
| 56 |
+ for _, f := range cleanupFuncs {
|
|
| 57 |
+ f() |
|
| 58 |
+ } |
|
| 59 |
+ |
|
| 60 |
+} |
|
| 61 |
+ |
|
| 62 |
+func (c *controller) addServiceBinding(name, sid, nid, eid string, vip net.IP, ingressPorts []*PortConfig, aliases []string, ip net.IP) error {
|
|
| 63 |
+ var ( |
|
| 64 |
+ s *service |
|
| 65 |
+ addService bool |
|
| 66 |
+ ) |
|
| 67 |
+ |
|
| 68 |
+ n, err := c.NetworkByID(nid) |
|
| 69 |
+ if err != nil {
|
|
| 70 |
+ return err |
|
| 71 |
+ } |
|
| 72 |
+ |
|
| 73 |
+ skey := serviceKey{
|
|
| 74 |
+ id: sid, |
|
| 75 |
+ ports: portConfigs(ingressPorts).String(), |
|
| 76 |
+ } |
|
| 77 |
+ |
|
| 78 |
+ c.Lock() |
|
| 79 |
+ s, ok := c.serviceBindings[skey] |
|
| 80 |
+ if !ok {
|
|
| 81 |
+ // Create a new service if we are seeing this service |
|
| 82 |
+ // for the first time. |
|
| 83 |
+ s = newService(name, sid, ingressPorts, aliases) |
|
| 84 |
+ c.serviceBindings[skey] = s |
|
| 85 |
+ } |
|
| 86 |
+ c.Unlock() |
|
| 87 |
+ |
|
| 88 |
+ // Add endpoint IP to special "tasks.svc_name" so that the |
|
| 89 |
+ // applications have access to DNS RR. |
|
| 90 |
+ n.(*network).addSvcRecords("tasks."+name, ip, nil, false)
|
|
| 91 |
+ for _, alias := range aliases {
|
|
| 92 |
+ n.(*network).addSvcRecords("tasks."+alias, ip, nil, false)
|
|
| 93 |
+ } |
|
| 94 |
+ |
|
| 95 |
+ // Add service name to vip in DNS, if vip is valid. Otherwise resort to DNS RR |
|
| 96 |
+ svcIP := vip |
|
| 97 |
+ if len(svcIP) == 0 {
|
|
| 98 |
+ svcIP = ip |
|
| 99 |
+ } |
|
| 100 |
+ n.(*network).addSvcRecords(name, svcIP, nil, false) |
|
| 101 |
+ for _, alias := range aliases {
|
|
| 102 |
+ n.(*network).addSvcRecords(alias, svcIP, nil, false) |
|
| 103 |
+ } |
|
| 104 |
+ |
|
| 105 |
+ s.Lock() |
|
| 106 |
+ defer s.Unlock() |
|
| 107 |
+ |
|
| 108 |
+ lb, ok := s.loadBalancers[nid] |
|
| 109 |
+ if !ok {
|
|
| 110 |
+ // Create a new load balancer if we are seeing this |
|
| 111 |
+ // network attachment on the service for the first |
|
| 112 |
+ // time. |
|
| 113 |
+ lb = &loadBalancer{
|
|
| 114 |
+ vip: vip, |
|
| 115 |
+ fwMark: fwMarkCtr, |
|
| 116 |
+ backEnds: make(map[string]net.IP), |
|
| 117 |
+ service: s, |
|
| 118 |
+ } |
|
| 119 |
+ |
|
| 120 |
+ fwMarkCtrMu.Lock() |
|
| 121 |
+ fwMarkCtr++ |
|
| 122 |
+ fwMarkCtrMu.Unlock() |
|
| 123 |
+ |
|
| 124 |
+ s.loadBalancers[nid] = lb |
|
| 125 |
+ |
|
| 126 |
+ // Since we just created this load balancer make sure |
|
| 127 |
+ // we add a new service service in IPVS rules. |
|
| 128 |
+ addService = true |
|
| 129 |
+ |
|
| 130 |
+ } |
|
| 131 |
+ |
|
| 132 |
+ lb.backEnds[eid] = ip |
|
| 133 |
+ |
|
| 134 |
+ // Add loadbalancer service and backend in all sandboxes in |
|
| 135 |
+ // the network only if vip is valid. |
|
| 136 |
+ if len(vip) != 0 {
|
|
| 137 |
+ n.(*network).addLBBackend(ip, vip, lb.fwMark, ingressPorts, addService) |
|
| 138 |
+ } |
|
| 139 |
+ |
|
| 140 |
+ return nil |
|
| 141 |
+} |
|
| 142 |
+ |
|
| 143 |
+func (c *controller) rmServiceBinding(name, sid, nid, eid string, vip net.IP, ingressPorts []*PortConfig, aliases []string, ip net.IP) error {
|
|
| 144 |
+ var rmService bool |
|
| 145 |
+ |
|
| 146 |
+ n, err := c.NetworkByID(nid) |
|
| 147 |
+ if err != nil {
|
|
| 148 |
+ return err |
|
| 149 |
+ } |
|
| 150 |
+ |
|
| 151 |
+ skey := serviceKey{
|
|
| 152 |
+ id: sid, |
|
| 153 |
+ ports: portConfigs(ingressPorts).String(), |
|
| 154 |
+ } |
|
| 155 |
+ |
|
| 156 |
+ c.Lock() |
|
| 157 |
+ s, ok := c.serviceBindings[skey] |
|
| 158 |
+ if !ok {
|
|
| 159 |
+ c.Unlock() |
|
| 160 |
+ return nil |
|
| 161 |
+ } |
|
| 162 |
+ c.Unlock() |
|
| 163 |
+ |
|
| 164 |
+ s.Lock() |
|
| 165 |
+ lb, ok := s.loadBalancers[nid] |
|
| 166 |
+ if !ok {
|
|
| 167 |
+ s.Unlock() |
|
| 168 |
+ return nil |
|
| 169 |
+ } |
|
| 170 |
+ |
|
| 171 |
+ _, ok = lb.backEnds[eid] |
|
| 172 |
+ if !ok {
|
|
| 173 |
+ s.Unlock() |
|
| 174 |
+ return nil |
|
| 175 |
+ } |
|
| 176 |
+ |
|
| 177 |
+ delete(lb.backEnds, eid) |
|
| 178 |
+ if len(lb.backEnds) == 0 {
|
|
| 179 |
+ // All the backends for this service have been |
|
| 180 |
+ // removed. Time to remove the load balancer and also |
|
| 181 |
+ // remove the service entry in IPVS. |
|
| 182 |
+ rmService = true |
|
| 183 |
+ |
|
| 184 |
+ delete(s.loadBalancers, nid) |
|
| 185 |
+ } |
|
| 186 |
+ |
|
| 187 |
+ if len(s.loadBalancers) == 0 {
|
|
| 188 |
+ // All loadbalancers for the service removed. Time to |
|
| 189 |
+ // remove the service itself. |
|
| 190 |
+ delete(c.serviceBindings, skey) |
|
| 191 |
+ } |
|
| 192 |
+ |
|
| 193 |
+ // Remove loadbalancer service(if needed) and backend in all |
|
| 194 |
+ // sandboxes in the network only if the vip is valid. |
|
| 195 |
+ if len(vip) != 0 {
|
|
| 196 |
+ n.(*network).rmLBBackend(ip, vip, lb.fwMark, ingressPorts, rmService) |
|
| 197 |
+ } |
|
| 198 |
+ s.Unlock() |
|
| 199 |
+ |
|
| 200 |
+ // Delete the special "tasks.svc_name" backend record. |
|
| 201 |
+ n.(*network).deleteSvcRecords("tasks."+name, ip, nil, false)
|
|
| 202 |
+ for _, alias := range aliases {
|
|
| 203 |
+ n.(*network).deleteSvcRecords("tasks."+alias, ip, nil, false)
|
|
| 204 |
+ } |
|
| 205 |
+ |
|
| 206 |
+ // If we are doing DNS RR add the endpoint IP to DNS record |
|
| 207 |
+ // right away. |
|
| 208 |
+ if len(vip) == 0 {
|
|
| 209 |
+ n.(*network).deleteSvcRecords(name, ip, nil, false) |
|
| 210 |
+ for _, alias := range aliases {
|
|
| 211 |
+ n.(*network).deleteSvcRecords(alias, ip, nil, false) |
|
| 212 |
+ } |
|
| 213 |
+ } |
|
| 214 |
+ |
|
| 215 |
+ // Remove the DNS record for VIP only if we are removing the service |
|
| 216 |
+ if rmService && len(vip) != 0 {
|
|
| 217 |
+ n.(*network).deleteSvcRecords(name, vip, nil, false) |
|
| 218 |
+ for _, alias := range aliases {
|
|
| 219 |
+ n.(*network).deleteSvcRecords(alias, vip, nil, false) |
|
| 220 |
+ } |
|
| 221 |
+ } |
|
| 222 |
+ |
|
| 223 |
+ return nil |
|
| 224 |
+} |
| ... | ... |
@@ -29,222 +29,6 @@ func init() {
|
| 29 | 29 |
reexec.Register("redirecter", redirecter)
|
| 30 | 30 |
} |
| 31 | 31 |
|
| 32 |
-func newService(name string, id string, ingressPorts []*PortConfig, aliases []string) *service {
|
|
| 33 |
- return &service{
|
|
| 34 |
- name: name, |
|
| 35 |
- id: id, |
|
| 36 |
- ingressPorts: ingressPorts, |
|
| 37 |
- loadBalancers: make(map[string]*loadBalancer), |
|
| 38 |
- aliases: aliases, |
|
| 39 |
- } |
|
| 40 |
-} |
|
| 41 |
- |
|
| 42 |
-func (c *controller) cleanupServiceBindings(cleanupNID string) {
|
|
| 43 |
- var cleanupFuncs []func() |
|
| 44 |
- |
|
| 45 |
- c.Lock() |
|
| 46 |
- services := make([]*service, 0, len(c.serviceBindings)) |
|
| 47 |
- for _, s := range c.serviceBindings {
|
|
| 48 |
- services = append(services, s) |
|
| 49 |
- } |
|
| 50 |
- c.Unlock() |
|
| 51 |
- |
|
| 52 |
- for _, s := range services {
|
|
| 53 |
- s.Lock() |
|
| 54 |
- for nid, lb := range s.loadBalancers {
|
|
| 55 |
- if cleanupNID != "" && nid != cleanupNID {
|
|
| 56 |
- continue |
|
| 57 |
- } |
|
| 58 |
- |
|
| 59 |
- for eid, ip := range lb.backEnds {
|
|
| 60 |
- service := s |
|
| 61 |
- loadBalancer := lb |
|
| 62 |
- networkID := nid |
|
| 63 |
- epID := eid |
|
| 64 |
- epIP := ip |
|
| 65 |
- |
|
| 66 |
- cleanupFuncs = append(cleanupFuncs, func() {
|
|
| 67 |
- if err := c.rmServiceBinding(service.name, service.id, networkID, epID, loadBalancer.vip, |
|
| 68 |
- service.ingressPorts, service.aliases, epIP); err != nil {
|
|
| 69 |
- logrus.Errorf("Failed to remove service bindings for service %s network %s endpoint %s while cleanup: %v",
|
|
| 70 |
- service.id, networkID, epID, err) |
|
| 71 |
- } |
|
| 72 |
- }) |
|
| 73 |
- } |
|
| 74 |
- } |
|
| 75 |
- s.Unlock() |
|
| 76 |
- } |
|
| 77 |
- |
|
| 78 |
- for _, f := range cleanupFuncs {
|
|
| 79 |
- f() |
|
| 80 |
- } |
|
| 81 |
- |
|
| 82 |
-} |
|
| 83 |
- |
|
| 84 |
-func (c *controller) addServiceBinding(name, sid, nid, eid string, vip net.IP, ingressPorts []*PortConfig, aliases []string, ip net.IP) error {
|
|
| 85 |
- var ( |
|
| 86 |
- s *service |
|
| 87 |
- addService bool |
|
| 88 |
- ) |
|
| 89 |
- |
|
| 90 |
- n, err := c.NetworkByID(nid) |
|
| 91 |
- if err != nil {
|
|
| 92 |
- return err |
|
| 93 |
- } |
|
| 94 |
- |
|
| 95 |
- skey := serviceKey{
|
|
| 96 |
- id: sid, |
|
| 97 |
- ports: portConfigs(ingressPorts).String(), |
|
| 98 |
- } |
|
| 99 |
- |
|
| 100 |
- c.Lock() |
|
| 101 |
- s, ok := c.serviceBindings[skey] |
|
| 102 |
- if !ok {
|
|
| 103 |
- // Create a new service if we are seeing this service |
|
| 104 |
- // for the first time. |
|
| 105 |
- s = newService(name, sid, ingressPorts, aliases) |
|
| 106 |
- c.serviceBindings[skey] = s |
|
| 107 |
- } |
|
| 108 |
- c.Unlock() |
|
| 109 |
- |
|
| 110 |
- // Add endpoint IP to special "tasks.svc_name" so that the |
|
| 111 |
- // applications have access to DNS RR. |
|
| 112 |
- n.(*network).addSvcRecords("tasks."+name, ip, nil, false)
|
|
| 113 |
- for _, alias := range aliases {
|
|
| 114 |
- n.(*network).addSvcRecords("tasks."+alias, ip, nil, false)
|
|
| 115 |
- } |
|
| 116 |
- |
|
| 117 |
- // Add service name to vip in DNS, if vip is valid. Otherwise resort to DNS RR |
|
| 118 |
- svcIP := vip |
|
| 119 |
- if len(svcIP) == 0 {
|
|
| 120 |
- svcIP = ip |
|
| 121 |
- } |
|
| 122 |
- n.(*network).addSvcRecords(name, svcIP, nil, false) |
|
| 123 |
- for _, alias := range aliases {
|
|
| 124 |
- n.(*network).addSvcRecords(alias, svcIP, nil, false) |
|
| 125 |
- } |
|
| 126 |
- |
|
| 127 |
- s.Lock() |
|
| 128 |
- defer s.Unlock() |
|
| 129 |
- |
|
| 130 |
- lb, ok := s.loadBalancers[nid] |
|
| 131 |
- if !ok {
|
|
| 132 |
- // Create a new load balancer if we are seeing this |
|
| 133 |
- // network attachment on the service for the first |
|
| 134 |
- // time. |
|
| 135 |
- lb = &loadBalancer{
|
|
| 136 |
- vip: vip, |
|
| 137 |
- fwMark: fwMarkCtr, |
|
| 138 |
- backEnds: make(map[string]net.IP), |
|
| 139 |
- service: s, |
|
| 140 |
- } |
|
| 141 |
- |
|
| 142 |
- fwMarkCtrMu.Lock() |
|
| 143 |
- fwMarkCtr++ |
|
| 144 |
- fwMarkCtrMu.Unlock() |
|
| 145 |
- |
|
| 146 |
- s.loadBalancers[nid] = lb |
|
| 147 |
- |
|
| 148 |
- // Since we just created this load balancer make sure |
|
| 149 |
- // we add a new service service in IPVS rules. |
|
| 150 |
- addService = true |
|
| 151 |
- |
|
| 152 |
- } |
|
| 153 |
- |
|
| 154 |
- lb.backEnds[eid] = ip |
|
| 155 |
- |
|
| 156 |
- // Add loadbalancer service and backend in all sandboxes in |
|
| 157 |
- // the network only if vip is valid. |
|
| 158 |
- if len(vip) != 0 {
|
|
| 159 |
- n.(*network).addLBBackend(ip, vip, lb.fwMark, ingressPorts, addService) |
|
| 160 |
- } |
|
| 161 |
- |
|
| 162 |
- return nil |
|
| 163 |
-} |
|
| 164 |
- |
|
| 165 |
-func (c *controller) rmServiceBinding(name, sid, nid, eid string, vip net.IP, ingressPorts []*PortConfig, aliases []string, ip net.IP) error {
|
|
| 166 |
- var rmService bool |
|
| 167 |
- |
|
| 168 |
- n, err := c.NetworkByID(nid) |
|
| 169 |
- if err != nil {
|
|
| 170 |
- return err |
|
| 171 |
- } |
|
| 172 |
- |
|
| 173 |
- skey := serviceKey{
|
|
| 174 |
- id: sid, |
|
| 175 |
- ports: portConfigs(ingressPorts).String(), |
|
| 176 |
- } |
|
| 177 |
- |
|
| 178 |
- c.Lock() |
|
| 179 |
- s, ok := c.serviceBindings[skey] |
|
| 180 |
- if !ok {
|
|
| 181 |
- c.Unlock() |
|
| 182 |
- return nil |
|
| 183 |
- } |
|
| 184 |
- c.Unlock() |
|
| 185 |
- |
|
| 186 |
- s.Lock() |
|
| 187 |
- lb, ok := s.loadBalancers[nid] |
|
| 188 |
- if !ok {
|
|
| 189 |
- s.Unlock() |
|
| 190 |
- return nil |
|
| 191 |
- } |
|
| 192 |
- |
|
| 193 |
- _, ok = lb.backEnds[eid] |
|
| 194 |
- if !ok {
|
|
| 195 |
- s.Unlock() |
|
| 196 |
- return nil |
|
| 197 |
- } |
|
| 198 |
- |
|
| 199 |
- delete(lb.backEnds, eid) |
|
| 200 |
- if len(lb.backEnds) == 0 {
|
|
| 201 |
- // All the backends for this service have been |
|
| 202 |
- // removed. Time to remove the load balancer and also |
|
| 203 |
- // remove the service entry in IPVS. |
|
| 204 |
- rmService = true |
|
| 205 |
- |
|
| 206 |
- delete(s.loadBalancers, nid) |
|
| 207 |
- } |
|
| 208 |
- |
|
| 209 |
- if len(s.loadBalancers) == 0 {
|
|
| 210 |
- // All loadbalancers for the service removed. Time to |
|
| 211 |
- // remove the service itself. |
|
| 212 |
- delete(c.serviceBindings, skey) |
|
| 213 |
- } |
|
| 214 |
- |
|
| 215 |
- // Remove loadbalancer service(if needed) and backend in all |
|
| 216 |
- // sandboxes in the network only if the vip is valid. |
|
| 217 |
- if len(vip) != 0 {
|
|
| 218 |
- n.(*network).rmLBBackend(ip, vip, lb.fwMark, ingressPorts, rmService) |
|
| 219 |
- } |
|
| 220 |
- s.Unlock() |
|
| 221 |
- |
|
| 222 |
- // Delete the special "tasks.svc_name" backend record. |
|
| 223 |
- n.(*network).deleteSvcRecords("tasks."+name, ip, nil, false)
|
|
| 224 |
- for _, alias := range aliases {
|
|
| 225 |
- n.(*network).deleteSvcRecords("tasks."+alias, ip, nil, false)
|
|
| 226 |
- } |
|
| 227 |
- |
|
| 228 |
- // If we are doing DNS RR add the endpoint IP to DNS record |
|
| 229 |
- // right away. |
|
| 230 |
- if len(vip) == 0 {
|
|
| 231 |
- n.(*network).deleteSvcRecords(name, ip, nil, false) |
|
| 232 |
- for _, alias := range aliases {
|
|
| 233 |
- n.(*network).deleteSvcRecords(alias, ip, nil, false) |
|
| 234 |
- } |
|
| 235 |
- } |
|
| 236 |
- |
|
| 237 |
- // Remove the DNS record for VIP only if we are removing the service |
|
| 238 |
- if rmService && len(vip) != 0 {
|
|
| 239 |
- n.(*network).deleteSvcRecords(name, vip, nil, false) |
|
| 240 |
- for _, alias := range aliases {
|
|
| 241 |
- n.(*network).deleteSvcRecords(alias, vip, nil, false) |
|
| 242 |
- } |
|
| 243 |
- } |
|
| 244 |
- |
|
| 245 |
- return nil |
|
| 246 |
-} |
|
| 247 |
- |
|
| 248 | 32 |
// Get all loadbalancers on this network that is currently discovered |
| 249 | 33 |
// on this node. |
| 250 | 34 |
func (n *network) connectedLoadbalancers() []*loadBalancer {
|
| 5 | 5 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,15 @@ |
| 0 |
+package libnetwork |
|
| 1 |
+ |
|
| 2 |
+import "net" |
|
| 3 |
+ |
|
| 4 |
+func (n *network) addLBBackend(ip, vip net.IP, fwMark uint32, ingressPorts []*PortConfig, addService bool) {
|
|
| 5 |
+} |
|
| 6 |
+ |
|
| 7 |
+func (n *network) rmLBBackend(ip, vip net.IP, fwMark uint32, ingressPorts []*PortConfig, rmService bool) {
|
|
| 8 |
+} |
|
| 9 |
+ |
|
| 10 |
+func (sb *sandbox) populateLoadbalancers(ep *endpoint) {
|
|
| 11 |
+} |
|
| 12 |
+ |
|
| 13 |
+func arrangeIngressFilterRule() {
|
|
| 14 |
+} |
| ... | ... |
@@ -3,7 +3,7 @@ package libnetwork |
| 3 | 3 |
import ( |
| 4 | 4 |
"fmt" |
| 5 | 5 |
|
| 6 |
- log "github.com/Sirupsen/logrus" |
|
| 6 |
+ "github.com/Sirupsen/logrus" |
|
| 7 | 7 |
"github.com/docker/libkv/store/boltdb" |
| 8 | 8 |
"github.com/docker/libkv/store/consul" |
| 9 | 9 |
"github.com/docker/libkv/store/etcd" |
| ... | ... |
@@ -85,7 +85,7 @@ func (c *controller) getNetworkFromStore(nid string) (*network, error) {
|
| 85 | 85 |
// Continue searching in the next store if the key is not found in this store |
| 86 | 86 |
if err != nil {
|
| 87 | 87 |
if err != datastore.ErrKeyNotFound {
|
| 88 |
- log.Debugf("could not find network %s: %v", nid, err)
|
|
| 88 |
+ logrus.Debugf("could not find network %s: %v", nid, err)
|
|
| 89 | 89 |
} |
| 90 | 90 |
continue |
| 91 | 91 |
} |
| ... | ... |
@@ -126,7 +126,7 @@ func (c *controller) getNetworksForScope(scope string) ([]*network, error) {
|
| 126 | 126 |
ec := &endpointCnt{n: n}
|
| 127 | 127 |
err = store.GetObject(datastore.Key(ec.Key()...), ec) |
| 128 | 128 |
if err != nil && !n.inDelete {
|
| 129 |
- log.Warnf("Could not find endpoint count key %s for network %s while listing: %v", datastore.Key(ec.Key()...), n.Name(), err)
|
|
| 129 |
+ logrus.Warnf("Could not find endpoint count key %s for network %s while listing: %v", datastore.Key(ec.Key()...), n.Name(), err)
|
|
| 130 | 130 |
continue |
| 131 | 131 |
} |
| 132 | 132 |
|
| ... | ... |
@@ -147,7 +147,7 @@ func (c *controller) getNetworksFromStore() ([]*network, error) {
|
| 147 | 147 |
// Continue searching in the next store if no keys found in this store |
| 148 | 148 |
if err != nil {
|
| 149 | 149 |
if err != datastore.ErrKeyNotFound {
|
| 150 |
- log.Debugf("failed to get networks for scope %s: %v", store.Scope(), err)
|
|
| 150 |
+ logrus.Debugf("failed to get networks for scope %s: %v", store.Scope(), err)
|
|
| 151 | 151 |
} |
| 152 | 152 |
continue |
| 153 | 153 |
} |
| ... | ... |
@@ -161,7 +161,7 @@ func (c *controller) getNetworksFromStore() ([]*network, error) {
|
| 161 | 161 |
ec := &endpointCnt{n: n}
|
| 162 | 162 |
err = store.GetObject(datastore.Key(ec.Key()...), ec) |
| 163 | 163 |
if err != nil && !n.inDelete {
|
| 164 |
- log.Warnf("could not find endpoint count key %s for network %s while listing: %v", datastore.Key(ec.Key()...), n.Name(), err)
|
|
| 164 |
+ logrus.Warnf("could not find endpoint count key %s for network %s while listing: %v", datastore.Key(ec.Key()...), n.Name(), err)
|
|
| 165 | 165 |
continue |
| 166 | 166 |
} |
| 167 | 167 |
|
| ... | ... |
@@ -185,7 +185,7 @@ func (n *network) getEndpointFromStore(eid string) (*endpoint, error) {
|
| 185 | 185 |
if err != nil {
|
| 186 | 186 |
if err != datastore.ErrKeyNotFound {
|
| 187 | 187 |
errors = append(errors, fmt.Sprintf("{%s:%v}, ", store.Scope(), err))
|
| 188 |
- log.Debugf("could not find endpoint %s in %s: %v", eid, store.Scope(), err)
|
|
| 188 |
+ logrus.Debugf("could not find endpoint %s in %s: %v", eid, store.Scope(), err)
|
|
| 189 | 189 |
} |
| 190 | 190 |
continue |
| 191 | 191 |
} |
| ... | ... |
@@ -203,7 +203,7 @@ func (n *network) getEndpointsFromStore() ([]*endpoint, error) {
|
| 203 | 203 |
// Continue searching in the next store if no keys found in this store |
| 204 | 204 |
if err != nil {
|
| 205 | 205 |
if err != datastore.ErrKeyNotFound {
|
| 206 |
- log.Debugf("failed to get endpoints for network %s scope %s: %v",
|
|
| 206 |
+ logrus.Debugf("failed to get endpoints for network %s scope %s: %v",
|
|
| 207 | 207 |
n.Name(), store.Scope(), err) |
| 208 | 208 |
} |
| 209 | 209 |
continue |
| ... | ... |
@@ -396,7 +396,7 @@ func (c *controller) processEndpointCreate(nmap map[string]*netWatch, ep *endpoi |
| 396 | 396 |
|
| 397 | 397 |
ch, err := store.Watch(ep.getNetwork().getEpCnt(), nw.stopCh) |
| 398 | 398 |
if err != nil {
|
| 399 |
- log.Warnf("Error creating watch for network: %v", err)
|
|
| 399 |
+ logrus.Warnf("Error creating watch for network: %v", err)
|
|
| 400 | 400 |
return |
| 401 | 401 |
} |
| 402 | 402 |
|
| ... | ... |
@@ -459,15 +459,15 @@ func (c *controller) startWatch() {
|
| 459 | 459 |
func (c *controller) networkCleanup() {
|
| 460 | 460 |
networks, err := c.getNetworksFromStore() |
| 461 | 461 |
if err != nil {
|
| 462 |
- log.Warnf("Could not retrieve networks from store(s) during network cleanup: %v", err)
|
|
| 462 |
+ logrus.Warnf("Could not retrieve networks from store(s) during network cleanup: %v", err)
|
|
| 463 | 463 |
return |
| 464 | 464 |
} |
| 465 | 465 |
|
| 466 | 466 |
for _, n := range networks {
|
| 467 | 467 |
if n.inDelete {
|
| 468 |
- log.Infof("Removing stale network %s (%s)", n.Name(), n.ID())
|
|
| 468 |
+ logrus.Infof("Removing stale network %s (%s)", n.Name(), n.ID())
|
|
| 469 | 469 |
if err := n.delete(true); err != nil {
|
| 470 |
- log.Debugf("Error while removing stale network: %v", err)
|
|
| 470 |
+ logrus.Debugf("Error while removing stale network: %v", err)
|
|
| 471 | 471 |
} |
| 472 | 472 |
} |
| 473 | 473 |
} |
| ... | ... |
@@ -476,7 +476,7 @@ func (c *controller) networkCleanup() {
|
| 476 | 476 |
var populateSpecial NetworkWalker = func(nw Network) bool {
|
| 477 | 477 |
if n := nw.(*network); n.hasSpecialDriver() {
|
| 478 | 478 |
if err := n.getController().addNetwork(n); err != nil {
|
| 479 |
- log.Warnf("Failed to populate network %q with driver %q", nw.Name(), nw.Type())
|
|
| 479 |
+ logrus.Warnf("Failed to populate network %q with driver %q", nw.Name(), nw.Type())
|
|
| 480 | 480 |
} |
| 481 | 481 |
} |
| 482 | 482 |
return false |
| 483 | 483 |
deleted file mode 100644 |
| ... | ... |
@@ -1,13 +0,0 @@ |
| 1 |
-package networkallocator |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "github.com/docker/libnetwork/drivers/overlay/ovmanager" |
|
| 5 |
- "github.com/docker/libnetwork/drivers/remote" |
|
| 6 |
-) |
|
| 7 |
- |
|
| 8 |
-func getInitializers() []initializer {
|
|
| 9 |
- return []initializer{
|
|
| 10 |
- {remote.Init, "remote"},
|
|
| 11 |
- {ovmanager.Init, "overlay"},
|
|
| 12 |
- } |
|
| 13 |
-} |
| 14 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,15 @@ |
| 0 |
+// +build linux windows |
|
| 1 |
+ |
|
| 2 |
+package networkallocator |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "github.com/docker/libnetwork/drivers/overlay/ovmanager" |
|
| 6 |
+ "github.com/docker/libnetwork/drivers/remote" |
|
| 7 |
+) |
|
| 8 |
+ |
|
| 9 |
+func getInitializers() []initializer {
|
|
| 10 |
+ return []initializer{
|
|
| 11 |
+ {remote.Init, "remote"},
|
|
| 12 |
+ {ovmanager.Init, "overlay"},
|
|
| 13 |
+ } |
|
| 14 |
+} |