Use tmp swarmkit fork for libnetwork import
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
This commit is contained in:
parent
a0a473125b
commit
7abc3e83c9
200 changed files with 31 additions and 45265 deletions
|
@ -145,7 +145,7 @@ github.com/klauspost/compress a3b7545c88eea469c2246bee0e6c
|
|||
github.com/pelletier/go-toml 65ca8064882c8c308e5c804c5d5443d409e0738c # v1.8.1
|
||||
|
||||
# cluster
|
||||
github.com/docker/swarmkit 5a5494a9a7b408b790533a5e4e1cb43ca1c32aad
|
||||
github.com/docker/swarmkit 60d87cb7cdb070801ec550d7f4d7dc1210fb7e9f git://github.com/cpuguy83/swarmkit.git
|
||||
github.com/gogo/protobuf b03c65ea87cdc3521ede29f62fe3ce239267c1bc # v1.3.2
|
||||
github.com/golang/protobuf 84668698ea25b64748563aa20726db66a6b8d299 # v1.3.5
|
||||
github.com/cloudflare/cfssl 5d63dbd981b5c408effbb58c442d54761ff94fbd # 1.3.2
|
||||
|
|
988
vendor/github.com/docker/libnetwork/agent.go
generated
vendored
988
vendor/github.com/docker/libnetwork/agent.go
generated
vendored
|
@ -1,988 +0,0 @@
|
|||
package libnetwork
|
||||
|
||||
//go:generate protoc -I.:Godeps/_workspace/src/github.com/gogo/protobuf --gogo_out=import_path=github.com/docker/libnetwork,Mgogoproto/gogo.proto=github.com/gogo/protobuf/gogoproto:. agent.proto
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"github.com/docker/go-events"
|
||||
"github.com/docker/libnetwork/cluster"
|
||||
"github.com/docker/libnetwork/datastore"
|
||||
"github.com/docker/libnetwork/discoverapi"
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/networkdb"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
subsysGossip = "networking:gossip"
|
||||
subsysIPSec = "networking:ipsec"
|
||||
keyringSize = 3
|
||||
)
|
||||
|
||||
// ByTime implements sort.Interface for []*types.EncryptionKey based on
|
||||
// the LamportTime field.
|
||||
type ByTime []*types.EncryptionKey
|
||||
|
||||
func (b ByTime) Len() int { return len(b) }
|
||||
func (b ByTime) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
|
||||
func (b ByTime) Less(i, j int) bool { return b[i].LamportTime < b[j].LamportTime }
|
||||
|
||||
type agent struct {
|
||||
networkDB *networkdb.NetworkDB
|
||||
bindAddr string
|
||||
advertiseAddr string
|
||||
dataPathAddr string
|
||||
coreCancelFuncs []func()
|
||||
driverCancelFuncs map[string][]func()
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
func (a *agent) dataPathAddress() string {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
if a.dataPathAddr != "" {
|
||||
return a.dataPathAddr
|
||||
}
|
||||
return a.advertiseAddr
|
||||
}
|
||||
|
||||
const libnetworkEPTable = "endpoint_table"
|
||||
|
||||
func getBindAddr(ifaceName string) (string, error) {
|
||||
iface, err := net.InterfaceByName(ifaceName)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to find interface %s: %v", ifaceName, err)
|
||||
}
|
||||
|
||||
addrs, err := iface.Addrs()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get interface addresses: %v", err)
|
||||
}
|
||||
|
||||
for _, a := range addrs {
|
||||
addr, ok := a.(*net.IPNet)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
addrIP := addr.IP
|
||||
|
||||
if addrIP.IsLinkLocalUnicast() {
|
||||
continue
|
||||
}
|
||||
|
||||
return addrIP.String(), nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("failed to get bind address")
|
||||
}
|
||||
|
||||
func resolveAddr(addrOrInterface string) (string, error) {
|
||||
// Try and see if this is a valid IP address
|
||||
if net.ParseIP(addrOrInterface) != nil {
|
||||
return addrOrInterface, nil
|
||||
}
|
||||
|
||||
addr, err := net.ResolveIPAddr("ip", addrOrInterface)
|
||||
if err != nil {
|
||||
// If not a valid IP address, it should be a valid interface
|
||||
return getBindAddr(addrOrInterface)
|
||||
}
|
||||
return addr.String(), nil
|
||||
}
|
||||
|
||||
func (c *controller) handleKeyChange(keys []*types.EncryptionKey) error {
|
||||
drvEnc := discoverapi.DriverEncryptionUpdate{}
|
||||
|
||||
a := c.getAgent()
|
||||
if a == nil {
|
||||
logrus.Debug("Skipping key change as agent is nil")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Find the deleted key. If the deleted key was the primary key,
|
||||
// a new primary key should be set before removing if from keyring.
|
||||
c.Lock()
|
||||
added := []byte{}
|
||||
deleted := []byte{}
|
||||
j := len(c.keys)
|
||||
for i := 0; i < j; {
|
||||
same := false
|
||||
for _, key := range keys {
|
||||
if same = key.LamportTime == c.keys[i].LamportTime; same {
|
||||
break
|
||||
}
|
||||
}
|
||||
if !same {
|
||||
cKey := c.keys[i]
|
||||
if cKey.Subsystem == subsysGossip {
|
||||
deleted = cKey.Key
|
||||
}
|
||||
|
||||
if cKey.Subsystem == subsysIPSec {
|
||||
drvEnc.Prune = cKey.Key
|
||||
drvEnc.PruneTag = cKey.LamportTime
|
||||
}
|
||||
c.keys[i], c.keys[j-1] = c.keys[j-1], c.keys[i]
|
||||
c.keys[j-1] = nil
|
||||
j--
|
||||
}
|
||||
i++
|
||||
}
|
||||
c.keys = c.keys[:j]
|
||||
|
||||
// Find the new key and add it to the key ring
|
||||
for _, key := range keys {
|
||||
same := false
|
||||
for _, cKey := range c.keys {
|
||||
if same = cKey.LamportTime == key.LamportTime; same {
|
||||
break
|
||||
}
|
||||
}
|
||||
if !same {
|
||||
c.keys = append(c.keys, key)
|
||||
if key.Subsystem == subsysGossip {
|
||||
added = key.Key
|
||||
}
|
||||
|
||||
if key.Subsystem == subsysIPSec {
|
||||
drvEnc.Key = key.Key
|
||||
drvEnc.Tag = key.LamportTime
|
||||
}
|
||||
}
|
||||
}
|
||||
c.Unlock()
|
||||
|
||||
if len(added) > 0 {
|
||||
a.networkDB.SetKey(added)
|
||||
}
|
||||
|
||||
key, _, err := c.getPrimaryKeyTag(subsysGossip)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.networkDB.SetPrimaryKey(key)
|
||||
|
||||
key, tag, err := c.getPrimaryKeyTag(subsysIPSec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
drvEnc.Primary = key
|
||||
drvEnc.PrimaryTag = tag
|
||||
|
||||
if len(deleted) > 0 {
|
||||
a.networkDB.RemoveKey(deleted)
|
||||
}
|
||||
|
||||
c.drvRegistry.WalkDrivers(func(name string, driver driverapi.Driver, capability driverapi.Capability) bool {
|
||||
err := driver.DiscoverNew(discoverapi.EncryptionKeysUpdate, drvEnc)
|
||||
if err != nil {
|
||||
logrus.Warnf("Failed to update datapath keys in driver %s: %v", name, err)
|
||||
// Attempt to reconfigure keys in case of a update failure
|
||||
// which can arise due to a mismatch of keys
|
||||
// if worker nodes get temporarily disconnected
|
||||
logrus.Warnf("Reconfiguring datapath keys for %s", name)
|
||||
drvCfgEnc := discoverapi.DriverEncryptionConfig{}
|
||||
drvCfgEnc.Keys, drvCfgEnc.Tags = c.getKeys(subsysIPSec)
|
||||
err = driver.DiscoverNew(discoverapi.EncryptionKeysConfig, drvCfgEnc)
|
||||
if err != nil {
|
||||
logrus.Warnf("Failed to reset datapath keys in driver %s: %v", name, err)
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *controller) agentSetup(clusterProvider cluster.Provider) error {
|
||||
agent := c.getAgent()
|
||||
|
||||
// If the agent is already present there is no need to try to initialize it again
|
||||
if agent != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
bindAddr := clusterProvider.GetLocalAddress()
|
||||
advAddr := clusterProvider.GetAdvertiseAddress()
|
||||
dataAddr := clusterProvider.GetDataPathAddress()
|
||||
remoteList := clusterProvider.GetRemoteAddressList()
|
||||
remoteAddrList := make([]string, 0, len(remoteList))
|
||||
for _, remote := range remoteList {
|
||||
addr, _, _ := net.SplitHostPort(remote)
|
||||
remoteAddrList = append(remoteAddrList, addr)
|
||||
}
|
||||
|
||||
listen := clusterProvider.GetListenAddress()
|
||||
listenAddr, _, _ := net.SplitHostPort(listen)
|
||||
|
||||
logrus.Infof("Initializing Libnetwork Agent Listen-Addr=%s Local-addr=%s Adv-addr=%s Data-addr=%s Remote-addr-list=%v MTU=%d",
|
||||
listenAddr, bindAddr, advAddr, dataAddr, remoteAddrList, c.Config().Daemon.NetworkControlPlaneMTU)
|
||||
if advAddr != "" && agent == nil {
|
||||
if err := c.agentInit(listenAddr, bindAddr, advAddr, dataAddr); err != nil {
|
||||
logrus.Errorf("error in agentInit: %v", err)
|
||||
return err
|
||||
}
|
||||
c.drvRegistry.WalkDrivers(func(name string, driver driverapi.Driver, capability driverapi.Capability) bool {
|
||||
if capability.ConnectivityScope == datastore.GlobalScope {
|
||||
c.agentDriverNotify(driver)
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
if len(remoteAddrList) > 0 {
|
||||
if err := c.agentJoin(remoteAddrList); err != nil {
|
||||
logrus.Errorf("Error in joining gossip cluster : %v(join will be retried in background)", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// For a given subsystem getKeys sorts the keys by lamport time and returns
|
||||
// slice of keys and lamport time which can used as a unique tag for the keys
|
||||
func (c *controller) getKeys(subsys string) ([][]byte, []uint64) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
sort.Sort(ByTime(c.keys))
|
||||
|
||||
keys := [][]byte{}
|
||||
tags := []uint64{}
|
||||
for _, key := range c.keys {
|
||||
if key.Subsystem == subsys {
|
||||
keys = append(keys, key.Key)
|
||||
tags = append(tags, key.LamportTime)
|
||||
}
|
||||
}
|
||||
|
||||
keys[0], keys[1] = keys[1], keys[0]
|
||||
tags[0], tags[1] = tags[1], tags[0]
|
||||
return keys, tags
|
||||
}
|
||||
|
||||
// getPrimaryKeyTag returns the primary key for a given subsystem from the
|
||||
// list of sorted key and the associated tag
|
||||
func (c *controller) getPrimaryKeyTag(subsys string) ([]byte, uint64, error) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
sort.Sort(ByTime(c.keys))
|
||||
keys := []*types.EncryptionKey{}
|
||||
for _, key := range c.keys {
|
||||
if key.Subsystem == subsys {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
}
|
||||
return keys[1].Key, keys[1].LamportTime, nil
|
||||
}
|
||||
|
||||
func (c *controller) agentInit(listenAddr, bindAddrOrInterface, advertiseAddr, dataPathAddr string) error {
|
||||
bindAddr, err := resolveAddr(bindAddrOrInterface)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
keys, _ := c.getKeys(subsysGossip)
|
||||
|
||||
netDBConf := networkdb.DefaultConfig()
|
||||
netDBConf.BindAddr = listenAddr
|
||||
netDBConf.AdvertiseAddr = advertiseAddr
|
||||
netDBConf.Keys = keys
|
||||
if c.Config().Daemon.NetworkControlPlaneMTU != 0 {
|
||||
// Consider the MTU remove the IP hdr (IPv4 or IPv6) and the TCP/UDP hdr.
|
||||
// To be on the safe side let's cut 100 bytes
|
||||
netDBConf.PacketBufferSize = (c.Config().Daemon.NetworkControlPlaneMTU - 100)
|
||||
logrus.Debugf("Control plane MTU: %d will initialize NetworkDB with: %d",
|
||||
c.Config().Daemon.NetworkControlPlaneMTU, netDBConf.PacketBufferSize)
|
||||
}
|
||||
nDB, err := networkdb.New(netDBConf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Register the diagnostic handlers
|
||||
c.DiagnosticServer.RegisterHandler(nDB, networkdb.NetDbPaths2Func)
|
||||
|
||||
var cancelList []func()
|
||||
ch, cancel := nDB.Watch(libnetworkEPTable, "", "")
|
||||
cancelList = append(cancelList, cancel)
|
||||
nodeCh, cancel := nDB.Watch(networkdb.NodeTable, "", "")
|
||||
cancelList = append(cancelList, cancel)
|
||||
|
||||
c.Lock()
|
||||
c.agent = &agent{
|
||||
networkDB: nDB,
|
||||
bindAddr: bindAddr,
|
||||
advertiseAddr: advertiseAddr,
|
||||
dataPathAddr: dataPathAddr,
|
||||
coreCancelFuncs: cancelList,
|
||||
driverCancelFuncs: make(map[string][]func()),
|
||||
}
|
||||
c.Unlock()
|
||||
|
||||
go c.handleTableEvents(ch, c.handleEpTableEvent)
|
||||
go c.handleTableEvents(nodeCh, c.handleNodeTableEvent)
|
||||
|
||||
drvEnc := discoverapi.DriverEncryptionConfig{}
|
||||
keys, tags := c.getKeys(subsysIPSec)
|
||||
drvEnc.Keys = keys
|
||||
drvEnc.Tags = tags
|
||||
|
||||
c.drvRegistry.WalkDrivers(func(name string, driver driverapi.Driver, capability driverapi.Capability) bool {
|
||||
err := driver.DiscoverNew(discoverapi.EncryptionKeysConfig, drvEnc)
|
||||
if err != nil {
|
||||
logrus.Warnf("Failed to set datapath keys in driver %s: %v", name, err)
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
c.WalkNetworks(joinCluster)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *controller) agentJoin(remoteAddrList []string) error {
|
||||
agent := c.getAgent()
|
||||
if agent == nil {
|
||||
return nil
|
||||
}
|
||||
return agent.networkDB.Join(remoteAddrList)
|
||||
}
|
||||
|
||||
func (c *controller) agentDriverNotify(d driverapi.Driver) {
|
||||
agent := c.getAgent()
|
||||
if agent == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := d.DiscoverNew(discoverapi.NodeDiscovery, discoverapi.NodeDiscoveryData{
|
||||
Address: agent.dataPathAddress(),
|
||||
BindAddress: agent.bindAddr,
|
||||
Self: true,
|
||||
}); err != nil {
|
||||
logrus.Warnf("Failed the node discovery in driver: %v", err)
|
||||
}
|
||||
|
||||
drvEnc := discoverapi.DriverEncryptionConfig{}
|
||||
keys, tags := c.getKeys(subsysIPSec)
|
||||
drvEnc.Keys = keys
|
||||
drvEnc.Tags = tags
|
||||
|
||||
if err := d.DiscoverNew(discoverapi.EncryptionKeysConfig, drvEnc); err != nil {
|
||||
logrus.Warnf("Failed to set datapath keys in driver: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *controller) agentClose() {
|
||||
// Acquire current agent instance and reset its pointer
|
||||
// then run closing functions
|
||||
c.Lock()
|
||||
agent := c.agent
|
||||
c.agent = nil
|
||||
c.Unlock()
|
||||
|
||||
// when the agent is closed the cluster provider should be cleaned up
|
||||
c.SetClusterProvider(nil)
|
||||
|
||||
if agent == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var cancelList []func()
|
||||
|
||||
agent.Lock()
|
||||
for _, cancelFuncs := range agent.driverCancelFuncs {
|
||||
cancelList = append(cancelList, cancelFuncs...)
|
||||
}
|
||||
|
||||
// Add also the cancel functions for the network db
|
||||
cancelList = append(cancelList, agent.coreCancelFuncs...)
|
||||
agent.Unlock()
|
||||
|
||||
for _, cancel := range cancelList {
|
||||
cancel()
|
||||
}
|
||||
|
||||
agent.networkDB.Close()
|
||||
}
|
||||
|
||||
// Task has the backend container details
|
||||
type Task struct {
|
||||
Name string
|
||||
EndpointID string
|
||||
EndpointIP string
|
||||
Info map[string]string
|
||||
}
|
||||
|
||||
// ServiceInfo has service specific details along with the list of backend tasks
|
||||
type ServiceInfo struct {
|
||||
VIP string
|
||||
LocalLBIndex int
|
||||
Tasks []Task
|
||||
Ports []string
|
||||
}
|
||||
|
||||
type epRecord struct {
|
||||
ep EndpointRecord
|
||||
info map[string]string
|
||||
lbIndex int
|
||||
}
|
||||
|
||||
func (n *network) Services() map[string]ServiceInfo {
|
||||
eps := make(map[string]epRecord)
|
||||
|
||||
if !n.isClusterEligible() {
|
||||
return nil
|
||||
}
|
||||
agent := n.getController().getAgent()
|
||||
if agent == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Walk through libnetworkEPTable and fetch the driver agnostic endpoint info
|
||||
entries := agent.networkDB.GetTableByNetwork(libnetworkEPTable, n.id)
|
||||
for eid, value := range entries {
|
||||
var epRec EndpointRecord
|
||||
nid := n.ID()
|
||||
if err := proto.Unmarshal(value.Value, &epRec); err != nil {
|
||||
logrus.Errorf("Unmarshal of libnetworkEPTable failed for endpoint %s in network %s, %v", eid, nid, err)
|
||||
continue
|
||||
}
|
||||
i := n.getController().getLBIndex(epRec.ServiceID, nid, epRec.IngressPorts)
|
||||
eps[eid] = epRecord{
|
||||
ep: epRec,
|
||||
lbIndex: i,
|
||||
}
|
||||
}
|
||||
|
||||
// Walk through the driver's tables, have the driver decode the entries
|
||||
// and return the tuple {ep ID, value}. value is a string that coveys
|
||||
// relevant info about the endpoint.
|
||||
d, err := n.driver(true)
|
||||
if err != nil {
|
||||
logrus.Errorf("Could not resolve driver for network %s/%s while fetching services: %v", n.networkType, n.ID(), err)
|
||||
return nil
|
||||
}
|
||||
for _, table := range n.driverTables {
|
||||
if table.objType != driverapi.EndpointObject {
|
||||
continue
|
||||
}
|
||||
entries := agent.networkDB.GetTableByNetwork(table.name, n.id)
|
||||
for key, value := range entries {
|
||||
epID, info := d.DecodeTableEntry(table.name, key, value.Value)
|
||||
if ep, ok := eps[epID]; !ok {
|
||||
logrus.Errorf("Inconsistent driver and libnetwork state for endpoint %s", epID)
|
||||
} else {
|
||||
ep.info = info
|
||||
eps[epID] = ep
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// group the endpoints into a map keyed by the service name
|
||||
sinfo := make(map[string]ServiceInfo)
|
||||
for ep, epr := range eps {
|
||||
var (
|
||||
s ServiceInfo
|
||||
ok bool
|
||||
)
|
||||
if s, ok = sinfo[epr.ep.ServiceName]; !ok {
|
||||
s = ServiceInfo{
|
||||
VIP: epr.ep.VirtualIP,
|
||||
LocalLBIndex: epr.lbIndex,
|
||||
}
|
||||
}
|
||||
ports := []string{}
|
||||
if s.Ports == nil {
|
||||
for _, port := range epr.ep.IngressPorts {
|
||||
p := fmt.Sprintf("Target: %d, Publish: %d", port.TargetPort, port.PublishedPort)
|
||||
ports = append(ports, p)
|
||||
}
|
||||
s.Ports = ports
|
||||
}
|
||||
s.Tasks = append(s.Tasks, Task{
|
||||
Name: epr.ep.Name,
|
||||
EndpointID: ep,
|
||||
EndpointIP: epr.ep.EndpointIP,
|
||||
Info: epr.info,
|
||||
})
|
||||
sinfo[epr.ep.ServiceName] = s
|
||||
}
|
||||
return sinfo
|
||||
}
|
||||
|
||||
func (n *network) isClusterEligible() bool {
|
||||
if n.scope != datastore.SwarmScope || !n.driverIsMultihost() {
|
||||
return false
|
||||
}
|
||||
return n.getController().getAgent() != nil
|
||||
}
|
||||
|
||||
func (n *network) joinCluster() error {
|
||||
if !n.isClusterEligible() {
|
||||
return nil
|
||||
}
|
||||
|
||||
agent := n.getController().getAgent()
|
||||
if agent == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return agent.networkDB.JoinNetwork(n.ID())
|
||||
}
|
||||
|
||||
func (n *network) leaveCluster() error {
|
||||
if !n.isClusterEligible() {
|
||||
return nil
|
||||
}
|
||||
|
||||
agent := n.getController().getAgent()
|
||||
if agent == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return agent.networkDB.LeaveNetwork(n.ID())
|
||||
}
|
||||
|
||||
func (ep *endpoint) addDriverInfoToCluster() error {
|
||||
n := ep.getNetwork()
|
||||
if !n.isClusterEligible() {
|
||||
return nil
|
||||
}
|
||||
if ep.joinInfo == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
agent := n.getController().getAgent()
|
||||
if agent == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, te := range ep.joinInfo.driverTableEntries {
|
||||
if err := agent.networkDB.CreateEntry(te.tableName, n.ID(), te.key, te.value); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ep *endpoint) deleteDriverInfoFromCluster() error {
|
||||
n := ep.getNetwork()
|
||||
if !n.isClusterEligible() {
|
||||
return nil
|
||||
}
|
||||
if ep.joinInfo == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
agent := n.getController().getAgent()
|
||||
if agent == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, te := range ep.joinInfo.driverTableEntries {
|
||||
if err := agent.networkDB.DeleteEntry(te.tableName, n.ID(), te.key); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ep *endpoint) addServiceInfoToCluster(sb *sandbox) error {
|
||||
if ep.isAnonymous() && len(ep.myAliases) == 0 || ep.Iface() == nil || ep.Iface().Address() == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
n := ep.getNetwork()
|
||||
if !n.isClusterEligible() {
|
||||
return nil
|
||||
}
|
||||
|
||||
sb.Service.Lock()
|
||||
defer sb.Service.Unlock()
|
||||
logrus.Debugf("addServiceInfoToCluster START for %s %s", ep.svcName, ep.ID())
|
||||
|
||||
// Check that the endpoint is still present on the sandbox before adding it to the service discovery.
|
||||
// This is to handle a race between the EnableService and the sbLeave
|
||||
// It is possible that the EnableService starts, fetches the list of the endpoints and
|
||||
// by the time the addServiceInfoToCluster is called the endpoint got removed from the sandbox
|
||||
// The risk is that the deleteServiceInfoToCluster happens before the addServiceInfoToCluster.
|
||||
// This check under the Service lock of the sandbox ensure the correct behavior.
|
||||
// If the addServiceInfoToCluster arrives first may find or not the endpoint and will proceed or exit
|
||||
// but in any case the deleteServiceInfoToCluster will follow doing the cleanup if needed.
|
||||
// In case the deleteServiceInfoToCluster arrives first, this one is happening after the endpoint is
|
||||
// removed from the list, in this situation the delete will bail out not finding any data to cleanup
|
||||
// and the add will bail out not finding the endpoint on the sandbox.
|
||||
if e := sb.getEndpoint(ep.ID()); e == nil {
|
||||
logrus.Warnf("addServiceInfoToCluster suppressing service resolution ep is not anymore in the sandbox %s", ep.ID())
|
||||
return nil
|
||||
}
|
||||
|
||||
c := n.getController()
|
||||
agent := c.getAgent()
|
||||
|
||||
name := ep.Name()
|
||||
if ep.isAnonymous() {
|
||||
name = ep.MyAliases()[0]
|
||||
}
|
||||
|
||||
var ingressPorts []*PortConfig
|
||||
if ep.svcID != "" {
|
||||
// This is a task part of a service
|
||||
// Gossip ingress ports only in ingress network.
|
||||
if n.ingress {
|
||||
ingressPorts = ep.ingressPorts
|
||||
}
|
||||
if err := c.addServiceBinding(ep.svcName, ep.svcID, n.ID(), ep.ID(), name, ep.virtualIP, ingressPorts, ep.svcAliases, ep.myAliases, ep.Iface().Address().IP, "addServiceInfoToCluster"); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// This is a container simply attached to an attachable network
|
||||
if err := c.addContainerNameResolution(n.ID(), ep.ID(), name, ep.myAliases, ep.Iface().Address().IP, "addServiceInfoToCluster"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
buf, err := proto.Marshal(&EndpointRecord{
|
||||
Name: name,
|
||||
ServiceName: ep.svcName,
|
||||
ServiceID: ep.svcID,
|
||||
VirtualIP: ep.virtualIP.String(),
|
||||
IngressPorts: ingressPorts,
|
||||
Aliases: ep.svcAliases,
|
||||
TaskAliases: ep.myAliases,
|
||||
EndpointIP: ep.Iface().Address().IP.String(),
|
||||
ServiceDisabled: false,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if agent != nil {
|
||||
if err := agent.networkDB.CreateEntry(libnetworkEPTable, n.ID(), ep.ID(), buf); err != nil {
|
||||
logrus.Warnf("addServiceInfoToCluster NetworkDB CreateEntry failed for %s %s err:%s", ep.id, n.id, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
logrus.Debugf("addServiceInfoToCluster END for %s %s", ep.svcName, ep.ID())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ep *endpoint) deleteServiceInfoFromCluster(sb *sandbox, fullRemove bool, method string) error {
|
||||
if ep.isAnonymous() && len(ep.myAliases) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
n := ep.getNetwork()
|
||||
if !n.isClusterEligible() {
|
||||
return nil
|
||||
}
|
||||
|
||||
sb.Service.Lock()
|
||||
defer sb.Service.Unlock()
|
||||
logrus.Debugf("deleteServiceInfoFromCluster from %s START for %s %s", method, ep.svcName, ep.ID())
|
||||
|
||||
// Avoid a race w/ with a container that aborts preemptively. This would
|
||||
// get caught in disableServceInNetworkDB, but we check here to make the
|
||||
// nature of the condition more clear.
|
||||
// See comment in addServiceInfoToCluster()
|
||||
if e := sb.getEndpoint(ep.ID()); e == nil {
|
||||
logrus.Warnf("deleteServiceInfoFromCluster suppressing service resolution ep is not anymore in the sandbox %s", ep.ID())
|
||||
return nil
|
||||
}
|
||||
|
||||
c := n.getController()
|
||||
agent := c.getAgent()
|
||||
|
||||
name := ep.Name()
|
||||
if ep.isAnonymous() {
|
||||
name = ep.MyAliases()[0]
|
||||
}
|
||||
|
||||
if agent != nil {
|
||||
// First update the networkDB then locally
|
||||
if fullRemove {
|
||||
if err := agent.networkDB.DeleteEntry(libnetworkEPTable, n.ID(), ep.ID()); err != nil {
|
||||
logrus.Warnf("deleteServiceInfoFromCluster NetworkDB DeleteEntry failed for %s %s err:%s", ep.id, n.id, err)
|
||||
}
|
||||
} else {
|
||||
disableServiceInNetworkDB(agent, n, ep)
|
||||
}
|
||||
}
|
||||
|
||||
if ep.Iface() != nil && ep.Iface().Address() != nil {
|
||||
if ep.svcID != "" {
|
||||
// This is a task part of a service
|
||||
var ingressPorts []*PortConfig
|
||||
if n.ingress {
|
||||
ingressPorts = ep.ingressPorts
|
||||
}
|
||||
if err := c.rmServiceBinding(ep.svcName, ep.svcID, n.ID(), ep.ID(), name, ep.virtualIP, ingressPorts, ep.svcAliases, ep.myAliases, ep.Iface().Address().IP, "deleteServiceInfoFromCluster", true, fullRemove); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// This is a container simply attached to an attachable network
|
||||
if err := c.delContainerNameResolution(n.ID(), ep.ID(), name, ep.myAliases, ep.Iface().Address().IP, "deleteServiceInfoFromCluster"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logrus.Debugf("deleteServiceInfoFromCluster from %s END for %s %s", method, ep.svcName, ep.ID())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func disableServiceInNetworkDB(a *agent, n *network, ep *endpoint) {
|
||||
var epRec EndpointRecord
|
||||
|
||||
logrus.Debugf("disableServiceInNetworkDB for %s %s", ep.svcName, ep.ID())
|
||||
|
||||
// Update existing record to indicate that the service is disabled
|
||||
inBuf, err := a.networkDB.GetEntry(libnetworkEPTable, n.ID(), ep.ID())
|
||||
if err != nil {
|
||||
logrus.Warnf("disableServiceInNetworkDB GetEntry failed for %s %s err:%s", ep.id, n.id, err)
|
||||
return
|
||||
}
|
||||
// Should never fail
|
||||
if err := proto.Unmarshal(inBuf, &epRec); err != nil {
|
||||
logrus.Errorf("disableServiceInNetworkDB unmarshal failed for %s %s err:%s", ep.id, n.id, err)
|
||||
return
|
||||
}
|
||||
epRec.ServiceDisabled = true
|
||||
// Should never fail
|
||||
outBuf, err := proto.Marshal(&epRec)
|
||||
if err != nil {
|
||||
logrus.Errorf("disableServiceInNetworkDB marshalling failed for %s %s err:%s", ep.id, n.id, err)
|
||||
return
|
||||
}
|
||||
// Send update to the whole cluster
|
||||
if err := a.networkDB.UpdateEntry(libnetworkEPTable, n.ID(), ep.ID(), outBuf); err != nil {
|
||||
logrus.Warnf("disableServiceInNetworkDB UpdateEntry failed for %s %s err:%s", ep.id, n.id, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (n *network) addDriverWatches() {
|
||||
if !n.isClusterEligible() {
|
||||
return
|
||||
}
|
||||
|
||||
c := n.getController()
|
||||
agent := c.getAgent()
|
||||
if agent == nil {
|
||||
return
|
||||
}
|
||||
for _, table := range n.driverTables {
|
||||
ch, cancel := agent.networkDB.Watch(table.name, n.ID(), "")
|
||||
agent.Lock()
|
||||
agent.driverCancelFuncs[n.ID()] = append(agent.driverCancelFuncs[n.ID()], cancel)
|
||||
agent.Unlock()
|
||||
go c.handleTableEvents(ch, n.handleDriverTableEvent)
|
||||
d, err := n.driver(false)
|
||||
if err != nil {
|
||||
logrus.Errorf("Could not resolve driver %s while walking driver tabl: %v", n.networkType, err)
|
||||
return
|
||||
}
|
||||
|
||||
agent.networkDB.WalkTable(table.name, func(nid, key string, value []byte, deleted bool) bool {
|
||||
// skip the entries that are mark for deletion, this is safe because this function is
|
||||
// called at initialization time so there is no state to delete
|
||||
if nid == n.ID() && !deleted {
|
||||
d.EventNotify(driverapi.Create, nid, table.name, key, value)
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (n *network) cancelDriverWatches() {
|
||||
if !n.isClusterEligible() {
|
||||
return
|
||||
}
|
||||
|
||||
agent := n.getController().getAgent()
|
||||
if agent == nil {
|
||||
return
|
||||
}
|
||||
|
||||
agent.Lock()
|
||||
cancelFuncs := agent.driverCancelFuncs[n.ID()]
|
||||
delete(agent.driverCancelFuncs, n.ID())
|
||||
agent.Unlock()
|
||||
|
||||
for _, cancel := range cancelFuncs {
|
||||
cancel()
|
||||
}
|
||||
}
|
||||
|
||||
func (c *controller) handleTableEvents(ch *events.Channel, fn func(events.Event)) {
|
||||
for {
|
||||
select {
|
||||
case ev := <-ch.C:
|
||||
fn(ev)
|
||||
case <-ch.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (n *network) handleDriverTableEvent(ev events.Event) {
|
||||
d, err := n.driver(false)
|
||||
if err != nil {
|
||||
logrus.Errorf("Could not resolve driver %s while handling driver table event: %v", n.networkType, err)
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
etype driverapi.EventType
|
||||
tname string
|
||||
key string
|
||||
value []byte
|
||||
)
|
||||
|
||||
switch event := ev.(type) {
|
||||
case networkdb.CreateEvent:
|
||||
tname = event.Table
|
||||
key = event.Key
|
||||
value = event.Value
|
||||
etype = driverapi.Create
|
||||
case networkdb.DeleteEvent:
|
||||
tname = event.Table
|
||||
key = event.Key
|
||||
value = event.Value
|
||||
etype = driverapi.Delete
|
||||
case networkdb.UpdateEvent:
|
||||
tname = event.Table
|
||||
key = event.Key
|
||||
value = event.Value
|
||||
etype = driverapi.Delete
|
||||
}
|
||||
|
||||
d.EventNotify(etype, n.ID(), tname, key, value)
|
||||
}
|
||||
|
||||
func (c *controller) handleNodeTableEvent(ev events.Event) {
|
||||
var (
|
||||
value []byte
|
||||
isAdd bool
|
||||
nodeAddr networkdb.NodeAddr
|
||||
)
|
||||
switch event := ev.(type) {
|
||||
case networkdb.CreateEvent:
|
||||
value = event.Value
|
||||
isAdd = true
|
||||
case networkdb.DeleteEvent:
|
||||
value = event.Value
|
||||
case networkdb.UpdateEvent:
|
||||
logrus.Errorf("Unexpected update node table event = %#v", event)
|
||||
}
|
||||
|
||||
err := json.Unmarshal(value, &nodeAddr)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error unmarshalling node table event %v", err)
|
||||
return
|
||||
}
|
||||
c.processNodeDiscovery([]net.IP{nodeAddr.Addr}, isAdd)
|
||||
|
||||
}
|
||||
|
||||
func (c *controller) handleEpTableEvent(ev events.Event) {
|
||||
var (
|
||||
nid string
|
||||
eid string
|
||||
value []byte
|
||||
epRec EndpointRecord
|
||||
)
|
||||
|
||||
switch event := ev.(type) {
|
||||
case networkdb.CreateEvent:
|
||||
nid = event.NetworkID
|
||||
eid = event.Key
|
||||
value = event.Value
|
||||
case networkdb.DeleteEvent:
|
||||
nid = event.NetworkID
|
||||
eid = event.Key
|
||||
value = event.Value
|
||||
case networkdb.UpdateEvent:
|
||||
nid = event.NetworkID
|
||||
eid = event.Key
|
||||
value = event.Value
|
||||
default:
|
||||
logrus.Errorf("Unexpected update service table event = %#v", event)
|
||||
return
|
||||
}
|
||||
|
||||
err := proto.Unmarshal(value, &epRec)
|
||||
if err != nil {
|
||||
logrus.Errorf("Failed to unmarshal service table value: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
containerName := epRec.Name
|
||||
svcName := epRec.ServiceName
|
||||
svcID := epRec.ServiceID
|
||||
vip := net.ParseIP(epRec.VirtualIP)
|
||||
ip := net.ParseIP(epRec.EndpointIP)
|
||||
ingressPorts := epRec.IngressPorts
|
||||
serviceAliases := epRec.Aliases
|
||||
taskAliases := epRec.TaskAliases
|
||||
|
||||
if containerName == "" || ip == nil {
|
||||
logrus.Errorf("Invalid endpoint name/ip received while handling service table event %s", value)
|
||||
return
|
||||
}
|
||||
|
||||
switch ev.(type) {
|
||||
case networkdb.CreateEvent:
|
||||
logrus.Debugf("handleEpTableEvent ADD %s R:%v", eid, epRec)
|
||||
if svcID != "" {
|
||||
// This is a remote task part of a service
|
||||
if err := c.addServiceBinding(svcName, svcID, nid, eid, containerName, vip, ingressPorts, serviceAliases, taskAliases, ip, "handleEpTableEvent"); err != nil {
|
||||
logrus.Errorf("failed adding service binding for %s epRec:%v err:%v", eid, epRec, err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// This is a remote container simply attached to an attachable network
|
||||
if err := c.addContainerNameResolution(nid, eid, containerName, taskAliases, ip, "handleEpTableEvent"); err != nil {
|
||||
logrus.Errorf("failed adding container name resolution for %s epRec:%v err:%v", eid, epRec, err)
|
||||
}
|
||||
}
|
||||
|
||||
case networkdb.DeleteEvent:
|
||||
logrus.Debugf("handleEpTableEvent DEL %s R:%v", eid, epRec)
|
||||
if svcID != "" {
|
||||
// This is a remote task part of a service
|
||||
if err := c.rmServiceBinding(svcName, svcID, nid, eid, containerName, vip, ingressPorts, serviceAliases, taskAliases, ip, "handleEpTableEvent", true, true); err != nil {
|
||||
logrus.Errorf("failed removing service binding for %s epRec:%v err:%v", eid, epRec, err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// This is a remote container simply attached to an attachable network
|
||||
if err := c.delContainerNameResolution(nid, eid, containerName, taskAliases, ip, "handleEpTableEvent"); err != nil {
|
||||
logrus.Errorf("failed removing container name resolution for %s epRec:%v err:%v", eid, epRec, err)
|
||||
}
|
||||
}
|
||||
case networkdb.UpdateEvent:
|
||||
logrus.Debugf("handleEpTableEvent UPD %s R:%v", eid, epRec)
|
||||
// We currently should only get these to inform us that an endpoint
|
||||
// is disabled. Report if otherwise.
|
||||
if svcID == "" || !epRec.ServiceDisabled {
|
||||
logrus.Errorf("Unexpected update table event for %s epRec:%v", eid, epRec)
|
||||
return
|
||||
}
|
||||
// This is a remote task that is part of a service that is now disabled
|
||||
if err := c.rmServiceBinding(svcName, svcID, nid, eid, containerName, vip, ingressPorts, serviceAliases, taskAliases, ip, "handleEpTableEvent", true, false); err != nil {
|
||||
logrus.Errorf("failed disabling service binding for %s epRec:%v err:%v", eid, epRec, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
1095
vendor/github.com/docker/libnetwork/agent.pb.go
generated
vendored
1095
vendor/github.com/docker/libnetwork/agent.pb.go
generated
vendored
File diff suppressed because it is too large
Load diff
76
vendor/github.com/docker/libnetwork/agent.proto
generated
vendored
76
vendor/github.com/docker/libnetwork/agent.proto
generated
vendored
|
@ -1,76 +0,0 @@
|
|||
syntax = "proto3";
|
||||
|
||||
import "gogoproto/gogo.proto";
|
||||
|
||||
package libnetwork;
|
||||
|
||||
option (gogoproto.marshaler_all) = true;
|
||||
option (gogoproto.unmarshaler_all) = true;
|
||||
option (gogoproto.stringer_all) = true;
|
||||
option (gogoproto.gostring_all) = true;
|
||||
option (gogoproto.sizer_all) = true;
|
||||
option (gogoproto.goproto_stringer_all) = false;
|
||||
|
||||
// EndpointRecord specifies all the endpoint specific information that
|
||||
// needs to gossiped to nodes participating in the network.
|
||||
message EndpointRecord {
|
||||
// Name of the container
|
||||
string name = 1;
|
||||
|
||||
// Service name of the service to which this endpoint belongs.
|
||||
string service_name = 2;
|
||||
|
||||
// Service ID of the service to which this endpoint belongs.
|
||||
string service_id = 3 [(gogoproto.customname) = "ServiceID"];
|
||||
|
||||
// Virtual IP of the service to which this endpoint belongs.
|
||||
string virtual_ip = 4 [(gogoproto.customname) = "VirtualIP"];
|
||||
|
||||
// IP assigned to this endpoint.
|
||||
string endpoint_ip = 5 [(gogoproto.customname) = "EndpointIP"];
|
||||
|
||||
// IngressPorts exposed by the service to which this endpoint belongs.
|
||||
repeated PortConfig ingress_ports = 6;
|
||||
|
||||
// A list of aliases which are alternate names for the service
|
||||
repeated string aliases = 7;
|
||||
|
||||
// List of aliases task specific aliases
|
||||
repeated string task_aliases = 8;
|
||||
|
||||
// Whether this enpoint's service has been disabled
|
||||
bool service_disabled = 9;
|
||||
}
|
||||
|
||||
// PortConfig specifies an exposed port which can be
|
||||
// addressed using the given name. This can be later queried
|
||||
// using a service discovery api or a DNS SRV query. The node
|
||||
// port specifies a port that can be used to address this
|
||||
// service external to the cluster by sending a connection
|
||||
// request to this port to any node on the cluster.
|
||||
message PortConfig {
|
||||
enum Protocol {
|
||||
option (gogoproto.goproto_enum_prefix) = false;
|
||||
|
||||
TCP = 0 [(gogoproto.enumvalue_customname) = "ProtocolTCP"];
|
||||
UDP = 1 [(gogoproto.enumvalue_customname) = "ProtocolUDP"];
|
||||
SCTP = 2 [(gogoproto.enumvalue_customname) = "ProtocolSCTP"];
|
||||
}
|
||||
|
||||
// Name for the port. If provided the port information can
|
||||
// be queried using the name as in a DNS SRV query.
|
||||
string name = 1;
|
||||
|
||||
// Protocol for the port which is exposed.
|
||||
Protocol protocol = 2;
|
||||
|
||||
// The port which the application is exposing and is bound to.
|
||||
uint32 target_port = 3;
|
||||
|
||||
// PublishedPort specifies the port on which the service is
|
||||
// exposed on all nodes on the cluster. If not specified an
|
||||
// arbitrary port in the node port range is allocated by the
|
||||
// system. If specified it should be within the node port
|
||||
// range and it should be available.
|
||||
uint32 published_port = 4;
|
||||
}
|
736
vendor/github.com/docker/libnetwork/bitseq/sequence.go
generated
vendored
736
vendor/github.com/docker/libnetwork/bitseq/sequence.go
generated
vendored
|
@ -1,736 +0,0 @@
|
|||
// Package bitseq provides a structure and utilities for representing long bitmask
|
||||
// as sequence of run-length encoded blocks. It operates directly on the encoded
|
||||
// representation, it does not decode/encode.
|
||||
package bitseq
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/docker/libnetwork/datastore"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// block sequence constants
|
||||
// If needed we can think of making these configurable
|
||||
const (
|
||||
blockLen = uint32(32)
|
||||
blockBytes = uint64(blockLen / 8)
|
||||
blockMAX = uint32(1<<blockLen - 1)
|
||||
blockFirstBit = uint32(1) << (blockLen - 1)
|
||||
invalidPos = uint64(0xFFFFFFFFFFFFFFFF)
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrNoBitAvailable is returned when no more bits are available to set
|
||||
ErrNoBitAvailable = errors.New("no bit available")
|
||||
// ErrBitAllocated is returned when the specific bit requested is already set
|
||||
ErrBitAllocated = errors.New("requested bit is already allocated")
|
||||
)
|
||||
|
||||
// Handle contains the sequence representing the bitmask and its identifier
|
||||
type Handle struct {
|
||||
bits uint64
|
||||
unselected uint64
|
||||
head *sequence
|
||||
app string
|
||||
id string
|
||||
dbIndex uint64
|
||||
dbExists bool
|
||||
curr uint64
|
||||
store datastore.DataStore
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// NewHandle returns a thread-safe instance of the bitmask handler
|
||||
func NewHandle(app string, ds datastore.DataStore, id string, numElements uint64) (*Handle, error) {
|
||||
h := &Handle{
|
||||
app: app,
|
||||
id: id,
|
||||
store: ds,
|
||||
bits: numElements,
|
||||
unselected: numElements,
|
||||
head: &sequence{
|
||||
block: 0x0,
|
||||
count: getNumBlocks(numElements),
|
||||
},
|
||||
}
|
||||
|
||||
if h.store == nil {
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// Get the initial status from the ds if present.
|
||||
if err := h.store.GetObject(datastore.Key(h.Key()...), h); err != nil && err != datastore.ErrKeyNotFound {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If the handle is not in store, write it.
|
||||
if !h.Exists() {
|
||||
if err := h.writeToStore(); err != nil {
|
||||
return nil, fmt.Errorf("failed to write bitsequence to store: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// sequence represents a recurring sequence of 32 bits long bitmasks
|
||||
type sequence struct {
|
||||
block uint32 // block is a symbol representing 4 byte long allocation bitmask
|
||||
count uint64 // number of consecutive blocks (symbols)
|
||||
next *sequence // next sequence
|
||||
}
|
||||
|
||||
// String returns a string representation of the block sequence starting from this block
|
||||
func (s *sequence) toString() string {
|
||||
var nextBlock string
|
||||
if s.next == nil {
|
||||
nextBlock = "end"
|
||||
} else {
|
||||
nextBlock = s.next.toString()
|
||||
}
|
||||
return fmt.Sprintf("(0x%x, %d)->%s", s.block, s.count, nextBlock)
|
||||
}
|
||||
|
||||
// GetAvailableBit returns the position of the first unset bit in the bitmask represented by this sequence
|
||||
func (s *sequence) getAvailableBit(from uint64) (uint64, uint64, error) {
|
||||
if s.block == blockMAX || s.count == 0 {
|
||||
return invalidPos, invalidPos, ErrNoBitAvailable
|
||||
}
|
||||
bits := from
|
||||
bitSel := blockFirstBit >> from
|
||||
for bitSel > 0 && s.block&bitSel != 0 {
|
||||
bitSel >>= 1
|
||||
bits++
|
||||
}
|
||||
// Check if the loop exited because it could not
|
||||
// find any available bit int block starting from
|
||||
// "from". Return invalid pos in that case.
|
||||
if bitSel == 0 {
|
||||
return invalidPos, invalidPos, ErrNoBitAvailable
|
||||
}
|
||||
return bits / 8, bits % 8, nil
|
||||
}
|
||||
|
||||
// GetCopy returns a copy of the linked list rooted at this node
|
||||
func (s *sequence) getCopy() *sequence {
|
||||
n := &sequence{block: s.block, count: s.count}
|
||||
pn := n
|
||||
ps := s.next
|
||||
for ps != nil {
|
||||
pn.next = &sequence{block: ps.block, count: ps.count}
|
||||
pn = pn.next
|
||||
ps = ps.next
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// Equal checks if this sequence is equal to the passed one
|
||||
func (s *sequence) equal(o *sequence) bool {
|
||||
this := s
|
||||
other := o
|
||||
for this != nil {
|
||||
if other == nil {
|
||||
return false
|
||||
}
|
||||
if this.block != other.block || this.count != other.count {
|
||||
return false
|
||||
}
|
||||
this = this.next
|
||||
other = other.next
|
||||
}
|
||||
// Check if other is longer than this
|
||||
if other != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ToByteArray converts the sequence into a byte array
|
||||
func (s *sequence) toByteArray() ([]byte, error) {
|
||||
var bb []byte
|
||||
|
||||
p := s
|
||||
for p != nil {
|
||||
b := make([]byte, 12)
|
||||
binary.BigEndian.PutUint32(b[0:], p.block)
|
||||
binary.BigEndian.PutUint64(b[4:], p.count)
|
||||
bb = append(bb, b...)
|
||||
p = p.next
|
||||
}
|
||||
|
||||
return bb, nil
|
||||
}
|
||||
|
||||
// fromByteArray construct the sequence from the byte array
|
||||
func (s *sequence) fromByteArray(data []byte) error {
|
||||
l := len(data)
|
||||
if l%12 != 0 {
|
||||
return fmt.Errorf("cannot deserialize byte sequence of length %d (%v)", l, data)
|
||||
}
|
||||
|
||||
p := s
|
||||
i := 0
|
||||
for {
|
||||
p.block = binary.BigEndian.Uint32(data[i : i+4])
|
||||
p.count = binary.BigEndian.Uint64(data[i+4 : i+12])
|
||||
i += 12
|
||||
if i == l {
|
||||
break
|
||||
}
|
||||
p.next = &sequence{}
|
||||
p = p.next
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Handle) getCopy() *Handle {
|
||||
return &Handle{
|
||||
bits: h.bits,
|
||||
unselected: h.unselected,
|
||||
head: h.head.getCopy(),
|
||||
app: h.app,
|
||||
id: h.id,
|
||||
dbIndex: h.dbIndex,
|
||||
dbExists: h.dbExists,
|
||||
store: h.store,
|
||||
curr: h.curr,
|
||||
}
|
||||
}
|
||||
|
||||
// SetAnyInRange atomically sets the first unset bit in the specified range in the sequence and returns the corresponding ordinal
|
||||
func (h *Handle) SetAnyInRange(start, end uint64, serial bool) (uint64, error) {
|
||||
if end < start || end >= h.bits {
|
||||
return invalidPos, fmt.Errorf("invalid bit range [%d, %d]", start, end)
|
||||
}
|
||||
if h.Unselected() == 0 {
|
||||
return invalidPos, ErrNoBitAvailable
|
||||
}
|
||||
return h.set(0, start, end, true, false, serial)
|
||||
}
|
||||
|
||||
// SetAny atomically sets the first unset bit in the sequence and returns the corresponding ordinal
|
||||
func (h *Handle) SetAny(serial bool) (uint64, error) {
|
||||
if h.Unselected() == 0 {
|
||||
return invalidPos, ErrNoBitAvailable
|
||||
}
|
||||
return h.set(0, 0, h.bits-1, true, false, serial)
|
||||
}
|
||||
|
||||
// Set atomically sets the corresponding bit in the sequence
|
||||
func (h *Handle) Set(ordinal uint64) error {
|
||||
if err := h.validateOrdinal(ordinal); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := h.set(ordinal, 0, 0, false, false, false)
|
||||
return err
|
||||
}
|
||||
|
||||
// Unset atomically unsets the corresponding bit in the sequence
|
||||
func (h *Handle) Unset(ordinal uint64) error {
|
||||
if err := h.validateOrdinal(ordinal); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := h.set(ordinal, 0, 0, false, true, false)
|
||||
return err
|
||||
}
|
||||
|
||||
// IsSet atomically checks if the ordinal bit is set. In case ordinal
|
||||
// is outside of the bit sequence limits, false is returned.
|
||||
func (h *Handle) IsSet(ordinal uint64) bool {
|
||||
if err := h.validateOrdinal(ordinal); err != nil {
|
||||
return false
|
||||
}
|
||||
h.Lock()
|
||||
_, _, err := checkIfAvailable(h.head, ordinal)
|
||||
h.Unlock()
|
||||
return err != nil
|
||||
}
|
||||
|
||||
func (h *Handle) runConsistencyCheck() bool {
|
||||
corrupted := false
|
||||
for p, c := h.head, h.head.next; c != nil; c = c.next {
|
||||
if c.count == 0 {
|
||||
corrupted = true
|
||||
p.next = c.next
|
||||
continue // keep same p
|
||||
}
|
||||
p = c
|
||||
}
|
||||
return corrupted
|
||||
}
|
||||
|
||||
// CheckConsistency checks if the bit sequence is in an inconsistent state and attempts to fix it.
|
||||
// It looks for a corruption signature that may happen in docker 1.9.0 and 1.9.1.
|
||||
func (h *Handle) CheckConsistency() error {
|
||||
for {
|
||||
h.Lock()
|
||||
store := h.store
|
||||
h.Unlock()
|
||||
|
||||
if store != nil {
|
||||
if err := store.GetObject(datastore.Key(h.Key()...), h); err != nil && err != datastore.ErrKeyNotFound {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
h.Lock()
|
||||
nh := h.getCopy()
|
||||
h.Unlock()
|
||||
|
||||
if !nh.runConsistencyCheck() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := nh.writeToStore(); err != nil {
|
||||
if _, ok := err.(types.RetryError); !ok {
|
||||
return fmt.Errorf("internal failure while fixing inconsistent bitsequence: %v", err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
logrus.Infof("Fixed inconsistent bit sequence in datastore:\n%s\n%s", h, nh)
|
||||
|
||||
h.Lock()
|
||||
h.head = nh.head
|
||||
h.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// set/reset the bit
|
||||
func (h *Handle) set(ordinal, start, end uint64, any bool, release bool, serial bool) (uint64, error) {
|
||||
var (
|
||||
bitPos uint64
|
||||
bytePos uint64
|
||||
ret uint64
|
||||
err error
|
||||
)
|
||||
|
||||
for {
|
||||
var store datastore.DataStore
|
||||
curr := uint64(0)
|
||||
h.Lock()
|
||||
store = h.store
|
||||
if store != nil {
|
||||
h.Unlock() // The lock is acquired in the GetObject
|
||||
if err := store.GetObject(datastore.Key(h.Key()...), h); err != nil && err != datastore.ErrKeyNotFound {
|
||||
return ret, err
|
||||
}
|
||||
h.Lock() // Acquire the lock back
|
||||
}
|
||||
if serial {
|
||||
curr = h.curr
|
||||
}
|
||||
// Get position if available
|
||||
if release {
|
||||
bytePos, bitPos = ordinalToPos(ordinal)
|
||||
} else {
|
||||
if any {
|
||||
bytePos, bitPos, err = getAvailableFromCurrent(h.head, start, curr, end)
|
||||
ret = posToOrdinal(bytePos, bitPos)
|
||||
if err == nil {
|
||||
h.curr = ret + 1
|
||||
}
|
||||
} else {
|
||||
bytePos, bitPos, err = checkIfAvailable(h.head, ordinal)
|
||||
ret = ordinal
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
h.Unlock()
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Create a private copy of h and work on it
|
||||
nh := h.getCopy()
|
||||
|
||||
nh.head = pushReservation(bytePos, bitPos, nh.head, release)
|
||||
if release {
|
||||
nh.unselected++
|
||||
} else {
|
||||
nh.unselected--
|
||||
}
|
||||
|
||||
if h.store != nil {
|
||||
h.Unlock()
|
||||
// Attempt to write private copy to store
|
||||
if err := nh.writeToStore(); err != nil {
|
||||
if _, ok := err.(types.RetryError); !ok {
|
||||
return ret, fmt.Errorf("internal failure while setting the bit: %v", err)
|
||||
}
|
||||
// Retry
|
||||
continue
|
||||
}
|
||||
h.Lock()
|
||||
}
|
||||
|
||||
// Previous atomic push was successful. Save private copy to local copy
|
||||
h.unselected = nh.unselected
|
||||
h.head = nh.head
|
||||
h.dbExists = nh.dbExists
|
||||
h.dbIndex = nh.dbIndex
|
||||
h.Unlock()
|
||||
return ret, nil
|
||||
}
|
||||
}
|
||||
|
||||
// checks is needed because to cover the case where the number of bits is not a multiple of blockLen
|
||||
func (h *Handle) validateOrdinal(ordinal uint64) error {
|
||||
h.Lock()
|
||||
defer h.Unlock()
|
||||
if ordinal >= h.bits {
|
||||
return errors.New("bit does not belong to the sequence")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Destroy removes from the datastore the data belonging to this handle
|
||||
func (h *Handle) Destroy() error {
|
||||
for {
|
||||
if err := h.deleteFromStore(); err != nil {
|
||||
if _, ok := err.(types.RetryError); !ok {
|
||||
return fmt.Errorf("internal failure while destroying the sequence: %v", err)
|
||||
}
|
||||
// Fetch latest
|
||||
if err := h.store.GetObject(datastore.Key(h.Key()...), h); err != nil {
|
||||
if err == datastore.ErrKeyNotFound { // already removed
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("failed to fetch from store when destroying the sequence: %v", err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ToByteArray converts this handle's data into a byte array
|
||||
func (h *Handle) ToByteArray() ([]byte, error) {
|
||||
|
||||
h.Lock()
|
||||
defer h.Unlock()
|
||||
ba := make([]byte, 16)
|
||||
binary.BigEndian.PutUint64(ba[0:], h.bits)
|
||||
binary.BigEndian.PutUint64(ba[8:], h.unselected)
|
||||
bm, err := h.head.toByteArray()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to serialize head: %s", err.Error())
|
||||
}
|
||||
ba = append(ba, bm...)
|
||||
|
||||
return ba, nil
|
||||
}
|
||||
|
||||
// FromByteArray reads his handle's data from a byte array
|
||||
func (h *Handle) FromByteArray(ba []byte) error {
|
||||
if ba == nil {
|
||||
return errors.New("nil byte array")
|
||||
}
|
||||
|
||||
nh := &sequence{}
|
||||
err := nh.fromByteArray(ba[16:])
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to deserialize head: %s", err.Error())
|
||||
}
|
||||
|
||||
h.Lock()
|
||||
h.head = nh
|
||||
h.bits = binary.BigEndian.Uint64(ba[0:8])
|
||||
h.unselected = binary.BigEndian.Uint64(ba[8:16])
|
||||
h.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Bits returns the length of the bit sequence
|
||||
func (h *Handle) Bits() uint64 {
|
||||
return h.bits
|
||||
}
|
||||
|
||||
// Unselected returns the number of bits which are not selected
|
||||
func (h *Handle) Unselected() uint64 {
|
||||
h.Lock()
|
||||
defer h.Unlock()
|
||||
return h.unselected
|
||||
}
|
||||
|
||||
func (h *Handle) String() string {
|
||||
h.Lock()
|
||||
defer h.Unlock()
|
||||
return fmt.Sprintf("App: %s, ID: %s, DBIndex: 0x%x, Bits: %d, Unselected: %d, Sequence: %s Curr:%d",
|
||||
h.app, h.id, h.dbIndex, h.bits, h.unselected, h.head.toString(), h.curr)
|
||||
}
|
||||
|
||||
// MarshalJSON encodes Handle into json message
|
||||
func (h *Handle) MarshalJSON() ([]byte, error) {
|
||||
m := map[string]interface{}{
|
||||
"id": h.id,
|
||||
}
|
||||
|
||||
b, err := h.ToByteArray()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m["sequence"] = b
|
||||
return json.Marshal(m)
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes json message into Handle
|
||||
func (h *Handle) UnmarshalJSON(data []byte) error {
|
||||
var (
|
||||
m map[string]interface{}
|
||||
b []byte
|
||||
err error
|
||||
)
|
||||
if err = json.Unmarshal(data, &m); err != nil {
|
||||
return err
|
||||
}
|
||||
h.id = m["id"].(string)
|
||||
bi, _ := json.Marshal(m["sequence"])
|
||||
if err := json.Unmarshal(bi, &b); err != nil {
|
||||
return err
|
||||
}
|
||||
return h.FromByteArray(b)
|
||||
}
|
||||
|
||||
// getFirstAvailable looks for the first unset bit in passed mask starting from start
|
||||
func getFirstAvailable(head *sequence, start uint64) (uint64, uint64, error) {
|
||||
// Find sequence which contains the start bit
|
||||
byteStart, bitStart := ordinalToPos(start)
|
||||
current, _, precBlocks, inBlockBytePos := findSequence(head, byteStart)
|
||||
// Derive the this sequence offsets
|
||||
byteOffset := byteStart - inBlockBytePos
|
||||
bitOffset := inBlockBytePos*8 + bitStart
|
||||
for current != nil {
|
||||
if current.block != blockMAX {
|
||||
// If the current block is not full, check if there is any bit
|
||||
// from the current bit in the current block. If not, before proceeding to the
|
||||
// next block node, make sure we check for available bit in the next
|
||||
// instance of the same block. Due to RLE same block signature will be
|
||||
// compressed.
|
||||
retry:
|
||||
bytePos, bitPos, err := current.getAvailableBit(bitOffset)
|
||||
if err != nil && precBlocks == current.count-1 {
|
||||
// This is the last instance in the same block node,
|
||||
// so move to the next block.
|
||||
goto next
|
||||
}
|
||||
if err != nil {
|
||||
// There are some more instances of the same block, so add the offset
|
||||
// and be optimistic that you will find the available bit in the next
|
||||
// instance of the same block.
|
||||
bitOffset = 0
|
||||
byteOffset += blockBytes
|
||||
precBlocks++
|
||||
goto retry
|
||||
}
|
||||
return byteOffset + bytePos, bitPos, err
|
||||
}
|
||||
// Moving to next block: Reset bit offset.
|
||||
next:
|
||||
bitOffset = 0
|
||||
byteOffset += (current.count * blockBytes) - (precBlocks * blockBytes)
|
||||
precBlocks = 0
|
||||
current = current.next
|
||||
}
|
||||
return invalidPos, invalidPos, ErrNoBitAvailable
|
||||
}
|
||||
|
||||
// getAvailableFromCurrent will look for available ordinal from the current ordinal.
|
||||
// If none found then it will loop back to the start to check of the available bit.
|
||||
// This can be further optimized to check from start till curr in case of a rollover
|
||||
func getAvailableFromCurrent(head *sequence, start, curr, end uint64) (uint64, uint64, error) {
|
||||
var bytePos, bitPos uint64
|
||||
var err error
|
||||
if curr != 0 && curr > start {
|
||||
bytePos, bitPos, err = getFirstAvailable(head, curr)
|
||||
ret := posToOrdinal(bytePos, bitPos)
|
||||
if end < ret || err != nil {
|
||||
goto begin
|
||||
}
|
||||
return bytePos, bitPos, nil
|
||||
}
|
||||
|
||||
begin:
|
||||
bytePos, bitPos, err = getFirstAvailable(head, start)
|
||||
ret := posToOrdinal(bytePos, bitPos)
|
||||
if end < ret || err != nil {
|
||||
return invalidPos, invalidPos, ErrNoBitAvailable
|
||||
}
|
||||
return bytePos, bitPos, nil
|
||||
}
|
||||
|
||||
// checkIfAvailable checks if the bit correspondent to the specified ordinal is unset
|
||||
// If the ordinal is beyond the sequence limits, a negative response is returned
|
||||
func checkIfAvailable(head *sequence, ordinal uint64) (uint64, uint64, error) {
|
||||
bytePos, bitPos := ordinalToPos(ordinal)
|
||||
|
||||
// Find the sequence containing this byte
|
||||
current, _, _, inBlockBytePos := findSequence(head, bytePos)
|
||||
if current != nil {
|
||||
// Check whether the bit corresponding to the ordinal address is unset
|
||||
bitSel := blockFirstBit >> (inBlockBytePos*8 + bitPos)
|
||||
if current.block&bitSel == 0 {
|
||||
return bytePos, bitPos, nil
|
||||
}
|
||||
}
|
||||
|
||||
return invalidPos, invalidPos, ErrBitAllocated
|
||||
}
|
||||
|
||||
// Given the byte position and the sequences list head, return the pointer to the
|
||||
// sequence containing the byte (current), the pointer to the previous sequence,
|
||||
// the number of blocks preceding the block containing the byte inside the current sequence.
|
||||
// If bytePos is outside of the list, function will return (nil, nil, 0, invalidPos)
|
||||
func findSequence(head *sequence, bytePos uint64) (*sequence, *sequence, uint64, uint64) {
|
||||
// Find the sequence containing this byte
|
||||
previous := head
|
||||
current := head
|
||||
n := bytePos
|
||||
for current.next != nil && n >= (current.count*blockBytes) { // Nil check for less than 32 addresses masks
|
||||
n -= (current.count * blockBytes)
|
||||
previous = current
|
||||
current = current.next
|
||||
}
|
||||
|
||||
// If byte is outside of the list, let caller know
|
||||
if n >= (current.count * blockBytes) {
|
||||
return nil, nil, 0, invalidPos
|
||||
}
|
||||
|
||||
// Find the byte position inside the block and the number of blocks
|
||||
// preceding the block containing the byte inside this sequence
|
||||
precBlocks := n / blockBytes
|
||||
inBlockBytePos := bytePos % blockBytes
|
||||
|
||||
return current, previous, precBlocks, inBlockBytePos
|
||||
}
|
||||
|
||||
// PushReservation pushes the bit reservation inside the bitmask.
|
||||
// Given byte and bit positions, identify the sequence (current) which holds the block containing the affected bit.
|
||||
// Create a new block with the modified bit according to the operation (allocate/release).
|
||||
// Create a new sequence containing the new block and insert it in the proper position.
|
||||
// Remove current sequence if empty.
|
||||
// Check if new sequence can be merged with neighbour (previous/next) sequences.
|
||||
//
|
||||
//
|
||||
// Identify "current" sequence containing block:
|
||||
// [prev seq] [current seq] [next seq]
|
||||
//
|
||||
// Based on block position, resulting list of sequences can be any of three forms:
|
||||
//
|
||||
// block position Resulting list of sequences
|
||||
// A) block is first in current: [prev seq] [new] [modified current seq] [next seq]
|
||||
// B) block is last in current: [prev seq] [modified current seq] [new] [next seq]
|
||||
// C) block is in the middle of current: [prev seq] [curr pre] [new] [curr post] [next seq]
|
||||
func pushReservation(bytePos, bitPos uint64, head *sequence, release bool) *sequence {
|
||||
// Store list's head
|
||||
newHead := head
|
||||
|
||||
// Find the sequence containing this byte
|
||||
current, previous, precBlocks, inBlockBytePos := findSequence(head, bytePos)
|
||||
if current == nil {
|
||||
return newHead
|
||||
}
|
||||
|
||||
// Construct updated block
|
||||
bitSel := blockFirstBit >> (inBlockBytePos*8 + bitPos)
|
||||
newBlock := current.block
|
||||
if release {
|
||||
newBlock &^= bitSel
|
||||
} else {
|
||||
newBlock |= bitSel
|
||||
}
|
||||
|
||||
// Quit if it was a redundant request
|
||||
if current.block == newBlock {
|
||||
return newHead
|
||||
}
|
||||
|
||||
// Current sequence inevitably looses one block, upadate count
|
||||
current.count--
|
||||
|
||||
// Create new sequence
|
||||
newSequence := &sequence{block: newBlock, count: 1}
|
||||
|
||||
// Insert the new sequence in the list based on block position
|
||||
if precBlocks == 0 { // First in sequence (A)
|
||||
newSequence.next = current
|
||||
if current == head {
|
||||
newHead = newSequence
|
||||
previous = newHead
|
||||
} else {
|
||||
previous.next = newSequence
|
||||
}
|
||||
removeCurrentIfEmpty(&newHead, newSequence, current)
|
||||
mergeSequences(previous)
|
||||
} else if precBlocks == current.count { // Last in sequence (B)
|
||||
newSequence.next = current.next
|
||||
current.next = newSequence
|
||||
mergeSequences(current)
|
||||
} else { // In between the sequence (C)
|
||||
currPre := &sequence{block: current.block, count: precBlocks, next: newSequence}
|
||||
currPost := current
|
||||
currPost.count -= precBlocks
|
||||
newSequence.next = currPost
|
||||
if currPost == head {
|
||||
newHead = currPre
|
||||
} else {
|
||||
previous.next = currPre
|
||||
}
|
||||
// No merging or empty current possible here
|
||||
}
|
||||
|
||||
return newHead
|
||||
}
|
||||
|
||||
// Removes the current sequence from the list if empty, adjusting the head pointer if needed
|
||||
func removeCurrentIfEmpty(head **sequence, previous, current *sequence) {
|
||||
if current.count == 0 {
|
||||
if current == *head {
|
||||
*head = current.next
|
||||
} else {
|
||||
previous.next = current.next
|
||||
current = current.next
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Given a pointer to a sequence, it checks if it can be merged with any following sequences
|
||||
// It stops when no more merging is possible.
|
||||
// TODO: Optimization: only attempt merge from start to end sequence, no need to scan till the end of the list
|
||||
func mergeSequences(seq *sequence) {
|
||||
if seq != nil {
|
||||
// Merge all what possible from seq
|
||||
for seq.next != nil && seq.block == seq.next.block {
|
||||
seq.count += seq.next.count
|
||||
seq.next = seq.next.next
|
||||
}
|
||||
// Move to next
|
||||
mergeSequences(seq.next)
|
||||
}
|
||||
}
|
||||
|
||||
func getNumBlocks(numBits uint64) uint64 {
|
||||
numBlocks := numBits / uint64(blockLen)
|
||||
if numBits%uint64(blockLen) != 0 {
|
||||
numBlocks++
|
||||
}
|
||||
return numBlocks
|
||||
}
|
||||
|
||||
func ordinalToPos(ordinal uint64) (uint64, uint64) {
|
||||
return ordinal / 8, ordinal % 8
|
||||
}
|
||||
|
||||
func posToOrdinal(bytePos, bitPos uint64) uint64 {
|
||||
return bytePos*8 + bitPos
|
||||
}
|
142
vendor/github.com/docker/libnetwork/bitseq/store.go
generated
vendored
142
vendor/github.com/docker/libnetwork/bitseq/store.go
generated
vendored
|
@ -1,142 +0,0 @@
|
|||
package bitseq
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/libnetwork/datastore"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
// Key provides the Key to be used in KV Store
|
||||
func (h *Handle) Key() []string {
|
||||
h.Lock()
|
||||
defer h.Unlock()
|
||||
return []string{h.app, h.id}
|
||||
}
|
||||
|
||||
// KeyPrefix returns the immediate parent key that can be used for tree walk
|
||||
func (h *Handle) KeyPrefix() []string {
|
||||
h.Lock()
|
||||
defer h.Unlock()
|
||||
return []string{h.app}
|
||||
}
|
||||
|
||||
// Value marshals the data to be stored in the KV store
|
||||
func (h *Handle) Value() []byte {
|
||||
b, err := json.Marshal(h)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// SetValue unmarshals the data from the KV store
|
||||
func (h *Handle) SetValue(value []byte) error {
|
||||
return json.Unmarshal(value, h)
|
||||
}
|
||||
|
||||
// Index returns the latest DB Index as seen by this object
|
||||
func (h *Handle) Index() uint64 {
|
||||
h.Lock()
|
||||
defer h.Unlock()
|
||||
return h.dbIndex
|
||||
}
|
||||
|
||||
// SetIndex method allows the datastore to store the latest DB Index into this object
|
||||
func (h *Handle) SetIndex(index uint64) {
|
||||
h.Lock()
|
||||
h.dbIndex = index
|
||||
h.dbExists = true
|
||||
h.Unlock()
|
||||
}
|
||||
|
||||
// Exists method is true if this object has been stored in the DB.
|
||||
func (h *Handle) Exists() bool {
|
||||
h.Lock()
|
||||
defer h.Unlock()
|
||||
return h.dbExists
|
||||
}
|
||||
|
||||
// New method returns a handle based on the receiver handle
|
||||
func (h *Handle) New() datastore.KVObject {
|
||||
h.Lock()
|
||||
defer h.Unlock()
|
||||
|
||||
return &Handle{
|
||||
app: h.app,
|
||||
store: h.store,
|
||||
}
|
||||
}
|
||||
|
||||
// CopyTo deep copies the handle into the passed destination object
|
||||
func (h *Handle) CopyTo(o datastore.KVObject) error {
|
||||
h.Lock()
|
||||
defer h.Unlock()
|
||||
|
||||
dstH := o.(*Handle)
|
||||
if h == dstH {
|
||||
return nil
|
||||
}
|
||||
dstH.Lock()
|
||||
dstH.bits = h.bits
|
||||
dstH.unselected = h.unselected
|
||||
dstH.head = h.head.getCopy()
|
||||
dstH.app = h.app
|
||||
dstH.id = h.id
|
||||
dstH.dbIndex = h.dbIndex
|
||||
dstH.dbExists = h.dbExists
|
||||
dstH.store = h.store
|
||||
dstH.curr = h.curr
|
||||
dstH.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Skip provides a way for a KV Object to avoid persisting it in the KV Store
|
||||
func (h *Handle) Skip() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// DataScope method returns the storage scope of the datastore
|
||||
func (h *Handle) DataScope() string {
|
||||
h.Lock()
|
||||
defer h.Unlock()
|
||||
|
||||
return h.store.Scope()
|
||||
}
|
||||
|
||||
func (h *Handle) fromDsValue(value []byte) error {
|
||||
var ba []byte
|
||||
if err := json.Unmarshal(value, &ba); err != nil {
|
||||
return fmt.Errorf("failed to decode json: %s", err.Error())
|
||||
}
|
||||
if err := h.FromByteArray(ba); err != nil {
|
||||
return fmt.Errorf("failed to decode handle: %s", err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Handle) writeToStore() error {
|
||||
h.Lock()
|
||||
store := h.store
|
||||
h.Unlock()
|
||||
if store == nil {
|
||||
return nil
|
||||
}
|
||||
err := store.PutObjectAtomic(h)
|
||||
if err == datastore.ErrKeyModified {
|
||||
return types.RetryErrorf("failed to perform atomic write (%v). Retry might fix the error", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (h *Handle) deleteFromStore() error {
|
||||
h.Lock()
|
||||
store := h.store
|
||||
h.Unlock()
|
||||
if store == nil {
|
||||
return nil
|
||||
}
|
||||
return store.DeleteObjectAtomic(h)
|
||||
}
|
37
vendor/github.com/docker/libnetwork/cluster/provider.go
generated
vendored
37
vendor/github.com/docker/libnetwork/cluster/provider.go
generated
vendored
|
@ -1,37 +0,0 @@
|
|||
package cluster
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/docker/docker/api/types/network"
|
||||
)
|
||||
|
||||
const (
|
||||
// EventSocketChange control socket changed
|
||||
EventSocketChange = iota
|
||||
// EventNodeReady cluster node in ready state
|
||||
EventNodeReady
|
||||
// EventNodeLeave node is leaving the cluster
|
||||
EventNodeLeave
|
||||
// EventNetworkKeysAvailable network keys correctly configured in the networking layer
|
||||
EventNetworkKeysAvailable
|
||||
)
|
||||
|
||||
// ConfigEventType type of the event produced by the cluster
|
||||
type ConfigEventType uint8
|
||||
|
||||
// Provider provides clustering config details
|
||||
type Provider interface {
|
||||
IsManager() bool
|
||||
IsAgent() bool
|
||||
GetLocalAddress() string
|
||||
GetListenAddress() string
|
||||
GetAdvertiseAddress() string
|
||||
GetDataPathAddress() string
|
||||
GetRemoteAddressList() []string
|
||||
ListenClusterEvents() <-chan ConfigEventType
|
||||
AttachNetwork(string, string, []string) (*network.NetworkingConfig, error)
|
||||
DetachNetwork(string, string) error
|
||||
UpdateAttachment(string, string, *network.NetworkingConfig) error
|
||||
WaitForDetachment(context.Context, string, string, string, string) error
|
||||
}
|
328
vendor/github.com/docker/libnetwork/config/config.go
generated
vendored
328
vendor/github.com/docker/libnetwork/config/config.go
generated
vendored
|
@ -1,328 +0,0 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/docker/docker/pkg/discovery"
|
||||
"github.com/docker/docker/pkg/plugingetter"
|
||||
"github.com/docker/go-connections/tlsconfig"
|
||||
"github.com/docker/libkv/store"
|
||||
"github.com/docker/libnetwork/cluster"
|
||||
"github.com/docker/libnetwork/datastore"
|
||||
"github.com/docker/libnetwork/ipamutils"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/osl"
|
||||
"github.com/docker/libnetwork/portallocator"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
warningThNetworkControlPlaneMTU = 1500
|
||||
minimumNetworkControlPlaneMTU = 500
|
||||
)
|
||||
|
||||
// Config encapsulates configurations of various Libnetwork components
|
||||
type Config struct {
|
||||
Daemon DaemonCfg
|
||||
Cluster ClusterCfg
|
||||
Scopes map[string]*datastore.ScopeCfg
|
||||
ActiveSandboxes map[string]interface{}
|
||||
PluginGetter plugingetter.PluginGetter
|
||||
}
|
||||
|
||||
// DaemonCfg represents libnetwork core configuration
|
||||
type DaemonCfg struct {
|
||||
Debug bool
|
||||
Experimental bool
|
||||
DataDir string
|
||||
ExecRoot string
|
||||
DefaultNetwork string
|
||||
DefaultDriver string
|
||||
Labels []string
|
||||
DriverCfg map[string]interface{}
|
||||
ClusterProvider cluster.Provider
|
||||
NetworkControlPlaneMTU int
|
||||
DefaultAddressPool []*ipamutils.NetworkToSplit
|
||||
}
|
||||
|
||||
// ClusterCfg represents cluster configuration
|
||||
type ClusterCfg struct {
|
||||
Watcher discovery.Watcher
|
||||
Address string
|
||||
Discovery string
|
||||
Heartbeat uint64
|
||||
}
|
||||
|
||||
// LoadDefaultScopes loads default scope configs for scopes which
|
||||
// doesn't have explicit user specified configs.
|
||||
func (c *Config) LoadDefaultScopes(dataDir string) {
|
||||
for k, v := range datastore.DefaultScopes(dataDir) {
|
||||
if _, ok := c.Scopes[k]; !ok {
|
||||
c.Scopes[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ParseConfig parses the libnetwork configuration file
|
||||
func ParseConfig(tomlCfgFile string) (*Config, error) {
|
||||
cfg := &Config{
|
||||
Scopes: map[string]*datastore.ScopeCfg{},
|
||||
}
|
||||
|
||||
if _, err := toml.DecodeFile(tomlCfgFile, cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cfg.LoadDefaultScopes(cfg.Daemon.DataDir)
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
// ParseConfigOptions parses the configuration options and returns
|
||||
// a reference to the corresponding Config structure
|
||||
func ParseConfigOptions(cfgOptions ...Option) *Config {
|
||||
cfg := &Config{
|
||||
Daemon: DaemonCfg{
|
||||
DriverCfg: make(map[string]interface{}),
|
||||
},
|
||||
Scopes: make(map[string]*datastore.ScopeCfg),
|
||||
}
|
||||
|
||||
cfg.ProcessOptions(cfgOptions...)
|
||||
cfg.LoadDefaultScopes(cfg.Daemon.DataDir)
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
// Option is an option setter function type used to pass various configurations
|
||||
// to the controller
|
||||
type Option func(c *Config)
|
||||
|
||||
// OptionDefaultNetwork function returns an option setter for a default network
|
||||
func OptionDefaultNetwork(dn string) Option {
|
||||
return func(c *Config) {
|
||||
logrus.Debugf("Option DefaultNetwork: %s", dn)
|
||||
c.Daemon.DefaultNetwork = strings.TrimSpace(dn)
|
||||
}
|
||||
}
|
||||
|
||||
// OptionDefaultDriver function returns an option setter for default driver
|
||||
func OptionDefaultDriver(dd string) Option {
|
||||
return func(c *Config) {
|
||||
logrus.Debugf("Option DefaultDriver: %s", dd)
|
||||
c.Daemon.DefaultDriver = strings.TrimSpace(dd)
|
||||
}
|
||||
}
|
||||
|
||||
// OptionDefaultAddressPoolConfig function returns an option setter for default address pool
|
||||
func OptionDefaultAddressPoolConfig(addressPool []*ipamutils.NetworkToSplit) Option {
|
||||
return func(c *Config) {
|
||||
c.Daemon.DefaultAddressPool = addressPool
|
||||
}
|
||||
}
|
||||
|
||||
// OptionDriverConfig returns an option setter for driver configuration.
|
||||
func OptionDriverConfig(networkType string, config map[string]interface{}) Option {
|
||||
return func(c *Config) {
|
||||
c.Daemon.DriverCfg[networkType] = config
|
||||
}
|
||||
}
|
||||
|
||||
// OptionLabels function returns an option setter for labels
|
||||
func OptionLabels(labels []string) Option {
|
||||
return func(c *Config) {
|
||||
for _, label := range labels {
|
||||
if strings.HasPrefix(label, netlabel.Prefix) {
|
||||
c.Daemon.Labels = append(c.Daemon.Labels, label)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// OptionKVProvider function returns an option setter for kvstore provider
|
||||
func OptionKVProvider(provider string) Option {
|
||||
return func(c *Config) {
|
||||
logrus.Debugf("Option OptionKVProvider: %s", provider)
|
||||
if _, ok := c.Scopes[datastore.GlobalScope]; !ok {
|
||||
c.Scopes[datastore.GlobalScope] = &datastore.ScopeCfg{}
|
||||
}
|
||||
c.Scopes[datastore.GlobalScope].Client.Provider = strings.TrimSpace(provider)
|
||||
}
|
||||
}
|
||||
|
||||
// OptionKVProviderURL function returns an option setter for kvstore url
|
||||
func OptionKVProviderURL(url string) Option {
|
||||
return func(c *Config) {
|
||||
logrus.Debugf("Option OptionKVProviderURL: %s", url)
|
||||
if _, ok := c.Scopes[datastore.GlobalScope]; !ok {
|
||||
c.Scopes[datastore.GlobalScope] = &datastore.ScopeCfg{}
|
||||
}
|
||||
c.Scopes[datastore.GlobalScope].Client.Address = strings.TrimSpace(url)
|
||||
}
|
||||
}
|
||||
|
||||
// OptionKVOpts function returns an option setter for kvstore options
|
||||
func OptionKVOpts(opts map[string]string) Option {
|
||||
return func(c *Config) {
|
||||
if opts["kv.cacertfile"] != "" && opts["kv.certfile"] != "" && opts["kv.keyfile"] != "" {
|
||||
logrus.Info("Option Initializing KV with TLS")
|
||||
tlsConfig, err := tlsconfig.Client(tlsconfig.Options{
|
||||
CAFile: opts["kv.cacertfile"],
|
||||
CertFile: opts["kv.certfile"],
|
||||
KeyFile: opts["kv.keyfile"],
|
||||
})
|
||||
if err != nil {
|
||||
logrus.Errorf("Unable to set up TLS: %s", err)
|
||||
return
|
||||
}
|
||||
if _, ok := c.Scopes[datastore.GlobalScope]; !ok {
|
||||
c.Scopes[datastore.GlobalScope] = &datastore.ScopeCfg{}
|
||||
}
|
||||
if c.Scopes[datastore.GlobalScope].Client.Config == nil {
|
||||
c.Scopes[datastore.GlobalScope].Client.Config = &store.Config{TLS: tlsConfig}
|
||||
} else {
|
||||
c.Scopes[datastore.GlobalScope].Client.Config.TLS = tlsConfig
|
||||
}
|
||||
// Workaround libkv/etcd bug for https
|
||||
c.Scopes[datastore.GlobalScope].Client.Config.ClientTLS = &store.ClientTLSConfig{
|
||||
CACertFile: opts["kv.cacertfile"],
|
||||
CertFile: opts["kv.certfile"],
|
||||
KeyFile: opts["kv.keyfile"],
|
||||
}
|
||||
} else {
|
||||
logrus.Info("Option Initializing KV without TLS")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// OptionDiscoveryWatcher function returns an option setter for discovery watcher
|
||||
func OptionDiscoveryWatcher(watcher discovery.Watcher) Option {
|
||||
return func(c *Config) {
|
||||
c.Cluster.Watcher = watcher
|
||||
}
|
||||
}
|
||||
|
||||
// OptionDiscoveryAddress function returns an option setter for self discovery address
|
||||
func OptionDiscoveryAddress(address string) Option {
|
||||
return func(c *Config) {
|
||||
c.Cluster.Address = address
|
||||
}
|
||||
}
|
||||
|
||||
// OptionDataDir function returns an option setter for data folder
|
||||
func OptionDataDir(dataDir string) Option {
|
||||
return func(c *Config) {
|
||||
c.Daemon.DataDir = dataDir
|
||||
}
|
||||
}
|
||||
|
||||
// OptionExecRoot function returns an option setter for exec root folder
|
||||
func OptionExecRoot(execRoot string) Option {
|
||||
return func(c *Config) {
|
||||
c.Daemon.ExecRoot = execRoot
|
||||
osl.SetBasePath(execRoot)
|
||||
}
|
||||
}
|
||||
|
||||
// OptionPluginGetter returns a plugingetter for remote drivers.
|
||||
func OptionPluginGetter(pg plugingetter.PluginGetter) Option {
|
||||
return func(c *Config) {
|
||||
c.PluginGetter = pg
|
||||
}
|
||||
}
|
||||
|
||||
// OptionExperimental function returns an option setter for experimental daemon
|
||||
func OptionExperimental(exp bool) Option {
|
||||
return func(c *Config) {
|
||||
logrus.Debugf("Option Experimental: %v", exp)
|
||||
c.Daemon.Experimental = exp
|
||||
}
|
||||
}
|
||||
|
||||
// OptionDynamicPortRange function returns an option setter for service port allocation range
|
||||
func OptionDynamicPortRange(in string) Option {
|
||||
return func(c *Config) {
|
||||
start, end := 0, 0
|
||||
if len(in) > 0 {
|
||||
n, err := fmt.Sscanf(in, "%d-%d", &start, &end)
|
||||
if n != 2 || err != nil {
|
||||
logrus.Errorf("Failed to parse range string with err %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if err := portallocator.Get().SetPortRange(start, end); err != nil {
|
||||
logrus.Errorf("Failed to set port range with err %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// OptionNetworkControlPlaneMTU function returns an option setter for control plane MTU
|
||||
func OptionNetworkControlPlaneMTU(exp int) Option {
|
||||
return func(c *Config) {
|
||||
logrus.Debugf("Network Control Plane MTU: %d", exp)
|
||||
if exp < warningThNetworkControlPlaneMTU {
|
||||
logrus.Warnf("Received a MTU of %d, this value is very low, the network control plane can misbehave,"+
|
||||
" defaulting to minimum value (%d)", exp, minimumNetworkControlPlaneMTU)
|
||||
if exp < minimumNetworkControlPlaneMTU {
|
||||
exp = minimumNetworkControlPlaneMTU
|
||||
}
|
||||
}
|
||||
c.Daemon.NetworkControlPlaneMTU = exp
|
||||
}
|
||||
}
|
||||
|
||||
// ProcessOptions processes options and stores it in config
|
||||
func (c *Config) ProcessOptions(options ...Option) {
|
||||
for _, opt := range options {
|
||||
if opt != nil {
|
||||
opt(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IsValidName validates configuration objects supported by libnetwork
|
||||
func IsValidName(name string) bool {
|
||||
return strings.TrimSpace(name) != ""
|
||||
}
|
||||
|
||||
// OptionLocalKVProvider function returns an option setter for kvstore provider
|
||||
func OptionLocalKVProvider(provider string) Option {
|
||||
return func(c *Config) {
|
||||
logrus.Debugf("Option OptionLocalKVProvider: %s", provider)
|
||||
if _, ok := c.Scopes[datastore.LocalScope]; !ok {
|
||||
c.Scopes[datastore.LocalScope] = &datastore.ScopeCfg{}
|
||||
}
|
||||
c.Scopes[datastore.LocalScope].Client.Provider = strings.TrimSpace(provider)
|
||||
}
|
||||
}
|
||||
|
||||
// OptionLocalKVProviderURL function returns an option setter for kvstore url
|
||||
func OptionLocalKVProviderURL(url string) Option {
|
||||
return func(c *Config) {
|
||||
logrus.Debugf("Option OptionLocalKVProviderURL: %s", url)
|
||||
if _, ok := c.Scopes[datastore.LocalScope]; !ok {
|
||||
c.Scopes[datastore.LocalScope] = &datastore.ScopeCfg{}
|
||||
}
|
||||
c.Scopes[datastore.LocalScope].Client.Address = strings.TrimSpace(url)
|
||||
}
|
||||
}
|
||||
|
||||
// OptionLocalKVProviderConfig function returns an option setter for kvstore config
|
||||
func OptionLocalKVProviderConfig(config *store.Config) Option {
|
||||
return func(c *Config) {
|
||||
logrus.Debugf("Option OptionLocalKVProviderConfig: %v", config)
|
||||
if _, ok := c.Scopes[datastore.LocalScope]; !ok {
|
||||
c.Scopes[datastore.LocalScope] = &datastore.ScopeCfg{}
|
||||
}
|
||||
c.Scopes[datastore.LocalScope].Client.Config = config
|
||||
}
|
||||
}
|
||||
|
||||
// OptionActiveSandboxes function returns an option setter for passing the sandboxes
|
||||
// which were active during previous daemon life
|
||||
func OptionActiveSandboxes(sandboxes map[string]interface{}) Option {
|
||||
return func(c *Config) {
|
||||
c.ActiveSandboxes = sandboxes
|
||||
}
|
||||
}
|
1389
vendor/github.com/docker/libnetwork/controller.go
generated
vendored
1389
vendor/github.com/docker/libnetwork/controller.go
generated
vendored
File diff suppressed because it is too large
Load diff
178
vendor/github.com/docker/libnetwork/datastore/cache.go
generated
vendored
178
vendor/github.com/docker/libnetwork/datastore/cache.go
generated
vendored
|
@ -1,178 +0,0 @@
|
|||
package datastore
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/docker/libkv/store"
|
||||
)
|
||||
|
||||
type kvMap map[string]KVObject
|
||||
|
||||
type cache struct {
|
||||
sync.Mutex
|
||||
kmm map[string]kvMap
|
||||
ds *datastore
|
||||
}
|
||||
|
||||
func newCache(ds *datastore) *cache {
|
||||
return &cache{kmm: make(map[string]kvMap), ds: ds}
|
||||
}
|
||||
|
||||
func (c *cache) kmap(kvObject KVObject) (kvMap, error) {
|
||||
var err error
|
||||
|
||||
c.Lock()
|
||||
keyPrefix := Key(kvObject.KeyPrefix()...)
|
||||
kmap, ok := c.kmm[keyPrefix]
|
||||
c.Unlock()
|
||||
|
||||
if ok {
|
||||
return kmap, nil
|
||||
}
|
||||
|
||||
kmap = kvMap{}
|
||||
|
||||
// Bail out right away if the kvObject does not implement KVConstructor
|
||||
ctor, ok := kvObject.(KVConstructor)
|
||||
if !ok {
|
||||
return nil, errors.New("error while populating kmap, object does not implement KVConstructor interface")
|
||||
}
|
||||
|
||||
kvList, err := c.ds.store.List(keyPrefix)
|
||||
if err != nil {
|
||||
if err == store.ErrKeyNotFound {
|
||||
// If the store doesn't have anything then there is nothing to
|
||||
// populate in the cache. Just bail out.
|
||||
goto out
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("error while populating kmap: %v", err)
|
||||
}
|
||||
|
||||
for _, kvPair := range kvList {
|
||||
// Ignore empty kvPair values
|
||||
if len(kvPair.Value) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
dstO := ctor.New()
|
||||
err = dstO.SetValue(kvPair.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Make sure the object has a correct view of the DB index in
|
||||
// case we need to modify it and update the DB.
|
||||
dstO.SetIndex(kvPair.LastIndex)
|
||||
|
||||
kmap[Key(dstO.Key()...)] = dstO
|
||||
}
|
||||
|
||||
out:
|
||||
// There may multiple go routines racing to fill the
|
||||
// cache. The one which places the kmap in c.kmm first
|
||||
// wins. The others should just use what the first populated.
|
||||
c.Lock()
|
||||
kmapNew, ok := c.kmm[keyPrefix]
|
||||
if ok {
|
||||
c.Unlock()
|
||||
return kmapNew, nil
|
||||
}
|
||||
|
||||
c.kmm[keyPrefix] = kmap
|
||||
c.Unlock()
|
||||
|
||||
return kmap, nil
|
||||
}
|
||||
|
||||
func (c *cache) add(kvObject KVObject, atomic bool) error {
|
||||
kmap, err := c.kmap(kvObject)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.Lock()
|
||||
// If atomic is true, cache needs to maintain its own index
|
||||
// for atomicity and the add needs to be atomic.
|
||||
if atomic {
|
||||
if prev, ok := kmap[Key(kvObject.Key()...)]; ok {
|
||||
if prev.Index() != kvObject.Index() {
|
||||
c.Unlock()
|
||||
return ErrKeyModified
|
||||
}
|
||||
}
|
||||
|
||||
// Increment index
|
||||
index := kvObject.Index()
|
||||
index++
|
||||
kvObject.SetIndex(index)
|
||||
}
|
||||
|
||||
kmap[Key(kvObject.Key()...)] = kvObject
|
||||
c.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *cache) del(kvObject KVObject, atomic bool) error {
|
||||
kmap, err := c.kmap(kvObject)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.Lock()
|
||||
// If atomic is true, cache needs to maintain its own index
|
||||
// for atomicity and del needs to be atomic.
|
||||
if atomic {
|
||||
if prev, ok := kmap[Key(kvObject.Key()...)]; ok {
|
||||
if prev.Index() != kvObject.Index() {
|
||||
c.Unlock()
|
||||
return ErrKeyModified
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete(kmap, Key(kvObject.Key()...))
|
||||
c.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *cache) get(key string, kvObject KVObject) error {
|
||||
kmap, err := c.kmap(kvObject)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
o, ok := kmap[Key(kvObject.Key()...)]
|
||||
if !ok {
|
||||
return ErrKeyNotFound
|
||||
}
|
||||
|
||||
ctor, ok := o.(KVConstructor)
|
||||
if !ok {
|
||||
return errors.New("kvobject does not implement KVConstructor interface. could not get object")
|
||||
}
|
||||
|
||||
return ctor.CopyTo(kvObject)
|
||||
}
|
||||
|
||||
func (c *cache) list(kvObject KVObject) ([]KVObject, error) {
|
||||
kmap, err := c.kmap(kvObject)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
var kvol []KVObject
|
||||
for _, v := range kmap {
|
||||
kvol = append(kvol, v)
|
||||
}
|
||||
|
||||
return kvol, nil
|
||||
}
|
660
vendor/github.com/docker/libnetwork/datastore/datastore.go
generated
vendored
660
vendor/github.com/docker/libnetwork/datastore/datastore.go
generated
vendored
|
@ -1,660 +0,0 @@
|
|||
package datastore
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/docker/libkv"
|
||||
"github.com/docker/libkv/store"
|
||||
"github.com/docker/libnetwork/discoverapi"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
//DataStore exported
|
||||
type DataStore interface {
|
||||
// GetObject gets data from datastore and unmarshals to the specified object
|
||||
GetObject(key string, o KVObject) error
|
||||
// PutObject adds a new Record based on an object into the datastore
|
||||
PutObject(kvObject KVObject) error
|
||||
// PutObjectAtomic provides an atomic add and update operation for a Record
|
||||
PutObjectAtomic(kvObject KVObject) error
|
||||
// DeleteObject deletes a record
|
||||
DeleteObject(kvObject KVObject) error
|
||||
// DeleteObjectAtomic performs an atomic delete operation
|
||||
DeleteObjectAtomic(kvObject KVObject) error
|
||||
// DeleteTree deletes a record
|
||||
DeleteTree(kvObject KVObject) error
|
||||
// Watchable returns whether the store is watchable or not
|
||||
Watchable() bool
|
||||
// Watch for changes on a KVObject
|
||||
Watch(kvObject KVObject, stopCh <-chan struct{}) (<-chan KVObject, error)
|
||||
// RestartWatch retriggers stopped Watches
|
||||
RestartWatch()
|
||||
// Active returns if the store is active
|
||||
Active() bool
|
||||
// List returns of a list of KVObjects belonging to the parent
|
||||
// key. The caller must pass a KVObject of the same type as
|
||||
// the objects that need to be listed
|
||||
List(string, KVObject) ([]KVObject, error)
|
||||
// Map returns a Map of KVObjects
|
||||
Map(key string, kvObject KVObject) (map[string]KVObject, error)
|
||||
// Scope returns the scope of the store
|
||||
Scope() string
|
||||
// KVStore returns access to the KV Store
|
||||
KVStore() store.Store
|
||||
// Close closes the data store
|
||||
Close()
|
||||
}
|
||||
|
||||
// ErrKeyModified is raised for an atomic update when the update is working on a stale state
|
||||
var (
|
||||
ErrKeyModified = store.ErrKeyModified
|
||||
ErrKeyNotFound = store.ErrKeyNotFound
|
||||
)
|
||||
|
||||
type datastore struct {
|
||||
scope string
|
||||
store store.Store
|
||||
cache *cache
|
||||
watchCh chan struct{}
|
||||
active bool
|
||||
sequential bool
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// KVObject is Key/Value interface used by objects to be part of the DataStore
|
||||
type KVObject interface {
|
||||
// Key method lets an object provide the Key to be used in KV Store
|
||||
Key() []string
|
||||
// KeyPrefix method lets an object return immediate parent key that can be used for tree walk
|
||||
KeyPrefix() []string
|
||||
// Value method lets an object marshal its content to be stored in the KV store
|
||||
Value() []byte
|
||||
// SetValue is used by the datastore to set the object's value when loaded from the data store.
|
||||
SetValue([]byte) error
|
||||
// Index method returns the latest DB Index as seen by the object
|
||||
Index() uint64
|
||||
// SetIndex method allows the datastore to store the latest DB Index into the object
|
||||
SetIndex(uint64)
|
||||
// True if the object exists in the datastore, false if it hasn't been stored yet.
|
||||
// When SetIndex() is called, the object has been stored.
|
||||
Exists() bool
|
||||
// DataScope indicates the storage scope of the KV object
|
||||
DataScope() string
|
||||
// Skip provides a way for a KV Object to avoid persisting it in the KV Store
|
||||
Skip() bool
|
||||
}
|
||||
|
||||
// KVConstructor interface defines methods which can construct a KVObject from another.
|
||||
type KVConstructor interface {
|
||||
// New returns a new object which is created based on the
|
||||
// source object
|
||||
New() KVObject
|
||||
// CopyTo deep copies the contents of the implementing object
|
||||
// to the passed destination object
|
||||
CopyTo(KVObject) error
|
||||
}
|
||||
|
||||
// ScopeCfg represents Datastore configuration.
|
||||
type ScopeCfg struct {
|
||||
Client ScopeClientCfg
|
||||
}
|
||||
|
||||
// ScopeClientCfg represents Datastore Client-only mode configuration
|
||||
type ScopeClientCfg struct {
|
||||
Provider string
|
||||
Address string
|
||||
Config *store.Config
|
||||
}
|
||||
|
||||
const (
|
||||
// LocalScope indicates to store the KV object in local datastore such as boltdb
|
||||
LocalScope = "local"
|
||||
// GlobalScope indicates to store the KV object in global datastore such as consul/etcd/zookeeper
|
||||
GlobalScope = "global"
|
||||
// SwarmScope is not indicating a datastore location. It is defined here
|
||||
// along with the other two scopes just for consistency.
|
||||
SwarmScope = "swarm"
|
||||
defaultPrefix = "/var/lib/docker/network/files"
|
||||
)
|
||||
|
||||
const (
|
||||
// NetworkKeyPrefix is the prefix for network key in the kv store
|
||||
NetworkKeyPrefix = "network"
|
||||
// EndpointKeyPrefix is the prefix for endpoint key in the kv store
|
||||
EndpointKeyPrefix = "endpoint"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultScopes = makeDefaultScopes()
|
||||
)
|
||||
|
||||
func makeDefaultScopes() map[string]*ScopeCfg {
|
||||
def := make(map[string]*ScopeCfg)
|
||||
def[LocalScope] = &ScopeCfg{
|
||||
Client: ScopeClientCfg{
|
||||
Provider: string(store.BOLTDB),
|
||||
Address: defaultPrefix + "/local-kv.db",
|
||||
Config: &store.Config{
|
||||
Bucket: "libnetwork",
|
||||
ConnectionTimeout: time.Minute,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return def
|
||||
}
|
||||
|
||||
var defaultRootChain = []string{"docker", "network", "v1.0"}
|
||||
var rootChain = defaultRootChain
|
||||
|
||||
// DefaultScopes returns a map of default scopes and its config for clients to use.
|
||||
func DefaultScopes(dataDir string) map[string]*ScopeCfg {
|
||||
if dataDir != "" {
|
||||
defaultScopes[LocalScope].Client.Address = dataDir + "/network/files/local-kv.db"
|
||||
return defaultScopes
|
||||
}
|
||||
|
||||
defaultScopes[LocalScope].Client.Address = defaultPrefix + "/local-kv.db"
|
||||
return defaultScopes
|
||||
}
|
||||
|
||||
// IsValid checks if the scope config has valid configuration.
|
||||
func (cfg *ScopeCfg) IsValid() bool {
|
||||
if cfg == nil ||
|
||||
strings.TrimSpace(cfg.Client.Provider) == "" ||
|
||||
strings.TrimSpace(cfg.Client.Address) == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
//Key provides convenient method to create a Key
|
||||
func Key(key ...string) string {
|
||||
keychain := append(rootChain, key...)
|
||||
str := strings.Join(keychain, "/")
|
||||
return str + "/"
|
||||
}
|
||||
|
||||
//ParseKey provides convenient method to unpack the key to complement the Key function
|
||||
func ParseKey(key string) ([]string, error) {
|
||||
chain := strings.Split(strings.Trim(key, "/"), "/")
|
||||
|
||||
// The key must at least be equal to the rootChain in order to be considered as valid
|
||||
if len(chain) <= len(rootChain) || !reflect.DeepEqual(chain[0:len(rootChain)], rootChain) {
|
||||
return nil, types.BadRequestErrorf("invalid Key : %s", key)
|
||||
}
|
||||
return chain[len(rootChain):], nil
|
||||
}
|
||||
|
||||
// newClient used to connect to KV Store
|
||||
func newClient(scope string, kv string, addr string, config *store.Config, cached bool) (DataStore, error) {
|
||||
|
||||
if cached && scope != LocalScope {
|
||||
return nil, fmt.Errorf("caching supported only for scope %s", LocalScope)
|
||||
}
|
||||
sequential := false
|
||||
if scope == LocalScope {
|
||||
sequential = true
|
||||
}
|
||||
|
||||
if config == nil {
|
||||
config = &store.Config{}
|
||||
}
|
||||
|
||||
var addrs []string
|
||||
|
||||
if kv == string(store.BOLTDB) {
|
||||
// Parse file path
|
||||
addrs = strings.Split(addr, ",")
|
||||
} else {
|
||||
// Parse URI
|
||||
parts := strings.SplitN(addr, "/", 2)
|
||||
addrs = strings.Split(parts[0], ",")
|
||||
|
||||
// Add the custom prefix to the root chain
|
||||
if len(parts) == 2 {
|
||||
rootChain = append([]string{parts[1]}, defaultRootChain...)
|
||||
}
|
||||
}
|
||||
|
||||
store, err := libkv.NewStore(store.Backend(kv), addrs, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ds := &datastore{scope: scope, store: store, active: true, watchCh: make(chan struct{}), sequential: sequential}
|
||||
if cached {
|
||||
ds.cache = newCache(ds)
|
||||
}
|
||||
|
||||
return ds, nil
|
||||
}
|
||||
|
||||
// NewDataStore creates a new instance of LibKV data store
|
||||
func NewDataStore(scope string, cfg *ScopeCfg) (DataStore, error) {
|
||||
if cfg == nil || cfg.Client.Provider == "" || cfg.Client.Address == "" {
|
||||
c, ok := defaultScopes[scope]
|
||||
if !ok || c.Client.Provider == "" || c.Client.Address == "" {
|
||||
return nil, fmt.Errorf("unexpected scope %s without configuration passed", scope)
|
||||
}
|
||||
|
||||
cfg = c
|
||||
}
|
||||
|
||||
var cached bool
|
||||
if scope == LocalScope {
|
||||
cached = true
|
||||
}
|
||||
|
||||
return newClient(scope, cfg.Client.Provider, cfg.Client.Address, cfg.Client.Config, cached)
|
||||
}
|
||||
|
||||
// NewDataStoreFromConfig creates a new instance of LibKV data store starting from the datastore config data
|
||||
func NewDataStoreFromConfig(dsc discoverapi.DatastoreConfigData) (DataStore, error) {
|
||||
var (
|
||||
ok bool
|
||||
sCfgP *store.Config
|
||||
)
|
||||
|
||||
sCfgP, ok = dsc.Config.(*store.Config)
|
||||
if !ok && dsc.Config != nil {
|
||||
return nil, fmt.Errorf("cannot parse store configuration: %v", dsc.Config)
|
||||
}
|
||||
|
||||
scopeCfg := &ScopeCfg{
|
||||
Client: ScopeClientCfg{
|
||||
Address: dsc.Address,
|
||||
Provider: dsc.Provider,
|
||||
Config: sCfgP,
|
||||
},
|
||||
}
|
||||
|
||||
ds, err := NewDataStore(dsc.Scope, scopeCfg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to construct datastore client from datastore configuration %v: %v", dsc, err)
|
||||
}
|
||||
|
||||
return ds, err
|
||||
}
|
||||
|
||||
func (ds *datastore) Close() {
|
||||
ds.store.Close()
|
||||
}
|
||||
|
||||
func (ds *datastore) Scope() string {
|
||||
return ds.scope
|
||||
}
|
||||
|
||||
func (ds *datastore) Active() bool {
|
||||
return ds.active
|
||||
}
|
||||
|
||||
func (ds *datastore) Watchable() bool {
|
||||
return ds.scope != LocalScope
|
||||
}
|
||||
|
||||
func (ds *datastore) Watch(kvObject KVObject, stopCh <-chan struct{}) (<-chan KVObject, error) {
|
||||
sCh := make(chan struct{})
|
||||
|
||||
ctor, ok := kvObject.(KVConstructor)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("error watching object type %T, object does not implement KVConstructor interface", kvObject)
|
||||
}
|
||||
|
||||
kvpCh, err := ds.store.Watch(Key(kvObject.Key()...), sCh)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
kvoCh := make(chan KVObject)
|
||||
|
||||
go func() {
|
||||
retry_watch:
|
||||
var err error
|
||||
|
||||
// Make sure to get a new instance of watch channel
|
||||
ds.Lock()
|
||||
watchCh := ds.watchCh
|
||||
ds.Unlock()
|
||||
|
||||
loop:
|
||||
for {
|
||||
select {
|
||||
case <-stopCh:
|
||||
close(sCh)
|
||||
return
|
||||
case kvPair := <-kvpCh:
|
||||
// If the backend KV store gets reset libkv's go routine
|
||||
// for the watch can exit resulting in a nil value in
|
||||
// channel.
|
||||
if kvPair == nil {
|
||||
ds.Lock()
|
||||
ds.active = false
|
||||
ds.Unlock()
|
||||
break loop
|
||||
}
|
||||
|
||||
dstO := ctor.New()
|
||||
|
||||
if err = dstO.SetValue(kvPair.Value); err != nil {
|
||||
log.Printf("Could not unmarshal kvpair value = %s", string(kvPair.Value))
|
||||
break
|
||||
}
|
||||
|
||||
dstO.SetIndex(kvPair.LastIndex)
|
||||
kvoCh <- dstO
|
||||
}
|
||||
}
|
||||
|
||||
// Wait on watch channel for a re-trigger when datastore becomes active
|
||||
<-watchCh
|
||||
|
||||
kvpCh, err = ds.store.Watch(Key(kvObject.Key()...), sCh)
|
||||
if err != nil {
|
||||
log.Printf("Could not watch the key %s in store: %v", Key(kvObject.Key()...), err)
|
||||
}
|
||||
|
||||
goto retry_watch
|
||||
}()
|
||||
|
||||
return kvoCh, nil
|
||||
}
|
||||
|
||||
func (ds *datastore) RestartWatch() {
|
||||
ds.Lock()
|
||||
defer ds.Unlock()
|
||||
|
||||
ds.active = true
|
||||
watchCh := ds.watchCh
|
||||
ds.watchCh = make(chan struct{})
|
||||
close(watchCh)
|
||||
}
|
||||
|
||||
func (ds *datastore) KVStore() store.Store {
|
||||
return ds.store
|
||||
}
|
||||
|
||||
// PutObjectAtomic adds a new Record based on an object into the datastore
|
||||
func (ds *datastore) PutObjectAtomic(kvObject KVObject) error {
|
||||
var (
|
||||
previous *store.KVPair
|
||||
pair *store.KVPair
|
||||
err error
|
||||
)
|
||||
if ds.sequential {
|
||||
ds.Lock()
|
||||
defer ds.Unlock()
|
||||
}
|
||||
|
||||
if kvObject == nil {
|
||||
return types.BadRequestErrorf("invalid KV Object : nil")
|
||||
}
|
||||
|
||||
kvObjValue := kvObject.Value()
|
||||
|
||||
if kvObjValue == nil {
|
||||
return types.BadRequestErrorf("invalid KV Object with a nil Value for key %s", Key(kvObject.Key()...))
|
||||
}
|
||||
|
||||
if kvObject.Skip() {
|
||||
goto add_cache
|
||||
}
|
||||
|
||||
if kvObject.Exists() {
|
||||
previous = &store.KVPair{Key: Key(kvObject.Key()...), LastIndex: kvObject.Index()}
|
||||
} else {
|
||||
previous = nil
|
||||
}
|
||||
|
||||
_, pair, err = ds.store.AtomicPut(Key(kvObject.Key()...), kvObjValue, previous, nil)
|
||||
if err != nil {
|
||||
if err == store.ErrKeyExists {
|
||||
return ErrKeyModified
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
kvObject.SetIndex(pair.LastIndex)
|
||||
|
||||
add_cache:
|
||||
if ds.cache != nil {
|
||||
// If persistent store is skipped, sequencing needs to
|
||||
// happen in cache.
|
||||
return ds.cache.add(kvObject, kvObject.Skip())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// PutObject adds a new Record based on an object into the datastore
|
||||
func (ds *datastore) PutObject(kvObject KVObject) error {
|
||||
if ds.sequential {
|
||||
ds.Lock()
|
||||
defer ds.Unlock()
|
||||
}
|
||||
|
||||
if kvObject == nil {
|
||||
return types.BadRequestErrorf("invalid KV Object : nil")
|
||||
}
|
||||
|
||||
if kvObject.Skip() {
|
||||
goto add_cache
|
||||
}
|
||||
|
||||
if err := ds.putObjectWithKey(kvObject, kvObject.Key()...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
add_cache:
|
||||
if ds.cache != nil {
|
||||
// If persistent store is skipped, sequencing needs to
|
||||
// happen in cache.
|
||||
return ds.cache.add(kvObject, kvObject.Skip())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ds *datastore) putObjectWithKey(kvObject KVObject, key ...string) error {
|
||||
kvObjValue := kvObject.Value()
|
||||
|
||||
if kvObjValue == nil {
|
||||
return types.BadRequestErrorf("invalid KV Object with a nil Value for key %s", Key(kvObject.Key()...))
|
||||
}
|
||||
return ds.store.Put(Key(key...), kvObjValue, nil)
|
||||
}
|
||||
|
||||
// GetObject returns a record matching the key
|
||||
func (ds *datastore) GetObject(key string, o KVObject) error {
|
||||
if ds.sequential {
|
||||
ds.Lock()
|
||||
defer ds.Unlock()
|
||||
}
|
||||
|
||||
if ds.cache != nil {
|
||||
return ds.cache.get(key, o)
|
||||
}
|
||||
|
||||
kvPair, err := ds.store.Get(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := o.SetValue(kvPair.Value); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Make sure the object has a correct view of the DB index in
|
||||
// case we need to modify it and update the DB.
|
||||
o.SetIndex(kvPair.LastIndex)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ds *datastore) ensureParent(parent string) error {
|
||||
exists, err := ds.store.Exists(parent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if exists {
|
||||
return nil
|
||||
}
|
||||
return ds.store.Put(parent, []byte{}, &store.WriteOptions{IsDir: true})
|
||||
}
|
||||
|
||||
func (ds *datastore) List(key string, kvObject KVObject) ([]KVObject, error) {
|
||||
if ds.sequential {
|
||||
ds.Lock()
|
||||
defer ds.Unlock()
|
||||
}
|
||||
|
||||
if ds.cache != nil {
|
||||
return ds.cache.list(kvObject)
|
||||
}
|
||||
|
||||
var kvol []KVObject
|
||||
cb := func(key string, val KVObject) {
|
||||
kvol = append(kvol, val)
|
||||
}
|
||||
err := ds.iterateKVPairsFromStore(key, kvObject, cb)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return kvol, nil
|
||||
}
|
||||
|
||||
func (ds *datastore) iterateKVPairsFromStore(key string, kvObject KVObject, callback func(string, KVObject)) error {
|
||||
// Bail out right away if the kvObject does not implement KVConstructor
|
||||
ctor, ok := kvObject.(KVConstructor)
|
||||
if !ok {
|
||||
return fmt.Errorf("error listing objects, object does not implement KVConstructor interface")
|
||||
}
|
||||
|
||||
// Make sure the parent key exists
|
||||
if err := ds.ensureParent(key); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
kvList, err := ds.store.List(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, kvPair := range kvList {
|
||||
if len(kvPair.Value) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
dstO := ctor.New()
|
||||
if err := dstO.SetValue(kvPair.Value); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Make sure the object has a correct view of the DB index in
|
||||
// case we need to modify it and update the DB.
|
||||
dstO.SetIndex(kvPair.LastIndex)
|
||||
callback(kvPair.Key, dstO)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ds *datastore) Map(key string, kvObject KVObject) (map[string]KVObject, error) {
|
||||
if ds.sequential {
|
||||
ds.Lock()
|
||||
defer ds.Unlock()
|
||||
}
|
||||
|
||||
kvol := make(map[string]KVObject)
|
||||
cb := func(key string, val KVObject) {
|
||||
// Trim the leading & trailing "/" to make it consistent across all stores
|
||||
kvol[strings.Trim(key, "/")] = val
|
||||
}
|
||||
err := ds.iterateKVPairsFromStore(key, kvObject, cb)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return kvol, nil
|
||||
}
|
||||
|
||||
// DeleteObject unconditionally deletes a record from the store
|
||||
func (ds *datastore) DeleteObject(kvObject KVObject) error {
|
||||
if ds.sequential {
|
||||
ds.Lock()
|
||||
defer ds.Unlock()
|
||||
}
|
||||
|
||||
// cleanup the cache first
|
||||
if ds.cache != nil {
|
||||
// If persistent store is skipped, sequencing needs to
|
||||
// happen in cache.
|
||||
ds.cache.del(kvObject, kvObject.Skip())
|
||||
}
|
||||
|
||||
if kvObject.Skip() {
|
||||
return nil
|
||||
}
|
||||
|
||||
return ds.store.Delete(Key(kvObject.Key()...))
|
||||
}
|
||||
|
||||
// DeleteObjectAtomic performs atomic delete on a record
|
||||
func (ds *datastore) DeleteObjectAtomic(kvObject KVObject) error {
|
||||
if ds.sequential {
|
||||
ds.Lock()
|
||||
defer ds.Unlock()
|
||||
}
|
||||
|
||||
if kvObject == nil {
|
||||
return types.BadRequestErrorf("invalid KV Object : nil")
|
||||
}
|
||||
|
||||
previous := &store.KVPair{Key: Key(kvObject.Key()...), LastIndex: kvObject.Index()}
|
||||
|
||||
if kvObject.Skip() {
|
||||
goto del_cache
|
||||
}
|
||||
|
||||
if _, err := ds.store.AtomicDelete(Key(kvObject.Key()...), previous); err != nil {
|
||||
if err == store.ErrKeyExists {
|
||||
return ErrKeyModified
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
del_cache:
|
||||
// cleanup the cache only if AtomicDelete went through successfully
|
||||
if ds.cache != nil {
|
||||
// If persistent store is skipped, sequencing needs to
|
||||
// happen in cache.
|
||||
return ds.cache.del(kvObject, kvObject.Skip())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteTree unconditionally deletes a record from the store
|
||||
func (ds *datastore) DeleteTree(kvObject KVObject) error {
|
||||
if ds.sequential {
|
||||
ds.Lock()
|
||||
defer ds.Unlock()
|
||||
}
|
||||
|
||||
// cleanup the cache first
|
||||
if ds.cache != nil {
|
||||
// If persistent store is skipped, sequencing needs to
|
||||
// happen in cache.
|
||||
ds.cache.del(kvObject, kvObject.Skip())
|
||||
}
|
||||
|
||||
if kvObject.Skip() {
|
||||
return nil
|
||||
}
|
||||
|
||||
return ds.store.DeleteTree(Key(kvObject.KeyPrefix()...))
|
||||
}
|
129
vendor/github.com/docker/libnetwork/datastore/mock_store.go
generated
vendored
129
vendor/github.com/docker/libnetwork/datastore/mock_store.go
generated
vendored
|
@ -1,129 +0,0 @@
|
|||
package datastore
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/docker/libkv/store"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrNotImplemented exported
|
||||
ErrNotImplemented = errors.New("Functionality not implemented")
|
||||
)
|
||||
|
||||
// MockData exported
|
||||
type MockData struct {
|
||||
Data []byte
|
||||
Index uint64
|
||||
}
|
||||
|
||||
// MockStore exported
|
||||
type MockStore struct {
|
||||
db map[string]*MockData
|
||||
}
|
||||
|
||||
// NewMockStore creates a Map backed Datastore that is useful for mocking
|
||||
func NewMockStore() *MockStore {
|
||||
db := make(map[string]*MockData)
|
||||
return &MockStore{db}
|
||||
}
|
||||
|
||||
// Get the value at "key", returns the last modified index
|
||||
// to use in conjunction to CAS calls
|
||||
func (s *MockStore) Get(key string) (*store.KVPair, error) {
|
||||
mData := s.db[key]
|
||||
if mData == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return &store.KVPair{Value: mData.Data, LastIndex: mData.Index}, nil
|
||||
|
||||
}
|
||||
|
||||
// Put a value at "key"
|
||||
func (s *MockStore) Put(key string, value []byte, options *store.WriteOptions) error {
|
||||
mData := s.db[key]
|
||||
if mData == nil {
|
||||
mData = &MockData{value, 0}
|
||||
}
|
||||
mData.Index = mData.Index + 1
|
||||
s.db[key] = mData
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delete a value at "key"
|
||||
func (s *MockStore) Delete(key string) error {
|
||||
delete(s.db, key)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Exists checks that the key exists inside the store
|
||||
func (s *MockStore) Exists(key string) (bool, error) {
|
||||
_, ok := s.db[key]
|
||||
return ok, nil
|
||||
}
|
||||
|
||||
// List gets a range of values at "directory"
|
||||
func (s *MockStore) List(prefix string) ([]*store.KVPair, error) {
|
||||
return nil, ErrNotImplemented
|
||||
}
|
||||
|
||||
// DeleteTree deletes a range of values at "directory"
|
||||
func (s *MockStore) DeleteTree(prefix string) error {
|
||||
delete(s.db, prefix)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Watch a single key for modifications
|
||||
func (s *MockStore) Watch(key string, stopCh <-chan struct{}) (<-chan *store.KVPair, error) {
|
||||
return nil, ErrNotImplemented
|
||||
}
|
||||
|
||||
// WatchTree triggers a watch on a range of values at "directory"
|
||||
func (s *MockStore) WatchTree(prefix string, stopCh <-chan struct{}) (<-chan []*store.KVPair, error) {
|
||||
return nil, ErrNotImplemented
|
||||
}
|
||||
|
||||
// NewLock exposed
|
||||
func (s *MockStore) NewLock(key string, options *store.LockOptions) (store.Locker, error) {
|
||||
return nil, ErrNotImplemented
|
||||
}
|
||||
|
||||
// AtomicPut put a value at "key" if the key has not been
|
||||
// modified in the meantime, throws an error if this is the case
|
||||
func (s *MockStore) AtomicPut(key string, newValue []byte, previous *store.KVPair, options *store.WriteOptions) (bool, *store.KVPair, error) {
|
||||
mData := s.db[key]
|
||||
|
||||
if previous == nil {
|
||||
if mData != nil {
|
||||
return false, nil, types.BadRequestErrorf("atomic put failed because key exists")
|
||||
} // Else OK.
|
||||
} else {
|
||||
if mData == nil {
|
||||
return false, nil, types.BadRequestErrorf("atomic put failed because key exists")
|
||||
}
|
||||
if mData != nil && mData.Index != previous.LastIndex {
|
||||
return false, nil, types.BadRequestErrorf("atomic put failed due to mismatched Index")
|
||||
} // Else OK.
|
||||
}
|
||||
err := s.Put(key, newValue, nil)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
return true, &store.KVPair{Key: key, Value: newValue, LastIndex: s.db[key].Index}, nil
|
||||
}
|
||||
|
||||
// AtomicDelete deletes a value at "key" if the key has not
|
||||
// been modified in the meantime, throws an error if this is the case
|
||||
func (s *MockStore) AtomicDelete(key string, previous *store.KVPair) (bool, error) {
|
||||
mData := s.db[key]
|
||||
if mData != nil && mData.Index != previous.LastIndex {
|
||||
return false, types.BadRequestErrorf("atomic delete failed due to mismatched Index")
|
||||
}
|
||||
return true, s.Delete(key)
|
||||
}
|
||||
|
||||
// Close closes the client connection
|
||||
func (s *MockStore) Close() {
|
||||
return
|
||||
}
|
201
vendor/github.com/docker/libnetwork/default_gateway.go
generated
vendored
201
vendor/github.com/docker/libnetwork/default_gateway.go
generated
vendored
|
@ -1,201 +0,0 @@
|
|||
package libnetwork
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
gwEPlen = 12
|
||||
)
|
||||
|
||||
var procGwNetwork = make(chan (bool), 1)
|
||||
|
||||
/*
|
||||
libnetwork creates a bridge network "docker_gw_bridge" for providing
|
||||
default gateway for the containers if none of the container's endpoints
|
||||
have GW set by the driver. ICC is set to false for the GW_bridge network.
|
||||
|
||||
If a driver can't provide external connectivity it can choose to not set
|
||||
the GW IP for the endpoint.
|
||||
|
||||
endpoint on the GW_bridge network is managed dynamically by libnetwork.
|
||||
ie:
|
||||
- its created when an endpoint without GW joins the container
|
||||
- its deleted when an endpoint with GW joins the container
|
||||
*/
|
||||
|
||||
func (sb *sandbox) setupDefaultGW() error {
|
||||
|
||||
// check if the container already has a GW endpoint
|
||||
if ep := sb.getEndpointInGWNetwork(); ep != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
c := sb.controller
|
||||
|
||||
// Look for default gw network. In case of error (includes not found),
|
||||
// retry and create it if needed in a serialized execution.
|
||||
n, err := c.NetworkByName(libnGWNetwork)
|
||||
if err != nil {
|
||||
if n, err = c.defaultGwNetwork(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
createOptions := []EndpointOption{CreateOptionAnonymous()}
|
||||
|
||||
var gwName string
|
||||
if len(sb.containerID) <= gwEPlen {
|
||||
gwName = "gateway_" + sb.containerID
|
||||
} else {
|
||||
gwName = "gateway_" + sb.id[:gwEPlen]
|
||||
}
|
||||
|
||||
sbLabels := sb.Labels()
|
||||
|
||||
if sbLabels[netlabel.PortMap] != nil {
|
||||
createOptions = append(createOptions, CreateOptionPortMapping(sbLabels[netlabel.PortMap].([]types.PortBinding)))
|
||||
}
|
||||
|
||||
if sbLabels[netlabel.ExposedPorts] != nil {
|
||||
createOptions = append(createOptions, CreateOptionExposedPorts(sbLabels[netlabel.ExposedPorts].([]types.TransportPort)))
|
||||
}
|
||||
|
||||
epOption := getPlatformOption()
|
||||
if epOption != nil {
|
||||
createOptions = append(createOptions, epOption)
|
||||
}
|
||||
|
||||
newEp, err := n.CreateEndpoint(gwName, createOptions...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("container %s: endpoint create on GW Network failed: %v", sb.containerID, err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if err2 := newEp.Delete(true); err2 != nil {
|
||||
logrus.Warnf("Failed to remove gw endpoint for container %s after failing to join the gateway network: %v",
|
||||
sb.containerID, err2)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
epLocal := newEp.(*endpoint)
|
||||
|
||||
if err = epLocal.sbJoin(sb); err != nil {
|
||||
return fmt.Errorf("container %s: endpoint join on GW Network failed: %v", sb.containerID, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// If present, detach and remove the endpoint connecting the sandbox to the default gw network.
|
||||
func (sb *sandbox) clearDefaultGW() error {
|
||||
var ep *endpoint
|
||||
|
||||
if ep = sb.getEndpointInGWNetwork(); ep == nil {
|
||||
return nil
|
||||
}
|
||||
if err := ep.sbLeave(sb, false); err != nil {
|
||||
return fmt.Errorf("container %s: endpoint leaving GW Network failed: %v", sb.containerID, err)
|
||||
}
|
||||
if err := ep.Delete(false); err != nil {
|
||||
return fmt.Errorf("container %s: deleting endpoint on GW Network failed: %v", sb.containerID, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Evaluate whether the sandbox requires a default gateway based
|
||||
// on the endpoints to which it is connected. It does not account
|
||||
// for the default gateway network endpoint.
|
||||
|
||||
func (sb *sandbox) needDefaultGW() bool {
|
||||
var needGW bool
|
||||
|
||||
for _, ep := range sb.getConnectedEndpoints() {
|
||||
if ep.endpointInGWNetwork() {
|
||||
continue
|
||||
}
|
||||
if ep.getNetwork().Type() == "null" || ep.getNetwork().Type() == "host" {
|
||||
continue
|
||||
}
|
||||
if ep.getNetwork().Internal() {
|
||||
continue
|
||||
}
|
||||
// During stale sandbox cleanup, joinInfo may be nil
|
||||
if ep.joinInfo != nil && ep.joinInfo.disableGatewayService {
|
||||
continue
|
||||
}
|
||||
// TODO v6 needs to be handled.
|
||||
if len(ep.Gateway()) > 0 {
|
||||
return false
|
||||
}
|
||||
for _, r := range ep.StaticRoutes() {
|
||||
if r.Destination != nil && r.Destination.String() == "0.0.0.0/0" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
needGW = true
|
||||
}
|
||||
|
||||
return needGW
|
||||
}
|
||||
|
||||
func (sb *sandbox) getEndpointInGWNetwork() *endpoint {
|
||||
for _, ep := range sb.getConnectedEndpoints() {
|
||||
if ep.getNetwork().name == libnGWNetwork && strings.HasPrefix(ep.Name(), "gateway_") {
|
||||
return ep
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ep *endpoint) endpointInGWNetwork() bool {
|
||||
if ep.getNetwork().name == libnGWNetwork && strings.HasPrefix(ep.Name(), "gateway_") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (sb *sandbox) getEPwithoutGateway() *endpoint {
|
||||
for _, ep := range sb.getConnectedEndpoints() {
|
||||
if ep.getNetwork().Type() == "null" || ep.getNetwork().Type() == "host" {
|
||||
continue
|
||||
}
|
||||
if len(ep.Gateway()) == 0 {
|
||||
return ep
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Looks for the default gw network and creates it if not there.
|
||||
// Parallel executions are serialized.
|
||||
func (c *controller) defaultGwNetwork() (Network, error) {
|
||||
procGwNetwork <- true
|
||||
defer func() { <-procGwNetwork }()
|
||||
|
||||
n, err := c.NetworkByName(libnGWNetwork)
|
||||
if _, ok := err.(types.NotFoundError); ok {
|
||||
n, err = c.createGWNetwork()
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Returns the endpoint which is providing external connectivity to the sandbox
|
||||
func (sb *sandbox) getGatewayEndpoint() *endpoint {
|
||||
for _, ep := range sb.getConnectedEndpoints() {
|
||||
if ep.getNetwork().Type() == "null" || ep.getNetwork().Type() == "host" {
|
||||
continue
|
||||
}
|
||||
if len(ep.Gateway()) != 0 {
|
||||
return ep
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
13
vendor/github.com/docker/libnetwork/default_gateway_freebsd.go
generated
vendored
13
vendor/github.com/docker/libnetwork/default_gateway_freebsd.go
generated
vendored
|
@ -1,13 +0,0 @@
|
|||
package libnetwork
|
||||
|
||||
import "github.com/docker/libnetwork/types"
|
||||
|
||||
const libnGWNetwork = "docker_gwbridge"
|
||||
|
||||
func getPlatformOption() EndpointOption {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *controller) createGWNetwork() (Network, error) {
|
||||
return nil, types.NotImplementedErrorf("default gateway functionality is not implemented in freebsd")
|
||||
}
|
32
vendor/github.com/docker/libnetwork/default_gateway_linux.go
generated
vendored
32
vendor/github.com/docker/libnetwork/default_gateway_linux.go
generated
vendored
|
@ -1,32 +0,0 @@
|
|||
package libnetwork
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/docker/libnetwork/drivers/bridge"
|
||||
)
|
||||
|
||||
const libnGWNetwork = "docker_gwbridge"
|
||||
|
||||
func getPlatformOption() EndpointOption {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *controller) createGWNetwork() (Network, error) {
|
||||
netOption := map[string]string{
|
||||
bridge.BridgeName: libnGWNetwork,
|
||||
bridge.EnableICC: strconv.FormatBool(false),
|
||||
bridge.EnableIPMasquerade: strconv.FormatBool(true),
|
||||
}
|
||||
|
||||
n, err := c.NewNetwork("bridge", libnGWNetwork, "",
|
||||
NetworkOptionDriverOpts(netOption),
|
||||
NetworkOptionEnableIPv6(false),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating external connectivity network: %v", err)
|
||||
}
|
||||
return n, err
|
||||
}
|
22
vendor/github.com/docker/libnetwork/default_gateway_windows.go
generated
vendored
22
vendor/github.com/docker/libnetwork/default_gateway_windows.go
generated
vendored
|
@ -1,22 +0,0 @@
|
|||
package libnetwork
|
||||
|
||||
import (
|
||||
windriver "github.com/docker/libnetwork/drivers/windows"
|
||||
"github.com/docker/libnetwork/options"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
const libnGWNetwork = "nat"
|
||||
|
||||
func getPlatformOption() EndpointOption {
|
||||
|
||||
epOption := options.Generic{
|
||||
windriver.DisableICC: true,
|
||||
windriver.DisableDNS: true,
|
||||
}
|
||||
return EndpointOptionGeneric(epOption)
|
||||
}
|
||||
|
||||
func (c *controller) createGWNetwork() (Network, error) {
|
||||
return nil, types.NotImplementedErrorf("default gateway functionality is not implemented in windows")
|
||||
}
|
227
vendor/github.com/docker/libnetwork/diagnostic/server.go
generated
vendored
227
vendor/github.com/docker/libnetwork/diagnostic/server.go
generated
vendored
|
@ -1,227 +0,0 @@
|
|||
package diagnostic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
stackdump "github.com/docker/docker/pkg/signal"
|
||||
"github.com/docker/libnetwork/internal/caller"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// HTTPHandlerFunc TODO
|
||||
type HTTPHandlerFunc func(interface{}, http.ResponseWriter, *http.Request)
|
||||
|
||||
type httpHandlerCustom struct {
|
||||
ctx interface{}
|
||||
F func(interface{}, http.ResponseWriter, *http.Request)
|
||||
}
|
||||
|
||||
// ServeHTTP TODO
|
||||
func (h httpHandlerCustom) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
h.F(h.ctx, w, r)
|
||||
}
|
||||
|
||||
var diagPaths2Func = map[string]HTTPHandlerFunc{
|
||||
"/": notImplemented,
|
||||
"/help": help,
|
||||
"/ready": ready,
|
||||
"/stackdump": stackTrace,
|
||||
}
|
||||
|
||||
// Server when the debug is enabled exposes a
|
||||
// This data structure is protected by the Agent mutex so does not require and additional mutex here
|
||||
type Server struct {
|
||||
enable int32
|
||||
srv *http.Server
|
||||
port int
|
||||
mux *http.ServeMux
|
||||
registeredHanders map[string]bool
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// New creates a new diagnostic server
|
||||
func New() *Server {
|
||||
return &Server{
|
||||
registeredHanders: make(map[string]bool),
|
||||
}
|
||||
}
|
||||
|
||||
// Init initialize the mux for the http handling and register the base hooks
|
||||
func (s *Server) Init() {
|
||||
s.mux = http.NewServeMux()
|
||||
|
||||
// Register local handlers
|
||||
s.RegisterHandler(s, diagPaths2Func)
|
||||
}
|
||||
|
||||
// RegisterHandler allows to register new handlers to the mux and to a specific path
|
||||
func (s *Server) RegisterHandler(ctx interface{}, hdlrs map[string]HTTPHandlerFunc) {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
for path, fun := range hdlrs {
|
||||
if _, ok := s.registeredHanders[path]; ok {
|
||||
continue
|
||||
}
|
||||
s.mux.Handle(path, httpHandlerCustom{ctx, fun})
|
||||
s.registeredHanders[path] = true
|
||||
}
|
||||
}
|
||||
|
||||
// ServeHTTP this is the method called bu the ListenAndServe, and is needed to allow us to
|
||||
// use our custom mux
|
||||
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
s.mux.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// EnableDiagnostic opens a TCP socket to debug the passed network DB
|
||||
func (s *Server) EnableDiagnostic(ip string, port int) {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
s.port = port
|
||||
|
||||
if s.enable == 1 {
|
||||
logrus.Info("The server is already up and running")
|
||||
return
|
||||
}
|
||||
|
||||
logrus.Infof("Starting the diagnostic server listening on %d for commands", port)
|
||||
srv := &http.Server{Addr: fmt.Sprintf("%s:%d", ip, port), Handler: s}
|
||||
s.srv = srv
|
||||
s.enable = 1
|
||||
go func(n *Server) {
|
||||
// Ignore ErrServerClosed that is returned on the Shutdown call
|
||||
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
logrus.Errorf("ListenAndServe error: %s", err)
|
||||
atomic.SwapInt32(&n.enable, 0)
|
||||
}
|
||||
}(s)
|
||||
}
|
||||
|
||||
// DisableDiagnostic stop the dubug and closes the tcp socket
|
||||
func (s *Server) DisableDiagnostic() {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
s.srv.Shutdown(context.Background())
|
||||
s.srv = nil
|
||||
s.enable = 0
|
||||
logrus.Info("Disabling the diagnostic server")
|
||||
}
|
||||
|
||||
// IsDiagnosticEnabled returns true when the debug is enabled
|
||||
func (s *Server) IsDiagnosticEnabled() bool {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
return s.enable == 1
|
||||
}
|
||||
|
||||
func notImplemented(ctx interface{}, w http.ResponseWriter, r *http.Request) {
|
||||
r.ParseForm()
|
||||
_, json := ParseHTTPFormOptions(r)
|
||||
rsp := WrongCommand("not implemented", fmt.Sprintf("URL path: %s no method implemented check /help\n", r.URL.Path))
|
||||
|
||||
// audit logs
|
||||
log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()})
|
||||
log.Info("command not implemented done")
|
||||
|
||||
HTTPReply(w, rsp, json)
|
||||
}
|
||||
|
||||
func help(ctx interface{}, w http.ResponseWriter, r *http.Request) {
|
||||
r.ParseForm()
|
||||
_, json := ParseHTTPFormOptions(r)
|
||||
|
||||
// audit logs
|
||||
log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()})
|
||||
log.Info("help done")
|
||||
|
||||
n, ok := ctx.(*Server)
|
||||
var result string
|
||||
if ok {
|
||||
for path := range n.registeredHanders {
|
||||
result += fmt.Sprintf("%s\n", path)
|
||||
}
|
||||
HTTPReply(w, CommandSucceed(&StringCmd{Info: result}), json)
|
||||
}
|
||||
}
|
||||
|
||||
func ready(ctx interface{}, w http.ResponseWriter, r *http.Request) {
|
||||
r.ParseForm()
|
||||
_, json := ParseHTTPFormOptions(r)
|
||||
|
||||
// audit logs
|
||||
log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()})
|
||||
log.Info("ready done")
|
||||
HTTPReply(w, CommandSucceed(&StringCmd{Info: "OK"}), json)
|
||||
}
|
||||
|
||||
func stackTrace(ctx interface{}, w http.ResponseWriter, r *http.Request) {
|
||||
r.ParseForm()
|
||||
_, json := ParseHTTPFormOptions(r)
|
||||
|
||||
// audit logs
|
||||
log := logrus.WithFields(logrus.Fields{"component": "diagnostic", "remoteIP": r.RemoteAddr, "method": caller.Name(0), "url": r.URL.String()})
|
||||
log.Info("stack trace")
|
||||
|
||||
path, err := stackdump.DumpStacks("/tmp/")
|
||||
if err != nil {
|
||||
log.WithError(err).Error("failed to write goroutines dump")
|
||||
HTTPReply(w, FailCommand(err), json)
|
||||
} else {
|
||||
log.Info("stack trace done")
|
||||
HTTPReply(w, CommandSucceed(&StringCmd{Info: fmt.Sprintf("goroutine stacks written to %s", path)}), json)
|
||||
}
|
||||
}
|
||||
|
||||
// DebugHTTPForm helper to print the form url parameters
|
||||
func DebugHTTPForm(r *http.Request) {
|
||||
for k, v := range r.Form {
|
||||
logrus.Debugf("Form[%q] = %q\n", k, v)
|
||||
}
|
||||
}
|
||||
|
||||
// JSONOutput contains details on JSON output printing
|
||||
type JSONOutput struct {
|
||||
enable bool
|
||||
prettyPrint bool
|
||||
}
|
||||
|
||||
// ParseHTTPFormOptions easily parse the JSON printing options
|
||||
func ParseHTTPFormOptions(r *http.Request) (bool, *JSONOutput) {
|
||||
_, unsafe := r.Form["unsafe"]
|
||||
v, json := r.Form["json"]
|
||||
var pretty bool
|
||||
if len(v) > 0 {
|
||||
pretty = v[0] == "pretty"
|
||||
}
|
||||
return unsafe, &JSONOutput{enable: json, prettyPrint: pretty}
|
||||
}
|
||||
|
||||
// HTTPReply helper function that takes care of sending the message out
|
||||
func HTTPReply(w http.ResponseWriter, r *HTTPResult, j *JSONOutput) (int, error) {
|
||||
var response []byte
|
||||
if j.enable {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
var err error
|
||||
if j.prettyPrint {
|
||||
response, err = json.MarshalIndent(r, "", " ")
|
||||
if err != nil {
|
||||
response, _ = json.MarshalIndent(FailCommand(err), "", " ")
|
||||
}
|
||||
} else {
|
||||
response, err = json.Marshal(r)
|
||||
if err != nil {
|
||||
response, _ = json.Marshal(FailCommand(err))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
response = []byte(r.String())
|
||||
}
|
||||
return fmt.Fprint(w, string(response))
|
||||
}
|
132
vendor/github.com/docker/libnetwork/diagnostic/types.go
generated
vendored
132
vendor/github.com/docker/libnetwork/diagnostic/types.go
generated
vendored
|
@ -1,132 +0,0 @@
|
|||
package diagnostic
|
||||
|
||||
import "fmt"
|
||||
|
||||
// StringInterface interface that has to be implemented by messages
|
||||
type StringInterface interface {
|
||||
String() string
|
||||
}
|
||||
|
||||
// CommandSucceed creates a success message
|
||||
func CommandSucceed(result StringInterface) *HTTPResult {
|
||||
return &HTTPResult{
|
||||
Message: "OK",
|
||||
Details: result,
|
||||
}
|
||||
}
|
||||
|
||||
// FailCommand creates a failure message with error
|
||||
func FailCommand(err error) *HTTPResult {
|
||||
return &HTTPResult{
|
||||
Message: "FAIL",
|
||||
Details: &ErrorCmd{Error: err.Error()},
|
||||
}
|
||||
}
|
||||
|
||||
// WrongCommand creates a wrong command response
|
||||
func WrongCommand(message, usage string) *HTTPResult {
|
||||
return &HTTPResult{
|
||||
Message: message,
|
||||
Details: &UsageCmd{Usage: usage},
|
||||
}
|
||||
}
|
||||
|
||||
// HTTPResult Diagnostic Server HTTP result operation
|
||||
type HTTPResult struct {
|
||||
Message string `json:"message"`
|
||||
Details StringInterface `json:"details"`
|
||||
}
|
||||
|
||||
func (h *HTTPResult) String() string {
|
||||
rsp := h.Message
|
||||
if h.Details != nil {
|
||||
rsp += "\n" + h.Details.String()
|
||||
}
|
||||
return rsp
|
||||
}
|
||||
|
||||
// UsageCmd command with usage field
|
||||
type UsageCmd struct {
|
||||
Usage string `json:"usage"`
|
||||
}
|
||||
|
||||
func (u *UsageCmd) String() string {
|
||||
return "Usage: " + u.Usage
|
||||
}
|
||||
|
||||
// StringCmd command with info string
|
||||
type StringCmd struct {
|
||||
Info string `json:"info"`
|
||||
}
|
||||
|
||||
func (s *StringCmd) String() string {
|
||||
return s.Info
|
||||
}
|
||||
|
||||
// ErrorCmd command with error
|
||||
type ErrorCmd struct {
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
func (e *ErrorCmd) String() string {
|
||||
return "Error: " + e.Error
|
||||
}
|
||||
|
||||
// TableObj network db table object
|
||||
type TableObj struct {
|
||||
Length int `json:"size"`
|
||||
Elements []StringInterface `json:"entries"`
|
||||
}
|
||||
|
||||
func (t *TableObj) String() string {
|
||||
output := fmt.Sprintf("total entries: %d\n", t.Length)
|
||||
for _, e := range t.Elements {
|
||||
output += e.String()
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
||||
// PeerEntryObj entry in the networkdb peer table
|
||||
type PeerEntryObj struct {
|
||||
Index int `json:"-"`
|
||||
Name string `json:"-=name"`
|
||||
IP string `json:"ip"`
|
||||
}
|
||||
|
||||
func (p *PeerEntryObj) String() string {
|
||||
return fmt.Sprintf("%d) %s -> %s\n", p.Index, p.Name, p.IP)
|
||||
}
|
||||
|
||||
// TableEntryObj network db table entry object
|
||||
type TableEntryObj struct {
|
||||
Index int `json:"-"`
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
Owner string `json:"owner"`
|
||||
}
|
||||
|
||||
func (t *TableEntryObj) String() string {
|
||||
return fmt.Sprintf("%d) k:`%s` -> v:`%s` owner:`%s`\n", t.Index, t.Key, t.Value, t.Owner)
|
||||
}
|
||||
|
||||
// TableEndpointsResult fully typed message for proper unmarshaling on the client side
|
||||
type TableEndpointsResult struct {
|
||||
TableObj
|
||||
Elements []TableEntryObj `json:"entries"`
|
||||
}
|
||||
|
||||
// TablePeersResult fully typed message for proper unmarshaling on the client side
|
||||
type TablePeersResult struct {
|
||||
TableObj
|
||||
Elements []PeerEntryObj `json:"entries"`
|
||||
}
|
||||
|
||||
// NetworkStatsResult network db stats related to entries and queue len for a network
|
||||
type NetworkStatsResult struct {
|
||||
Entries int `json:"entries"`
|
||||
QueueLen int `jsoin:"qlen"`
|
||||
}
|
||||
|
||||
func (n *NetworkStatsResult) String() string {
|
||||
return fmt.Sprintf("entries: %d, qlen: %d\n", n.Entries, n.QueueLen)
|
||||
}
|
60
vendor/github.com/docker/libnetwork/discoverapi/discoverapi.go
generated
vendored
60
vendor/github.com/docker/libnetwork/discoverapi/discoverapi.go
generated
vendored
|
@ -1,60 +0,0 @@
|
|||
package discoverapi
|
||||
|
||||
// Discover is an interface to be implemented by the component interested in receiving discover events
|
||||
// like new node joining the cluster or datastore updates
|
||||
type Discover interface {
|
||||
// DiscoverNew is a notification for a new discovery event, Example:a new node joining a cluster
|
||||
DiscoverNew(dType DiscoveryType, data interface{}) error
|
||||
|
||||
// DiscoverDelete is a notification for a discovery delete event, Example:a node leaving a cluster
|
||||
DiscoverDelete(dType DiscoveryType, data interface{}) error
|
||||
}
|
||||
|
||||
// DiscoveryType represents the type of discovery element the DiscoverNew function is invoked on
|
||||
type DiscoveryType int
|
||||
|
||||
const (
|
||||
// NodeDiscovery represents Node join/leave events provided by discovery
|
||||
NodeDiscovery = iota + 1
|
||||
// DatastoreConfig represents an add/remove datastore event
|
||||
DatastoreConfig
|
||||
// EncryptionKeysConfig represents the initial key(s) for performing datapath encryption
|
||||
EncryptionKeysConfig
|
||||
// EncryptionKeysUpdate represents an update to the datapath encryption key(s)
|
||||
EncryptionKeysUpdate
|
||||
)
|
||||
|
||||
// NodeDiscoveryData represents the structure backing the node discovery data json string
|
||||
type NodeDiscoveryData struct {
|
||||
Address string
|
||||
BindAddress string
|
||||
Self bool
|
||||
}
|
||||
|
||||
// DatastoreConfigData is the data for the datastore update event message
|
||||
type DatastoreConfigData struct {
|
||||
Scope string
|
||||
Provider string
|
||||
Address string
|
||||
Config interface{}
|
||||
}
|
||||
|
||||
// DriverEncryptionConfig contains the initial datapath encryption key(s)
|
||||
// Key in first position is the primary key, the one to be used in tx.
|
||||
// Original key and tag types are []byte and uint64
|
||||
type DriverEncryptionConfig struct {
|
||||
Keys [][]byte
|
||||
Tags []uint64
|
||||
}
|
||||
|
||||
// DriverEncryptionUpdate carries an update to the encryption key(s) as:
|
||||
// a new key and/or set a primary key and/or a removal of an existing key.
|
||||
// Original key and tag types are []byte and uint64
|
||||
type DriverEncryptionUpdate struct {
|
||||
Key []byte
|
||||
Tag uint64
|
||||
Primary []byte
|
||||
PrimaryTag uint64
|
||||
Prune []byte
|
||||
PruneTag uint64
|
||||
}
|
218
vendor/github.com/docker/libnetwork/driverapi/driverapi.go
generated
vendored
218
vendor/github.com/docker/libnetwork/driverapi/driverapi.go
generated
vendored
|
@ -1,218 +0,0 @@
|
|||
package driverapi
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/docker/docker/pkg/plugingetter"
|
||||
"github.com/docker/libnetwork/discoverapi"
|
||||
)
|
||||
|
||||
// NetworkPluginEndpointType represents the Endpoint Type used by Plugin system
|
||||
const NetworkPluginEndpointType = "NetworkDriver"
|
||||
|
||||
// Driver is an interface that every plugin driver needs to implement.
|
||||
type Driver interface {
|
||||
discoverapi.Discover
|
||||
|
||||
// NetworkAllocate invokes the driver method to allocate network
|
||||
// specific resources passing network id and network specific config.
|
||||
// It returns a key,value pair of network specific driver allocations
|
||||
// to the caller.
|
||||
NetworkAllocate(nid string, options map[string]string, ipV4Data, ipV6Data []IPAMData) (map[string]string, error)
|
||||
|
||||
// NetworkFree invokes the driver method to free network specific resources
|
||||
// associated with a given network id.
|
||||
NetworkFree(nid string) error
|
||||
|
||||
// CreateNetwork invokes the driver method to create a network
|
||||
// passing the network id and network specific config. The
|
||||
// config mechanism will eventually be replaced with labels
|
||||
// which are yet to be introduced. The driver can return a
|
||||
// list of table names for which it is interested in receiving
|
||||
// notification when a CRUD operation is performed on any
|
||||
// entry in that table. This will be ignored for local scope
|
||||
// drivers.
|
||||
CreateNetwork(nid string, options map[string]interface{}, nInfo NetworkInfo, ipV4Data, ipV6Data []IPAMData) error
|
||||
|
||||
// DeleteNetwork invokes the driver method to delete network passing
|
||||
// the network id.
|
||||
DeleteNetwork(nid string) error
|
||||
|
||||
// CreateEndpoint invokes the driver method to create an endpoint
|
||||
// passing the network id, endpoint id endpoint information and driver
|
||||
// specific config. The endpoint information can be either consumed by
|
||||
// the driver or populated by the driver. The config mechanism will
|
||||
// eventually be replaced with labels which are yet to be introduced.
|
||||
CreateEndpoint(nid, eid string, ifInfo InterfaceInfo, options map[string]interface{}) error
|
||||
|
||||
// DeleteEndpoint invokes the driver method to delete an endpoint
|
||||
// passing the network id and endpoint id.
|
||||
DeleteEndpoint(nid, eid string) error
|
||||
|
||||
// EndpointOperInfo retrieves from the driver the operational data related to the specified endpoint
|
||||
EndpointOperInfo(nid, eid string) (map[string]interface{}, error)
|
||||
|
||||
// Join method is invoked when a Sandbox is attached to an endpoint.
|
||||
Join(nid, eid string, sboxKey string, jinfo JoinInfo, options map[string]interface{}) error
|
||||
|
||||
// Leave method is invoked when a Sandbox detaches from an endpoint.
|
||||
Leave(nid, eid string) error
|
||||
|
||||
// ProgramExternalConnectivity invokes the driver method which does the necessary
|
||||
// programming to allow the external connectivity dictated by the passed options
|
||||
ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error
|
||||
|
||||
// RevokeExternalConnectivity asks the driver to remove any external connectivity
|
||||
// programming that was done so far
|
||||
RevokeExternalConnectivity(nid, eid string) error
|
||||
|
||||
// EventNotify notifies the driver when a CRUD operation has
|
||||
// happened on a table of its interest as soon as this node
|
||||
// receives such an event in the gossip layer. This method is
|
||||
// only invoked for the global scope driver.
|
||||
EventNotify(event EventType, nid string, tableName string, key string, value []byte)
|
||||
|
||||
// DecodeTableEntry passes the driver a key, value pair from table it registered
|
||||
// with libnetwork. Driver should return {object ID, map[string]string} tuple.
|
||||
// If DecodeTableEntry is called for a table associated with NetworkObject or
|
||||
// EndpointObject the return object ID should be the network id or endpoint id
|
||||
// associated with that entry. map should have information about the object that
|
||||
// can be presented to the user.
|
||||
// For example: overlay driver returns the VTEP IP of the host that has the endpoint
|
||||
// which is shown in 'network inspect --verbose'
|
||||
DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string)
|
||||
|
||||
// Type returns the type of this driver, the network type this driver manages
|
||||
Type() string
|
||||
|
||||
// IsBuiltIn returns true if it is a built-in driver
|
||||
IsBuiltIn() bool
|
||||
}
|
||||
|
||||
// NetworkInfo provides a go interface for drivers to provide network
|
||||
// specific information to libnetwork.
|
||||
type NetworkInfo interface {
|
||||
// TableEventRegister registers driver interest in a given
|
||||
// table name.
|
||||
TableEventRegister(tableName string, objType ObjectType) error
|
||||
|
||||
// UpdateIPamConfig updates the networks IPAM configuration
|
||||
// based on information from the driver. In windows, the OS (HNS) chooses
|
||||
// the IP address space if the user does not specify an address space.
|
||||
UpdateIpamConfig(ipV4Data []IPAMData)
|
||||
}
|
||||
|
||||
// InterfaceInfo provides a go interface for drivers to retrieve
|
||||
// network information to interface resources.
|
||||
type InterfaceInfo interface {
|
||||
// SetMacAddress allows the driver to set the mac address to the endpoint interface
|
||||
// during the call to CreateEndpoint, if the mac address is not already set.
|
||||
SetMacAddress(mac net.HardwareAddr) error
|
||||
|
||||
// SetIPAddress allows the driver to set the ip address to the endpoint interface
|
||||
// during the call to CreateEndpoint, if the address is not already set.
|
||||
// The API is to be used to assign both the IPv4 and IPv6 address types.
|
||||
SetIPAddress(ip *net.IPNet) error
|
||||
|
||||
// MacAddress returns the MAC address.
|
||||
MacAddress() net.HardwareAddr
|
||||
|
||||
// Address returns the IPv4 address.
|
||||
Address() *net.IPNet
|
||||
|
||||
// AddressIPv6 returns the IPv6 address.
|
||||
AddressIPv6() *net.IPNet
|
||||
}
|
||||
|
||||
// InterfaceNameInfo provides a go interface for the drivers to assign names
|
||||
// to interfaces.
|
||||
type InterfaceNameInfo interface {
|
||||
// SetNames method assigns the srcName and dstPrefix for the interface.
|
||||
SetNames(srcName, dstPrefix string) error
|
||||
}
|
||||
|
||||
// JoinInfo represents a set of resources that the driver has the ability to provide during
|
||||
// join time.
|
||||
type JoinInfo interface {
|
||||
// InterfaceName returns an InterfaceNameInfo go interface to facilitate
|
||||
// setting the names for the interface.
|
||||
InterfaceName() InterfaceNameInfo
|
||||
|
||||
// SetGateway sets the default IPv4 gateway when a container joins the endpoint.
|
||||
SetGateway(net.IP) error
|
||||
|
||||
// SetGatewayIPv6 sets the default IPv6 gateway when a container joins the endpoint.
|
||||
SetGatewayIPv6(net.IP) error
|
||||
|
||||
// AddStaticRoute adds a route to the sandbox.
|
||||
// It may be used in addition to or instead of a default gateway (as above).
|
||||
AddStaticRoute(destination *net.IPNet, routeType int, nextHop net.IP) error
|
||||
|
||||
// DisableGatewayService tells libnetwork not to provide Default GW for the container
|
||||
DisableGatewayService()
|
||||
|
||||
// AddTableEntry adds a table entry to the gossip layer
|
||||
// passing the table name, key and an opaque value.
|
||||
AddTableEntry(tableName string, key string, value []byte) error
|
||||
}
|
||||
|
||||
// DriverCallback provides a Callback interface for Drivers into LibNetwork
|
||||
type DriverCallback interface {
|
||||
// GetPluginGetter returns the pluginv2 getter.
|
||||
GetPluginGetter() plugingetter.PluginGetter
|
||||
// RegisterDriver provides a way for Remote drivers to dynamically register new NetworkType and associate with a driver instance
|
||||
RegisterDriver(name string, driver Driver, capability Capability) error
|
||||
}
|
||||
|
||||
// Capability represents the high level capabilities of the drivers which libnetwork can make use of
|
||||
type Capability struct {
|
||||
DataScope string
|
||||
ConnectivityScope string
|
||||
}
|
||||
|
||||
// IPAMData represents the per-network ip related
|
||||
// operational information libnetwork will send
|
||||
// to the network driver during CreateNetwork()
|
||||
type IPAMData struct {
|
||||
AddressSpace string
|
||||
Pool *net.IPNet
|
||||
Gateway *net.IPNet
|
||||
AuxAddresses map[string]*net.IPNet
|
||||
}
|
||||
|
||||
// EventType defines a type for the CRUD event
|
||||
type EventType uint8
|
||||
|
||||
const (
|
||||
// Create event is generated when a table entry is created,
|
||||
Create EventType = 1 + iota
|
||||
// Update event is generated when a table entry is updated.
|
||||
Update
|
||||
// Delete event is generated when a table entry is deleted.
|
||||
Delete
|
||||
)
|
||||
|
||||
// ObjectType represents the type of object driver wants to store in libnetwork's networkDB
|
||||
type ObjectType int
|
||||
|
||||
const (
|
||||
// EndpointObject should be set for libnetwork endpoint object related data
|
||||
EndpointObject ObjectType = 1 + iota
|
||||
// NetworkObject should be set for libnetwork network object related data
|
||||
NetworkObject
|
||||
// OpaqueObject is for driver specific data with no corresponding libnetwork object
|
||||
OpaqueObject
|
||||
)
|
||||
|
||||
// IsValidType validates the passed in type against the valid object types
|
||||
func IsValidType(objType ObjectType) bool {
|
||||
switch objType {
|
||||
case EndpointObject:
|
||||
fallthrough
|
||||
case NetworkObject:
|
||||
fallthrough
|
||||
case OpaqueObject:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
56
vendor/github.com/docker/libnetwork/driverapi/errors.go
generated
vendored
56
vendor/github.com/docker/libnetwork/driverapi/errors.go
generated
vendored
|
@ -1,56 +0,0 @@
|
|||
package driverapi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// ErrNoNetwork is returned if no network with the specified id exists
|
||||
type ErrNoNetwork string
|
||||
|
||||
func (enn ErrNoNetwork) Error() string {
|
||||
return fmt.Sprintf("No network (%s) exists", string(enn))
|
||||
}
|
||||
|
||||
// NotFound denotes the type of this error
|
||||
func (enn ErrNoNetwork) NotFound() {}
|
||||
|
||||
// ErrEndpointExists is returned if more than one endpoint is added to the network
|
||||
type ErrEndpointExists string
|
||||
|
||||
func (ee ErrEndpointExists) Error() string {
|
||||
return fmt.Sprintf("Endpoint (%s) already exists (Only one endpoint allowed)", string(ee))
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (ee ErrEndpointExists) Forbidden() {}
|
||||
|
||||
// ErrNotImplemented is returned when a Driver has not implemented an API yet
|
||||
type ErrNotImplemented struct{}
|
||||
|
||||
func (eni *ErrNotImplemented) Error() string {
|
||||
return "The API is not implemented yet"
|
||||
}
|
||||
|
||||
// NotImplemented denotes the type of this error
|
||||
func (eni *ErrNotImplemented) NotImplemented() {}
|
||||
|
||||
// ErrNoEndpoint is returned if no endpoint with the specified id exists
|
||||
type ErrNoEndpoint string
|
||||
|
||||
func (ene ErrNoEndpoint) Error() string {
|
||||
return fmt.Sprintf("No endpoint (%s) exists", string(ene))
|
||||
}
|
||||
|
||||
// NotFound denotes the type of this error
|
||||
func (ene ErrNoEndpoint) NotFound() {}
|
||||
|
||||
// ErrActiveRegistration represents an error when a driver is registered to a networkType that is previously registered
|
||||
type ErrActiveRegistration string
|
||||
|
||||
// Error interface for ErrActiveRegistration
|
||||
func (ar ErrActiveRegistration) Error() string {
|
||||
return fmt.Sprintf("Driver already registered for type %q", string(ar))
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (ar ErrActiveRegistration) Forbidden() {}
|
103
vendor/github.com/docker/libnetwork/driverapi/ipamdata.go
generated
vendored
103
vendor/github.com/docker/libnetwork/driverapi/ipamdata.go
generated
vendored
|
@ -1,103 +0,0 @@
|
|||
package driverapi
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
// MarshalJSON encodes IPAMData into json message
|
||||
func (i *IPAMData) MarshalJSON() ([]byte, error) {
|
||||
m := map[string]interface{}{}
|
||||
m["AddressSpace"] = i.AddressSpace
|
||||
if i.Pool != nil {
|
||||
m["Pool"] = i.Pool.String()
|
||||
}
|
||||
if i.Gateway != nil {
|
||||
m["Gateway"] = i.Gateway.String()
|
||||
}
|
||||
if i.AuxAddresses != nil {
|
||||
am := make(map[string]string, len(i.AuxAddresses))
|
||||
for k, v := range i.AuxAddresses {
|
||||
am[k] = v.String()
|
||||
}
|
||||
m["AuxAddresses"] = am
|
||||
}
|
||||
return json.Marshal(m)
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes a json message into IPAMData
|
||||
func (i *IPAMData) UnmarshalJSON(data []byte) error {
|
||||
var (
|
||||
m map[string]interface{}
|
||||
err error
|
||||
)
|
||||
if err := json.Unmarshal(data, &m); err != nil {
|
||||
return err
|
||||
}
|
||||
i.AddressSpace = m["AddressSpace"].(string)
|
||||
if v, ok := m["Pool"]; ok {
|
||||
if i.Pool, err = types.ParseCIDR(v.(string)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if v, ok := m["Gateway"]; ok {
|
||||
if i.Gateway, err = types.ParseCIDR(v.(string)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if v, ok := m["AuxAddresses"]; ok {
|
||||
b, _ := json.Marshal(v)
|
||||
var am map[string]string
|
||||
if err = json.Unmarshal(b, &am); err != nil {
|
||||
return err
|
||||
}
|
||||
i.AuxAddresses = make(map[string]*net.IPNet, len(am))
|
||||
for k, v := range am {
|
||||
if i.AuxAddresses[k], err = types.ParseCIDR(v); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate checks whether the IPAMData structure contains congruent data
|
||||
func (i *IPAMData) Validate() error {
|
||||
var isV6 bool
|
||||
if i.Pool == nil {
|
||||
return types.BadRequestErrorf("invalid pool")
|
||||
}
|
||||
if i.Gateway == nil {
|
||||
return types.BadRequestErrorf("invalid gateway address")
|
||||
}
|
||||
isV6 = i.IsV6()
|
||||
if isV6 && i.Gateway.IP.To4() != nil || !isV6 && i.Gateway.IP.To4() == nil {
|
||||
return types.BadRequestErrorf("incongruent ip versions for pool and gateway")
|
||||
}
|
||||
for k, sip := range i.AuxAddresses {
|
||||
if isV6 && sip.IP.To4() != nil || !isV6 && sip.IP.To4() == nil {
|
||||
return types.BadRequestErrorf("incongruent ip versions for pool and secondary ip address %s", k)
|
||||
}
|
||||
}
|
||||
if !i.Pool.Contains(i.Gateway.IP) {
|
||||
return types.BadRequestErrorf("invalid gateway address (%s) does not belong to the pool (%s)", i.Gateway, i.Pool)
|
||||
}
|
||||
for k, sip := range i.AuxAddresses {
|
||||
if !i.Pool.Contains(sip.IP) {
|
||||
return types.BadRequestErrorf("invalid secondary address %s (%s) does not belong to the pool (%s)", k, i.Gateway, i.Pool)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsV6 returns whether this is an IPv6 IPAMData structure
|
||||
func (i *IPAMData) IsV6() bool {
|
||||
return nil == i.Pool.IP.To4()
|
||||
}
|
||||
|
||||
func (i *IPAMData) String() string {
|
||||
return fmt.Sprintf("AddressSpace: %s\nPool: %v\nGateway: %v\nAddresses: %v", i.AddressSpace, i.Pool, i.Gateway, i.AuxAddresses)
|
||||
}
|
1579
vendor/github.com/docker/libnetwork/drivers/bridge/bridge.go
generated
vendored
1579
vendor/github.com/docker/libnetwork/drivers/bridge/bridge.go
generated
vendored
File diff suppressed because it is too large
Load diff
398
vendor/github.com/docker/libnetwork/drivers/bridge/bridge_store.go
generated
vendored
398
vendor/github.com/docker/libnetwork/drivers/bridge/bridge_store.go
generated
vendored
|
@ -1,398 +0,0 @@
|
|||
package bridge
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/docker/libnetwork/datastore"
|
||||
"github.com/docker/libnetwork/discoverapi"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
// network config prefix was not specific enough.
|
||||
// To be backward compatible, need custom endpoint
|
||||
// prefix with different root
|
||||
bridgePrefix = "bridge"
|
||||
bridgeEndpointPrefix = "bridge-endpoint"
|
||||
)
|
||||
|
||||
func (d *driver) initStore(option map[string]interface{}) error {
|
||||
if data, ok := option[netlabel.LocalKVClient]; ok {
|
||||
var err error
|
||||
dsc, ok := data.(discoverapi.DatastoreConfigData)
|
||||
if !ok {
|
||||
return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
|
||||
}
|
||||
d.store, err = datastore.NewDataStoreFromConfig(dsc)
|
||||
if err != nil {
|
||||
return types.InternalErrorf("bridge driver failed to initialize data store: %v", err)
|
||||
}
|
||||
|
||||
err = d.populateNetworks()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = d.populateEndpoints()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) populateNetworks() error {
|
||||
kvol, err := d.store.List(datastore.Key(bridgePrefix), &networkConfiguration{})
|
||||
if err != nil && err != datastore.ErrKeyNotFound {
|
||||
return fmt.Errorf("failed to get bridge network configurations from store: %v", err)
|
||||
}
|
||||
|
||||
// It's normal for network configuration state to be empty. Just return.
|
||||
if err == datastore.ErrKeyNotFound {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, kvo := range kvol {
|
||||
ncfg := kvo.(*networkConfiguration)
|
||||
if err = d.createNetwork(ncfg); err != nil {
|
||||
logrus.Warnf("could not create bridge network for id %s bridge name %s while booting up from persistent state: %v", ncfg.ID, ncfg.BridgeName, err)
|
||||
}
|
||||
logrus.Debugf("Network (%.7s) restored", ncfg.ID)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) populateEndpoints() error {
|
||||
kvol, err := d.store.List(datastore.Key(bridgeEndpointPrefix), &bridgeEndpoint{})
|
||||
if err != nil && err != datastore.ErrKeyNotFound {
|
||||
return fmt.Errorf("failed to get bridge endpoints from store: %v", err)
|
||||
}
|
||||
|
||||
if err == datastore.ErrKeyNotFound {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, kvo := range kvol {
|
||||
ep := kvo.(*bridgeEndpoint)
|
||||
n, ok := d.networks[ep.nid]
|
||||
if !ok {
|
||||
logrus.Debugf("Network (%.7s) not found for restored bridge endpoint (%.7s)", ep.nid, ep.id)
|
||||
logrus.Debugf("Deleting stale bridge endpoint (%.7s) from store", ep.id)
|
||||
if err := d.storeDelete(ep); err != nil {
|
||||
logrus.Debugf("Failed to delete stale bridge endpoint (%.7s) from store", ep.id)
|
||||
}
|
||||
continue
|
||||
}
|
||||
n.endpoints[ep.id] = ep
|
||||
n.restorePortAllocations(ep)
|
||||
logrus.Debugf("Endpoint (%.7s) restored to network (%.7s)", ep.id, ep.nid)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) storeUpdate(kvObject datastore.KVObject) error {
|
||||
if d.store == nil {
|
||||
logrus.Warnf("bridge store not initialized. kv object %s is not added to the store", datastore.Key(kvObject.Key()...))
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := d.store.PutObjectAtomic(kvObject); err != nil {
|
||||
return fmt.Errorf("failed to update bridge store for object type %T: %v", kvObject, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) storeDelete(kvObject datastore.KVObject) error {
|
||||
if d.store == nil {
|
||||
logrus.Debugf("bridge store not initialized. kv object %s is not deleted from store", datastore.Key(kvObject.Key()...))
|
||||
return nil
|
||||
}
|
||||
|
||||
retry:
|
||||
if err := d.store.DeleteObjectAtomic(kvObject); err != nil {
|
||||
if err == datastore.ErrKeyModified {
|
||||
if err := d.store.GetObject(datastore.Key(kvObject.Key()...), kvObject); err != nil {
|
||||
return fmt.Errorf("could not update the kvobject to latest when trying to delete: %v", err)
|
||||
}
|
||||
goto retry
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) MarshalJSON() ([]byte, error) {
|
||||
nMap := make(map[string]interface{})
|
||||
nMap["ID"] = ncfg.ID
|
||||
nMap["BridgeName"] = ncfg.BridgeName
|
||||
nMap["EnableIPv6"] = ncfg.EnableIPv6
|
||||
nMap["EnableIPMasquerade"] = ncfg.EnableIPMasquerade
|
||||
nMap["EnableICC"] = ncfg.EnableICC
|
||||
nMap["InhibitIPv4"] = ncfg.InhibitIPv4
|
||||
nMap["Mtu"] = ncfg.Mtu
|
||||
nMap["Internal"] = ncfg.Internal
|
||||
nMap["DefaultBridge"] = ncfg.DefaultBridge
|
||||
nMap["DefaultBindingIP"] = ncfg.DefaultBindingIP.String()
|
||||
nMap["HostIP"] = ncfg.HostIP.String()
|
||||
nMap["DefaultGatewayIPv4"] = ncfg.DefaultGatewayIPv4.String()
|
||||
nMap["DefaultGatewayIPv6"] = ncfg.DefaultGatewayIPv6.String()
|
||||
nMap["ContainerIfacePrefix"] = ncfg.ContainerIfacePrefix
|
||||
nMap["BridgeIfaceCreator"] = ncfg.BridgeIfaceCreator
|
||||
|
||||
if ncfg.AddressIPv4 != nil {
|
||||
nMap["AddressIPv4"] = ncfg.AddressIPv4.String()
|
||||
}
|
||||
|
||||
if ncfg.AddressIPv6 != nil {
|
||||
nMap["AddressIPv6"] = ncfg.AddressIPv6.String()
|
||||
}
|
||||
|
||||
return json.Marshal(nMap)
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) UnmarshalJSON(b []byte) error {
|
||||
var (
|
||||
err error
|
||||
nMap map[string]interface{}
|
||||
)
|
||||
|
||||
if err = json.Unmarshal(b, &nMap); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if v, ok := nMap["AddressIPv4"]; ok {
|
||||
if ncfg.AddressIPv4, err = types.ParseCIDR(v.(string)); err != nil {
|
||||
return types.InternalErrorf("failed to decode bridge network address IPv4 after json unmarshal: %s", v.(string))
|
||||
}
|
||||
}
|
||||
|
||||
if v, ok := nMap["AddressIPv6"]; ok {
|
||||
if ncfg.AddressIPv6, err = types.ParseCIDR(v.(string)); err != nil {
|
||||
return types.InternalErrorf("failed to decode bridge network address IPv6 after json unmarshal: %s", v.(string))
|
||||
}
|
||||
}
|
||||
|
||||
if v, ok := nMap["ContainerIfacePrefix"]; ok {
|
||||
ncfg.ContainerIfacePrefix = v.(string)
|
||||
}
|
||||
|
||||
if v, ok := nMap["HostIP"]; ok {
|
||||
ncfg.HostIP = net.ParseIP(v.(string))
|
||||
}
|
||||
|
||||
ncfg.DefaultBridge = nMap["DefaultBridge"].(bool)
|
||||
ncfg.DefaultBindingIP = net.ParseIP(nMap["DefaultBindingIP"].(string))
|
||||
ncfg.DefaultGatewayIPv4 = net.ParseIP(nMap["DefaultGatewayIPv4"].(string))
|
||||
ncfg.DefaultGatewayIPv6 = net.ParseIP(nMap["DefaultGatewayIPv6"].(string))
|
||||
ncfg.ID = nMap["ID"].(string)
|
||||
ncfg.BridgeName = nMap["BridgeName"].(string)
|
||||
ncfg.EnableIPv6 = nMap["EnableIPv6"].(bool)
|
||||
ncfg.EnableIPMasquerade = nMap["EnableIPMasquerade"].(bool)
|
||||
ncfg.EnableICC = nMap["EnableICC"].(bool)
|
||||
if v, ok := nMap["InhibitIPv4"]; ok {
|
||||
ncfg.InhibitIPv4 = v.(bool)
|
||||
}
|
||||
|
||||
ncfg.Mtu = int(nMap["Mtu"].(float64))
|
||||
if v, ok := nMap["Internal"]; ok {
|
||||
ncfg.Internal = v.(bool)
|
||||
}
|
||||
|
||||
if v, ok := nMap["BridgeIfaceCreator"]; ok {
|
||||
ncfg.BridgeIfaceCreator = ifaceCreator(v.(float64))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) Key() []string {
|
||||
return []string{bridgePrefix, ncfg.ID}
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) KeyPrefix() []string {
|
||||
return []string{bridgePrefix}
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) Value() []byte {
|
||||
b, err := json.Marshal(ncfg)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) SetValue(value []byte) error {
|
||||
return json.Unmarshal(value, ncfg)
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) Index() uint64 {
|
||||
return ncfg.dbIndex
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) SetIndex(index uint64) {
|
||||
ncfg.dbIndex = index
|
||||
ncfg.dbExists = true
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) Exists() bool {
|
||||
return ncfg.dbExists
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) Skip() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) New() datastore.KVObject {
|
||||
return &networkConfiguration{}
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) CopyTo(o datastore.KVObject) error {
|
||||
dstNcfg := o.(*networkConfiguration)
|
||||
*dstNcfg = *ncfg
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) DataScope() string {
|
||||
return datastore.LocalScope
|
||||
}
|
||||
|
||||
func (ep *bridgeEndpoint) MarshalJSON() ([]byte, error) {
|
||||
epMap := make(map[string]interface{})
|
||||
epMap["id"] = ep.id
|
||||
epMap["nid"] = ep.nid
|
||||
epMap["SrcName"] = ep.srcName
|
||||
epMap["MacAddress"] = ep.macAddress.String()
|
||||
epMap["Addr"] = ep.addr.String()
|
||||
if ep.addrv6 != nil {
|
||||
epMap["Addrv6"] = ep.addrv6.String()
|
||||
}
|
||||
epMap["Config"] = ep.config
|
||||
epMap["ContainerConfig"] = ep.containerConfig
|
||||
epMap["ExternalConnConfig"] = ep.extConnConfig
|
||||
epMap["PortMapping"] = ep.portMapping
|
||||
|
||||
return json.Marshal(epMap)
|
||||
}
|
||||
|
||||
func (ep *bridgeEndpoint) UnmarshalJSON(b []byte) error {
|
||||
var (
|
||||
err error
|
||||
epMap map[string]interface{}
|
||||
)
|
||||
|
||||
if err = json.Unmarshal(b, &epMap); err != nil {
|
||||
return fmt.Errorf("Failed to unmarshal to bridge endpoint: %v", err)
|
||||
}
|
||||
|
||||
if v, ok := epMap["MacAddress"]; ok {
|
||||
if ep.macAddress, err = net.ParseMAC(v.(string)); err != nil {
|
||||
return types.InternalErrorf("failed to decode bridge endpoint MAC address (%s) after json unmarshal: %v", v.(string), err)
|
||||
}
|
||||
}
|
||||
if v, ok := epMap["Addr"]; ok {
|
||||
if ep.addr, err = types.ParseCIDR(v.(string)); err != nil {
|
||||
return types.InternalErrorf("failed to decode bridge endpoint IPv4 address (%s) after json unmarshal: %v", v.(string), err)
|
||||
}
|
||||
}
|
||||
if v, ok := epMap["Addrv6"]; ok {
|
||||
if ep.addrv6, err = types.ParseCIDR(v.(string)); err != nil {
|
||||
return types.InternalErrorf("failed to decode bridge endpoint IPv6 address (%s) after json unmarshal: %v", v.(string), err)
|
||||
}
|
||||
}
|
||||
ep.id = epMap["id"].(string)
|
||||
ep.nid = epMap["nid"].(string)
|
||||
ep.srcName = epMap["SrcName"].(string)
|
||||
d, _ := json.Marshal(epMap["Config"])
|
||||
if err := json.Unmarshal(d, &ep.config); err != nil {
|
||||
logrus.Warnf("Failed to decode endpoint config %v", err)
|
||||
}
|
||||
d, _ = json.Marshal(epMap["ContainerConfig"])
|
||||
if err := json.Unmarshal(d, &ep.containerConfig); err != nil {
|
||||
logrus.Warnf("Failed to decode endpoint container config %v", err)
|
||||
}
|
||||
d, _ = json.Marshal(epMap["ExternalConnConfig"])
|
||||
if err := json.Unmarshal(d, &ep.extConnConfig); err != nil {
|
||||
logrus.Warnf("Failed to decode endpoint external connectivity configuration %v", err)
|
||||
}
|
||||
d, _ = json.Marshal(epMap["PortMapping"])
|
||||
if err := json.Unmarshal(d, &ep.portMapping); err != nil {
|
||||
logrus.Warnf("Failed to decode endpoint port mapping %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ep *bridgeEndpoint) Key() []string {
|
||||
return []string{bridgeEndpointPrefix, ep.id}
|
||||
}
|
||||
|
||||
func (ep *bridgeEndpoint) KeyPrefix() []string {
|
||||
return []string{bridgeEndpointPrefix}
|
||||
}
|
||||
|
||||
func (ep *bridgeEndpoint) Value() []byte {
|
||||
b, err := json.Marshal(ep)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (ep *bridgeEndpoint) SetValue(value []byte) error {
|
||||
return json.Unmarshal(value, ep)
|
||||
}
|
||||
|
||||
func (ep *bridgeEndpoint) Index() uint64 {
|
||||
return ep.dbIndex
|
||||
}
|
||||
|
||||
func (ep *bridgeEndpoint) SetIndex(index uint64) {
|
||||
ep.dbIndex = index
|
||||
ep.dbExists = true
|
||||
}
|
||||
|
||||
func (ep *bridgeEndpoint) Exists() bool {
|
||||
return ep.dbExists
|
||||
}
|
||||
|
||||
func (ep *bridgeEndpoint) Skip() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (ep *bridgeEndpoint) New() datastore.KVObject {
|
||||
return &bridgeEndpoint{}
|
||||
}
|
||||
|
||||
func (ep *bridgeEndpoint) CopyTo(o datastore.KVObject) error {
|
||||
dstEp := o.(*bridgeEndpoint)
|
||||
*dstEp = *ep
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ep *bridgeEndpoint) DataScope() string {
|
||||
return datastore.LocalScope
|
||||
}
|
||||
|
||||
func (n *bridgeNetwork) restorePortAllocations(ep *bridgeEndpoint) {
|
||||
if ep.extConnConfig == nil ||
|
||||
ep.extConnConfig.ExposedPorts == nil ||
|
||||
ep.extConnConfig.PortBindings == nil {
|
||||
return
|
||||
}
|
||||
tmp := ep.extConnConfig.PortBindings
|
||||
ep.extConnConfig.PortBindings = ep.portMapping
|
||||
_, err := n.allocatePorts(ep, n.config.DefaultBindingIP, n.driver.config.EnableUserlandProxy)
|
||||
if err != nil {
|
||||
logrus.Warnf("Failed to reserve existing port mapping for endpoint %.7s:%v", ep.id, err)
|
||||
}
|
||||
ep.extConnConfig.PortBindings = tmp
|
||||
}
|
88
vendor/github.com/docker/libnetwork/drivers/bridge/brmanager/brmanager.go
generated
vendored
88
vendor/github.com/docker/libnetwork/drivers/bridge/brmanager/brmanager.go
generated
vendored
|
@ -1,88 +0,0 @@
|
|||
package brmanager
|
||||
|
||||
import (
|
||||
"github.com/docker/libnetwork/datastore"
|
||||
"github.com/docker/libnetwork/discoverapi"
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
const networkType = "bridge"
|
||||
|
||||
type driver struct{}
|
||||
|
||||
// Init registers a new instance of bridge manager driver
|
||||
func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
||||
c := driverapi.Capability{
|
||||
DataScope: datastore.LocalScope,
|
||||
ConnectivityScope: datastore.LocalScope,
|
||||
}
|
||||
return dc.RegisterDriver(networkType, &driver{}, c)
|
||||
}
|
||||
|
||||
func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {
|
||||
return nil, types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) NetworkFree(id string) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
|
||||
}
|
||||
|
||||
func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (d *driver) DeleteNetwork(nid string) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) DeleteEndpoint(nid, eid string) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) {
|
||||
return nil, types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) Leave(nid, eid string) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) Type() string {
|
||||
return networkType
|
||||
}
|
||||
|
||||
func (d *driver) IsBuiltIn() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
341
vendor/github.com/docker/libnetwork/drivers/bridge/errors.go
generated
vendored
341
vendor/github.com/docker/libnetwork/drivers/bridge/errors.go
generated
vendored
|
@ -1,341 +0,0 @@
|
|||
package bridge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
)
|
||||
|
||||
// ErrConfigExists error is returned when driver already has a config applied.
|
||||
type ErrConfigExists struct{}
|
||||
|
||||
func (ece *ErrConfigExists) Error() string {
|
||||
return "configuration already exists, bridge configuration can be applied only once"
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (ece *ErrConfigExists) Forbidden() {}
|
||||
|
||||
// ErrInvalidDriverConfig error is returned when Bridge Driver is passed an invalid config
|
||||
type ErrInvalidDriverConfig struct{}
|
||||
|
||||
func (eidc *ErrInvalidDriverConfig) Error() string {
|
||||
return "Invalid configuration passed to Bridge Driver"
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (eidc *ErrInvalidDriverConfig) BadRequest() {}
|
||||
|
||||
// ErrInvalidNetworkConfig error is returned when a network is created on a driver without valid config.
|
||||
type ErrInvalidNetworkConfig struct{}
|
||||
|
||||
func (einc *ErrInvalidNetworkConfig) Error() string {
|
||||
return "trying to create a network on a driver without valid config"
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (einc *ErrInvalidNetworkConfig) Forbidden() {}
|
||||
|
||||
// ErrInvalidContainerConfig error is returned when an endpoint create is attempted with an invalid configuration.
|
||||
type ErrInvalidContainerConfig struct{}
|
||||
|
||||
func (eicc *ErrInvalidContainerConfig) Error() string {
|
||||
return "Error in joining a container due to invalid configuration"
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (eicc *ErrInvalidContainerConfig) BadRequest() {}
|
||||
|
||||
// ErrInvalidEndpointConfig error is returned when an endpoint create is attempted with an invalid endpoint configuration.
|
||||
type ErrInvalidEndpointConfig struct{}
|
||||
|
||||
func (eiec *ErrInvalidEndpointConfig) Error() string {
|
||||
return "trying to create an endpoint with an invalid endpoint configuration"
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (eiec *ErrInvalidEndpointConfig) BadRequest() {}
|
||||
|
||||
// ErrNetworkExists error is returned when a network already exists and another network is created.
|
||||
type ErrNetworkExists struct{}
|
||||
|
||||
func (ene *ErrNetworkExists) Error() string {
|
||||
return "network already exists, bridge can only have one network"
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (ene *ErrNetworkExists) Forbidden() {}
|
||||
|
||||
// ErrIfaceName error is returned when a new name could not be generated.
|
||||
type ErrIfaceName struct{}
|
||||
|
||||
func (ein *ErrIfaceName) Error() string {
|
||||
return "failed to find name for new interface"
|
||||
}
|
||||
|
||||
// InternalError denotes the type of this error
|
||||
func (ein *ErrIfaceName) InternalError() {}
|
||||
|
||||
// ErrNoIPAddr error is returned when bridge has no IPv4 address configured.
|
||||
type ErrNoIPAddr struct{}
|
||||
|
||||
func (enip *ErrNoIPAddr) Error() string {
|
||||
return "bridge has no IPv4 address configured"
|
||||
}
|
||||
|
||||
// InternalError denotes the type of this error
|
||||
func (enip *ErrNoIPAddr) InternalError() {}
|
||||
|
||||
// ErrInvalidGateway is returned when the user provided default gateway (v4/v6) is not not valid.
|
||||
type ErrInvalidGateway struct{}
|
||||
|
||||
func (eig *ErrInvalidGateway) Error() string {
|
||||
return "default gateway ip must be part of the network"
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (eig *ErrInvalidGateway) BadRequest() {}
|
||||
|
||||
// ErrInvalidContainerSubnet is returned when the container subnet (FixedCIDR) is not valid.
|
||||
type ErrInvalidContainerSubnet struct{}
|
||||
|
||||
func (eis *ErrInvalidContainerSubnet) Error() string {
|
||||
return "container subnet must be a subset of bridge network"
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (eis *ErrInvalidContainerSubnet) BadRequest() {}
|
||||
|
||||
// ErrInvalidMtu is returned when the user provided MTU is not valid.
|
||||
type ErrInvalidMtu int
|
||||
|
||||
func (eim ErrInvalidMtu) Error() string {
|
||||
return fmt.Sprintf("invalid MTU number: %d", int(eim))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (eim ErrInvalidMtu) BadRequest() {}
|
||||
|
||||
// ErrInvalidPort is returned when the container or host port specified in the port binding is not valid.
|
||||
type ErrInvalidPort string
|
||||
|
||||
func (ip ErrInvalidPort) Error() string {
|
||||
return fmt.Sprintf("invalid transport port: %s", string(ip))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (ip ErrInvalidPort) BadRequest() {}
|
||||
|
||||
// ErrUnsupportedAddressType is returned when the specified address type is not supported.
|
||||
type ErrUnsupportedAddressType string
|
||||
|
||||
func (uat ErrUnsupportedAddressType) Error() string {
|
||||
return fmt.Sprintf("unsupported address type: %s", string(uat))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (uat ErrUnsupportedAddressType) BadRequest() {}
|
||||
|
||||
// ErrInvalidAddressBinding is returned when the host address specified in the port binding is not valid.
|
||||
type ErrInvalidAddressBinding string
|
||||
|
||||
func (iab ErrInvalidAddressBinding) Error() string {
|
||||
return fmt.Sprintf("invalid host address in port binding: %s", string(iab))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (iab ErrInvalidAddressBinding) BadRequest() {}
|
||||
|
||||
// ActiveEndpointsError is returned when there are
|
||||
// still active endpoints in the network being deleted.
|
||||
type ActiveEndpointsError string
|
||||
|
||||
func (aee ActiveEndpointsError) Error() string {
|
||||
return fmt.Sprintf("network %s has active endpoint", string(aee))
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (aee ActiveEndpointsError) Forbidden() {}
|
||||
|
||||
// InvalidNetworkIDError is returned when the passed
|
||||
// network id for an existing network is not a known id.
|
||||
type InvalidNetworkIDError string
|
||||
|
||||
func (inie InvalidNetworkIDError) Error() string {
|
||||
return fmt.Sprintf("invalid network id %s", string(inie))
|
||||
}
|
||||
|
||||
// NotFound denotes the type of this error
|
||||
func (inie InvalidNetworkIDError) NotFound() {}
|
||||
|
||||
// InvalidEndpointIDError is returned when the passed
|
||||
// endpoint id is not valid.
|
||||
type InvalidEndpointIDError string
|
||||
|
||||
func (ieie InvalidEndpointIDError) Error() string {
|
||||
return fmt.Sprintf("invalid endpoint id: %s", string(ieie))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (ieie InvalidEndpointIDError) BadRequest() {}
|
||||
|
||||
// InvalidSandboxIDError is returned when the passed
|
||||
// sandbox id is not valid.
|
||||
type InvalidSandboxIDError string
|
||||
|
||||
func (isie InvalidSandboxIDError) Error() string {
|
||||
return fmt.Sprintf("invalid sandbox id: %s", string(isie))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (isie InvalidSandboxIDError) BadRequest() {}
|
||||
|
||||
// EndpointNotFoundError is returned when the no endpoint
|
||||
// with the passed endpoint id is found.
|
||||
type EndpointNotFoundError string
|
||||
|
||||
func (enfe EndpointNotFoundError) Error() string {
|
||||
return fmt.Sprintf("endpoint not found: %s", string(enfe))
|
||||
}
|
||||
|
||||
// NotFound denotes the type of this error
|
||||
func (enfe EndpointNotFoundError) NotFound() {}
|
||||
|
||||
// NonDefaultBridgeExistError is returned when a non-default
|
||||
// bridge config is passed but it does not already exist.
|
||||
type NonDefaultBridgeExistError string
|
||||
|
||||
func (ndbee NonDefaultBridgeExistError) Error() string {
|
||||
return fmt.Sprintf("bridge device with non default name %s must be created manually", string(ndbee))
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (ndbee NonDefaultBridgeExistError) Forbidden() {}
|
||||
|
||||
// NonDefaultBridgeNeedsIPError is returned when a non-default
|
||||
// bridge config is passed but it has no ip configured
|
||||
type NonDefaultBridgeNeedsIPError string
|
||||
|
||||
func (ndbee NonDefaultBridgeNeedsIPError) Error() string {
|
||||
return fmt.Sprintf("bridge device with non default name %s must have a valid IP address", string(ndbee))
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (ndbee NonDefaultBridgeNeedsIPError) Forbidden() {}
|
||||
|
||||
// FixedCIDRv4Error is returned when fixed-cidrv4 configuration
|
||||
// failed.
|
||||
type FixedCIDRv4Error struct {
|
||||
Net *net.IPNet
|
||||
Subnet *net.IPNet
|
||||
Err error
|
||||
}
|
||||
|
||||
func (fcv4 *FixedCIDRv4Error) Error() string {
|
||||
return fmt.Sprintf("setup FixedCIDRv4 failed for subnet %s in %s: %v", fcv4.Subnet, fcv4.Net, fcv4.Err)
|
||||
}
|
||||
|
||||
// InternalError denotes the type of this error
|
||||
func (fcv4 *FixedCIDRv4Error) InternalError() {}
|
||||
|
||||
// FixedCIDRv6Error is returned when fixed-cidrv6 configuration
|
||||
// failed.
|
||||
type FixedCIDRv6Error struct {
|
||||
Net *net.IPNet
|
||||
Err error
|
||||
}
|
||||
|
||||
func (fcv6 *FixedCIDRv6Error) Error() string {
|
||||
return fmt.Sprintf("setup FixedCIDRv6 failed for subnet %s in %s: %v", fcv6.Net, fcv6.Net, fcv6.Err)
|
||||
}
|
||||
|
||||
// InternalError denotes the type of this error
|
||||
func (fcv6 *FixedCIDRv6Error) InternalError() {}
|
||||
|
||||
// IPTableCfgError is returned when an unexpected ip tables configuration is entered
|
||||
type IPTableCfgError string
|
||||
|
||||
func (name IPTableCfgError) Error() string {
|
||||
return fmt.Sprintf("unexpected request to set IP tables for interface: %s", string(name))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (name IPTableCfgError) BadRequest() {}
|
||||
|
||||
// InvalidIPTablesCfgError is returned when an invalid ip tables configuration is entered
|
||||
type InvalidIPTablesCfgError string
|
||||
|
||||
func (action InvalidIPTablesCfgError) Error() string {
|
||||
return fmt.Sprintf("Invalid IPTables action '%s'", string(action))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (action InvalidIPTablesCfgError) BadRequest() {}
|
||||
|
||||
// IPv4AddrRangeError is returned when a valid IP address range couldn't be found.
|
||||
type IPv4AddrRangeError string
|
||||
|
||||
func (name IPv4AddrRangeError) Error() string {
|
||||
return fmt.Sprintf("can't find an address range for interface %q", string(name))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (name IPv4AddrRangeError) BadRequest() {}
|
||||
|
||||
// IPv4AddrAddError is returned when IPv4 address could not be added to the bridge.
|
||||
type IPv4AddrAddError struct {
|
||||
IP *net.IPNet
|
||||
Err error
|
||||
}
|
||||
|
||||
func (ipv4 *IPv4AddrAddError) Error() string {
|
||||
return fmt.Sprintf("failed to add IPv4 address %s to bridge: %v", ipv4.IP, ipv4.Err)
|
||||
}
|
||||
|
||||
// InternalError denotes the type of this error
|
||||
func (ipv4 *IPv4AddrAddError) InternalError() {}
|
||||
|
||||
// IPv6AddrAddError is returned when IPv6 address could not be added to the bridge.
|
||||
type IPv6AddrAddError struct {
|
||||
IP *net.IPNet
|
||||
Err error
|
||||
}
|
||||
|
||||
func (ipv6 *IPv6AddrAddError) Error() string {
|
||||
return fmt.Sprintf("failed to add IPv6 address %s to bridge: %v", ipv6.IP, ipv6.Err)
|
||||
}
|
||||
|
||||
// InternalError denotes the type of this error
|
||||
func (ipv6 *IPv6AddrAddError) InternalError() {}
|
||||
|
||||
// IPv4AddrNoMatchError is returned when the bridge's IPv4 address does not match configured.
|
||||
type IPv4AddrNoMatchError struct {
|
||||
IP net.IP
|
||||
CfgIP net.IP
|
||||
}
|
||||
|
||||
func (ipv4 *IPv4AddrNoMatchError) Error() string {
|
||||
return fmt.Sprintf("bridge IPv4 (%s) does not match requested configuration %s", ipv4.IP, ipv4.CfgIP)
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (ipv4 *IPv4AddrNoMatchError) BadRequest() {}
|
||||
|
||||
// IPv6AddrNoMatchError is returned when the bridge's IPv6 address does not match configured.
|
||||
type IPv6AddrNoMatchError net.IPNet
|
||||
|
||||
func (ipv6 *IPv6AddrNoMatchError) Error() string {
|
||||
return fmt.Sprintf("bridge IPv6 addresses do not match the expected bridge configuration %s", (*net.IPNet)(ipv6).String())
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (ipv6 *IPv6AddrNoMatchError) BadRequest() {}
|
||||
|
||||
// InvalidLinkIPAddrError is returned when a link is configured to a container with an invalid ip address
|
||||
type InvalidLinkIPAddrError string
|
||||
|
||||
func (address InvalidLinkIPAddrError) Error() string {
|
||||
return fmt.Sprintf("Cannot link to a container with Invalid IP Address '%s'", string(address))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (address InvalidLinkIPAddrError) BadRequest() {}
|
86
vendor/github.com/docker/libnetwork/drivers/bridge/interface.go
generated
vendored
86
vendor/github.com/docker/libnetwork/drivers/bridge/interface.go
generated
vendored
|
@ -1,86 +0,0 @@
|
|||
package bridge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultBridgeName is the default name for the bridge interface managed
|
||||
// by the driver when unspecified by the caller.
|
||||
DefaultBridgeName = "docker0"
|
||||
)
|
||||
|
||||
// Interface models the bridge network device.
|
||||
type bridgeInterface struct {
|
||||
Link netlink.Link
|
||||
bridgeIPv4 *net.IPNet
|
||||
bridgeIPv6 *net.IPNet
|
||||
gatewayIPv4 net.IP
|
||||
gatewayIPv6 net.IP
|
||||
nlh *netlink.Handle
|
||||
}
|
||||
|
||||
// newInterface creates a new bridge interface structure. It attempts to find
|
||||
// an already existing device identified by the configuration BridgeName field,
|
||||
// or the default bridge name when unspecified, but doesn't attempt to create
|
||||
// one when missing
|
||||
func newInterface(nlh *netlink.Handle, config *networkConfiguration) (*bridgeInterface, error) {
|
||||
var err error
|
||||
i := &bridgeInterface{nlh: nlh}
|
||||
|
||||
// Initialize the bridge name to the default if unspecified.
|
||||
if config.BridgeName == "" {
|
||||
config.BridgeName = DefaultBridgeName
|
||||
}
|
||||
|
||||
// Attempt to find an existing bridge named with the specified name.
|
||||
i.Link, err = nlh.LinkByName(config.BridgeName)
|
||||
if err != nil {
|
||||
logrus.Debugf("Did not find any interface with name %s: %v", config.BridgeName, err)
|
||||
} else if _, ok := i.Link.(*netlink.Bridge); !ok {
|
||||
return nil, fmt.Errorf("existing interface %s is not a bridge", i.Link.Attrs().Name)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
// exists indicates if the existing bridge interface exists on the system.
|
||||
func (i *bridgeInterface) exists() bool {
|
||||
return i.Link != nil
|
||||
}
|
||||
|
||||
// addresses returns all IPv4 addresses and all IPv6 addresses for the bridge interface.
|
||||
func (i *bridgeInterface) addresses() ([]netlink.Addr, []netlink.Addr, error) {
|
||||
v4addr, err := i.nlh.AddrList(i.Link, netlink.FAMILY_V4)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("Failed to retrieve V4 addresses: %v", err)
|
||||
}
|
||||
|
||||
v6addr, err := i.nlh.AddrList(i.Link, netlink.FAMILY_V6)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("Failed to retrieve V6 addresses: %v", err)
|
||||
}
|
||||
|
||||
if len(v4addr) == 0 {
|
||||
return nil, v6addr, nil
|
||||
}
|
||||
return v4addr, v6addr, nil
|
||||
}
|
||||
|
||||
func (i *bridgeInterface) programIPv6Address() error {
|
||||
_, nlAddressList, err := i.addresses()
|
||||
if err != nil {
|
||||
return &IPv6AddrAddError{IP: i.bridgeIPv6, Err: fmt.Errorf("failed to retrieve address list: %v", err)}
|
||||
}
|
||||
nlAddr := netlink.Addr{IPNet: i.bridgeIPv6}
|
||||
if findIPv6Address(nlAddr, nlAddressList) {
|
||||
return nil
|
||||
}
|
||||
if err := i.nlh.AddrAdd(i.Link, &nlAddr); err != nil {
|
||||
return &IPv6AddrAddError{IP: i.bridgeIPv6, Err: err}
|
||||
}
|
||||
return nil
|
||||
}
|
21
vendor/github.com/docker/libnetwork/drivers/bridge/labels.go
generated
vendored
21
vendor/github.com/docker/libnetwork/drivers/bridge/labels.go
generated
vendored
|
@ -1,21 +0,0 @@
|
|||
package bridge
|
||||
|
||||
const (
|
||||
// BridgeName label for bridge driver
|
||||
BridgeName = "com.docker.network.bridge.name"
|
||||
|
||||
// EnableIPMasquerade label for bridge driver
|
||||
EnableIPMasquerade = "com.docker.network.bridge.enable_ip_masquerade"
|
||||
|
||||
// EnableICC label
|
||||
EnableICC = "com.docker.network.bridge.enable_icc"
|
||||
|
||||
// InhibitIPv4 label
|
||||
InhibitIPv4 = "com.docker.network.bridge.inhibit_ipv4"
|
||||
|
||||
// DefaultBindingIP label
|
||||
DefaultBindingIP = "com.docker.network.bridge.host_binding_ipv4"
|
||||
|
||||
// DefaultBridge label
|
||||
DefaultBridge = "com.docker.network.bridge.default_bridge"
|
||||
)
|
85
vendor/github.com/docker/libnetwork/drivers/bridge/link.go
generated
vendored
85
vendor/github.com/docker/libnetwork/drivers/bridge/link.go
generated
vendored
|
@ -1,85 +0,0 @@
|
|||
package bridge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/docker/libnetwork/iptables"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type link struct {
|
||||
parentIP string
|
||||
childIP string
|
||||
ports []types.TransportPort
|
||||
bridge string
|
||||
}
|
||||
|
||||
func (l *link) String() string {
|
||||
return fmt.Sprintf("%s <-> %s [%v] on %s", l.parentIP, l.childIP, l.ports, l.bridge)
|
||||
}
|
||||
|
||||
func newLink(parentIP, childIP string, ports []types.TransportPort, bridge string) *link {
|
||||
return &link{
|
||||
childIP: childIP,
|
||||
parentIP: parentIP,
|
||||
ports: ports,
|
||||
bridge: bridge,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (l *link) Enable() error {
|
||||
// -A == iptables append flag
|
||||
linkFunction := func() error {
|
||||
return linkContainers("-A", l.parentIP, l.childIP, l.ports, l.bridge, false)
|
||||
}
|
||||
|
||||
iptables.OnReloaded(func() { linkFunction() })
|
||||
return linkFunction()
|
||||
}
|
||||
|
||||
func (l *link) Disable() {
|
||||
// -D == iptables delete flag
|
||||
err := linkContainers("-D", l.parentIP, l.childIP, l.ports, l.bridge, true)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error removing IPTables rules for a link %s due to %s", l.String(), err.Error())
|
||||
}
|
||||
// Return proper error once we move to use a proper iptables package
|
||||
// that returns typed errors
|
||||
}
|
||||
|
||||
func linkContainers(action, parentIP, childIP string, ports []types.TransportPort, bridge string,
|
||||
ignoreErrors bool) error {
|
||||
var nfAction iptables.Action
|
||||
|
||||
switch action {
|
||||
case "-A":
|
||||
nfAction = iptables.Append
|
||||
case "-I":
|
||||
nfAction = iptables.Insert
|
||||
case "-D":
|
||||
nfAction = iptables.Delete
|
||||
default:
|
||||
return InvalidIPTablesCfgError(action)
|
||||
}
|
||||
|
||||
ip1 := net.ParseIP(parentIP)
|
||||
if ip1 == nil {
|
||||
return InvalidLinkIPAddrError(parentIP)
|
||||
}
|
||||
ip2 := net.ParseIP(childIP)
|
||||
if ip2 == nil {
|
||||
return InvalidLinkIPAddrError(childIP)
|
||||
}
|
||||
|
||||
chain := iptables.ChainInfo{Name: DockerChain}
|
||||
for _, port := range ports {
|
||||
err := chain.Link(nfAction, ip1, ip2, int(port.Port), port.Proto.String(), bridge)
|
||||
if !ignoreErrors && err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
126
vendor/github.com/docker/libnetwork/drivers/bridge/netlink_deprecated_linux.go
generated
vendored
126
vendor/github.com/docker/libnetwork/drivers/bridge/netlink_deprecated_linux.go
generated
vendored
|
@ -1,126 +0,0 @@
|
|||
package bridge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
ifNameSize = 16
|
||||
ioctlBrAdd = 0x89a0
|
||||
ioctlBrAddIf = 0x89a2
|
||||
)
|
||||
|
||||
type ifreqIndex struct {
|
||||
IfrnName [ifNameSize]byte
|
||||
IfruIndex int32
|
||||
}
|
||||
|
||||
type ifreqHwaddr struct {
|
||||
IfrnName [ifNameSize]byte
|
||||
IfruHwaddr syscall.RawSockaddr
|
||||
}
|
||||
|
||||
var rnd = rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
|
||||
// THIS CODE DOES NOT COMMUNICATE WITH KERNEL VIA RTNETLINK INTERFACE
|
||||
// IT IS HERE FOR BACKWARDS COMPATIBILITY WITH OLDER LINUX KERNELS
|
||||
// WHICH SHIP WITH OLDER NOT ENTIRELY FUNCTIONAL VERSION OF NETLINK
|
||||
func getIfSocket() (fd int, err error) {
|
||||
for _, socket := range []int{
|
||||
syscall.AF_INET,
|
||||
syscall.AF_PACKET,
|
||||
syscall.AF_INET6,
|
||||
} {
|
||||
if fd, err = syscall.Socket(socket, syscall.SOCK_DGRAM, 0); err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
return fd, nil
|
||||
}
|
||||
return -1, err
|
||||
}
|
||||
|
||||
func ifIoctBridge(iface, master *net.Interface, op uintptr) error {
|
||||
if len(master.Name) >= ifNameSize {
|
||||
return fmt.Errorf("Interface name %s too long", master.Name)
|
||||
}
|
||||
|
||||
s, err := getIfSocket()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer syscall.Close(s)
|
||||
|
||||
ifr := ifreqIndex{}
|
||||
copy(ifr.IfrnName[:len(ifr.IfrnName)-1], master.Name)
|
||||
ifr.IfruIndex = int32(iface.Index)
|
||||
|
||||
if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s), op, uintptr(unsafe.Pointer(&ifr))); err != 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Add a slave to a bridge device. This is more backward-compatible than
|
||||
// netlink.NetworkSetMaster and works on RHEL 6.
|
||||
func ioctlAddToBridge(iface, master *net.Interface) error {
|
||||
return ifIoctBridge(iface, master, ioctlBrAddIf)
|
||||
}
|
||||
|
||||
func ioctlSetMacAddress(name, addr string) error {
|
||||
if len(name) >= ifNameSize {
|
||||
return fmt.Errorf("Interface name %s too long", name)
|
||||
}
|
||||
|
||||
hw, err := net.ParseMAC(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s, err := getIfSocket()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer syscall.Close(s)
|
||||
|
||||
ifr := ifreqHwaddr{}
|
||||
ifr.IfruHwaddr.Family = syscall.ARPHRD_ETHER
|
||||
copy(ifr.IfrnName[:len(ifr.IfrnName)-1], name)
|
||||
|
||||
for i := 0; i < 6; i++ {
|
||||
ifr.IfruHwaddr.Data[i] = ifrDataByte(hw[i])
|
||||
}
|
||||
|
||||
if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s), syscall.SIOCSIFHWADDR, uintptr(unsafe.Pointer(&ifr))); err != 0 {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ioctlCreateBridge(name, macAddr string) error {
|
||||
if len(name) >= ifNameSize {
|
||||
return fmt.Errorf("Interface name %s too long", name)
|
||||
}
|
||||
|
||||
s, err := getIfSocket()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer syscall.Close(s)
|
||||
|
||||
nameBytePtr, err := syscall.BytePtrFromString(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s), ioctlBrAdd, uintptr(unsafe.Pointer(nameBytePtr))); err != 0 {
|
||||
return err
|
||||
}
|
||||
return ioctlSetMacAddress(name, macAddr)
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
// +build !arm,!ppc64,!ppc64le,!riscv64
|
||||
|
||||
package bridge
|
||||
|
||||
func ifrDataByte(b byte) int8 {
|
||||
return int8(b)
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
// +build arm ppc64 ppc64le riscv64
|
||||
|
||||
package bridge
|
||||
|
||||
func ifrDataByte(b byte) uint8 {
|
||||
return uint8(b)
|
||||
}
|
18
vendor/github.com/docker/libnetwork/drivers/bridge/netlink_deprecated_unsupported.go
generated
vendored
18
vendor/github.com/docker/libnetwork/drivers/bridge/netlink_deprecated_unsupported.go
generated
vendored
|
@ -1,18 +0,0 @@
|
|||
// +build !linux
|
||||
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
)
|
||||
|
||||
// Add a slave to a bridge device. This is more backward-compatible than
|
||||
// netlink.NetworkSetMaster and works on RHEL 6.
|
||||
func ioctlAddToBridge(iface, master *net.Interface) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
func ioctlCreateBridge(name string, setMacAddr bool) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
244
vendor/github.com/docker/libnetwork/drivers/bridge/port_mapping.go
generated
vendored
244
vendor/github.com/docker/libnetwork/drivers/bridge/port_mapping.go
generated
vendored
|
@ -1,244 +0,0 @@
|
|||
package bridge
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/ishidawataru/sctp"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func (n *bridgeNetwork) allocatePorts(ep *bridgeEndpoint, reqDefBindIP net.IP, ulPxyEnabled bool) ([]types.PortBinding, error) {
|
||||
if ep.extConnConfig == nil || ep.extConnConfig.PortBindings == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
defHostIP := net.IPv4zero // 0.0.0.0
|
||||
if reqDefBindIP != nil {
|
||||
defHostIP = reqDefBindIP
|
||||
}
|
||||
|
||||
var containerIPv6 net.IP
|
||||
if ep.addrv6 != nil {
|
||||
containerIPv6 = ep.addrv6.IP
|
||||
}
|
||||
|
||||
pb, err := n.allocatePortsInternal(ep.extConnConfig.PortBindings, ep.addr.IP, containerIPv6, defHostIP, ulPxyEnabled)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pb, nil
|
||||
}
|
||||
|
||||
func (n *bridgeNetwork) allocatePortsInternal(bindings []types.PortBinding, containerIPv4, containerIPv6, defHostIP net.IP, ulPxyEnabled bool) ([]types.PortBinding, error) {
|
||||
bs := make([]types.PortBinding, 0, len(bindings))
|
||||
for _, c := range bindings {
|
||||
bIPv4 := c.GetCopy()
|
||||
bIPv6 := c.GetCopy()
|
||||
// Allocate IPv4 Port mappings
|
||||
if ok := n.validatePortBindingIPv4(&bIPv4, containerIPv4, defHostIP); ok {
|
||||
if err := n.allocatePort(&bIPv4, ulPxyEnabled); err != nil {
|
||||
// On allocation failure, release previously allocated ports. On cleanup error, just log a warning message
|
||||
if cuErr := n.releasePortsInternal(bs); cuErr != nil {
|
||||
logrus.Warnf("allocation failure for %v, failed to clear previously allocated ipv4 port bindings: %v", bIPv4, cuErr)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
bs = append(bs, bIPv4)
|
||||
}
|
||||
|
||||
// skip adding implicit v6 addr, when the kernel was booted with `ipv6.disable=1`
|
||||
// https://github.com/moby/moby/issues/42288
|
||||
isV6Binding := c.HostIP != nil && c.HostIP.To4() == nil
|
||||
if !isV6Binding && !IsV6Listenable() {
|
||||
continue
|
||||
}
|
||||
|
||||
// Allocate IPv6 Port mappings
|
||||
// If the container has no IPv6 address, allow proxying host IPv6 traffic to it
|
||||
// by setting up the binding with the IPv4 interface if the userland proxy is enabled
|
||||
// This change was added to keep backward compatibility
|
||||
containerIP := containerIPv6
|
||||
if ulPxyEnabled && (containerIPv6 == nil) {
|
||||
containerIP = containerIPv4
|
||||
}
|
||||
if ok := n.validatePortBindingIPv6(&bIPv6, containerIP, defHostIP); ok {
|
||||
if err := n.allocatePort(&bIPv6, ulPxyEnabled); err != nil {
|
||||
// On allocation failure, release previously allocated ports. On cleanup error, just log a warning message
|
||||
if cuErr := n.releasePortsInternal(bs); cuErr != nil {
|
||||
logrus.Warnf("allocation failure for %v, failed to clear previously allocated ipv6 port bindings: %v", bIPv6, cuErr)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
bs = append(bs, bIPv6)
|
||||
}
|
||||
}
|
||||
return bs, nil
|
||||
}
|
||||
|
||||
// validatePortBindingIPv4 validates the port binding, populates the missing Host IP field and returns true
|
||||
// if this is a valid IPv4 binding, else returns false
|
||||
func (n *bridgeNetwork) validatePortBindingIPv4(bnd *types.PortBinding, containerIPv4, defHostIP net.IP) bool {
|
||||
//Return early if there is a valid Host IP, but its not a IPv4 address
|
||||
if len(bnd.HostIP) > 0 && bnd.HostIP.To4() == nil {
|
||||
return false
|
||||
}
|
||||
// Adjust the host address in the operational binding
|
||||
if len(bnd.HostIP) == 0 {
|
||||
// Return early if the default binding address is an IPv6 address
|
||||
if defHostIP.To4() == nil {
|
||||
return false
|
||||
}
|
||||
bnd.HostIP = defHostIP
|
||||
}
|
||||
bnd.IP = containerIPv4
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
// validatePortBindingIPv6 validates the port binding, populates the missing Host IP field and returns true
|
||||
// if this is a valid IPv6 binding, else returns false
|
||||
func (n *bridgeNetwork) validatePortBindingIPv6(bnd *types.PortBinding, containerIP, defHostIP net.IP) bool {
|
||||
// Return early if there is no container endpoint
|
||||
if containerIP == nil {
|
||||
return false
|
||||
}
|
||||
// Return early if there is a valid Host IP, which is a IPv4 address
|
||||
if len(bnd.HostIP) > 0 && bnd.HostIP.To4() != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// Setup a binding to "::" if Host IP is empty and the default binding IP is 0.0.0.0
|
||||
if len(bnd.HostIP) == 0 {
|
||||
if defHostIP.Equal(net.IPv4zero) {
|
||||
bnd.HostIP = net.IPv6zero
|
||||
// If the default binding IP is an IPv6 address, use it
|
||||
} else if defHostIP.To4() == nil {
|
||||
bnd.HostIP = defHostIP
|
||||
// Return false if default binding ip is an IPv4 address
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
bnd.IP = containerIP
|
||||
return true
|
||||
}
|
||||
|
||||
func (n *bridgeNetwork) allocatePort(bnd *types.PortBinding, ulPxyEnabled bool) error {
|
||||
var (
|
||||
host net.Addr
|
||||
err error
|
||||
)
|
||||
|
||||
// Adjust HostPortEnd if this is not a range.
|
||||
if bnd.HostPortEnd == 0 {
|
||||
bnd.HostPortEnd = bnd.HostPort
|
||||
}
|
||||
|
||||
// Construct the container side transport address
|
||||
container, err := bnd.ContainerAddr()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
portmapper := n.portMapper
|
||||
|
||||
if bnd.HostIP.To4() == nil {
|
||||
portmapper = n.portMapperV6
|
||||
}
|
||||
|
||||
// Try up to maxAllocatePortAttempts times to get a port that's not already allocated.
|
||||
for i := 0; i < maxAllocatePortAttempts; i++ {
|
||||
if host, err = portmapper.MapRange(container, bnd.HostIP, int(bnd.HostPort), int(bnd.HostPortEnd), ulPxyEnabled); err == nil {
|
||||
break
|
||||
}
|
||||
// There is no point in immediately retrying to map an explicitly chosen port.
|
||||
if bnd.HostPort != 0 {
|
||||
logrus.Warnf("Failed to allocate and map port %d-%d: %s", bnd.HostPort, bnd.HostPortEnd, err)
|
||||
break
|
||||
}
|
||||
logrus.Warnf("Failed to allocate and map port: %s, retry: %d", err, i+1)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Save the host port (regardless it was or not specified in the binding)
|
||||
switch netAddr := host.(type) {
|
||||
case *net.TCPAddr:
|
||||
bnd.HostPort = uint16(host.(*net.TCPAddr).Port)
|
||||
return nil
|
||||
case *net.UDPAddr:
|
||||
bnd.HostPort = uint16(host.(*net.UDPAddr).Port)
|
||||
return nil
|
||||
case *sctp.SCTPAddr:
|
||||
bnd.HostPort = uint16(host.(*sctp.SCTPAddr).Port)
|
||||
return nil
|
||||
default:
|
||||
// For completeness
|
||||
return ErrUnsupportedAddressType(fmt.Sprintf("%T", netAddr))
|
||||
}
|
||||
}
|
||||
|
||||
func (n *bridgeNetwork) releasePorts(ep *bridgeEndpoint) error {
|
||||
return n.releasePortsInternal(ep.portMapping)
|
||||
}
|
||||
|
||||
func (n *bridgeNetwork) releasePortsInternal(bindings []types.PortBinding) error {
|
||||
var errorBuf bytes.Buffer
|
||||
|
||||
// Attempt to release all port bindings, do not stop on failure
|
||||
for _, m := range bindings {
|
||||
if err := n.releasePort(m); err != nil {
|
||||
errorBuf.WriteString(fmt.Sprintf("\ncould not release %v because of %v", m, err))
|
||||
}
|
||||
}
|
||||
|
||||
if errorBuf.Len() != 0 {
|
||||
return errors.New(errorBuf.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *bridgeNetwork) releasePort(bnd types.PortBinding) error {
|
||||
// Construct the host side transport address
|
||||
host, err := bnd.HostAddr()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
portmapper := n.portMapper
|
||||
|
||||
if bnd.HostIP.To4() == nil {
|
||||
portmapper = n.portMapperV6
|
||||
}
|
||||
|
||||
return portmapper.Unmap(host)
|
||||
}
|
||||
|
||||
var (
|
||||
v6ListenableCached bool
|
||||
v6ListenableOnce sync.Once
|
||||
)
|
||||
|
||||
// IsV6Listenable returns true when `[::1]:0` is listenable.
|
||||
// IsV6Listenable returns false mostly when the kernel was booted with `ipv6.disable=1` option.
|
||||
func IsV6Listenable() bool {
|
||||
v6ListenableOnce.Do(func() {
|
||||
ln, err := net.Listen("tcp6", "[::1]:0")
|
||||
if err != nil {
|
||||
// When the kernel was booted with `ipv6.disable=1`,
|
||||
// we get err "listen tcp6 [::1]:0: socket: address family not supported by protocol"
|
||||
// https://github.com/moby/moby/issues/42288
|
||||
logrus.Debugf("port_mapping: v6Listenable=false (%v)", err)
|
||||
} else {
|
||||
v6ListenableCached = true
|
||||
ln.Close()
|
||||
}
|
||||
})
|
||||
return v6ListenableCached
|
||||
}
|
26
vendor/github.com/docker/libnetwork/drivers/bridge/setup.go
generated
vendored
26
vendor/github.com/docker/libnetwork/drivers/bridge/setup.go
generated
vendored
|
@ -1,26 +0,0 @@
|
|||
package bridge
|
||||
|
||||
type setupStep func(*networkConfiguration, *bridgeInterface) error
|
||||
|
||||
type bridgeSetup struct {
|
||||
config *networkConfiguration
|
||||
bridge *bridgeInterface
|
||||
steps []setupStep
|
||||
}
|
||||
|
||||
func newBridgeSetup(c *networkConfiguration, i *bridgeInterface) *bridgeSetup {
|
||||
return &bridgeSetup{config: c, bridge: i}
|
||||
}
|
||||
|
||||
func (b *bridgeSetup) apply() error {
|
||||
for _, fn := range b.steps {
|
||||
if err := fn(b.config, b.bridge); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *bridgeSetup) queueStep(step setupStep) {
|
||||
b.steps = append(b.steps, step)
|
||||
}
|
163
vendor/github.com/docker/libnetwork/drivers/bridge/setup_bridgenetfiltering.go
generated
vendored
163
vendor/github.com/docker/libnetwork/drivers/bridge/setup_bridgenetfiltering.go
generated
vendored
|
@ -1,163 +0,0 @@
|
|||
package bridge
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"syscall"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Enumeration type saying which versions of IP protocol to process.
|
||||
type ipVersion int
|
||||
|
||||
const (
|
||||
ipvnone ipVersion = iota
|
||||
ipv4
|
||||
ipv6
|
||||
ipvboth
|
||||
)
|
||||
|
||||
//Gets the IP version in use ( [ipv4], [ipv6] or [ipv4 and ipv6] )
|
||||
func getIPVersion(config *networkConfiguration) ipVersion {
|
||||
ipVersion := ipv4
|
||||
if config.AddressIPv6 != nil || config.EnableIPv6 {
|
||||
ipVersion |= ipv6
|
||||
}
|
||||
return ipVersion
|
||||
}
|
||||
|
||||
func setupBridgeNetFiltering(config *networkConfiguration, i *bridgeInterface) error {
|
||||
err := checkBridgeNetFiltering(config, i)
|
||||
if err != nil {
|
||||
if ptherr, ok := err.(*os.PathError); ok {
|
||||
if errno, ok := ptherr.Err.(syscall.Errno); ok && errno == syscall.ENOENT {
|
||||
if isRunningInContainer() {
|
||||
logrus.Warnf("running inside docker container, ignoring missing kernel params: %v", err)
|
||||
err = nil
|
||||
} else {
|
||||
err = errors.New("please ensure that br_netfilter kernel module is loaded")
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot restrict inter-container communication: %v", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//Enable bridge net filtering if ip forwarding is enabled. See github issue #11404
|
||||
func checkBridgeNetFiltering(config *networkConfiguration, i *bridgeInterface) error {
|
||||
ipVer := getIPVersion(config)
|
||||
iface := config.BridgeName
|
||||
doEnable := func(ipVer ipVersion) error {
|
||||
var ipVerName string
|
||||
if ipVer == ipv4 {
|
||||
ipVerName = "IPv4"
|
||||
} else {
|
||||
ipVerName = "IPv6"
|
||||
}
|
||||
enabled, err := isPacketForwardingEnabled(ipVer, iface)
|
||||
if err != nil {
|
||||
logrus.Warnf("failed to check %s forwarding: %v", ipVerName, err)
|
||||
} else if enabled {
|
||||
enabled, err := getKernelBoolParam(getBridgeNFKernelParam(ipVer))
|
||||
if err != nil || enabled {
|
||||
return err
|
||||
}
|
||||
return setKernelBoolParam(getBridgeNFKernelParam(ipVer), true)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
switch ipVer {
|
||||
case ipv4, ipv6:
|
||||
return doEnable(ipVer)
|
||||
case ipvboth:
|
||||
v4err := doEnable(ipv4)
|
||||
v6err := doEnable(ipv6)
|
||||
if v4err == nil {
|
||||
return v6err
|
||||
}
|
||||
return v4err
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Get kernel param path saying whether IPv${ipVer} traffic is being forwarded
|
||||
// on particular interface. Interface may be specified for IPv6 only. If
|
||||
// `iface` is empty, `default` will be assumed, which represents default value
|
||||
// for new interfaces.
|
||||
func getForwardingKernelParam(ipVer ipVersion, iface string) string {
|
||||
switch ipVer {
|
||||
case ipv4:
|
||||
return "/proc/sys/net/ipv4/ip_forward"
|
||||
case ipv6:
|
||||
if iface == "" {
|
||||
iface = "default"
|
||||
}
|
||||
return fmt.Sprintf("/proc/sys/net/ipv6/conf/%s/forwarding", iface)
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// Get kernel param path saying whether bridged IPv${ipVer} traffic shall be
|
||||
// passed to ip${ipVer}tables' chains.
|
||||
func getBridgeNFKernelParam(ipVer ipVersion) string {
|
||||
switch ipVer {
|
||||
case ipv4:
|
||||
return "/proc/sys/net/bridge/bridge-nf-call-iptables"
|
||||
case ipv6:
|
||||
return "/proc/sys/net/bridge/bridge-nf-call-ip6tables"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
//Gets the value of the kernel parameters located at the given path
|
||||
func getKernelBoolParam(path string) (bool, error) {
|
||||
enabled := false
|
||||
line, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if len(line) > 0 {
|
||||
enabled = line[0] == '1'
|
||||
}
|
||||
return enabled, err
|
||||
}
|
||||
|
||||
//Sets the value of the kernel parameter located at the given path
|
||||
func setKernelBoolParam(path string, on bool) error {
|
||||
value := byte('0')
|
||||
if on {
|
||||
value = byte('1')
|
||||
}
|
||||
return ioutil.WriteFile(path, []byte{value, '\n'}, 0644)
|
||||
}
|
||||
|
||||
//Checks to see if packet forwarding is enabled
|
||||
func isPacketForwardingEnabled(ipVer ipVersion, iface string) (bool, error) {
|
||||
switch ipVer {
|
||||
case ipv4, ipv6:
|
||||
return getKernelBoolParam(getForwardingKernelParam(ipVer, iface))
|
||||
case ipvboth:
|
||||
enabled, err := getKernelBoolParam(getForwardingKernelParam(ipv4, ""))
|
||||
if err != nil || !enabled {
|
||||
return enabled, err
|
||||
}
|
||||
return getKernelBoolParam(getForwardingKernelParam(ipv6, iface))
|
||||
default:
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
func isRunningInContainer() bool {
|
||||
_, err := os.Stat("/.dockerenv")
|
||||
return !os.IsNotExist(err)
|
||||
}
|
73
vendor/github.com/docker/libnetwork/drivers/bridge/setup_device.go
generated
vendored
73
vendor/github.com/docker/libnetwork/drivers/bridge/setup_device.go
generated
vendored
|
@ -1,73 +0,0 @@
|
|||
package bridge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
// SetupDevice create a new bridge interface/
|
||||
func setupDevice(config *networkConfiguration, i *bridgeInterface) error {
|
||||
// We only attempt to create the bridge when the requested device name is
|
||||
// the default one.
|
||||
if config.BridgeName != DefaultBridgeName && config.DefaultBridge {
|
||||
return NonDefaultBridgeExistError(config.BridgeName)
|
||||
}
|
||||
|
||||
// Set the bridgeInterface netlink.Bridge.
|
||||
i.Link = &netlink.Bridge{
|
||||
LinkAttrs: netlink.LinkAttrs{
|
||||
Name: config.BridgeName,
|
||||
},
|
||||
}
|
||||
|
||||
// Set the bridge's MAC address. Requires kernel version 3.3 or up.
|
||||
hwAddr := netutils.GenerateRandomMAC()
|
||||
i.Link.Attrs().HardwareAddr = hwAddr
|
||||
logrus.Debugf("Setting bridge mac address to %s", hwAddr)
|
||||
|
||||
if err := i.nlh.LinkAdd(i.Link); err != nil {
|
||||
logrus.Debugf("Failed to create bridge %s via netlink. Trying ioctl", config.BridgeName)
|
||||
return ioctlCreateBridge(config.BridgeName, hwAddr.String())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setupDefaultSysctl(config *networkConfiguration, i *bridgeInterface) error {
|
||||
// Disable IPv6 router advertisements originating on the bridge
|
||||
sysPath := filepath.Join("/proc/sys/net/ipv6/conf/", config.BridgeName, "accept_ra")
|
||||
if _, err := os.Stat(sysPath); err != nil {
|
||||
logrus.
|
||||
WithField("bridge", config.BridgeName).
|
||||
WithField("syspath", sysPath).
|
||||
Info("failed to read ipv6 net.ipv6.conf.<bridge>.accept_ra")
|
||||
return nil
|
||||
}
|
||||
if err := ioutil.WriteFile(sysPath, []byte{'0', '\n'}, 0644); err != nil {
|
||||
logrus.WithError(err).Warn("unable to disable IPv6 router advertisement")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetupDeviceUp ups the given bridge interface.
|
||||
func setupDeviceUp(config *networkConfiguration, i *bridgeInterface) error {
|
||||
err := i.nlh.LinkSetUp(i.Link)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to set link up for %s: %v", config.BridgeName, err)
|
||||
}
|
||||
|
||||
// Attempt to update the bridge interface to refresh the flags status,
|
||||
// ignoring any failure to do so.
|
||||
if lnk, err := i.nlh.LinkByName(config.BridgeName); err == nil {
|
||||
i.Link = lnk
|
||||
} else {
|
||||
logrus.Warnf("Failed to retrieve link for interface (%s): %v", config.BridgeName, err)
|
||||
}
|
||||
return nil
|
||||
}
|
35
vendor/github.com/docker/libnetwork/drivers/bridge/setup_firewalld.go
generated
vendored
35
vendor/github.com/docker/libnetwork/drivers/bridge/setup_firewalld.go
generated
vendored
|
@ -1,35 +0,0 @@
|
|||
package bridge
|
||||
|
||||
import "github.com/docker/libnetwork/iptables"
|
||||
|
||||
func (n *bridgeNetwork) setupFirewalld(config *networkConfiguration, i *bridgeInterface) error {
|
||||
d := n.driver
|
||||
d.Lock()
|
||||
driverConfig := d.config
|
||||
d.Unlock()
|
||||
|
||||
// Sanity check.
|
||||
if !driverConfig.EnableIPTables {
|
||||
return IPTableCfgError(config.BridgeName)
|
||||
}
|
||||
|
||||
iptables.OnReloaded(func() { n.setupIP4Tables(config, i) })
|
||||
iptables.OnReloaded(n.portMapper.ReMapAll)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *bridgeNetwork) setupFirewalld6(config *networkConfiguration, i *bridgeInterface) error {
|
||||
d := n.driver
|
||||
d.Lock()
|
||||
driverConfig := d.config
|
||||
d.Unlock()
|
||||
|
||||
// Sanity check.
|
||||
if !driverConfig.EnableIP6Tables {
|
||||
return IPTableCfgError(config.BridgeName)
|
||||
}
|
||||
|
||||
iptables.OnReloaded(func() { n.setupIP6Tables(config, i) })
|
||||
iptables.OnReloaded(n.portMapperV6.ReMapAll)
|
||||
return nil
|
||||
}
|
71
vendor/github.com/docker/libnetwork/drivers/bridge/setup_ip_forwarding.go
generated
vendored
71
vendor/github.com/docker/libnetwork/drivers/bridge/setup_ip_forwarding.go
generated
vendored
|
@ -1,71 +0,0 @@
|
|||
package bridge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/docker/libnetwork/iptables"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
ipv4ForwardConf = "/proc/sys/net/ipv4/ip_forward"
|
||||
ipv4ForwardConfPerm = 0644
|
||||
)
|
||||
|
||||
func configureIPForwarding(enable bool) error {
|
||||
var val byte
|
||||
if enable {
|
||||
val = '1'
|
||||
}
|
||||
return ioutil.WriteFile(ipv4ForwardConf, []byte{val, '\n'}, ipv4ForwardConfPerm)
|
||||
}
|
||||
|
||||
func setupIPForwarding(enableIPTables bool, enableIP6Tables bool) error {
|
||||
// Get current IPv4 forward setup
|
||||
ipv4ForwardData, err := ioutil.ReadFile(ipv4ForwardConf)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Cannot read IP forwarding setup: %v", err)
|
||||
}
|
||||
|
||||
// Enable IPv4 forwarding only if it is not already enabled
|
||||
if ipv4ForwardData[0] != '1' {
|
||||
// Enable IPv4 forwarding
|
||||
if err := configureIPForwarding(true); err != nil {
|
||||
return fmt.Errorf("Enabling IP forwarding failed: %v", err)
|
||||
}
|
||||
// When enabling ip_forward set the default policy on forward chain to
|
||||
// drop only if the daemon option iptables is not set to false.
|
||||
if enableIPTables {
|
||||
iptable := iptables.GetIptable(iptables.IPv4)
|
||||
if err := iptable.SetDefaultPolicy(iptables.Filter, "FORWARD", iptables.Drop); err != nil {
|
||||
if err := configureIPForwarding(false); err != nil {
|
||||
logrus.Errorf("Disabling IP forwarding failed, %v", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
iptables.OnReloaded(func() {
|
||||
logrus.Debug("Setting the default DROP policy on firewall reload")
|
||||
if err := iptable.SetDefaultPolicy(iptables.Filter, "FORWARD", iptables.Drop); err != nil {
|
||||
logrus.Warnf("Setting the default DROP policy on firewall reload failed, %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// add only iptables rules - forwarding is handled by setupIPv6Forwarding in setup_ipv6
|
||||
if enableIP6Tables {
|
||||
iptable := iptables.GetIptable(iptables.IPv6)
|
||||
if err := iptable.SetDefaultPolicy(iptables.Filter, "FORWARD", iptables.Drop); err != nil {
|
||||
logrus.Warnf("Setting the default DROP policy on firewall reload failed, %v", err)
|
||||
}
|
||||
iptables.OnReloaded(func() {
|
||||
logrus.Debug("Setting the default DROP policy on firewall reload")
|
||||
if err := iptable.SetDefaultPolicy(iptables.Filter, "FORWARD", iptables.Drop); err != nil {
|
||||
logrus.Warnf("Setting the default DROP policy on firewall reload failed, %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
429
vendor/github.com/docker/libnetwork/drivers/bridge/setup_ip_tables.go
generated
vendored
429
vendor/github.com/docker/libnetwork/drivers/bridge/setup_ip_tables.go
generated
vendored
|
@ -1,429 +0,0 @@
|
|||
package bridge
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/docker/libnetwork/iptables"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
// DockerChain: DOCKER iptable chain name
|
||||
const (
|
||||
DockerChain = "DOCKER"
|
||||
// Isolation between bridge networks is achieved in two stages by means
|
||||
// of the following two chains in the filter table. The first chain matches
|
||||
// on the source interface being a bridge network's bridge and the
|
||||
// destination being a different interface. A positive match leads to the
|
||||
// second isolation chain. No match returns to the parent chain. The second
|
||||
// isolation chain matches on destination interface being a bridge network's
|
||||
// bridge. A positive match identifies a packet originated from one bridge
|
||||
// network's bridge destined to another bridge network's bridge and will
|
||||
// result in the packet being dropped. No match returns to the parent chain.
|
||||
IsolationChain1 = "DOCKER-ISOLATION-STAGE-1"
|
||||
IsolationChain2 = "DOCKER-ISOLATION-STAGE-2"
|
||||
)
|
||||
|
||||
func setupIPChains(config *configuration, version iptables.IPVersion) (*iptables.ChainInfo, *iptables.ChainInfo, *iptables.ChainInfo, *iptables.ChainInfo, error) {
|
||||
// Sanity check.
|
||||
if config.EnableIPTables == false {
|
||||
return nil, nil, nil, nil, errors.New("cannot create new chains, EnableIPTable is disabled")
|
||||
}
|
||||
|
||||
hairpinMode := !config.EnableUserlandProxy
|
||||
|
||||
iptable := iptables.GetIptable(version)
|
||||
|
||||
natChain, err := iptable.NewChain(DockerChain, iptables.Nat, hairpinMode)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, fmt.Errorf("failed to create NAT chain %s: %v", DockerChain, err)
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if err := iptable.RemoveExistingChain(DockerChain, iptables.Nat); err != nil {
|
||||
logrus.Warnf("failed on removing iptables NAT chain %s on cleanup: %v", DockerChain, err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
filterChain, err := iptable.NewChain(DockerChain, iptables.Filter, false)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, fmt.Errorf("failed to create FILTER chain %s: %v", DockerChain, err)
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if err := iptable.RemoveExistingChain(DockerChain, iptables.Filter); err != nil {
|
||||
logrus.Warnf("failed on removing iptables FILTER chain %s on cleanup: %v", DockerChain, err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
isolationChain1, err := iptable.NewChain(IsolationChain1, iptables.Filter, false)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, fmt.Errorf("failed to create FILTER isolation chain: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if err := iptable.RemoveExistingChain(IsolationChain1, iptables.Filter); err != nil {
|
||||
logrus.Warnf("failed on removing iptables FILTER chain %s on cleanup: %v", IsolationChain1, err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
isolationChain2, err := iptable.NewChain(IsolationChain2, iptables.Filter, false)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, fmt.Errorf("failed to create FILTER isolation chain: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if err := iptable.RemoveExistingChain(IsolationChain2, iptables.Filter); err != nil {
|
||||
logrus.Warnf("failed on removing iptables FILTER chain %s on cleanup: %v", IsolationChain2, err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
if err := iptable.AddReturnRule(IsolationChain1); err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
|
||||
if err := iptable.AddReturnRule(IsolationChain2); err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
|
||||
return natChain, filterChain, isolationChain1, isolationChain2, nil
|
||||
}
|
||||
|
||||
func (n *bridgeNetwork) setupIP4Tables(config *networkConfiguration, i *bridgeInterface) error {
|
||||
d := n.driver
|
||||
d.Lock()
|
||||
driverConfig := d.config
|
||||
d.Unlock()
|
||||
|
||||
// Sanity check.
|
||||
if !driverConfig.EnableIPTables {
|
||||
return errors.New("Cannot program chains, EnableIPTable is disabled")
|
||||
}
|
||||
|
||||
maskedAddrv4 := &net.IPNet{
|
||||
IP: i.bridgeIPv4.IP.Mask(i.bridgeIPv4.Mask),
|
||||
Mask: i.bridgeIPv4.Mask,
|
||||
}
|
||||
return n.setupIPTables(iptables.IPv4, maskedAddrv4, config, i)
|
||||
}
|
||||
|
||||
func (n *bridgeNetwork) setupIP6Tables(config *networkConfiguration, i *bridgeInterface) error {
|
||||
d := n.driver
|
||||
d.Lock()
|
||||
driverConfig := d.config
|
||||
d.Unlock()
|
||||
|
||||
// Sanity check.
|
||||
if !driverConfig.EnableIP6Tables {
|
||||
return errors.New("Cannot program chains, EnableIP6Tables is disabled")
|
||||
}
|
||||
|
||||
maskedAddrv6 := &net.IPNet{
|
||||
IP: i.bridgeIPv6.IP.Mask(i.bridgeIPv6.Mask),
|
||||
Mask: i.bridgeIPv6.Mask,
|
||||
}
|
||||
|
||||
return n.setupIPTables(iptables.IPv6, maskedAddrv6, config, i)
|
||||
}
|
||||
|
||||
func (n *bridgeNetwork) setupIPTables(ipVersion iptables.IPVersion, maskedAddr *net.IPNet, config *networkConfiguration, i *bridgeInterface) error {
|
||||
var err error
|
||||
|
||||
d := n.driver
|
||||
d.Lock()
|
||||
driverConfig := d.config
|
||||
d.Unlock()
|
||||
|
||||
// Pickup this configuration option from driver
|
||||
hairpinMode := !driverConfig.EnableUserlandProxy
|
||||
|
||||
iptable := iptables.GetIptable(ipVersion)
|
||||
|
||||
if config.Internal {
|
||||
if err = setupInternalNetworkRules(config.BridgeName, maskedAddr, config.EnableICC, true); err != nil {
|
||||
return fmt.Errorf("Failed to Setup IP tables: %s", err.Error())
|
||||
}
|
||||
n.registerIptCleanFunc(func() error {
|
||||
return setupInternalNetworkRules(config.BridgeName, maskedAddr, config.EnableICC, false)
|
||||
})
|
||||
} else {
|
||||
if err = setupIPTablesInternal(config.HostIP, config.BridgeName, maskedAddr, config.EnableICC, config.EnableIPMasquerade, hairpinMode, true); err != nil {
|
||||
return fmt.Errorf("Failed to Setup IP tables: %s", err.Error())
|
||||
}
|
||||
n.registerIptCleanFunc(func() error {
|
||||
return setupIPTablesInternal(config.HostIP, config.BridgeName, maskedAddr, config.EnableICC, config.EnableIPMasquerade, hairpinMode, false)
|
||||
})
|
||||
natChain, filterChain, _, _, err := n.getDriverChains(ipVersion)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to setup IP tables, cannot acquire chain info %s", err.Error())
|
||||
}
|
||||
|
||||
err = iptable.ProgramChain(natChain, config.BridgeName, hairpinMode, true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to program NAT chain: %s", err.Error())
|
||||
}
|
||||
|
||||
err = iptable.ProgramChain(filterChain, config.BridgeName, hairpinMode, true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to program FILTER chain: %s", err.Error())
|
||||
}
|
||||
|
||||
n.registerIptCleanFunc(func() error {
|
||||
return iptable.ProgramChain(filterChain, config.BridgeName, hairpinMode, false)
|
||||
})
|
||||
|
||||
if ipVersion == iptables.IPv4 {
|
||||
n.portMapper.SetIptablesChain(natChain, n.getNetworkBridgeName())
|
||||
} else {
|
||||
n.portMapperV6.SetIptablesChain(natChain, n.getNetworkBridgeName())
|
||||
}
|
||||
}
|
||||
|
||||
d.Lock()
|
||||
err = iptable.EnsureJumpRule("FORWARD", IsolationChain1)
|
||||
d.Unlock()
|
||||
return err
|
||||
}
|
||||
|
||||
type iptRule struct {
|
||||
table iptables.Table
|
||||
chain string
|
||||
preArgs []string
|
||||
args []string
|
||||
}
|
||||
|
||||
func setupIPTablesInternal(hostIP net.IP, bridgeIface string, addr *net.IPNet, icc, ipmasq, hairpin, enable bool) error {
|
||||
|
||||
var (
|
||||
address = addr.String()
|
||||
skipDNAT = iptRule{table: iptables.Nat, chain: DockerChain, preArgs: []string{"-t", "nat"}, args: []string{"-i", bridgeIface, "-j", "RETURN"}}
|
||||
outRule = iptRule{table: iptables.Filter, chain: "FORWARD", args: []string{"-i", bridgeIface, "!", "-o", bridgeIface, "-j", "ACCEPT"}}
|
||||
natArgs []string
|
||||
hpNatArgs []string
|
||||
)
|
||||
// if hostIP is set use this address as the src-ip during SNAT
|
||||
if hostIP != nil {
|
||||
hostAddr := hostIP.String()
|
||||
natArgs = []string{"-s", address, "!", "-o", bridgeIface, "-j", "SNAT", "--to-source", hostAddr}
|
||||
hpNatArgs = []string{"-m", "addrtype", "--src-type", "LOCAL", "-o", bridgeIface, "-j", "SNAT", "--to-source", hostAddr}
|
||||
// Else use MASQUERADE which picks the src-ip based on NH from the route table
|
||||
} else {
|
||||
natArgs = []string{"-s", address, "!", "-o", bridgeIface, "-j", "MASQUERADE"}
|
||||
hpNatArgs = []string{"-m", "addrtype", "--src-type", "LOCAL", "-o", bridgeIface, "-j", "MASQUERADE"}
|
||||
}
|
||||
|
||||
natRule := iptRule{table: iptables.Nat, chain: "POSTROUTING", preArgs: []string{"-t", "nat"}, args: natArgs}
|
||||
hpNatRule := iptRule{table: iptables.Nat, chain: "POSTROUTING", preArgs: []string{"-t", "nat"}, args: hpNatArgs}
|
||||
|
||||
ipVersion := iptables.IPv4
|
||||
|
||||
if addr.IP.To4() == nil {
|
||||
ipVersion = iptables.IPv6
|
||||
}
|
||||
|
||||
// Set NAT.
|
||||
if ipmasq {
|
||||
if err := programChainRule(ipVersion, natRule, "NAT", enable); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if ipmasq && !hairpin {
|
||||
if err := programChainRule(ipVersion, skipDNAT, "SKIP DNAT", enable); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// In hairpin mode, masquerade traffic from localhost
|
||||
if hairpin {
|
||||
if err := programChainRule(ipVersion, hpNatRule, "MASQ LOCAL HOST", enable); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Set Inter Container Communication.
|
||||
if err := setIcc(ipVersion, bridgeIface, icc, enable); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Set Accept on all non-intercontainer outgoing packets.
|
||||
return programChainRule(ipVersion, outRule, "ACCEPT NON_ICC OUTGOING", enable)
|
||||
}
|
||||
|
||||
func programChainRule(version iptables.IPVersion, rule iptRule, ruleDescr string, insert bool) error {
|
||||
|
||||
iptable := iptables.GetIptable(version)
|
||||
|
||||
var (
|
||||
prefix []string
|
||||
operation string
|
||||
condition bool
|
||||
doesExist = iptable.Exists(rule.table, rule.chain, rule.args...)
|
||||
)
|
||||
|
||||
if insert {
|
||||
condition = !doesExist
|
||||
prefix = []string{"-I", rule.chain}
|
||||
operation = "enable"
|
||||
} else {
|
||||
condition = doesExist
|
||||
prefix = []string{"-D", rule.chain}
|
||||
operation = "disable"
|
||||
}
|
||||
if rule.preArgs != nil {
|
||||
prefix = append(rule.preArgs, prefix...)
|
||||
}
|
||||
|
||||
if condition {
|
||||
if err := iptable.RawCombinedOutput(append(prefix, rule.args...)...); err != nil {
|
||||
return fmt.Errorf("Unable to %s %s rule: %s", operation, ruleDescr, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setIcc(version iptables.IPVersion, bridgeIface string, iccEnable, insert bool) error {
|
||||
iptable := iptables.GetIptable(version)
|
||||
var (
|
||||
table = iptables.Filter
|
||||
chain = "FORWARD"
|
||||
args = []string{"-i", bridgeIface, "-o", bridgeIface, "-j"}
|
||||
acceptArgs = append(args, "ACCEPT")
|
||||
dropArgs = append(args, "DROP")
|
||||
)
|
||||
|
||||
if insert {
|
||||
if !iccEnable {
|
||||
iptable.Raw(append([]string{"-D", chain}, acceptArgs...)...)
|
||||
|
||||
if !iptable.Exists(table, chain, dropArgs...) {
|
||||
if err := iptable.RawCombinedOutput(append([]string{"-A", chain}, dropArgs...)...); err != nil {
|
||||
return fmt.Errorf("Unable to prevent intercontainer communication: %s", err.Error())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
iptable.Raw(append([]string{"-D", chain}, dropArgs...)...)
|
||||
|
||||
if !iptable.Exists(table, chain, acceptArgs...) {
|
||||
if err := iptable.RawCombinedOutput(append([]string{"-I", chain}, acceptArgs...)...); err != nil {
|
||||
return fmt.Errorf("Unable to allow intercontainer communication: %s", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Remove any ICC rule.
|
||||
if !iccEnable {
|
||||
if iptable.Exists(table, chain, dropArgs...) {
|
||||
iptable.Raw(append([]string{"-D", chain}, dropArgs...)...)
|
||||
}
|
||||
} else {
|
||||
if iptable.Exists(table, chain, acceptArgs...) {
|
||||
iptable.Raw(append([]string{"-D", chain}, acceptArgs...)...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Control Inter Network Communication. Install[Remove] only if it is [not] present.
|
||||
func setINC(version iptables.IPVersion, iface string, enable bool) error {
|
||||
iptable := iptables.GetIptable(version)
|
||||
var (
|
||||
action = iptables.Insert
|
||||
actionMsg = "add"
|
||||
chains = []string{IsolationChain1, IsolationChain2}
|
||||
rules = [][]string{
|
||||
{"-i", iface, "!", "-o", iface, "-j", IsolationChain2},
|
||||
{"-o", iface, "-j", "DROP"},
|
||||
}
|
||||
)
|
||||
|
||||
if !enable {
|
||||
action = iptables.Delete
|
||||
actionMsg = "remove"
|
||||
}
|
||||
|
||||
for i, chain := range chains {
|
||||
if err := iptable.ProgramRule(iptables.Filter, chain, action, rules[i]); err != nil {
|
||||
msg := fmt.Sprintf("unable to %s inter-network communication rule: %v", actionMsg, err)
|
||||
if enable {
|
||||
if i == 1 {
|
||||
// Rollback the rule installed on first chain
|
||||
if err2 := iptable.ProgramRule(iptables.Filter, chains[0], iptables.Delete, rules[0]); err2 != nil {
|
||||
logrus.Warnf("Failed to rollback iptables rule after failure (%v): %v", err, err2)
|
||||
}
|
||||
}
|
||||
return fmt.Errorf(msg)
|
||||
}
|
||||
logrus.Warn(msg)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Obsolete chain from previous docker versions
|
||||
const oldIsolationChain = "DOCKER-ISOLATION"
|
||||
|
||||
func removeIPChains(version iptables.IPVersion) {
|
||||
ipt := iptables.IPTable{Version: version}
|
||||
|
||||
// Remove obsolete rules from default chains
|
||||
ipt.ProgramRule(iptables.Filter, "FORWARD", iptables.Delete, []string{"-j", oldIsolationChain})
|
||||
|
||||
// Remove chains
|
||||
for _, chainInfo := range []iptables.ChainInfo{
|
||||
{Name: DockerChain, Table: iptables.Nat, IPTable: ipt},
|
||||
{Name: DockerChain, Table: iptables.Filter, IPTable: ipt},
|
||||
{Name: IsolationChain1, Table: iptables.Filter, IPTable: ipt},
|
||||
{Name: IsolationChain2, Table: iptables.Filter, IPTable: ipt},
|
||||
{Name: oldIsolationChain, Table: iptables.Filter, IPTable: ipt},
|
||||
} {
|
||||
|
||||
if err := chainInfo.Remove(); err != nil {
|
||||
logrus.Warnf("Failed to remove existing iptables entries in table %s chain %s : %v", chainInfo.Table, chainInfo.Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setupInternalNetworkRules(bridgeIface string, addr *net.IPNet, icc, insert bool) error {
|
||||
var (
|
||||
inDropRule = iptRule{table: iptables.Filter, chain: IsolationChain1, args: []string{"-i", bridgeIface, "!", "-d", addr.String(), "-j", "DROP"}}
|
||||
outDropRule = iptRule{table: iptables.Filter, chain: IsolationChain1, args: []string{"-o", bridgeIface, "!", "-s", addr.String(), "-j", "DROP"}}
|
||||
)
|
||||
|
||||
version := iptables.IPv4
|
||||
|
||||
if addr.IP.To4() == nil {
|
||||
version = iptables.IPv6
|
||||
}
|
||||
|
||||
if err := programChainRule(version, inDropRule, "DROP INCOMING", insert); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := programChainRule(version, outDropRule, "DROP OUTGOING", insert); err != nil {
|
||||
return err
|
||||
}
|
||||
// Set Inter Container Communication.
|
||||
return setIcc(version, bridgeIface, icc, insert)
|
||||
}
|
||||
|
||||
func clearEndpointConnections(nlh *netlink.Handle, ep *bridgeEndpoint) {
|
||||
var ipv4List []net.IP
|
||||
var ipv6List []net.IP
|
||||
if ep.addr != nil {
|
||||
ipv4List = append(ipv4List, ep.addr.IP)
|
||||
}
|
||||
if ep.addrv6 != nil {
|
||||
ipv6List = append(ipv6List, ep.addrv6.IP)
|
||||
}
|
||||
iptables.DeleteConntrackEntries(nlh, ipv4List, ipv6List)
|
||||
}
|
82
vendor/github.com/docker/libnetwork/drivers/bridge/setup_ipv4.go
generated
vendored
82
vendor/github.com/docker/libnetwork/drivers/bridge/setup_ipv4.go
generated
vendored
|
@ -1,82 +0,0 @@
|
|||
package bridge
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
func selectIPv4Address(addresses []netlink.Addr, selector *net.IPNet) (netlink.Addr, error) {
|
||||
if len(addresses) == 0 {
|
||||
return netlink.Addr{}, errors.New("unable to select an address as the address pool is empty")
|
||||
}
|
||||
if selector != nil {
|
||||
for _, addr := range addresses {
|
||||
if selector.Contains(addr.IP) {
|
||||
return addr, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return addresses[0], nil
|
||||
}
|
||||
|
||||
func setupBridgeIPv4(config *networkConfiguration, i *bridgeInterface) error {
|
||||
if !config.InhibitIPv4 {
|
||||
addrv4List, _, err := i.addresses()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to retrieve bridge interface addresses: %v", err)
|
||||
}
|
||||
|
||||
addrv4, _ := selectIPv4Address(addrv4List, config.AddressIPv4)
|
||||
|
||||
if !types.CompareIPNet(addrv4.IPNet, config.AddressIPv4) {
|
||||
if addrv4.IPNet != nil {
|
||||
if err := i.nlh.AddrDel(i.Link, &addrv4); err != nil {
|
||||
return fmt.Errorf("failed to remove current ip address from bridge: %v", err)
|
||||
}
|
||||
}
|
||||
logrus.Debugf("Assigning address to bridge interface %s: %s", config.BridgeName, config.AddressIPv4)
|
||||
if err := i.nlh.AddrAdd(i.Link, &netlink.Addr{IPNet: config.AddressIPv4}); err != nil {
|
||||
return &IPv4AddrAddError{IP: config.AddressIPv4, Err: err}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store bridge network and default gateway
|
||||
i.bridgeIPv4 = config.AddressIPv4
|
||||
i.gatewayIPv4 = config.AddressIPv4.IP
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setupGatewayIPv4(config *networkConfiguration, i *bridgeInterface) error {
|
||||
if !i.bridgeIPv4.Contains(config.DefaultGatewayIPv4) {
|
||||
return &ErrInvalidGateway{}
|
||||
}
|
||||
|
||||
// Store requested default gateway
|
||||
i.gatewayIPv4 = config.DefaultGatewayIPv4
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setupLoopbackAddressesRouting(config *networkConfiguration, i *bridgeInterface) error {
|
||||
sysPath := filepath.Join("/proc/sys/net/ipv4/conf", config.BridgeName, "route_localnet")
|
||||
ipv4LoRoutingData, err := ioutil.ReadFile(sysPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Cannot read IPv4 local routing setup: %v", err)
|
||||
}
|
||||
// Enable loopback addresses routing only if it isn't already enabled
|
||||
if ipv4LoRoutingData[0] != '1' {
|
||||
if err := ioutil.WriteFile(sysPath, []byte{'1', '\n'}, 0644); err != nil {
|
||||
return fmt.Errorf("Unable to enable local routing for hairpin mode: %v", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
119
vendor/github.com/docker/libnetwork/drivers/bridge/setup_ipv6.go
generated
vendored
119
vendor/github.com/docker/libnetwork/drivers/bridge/setup_ipv6.go
generated
vendored
|
@ -1,119 +0,0 @@
|
|||
package bridge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
var bridgeIPv6 *net.IPNet
|
||||
|
||||
const (
|
||||
bridgeIPv6Str = "fe80::1/64"
|
||||
ipv6ForwardConfPerm = 0644
|
||||
ipv6ForwardConfDefault = "/proc/sys/net/ipv6/conf/default/forwarding"
|
||||
ipv6ForwardConfAll = "/proc/sys/net/ipv6/conf/all/forwarding"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// We allow ourselves to panic in this special case because we indicate a
|
||||
// failure to parse a compile-time define constant.
|
||||
var err error
|
||||
if bridgeIPv6, err = types.ParseCIDR(bridgeIPv6Str); err != nil {
|
||||
panic(fmt.Sprintf("Cannot parse default bridge IPv6 address %q: %v", bridgeIPv6Str, err))
|
||||
}
|
||||
}
|
||||
|
||||
func setupBridgeIPv6(config *networkConfiguration, i *bridgeInterface) error {
|
||||
procFile := "/proc/sys/net/ipv6/conf/" + config.BridgeName + "/disable_ipv6"
|
||||
ipv6BridgeData, err := ioutil.ReadFile(procFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Cannot read IPv6 setup for bridge %v: %v", config.BridgeName, err)
|
||||
}
|
||||
// Enable IPv6 on the bridge only if it isn't already enabled
|
||||
if ipv6BridgeData[0] != '0' {
|
||||
if err := ioutil.WriteFile(procFile, []byte{'0', '\n'}, ipv6ForwardConfPerm); err != nil {
|
||||
return fmt.Errorf("Unable to enable IPv6 addresses on bridge: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Store bridge network and default gateway
|
||||
i.bridgeIPv6 = bridgeIPv6
|
||||
i.gatewayIPv6 = i.bridgeIPv6.IP
|
||||
|
||||
if err := i.programIPv6Address(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if config.AddressIPv6 == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Store the user specified bridge network and network gateway and program it
|
||||
i.bridgeIPv6 = config.AddressIPv6
|
||||
i.gatewayIPv6 = config.AddressIPv6.IP
|
||||
|
||||
if err := i.programIPv6Address(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Setting route to global IPv6 subnet
|
||||
logrus.Debugf("Adding route to IPv6 network %s via device %s", config.AddressIPv6.String(), config.BridgeName)
|
||||
err = i.nlh.RouteAdd(&netlink.Route{
|
||||
Scope: netlink.SCOPE_UNIVERSE,
|
||||
LinkIndex: i.Link.Attrs().Index,
|
||||
Dst: config.AddressIPv6,
|
||||
})
|
||||
if err != nil && !os.IsExist(err) {
|
||||
logrus.Errorf("Could not add route to IPv6 network %s via device %s: %s", config.AddressIPv6.String(), config.BridgeName, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setupGatewayIPv6(config *networkConfiguration, i *bridgeInterface) error {
|
||||
if config.AddressIPv6 == nil {
|
||||
return &ErrInvalidContainerSubnet{}
|
||||
}
|
||||
if !config.AddressIPv6.Contains(config.DefaultGatewayIPv6) {
|
||||
return &ErrInvalidGateway{}
|
||||
}
|
||||
|
||||
// Store requested default gateway
|
||||
i.gatewayIPv6 = config.DefaultGatewayIPv6
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setupIPv6Forwarding(config *networkConfiguration, i *bridgeInterface) error {
|
||||
// Get current IPv6 default forwarding setup
|
||||
ipv6ForwardDataDefault, err := ioutil.ReadFile(ipv6ForwardConfDefault)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Cannot read IPv6 default forwarding setup: %v", err)
|
||||
}
|
||||
// Enable IPv6 default forwarding only if it is not already enabled
|
||||
if ipv6ForwardDataDefault[0] != '1' {
|
||||
if err := ioutil.WriteFile(ipv6ForwardConfDefault, []byte{'1', '\n'}, ipv6ForwardConfPerm); err != nil {
|
||||
logrus.Warnf("Unable to enable IPv6 default forwarding: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Get current IPv6 all forwarding setup
|
||||
ipv6ForwardDataAll, err := ioutil.ReadFile(ipv6ForwardConfAll)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Cannot read IPv6 all forwarding setup: %v", err)
|
||||
}
|
||||
// Enable IPv6 all forwarding only if it is not already enabled
|
||||
if ipv6ForwardDataAll[0] != '1' {
|
||||
if err := ioutil.WriteFile(ipv6ForwardConfAll, []byte{'1', '\n'}, ipv6ForwardConfPerm); err != nil {
|
||||
logrus.Warnf("Unable to enable IPv6 all forwarding: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
73
vendor/github.com/docker/libnetwork/drivers/bridge/setup_verify.go
generated
vendored
73
vendor/github.com/docker/libnetwork/drivers/bridge/setup_verify.go
generated
vendored
|
@ -1,73 +0,0 @@
|
|||
package bridge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/libnetwork/ns"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
func setupVerifyAndReconcile(config *networkConfiguration, i *bridgeInterface) error {
|
||||
// Fetch a slice of IPv4 addresses and a slice of IPv6 addresses from the bridge.
|
||||
addrsv4, addrsv6, err := i.addresses()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to verify ip addresses: %v", err)
|
||||
}
|
||||
|
||||
addrv4, _ := selectIPv4Address(addrsv4, config.AddressIPv4)
|
||||
|
||||
// Verify that the bridge does have an IPv4 address.
|
||||
if addrv4.IPNet == nil {
|
||||
return &ErrNoIPAddr{}
|
||||
}
|
||||
|
||||
// Verify that the bridge IPv4 address matches the requested configuration.
|
||||
if config.AddressIPv4 != nil && !addrv4.IP.Equal(config.AddressIPv4.IP) {
|
||||
return &IPv4AddrNoMatchError{IP: addrv4.IP, CfgIP: config.AddressIPv4.IP}
|
||||
}
|
||||
|
||||
// Verify that one of the bridge IPv6 addresses matches the requested
|
||||
// configuration.
|
||||
if config.EnableIPv6 && !findIPv6Address(netlink.Addr{IPNet: bridgeIPv6}, addrsv6) {
|
||||
return (*IPv6AddrNoMatchError)(bridgeIPv6)
|
||||
}
|
||||
|
||||
// Release any residual IPv6 address that might be there because of older daemon instances
|
||||
for _, addrv6 := range addrsv6 {
|
||||
if addrv6.IP.IsGlobalUnicast() && !types.CompareIPNet(addrv6.IPNet, i.bridgeIPv6) {
|
||||
if err := i.nlh.AddrDel(i.Link, &addrv6); err != nil {
|
||||
logrus.Warnf("Failed to remove residual IPv6 address %s from bridge: %v", addrv6.IPNet, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func findIPv6Address(addr netlink.Addr, addresses []netlink.Addr) bool {
|
||||
for _, addrv6 := range addresses {
|
||||
if addrv6.String() == addr.String() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func bridgeInterfaceExists(name string) (bool, error) {
|
||||
nlh := ns.NlHandle()
|
||||
link, err := nlh.LinkByName(name)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "Link not found") {
|
||||
return false, nil
|
||||
}
|
||||
return false, fmt.Errorf("failed to check bridge interface existence: %v", err)
|
||||
}
|
||||
|
||||
if link.Type() == "bridge" {
|
||||
return true, nil
|
||||
}
|
||||
return false, fmt.Errorf("existing interface %s is not a bridge", name)
|
||||
}
|
106
vendor/github.com/docker/libnetwork/drivers/host/host.go
generated
vendored
106
vendor/github.com/docker/libnetwork/drivers/host/host.go
generated
vendored
|
@ -1,106 +0,0 @@
|
|||
package host
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/docker/libnetwork/datastore"
|
||||
"github.com/docker/libnetwork/discoverapi"
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
const networkType = "host"
|
||||
|
||||
type driver struct {
|
||||
network string
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// Init registers a new instance of host driver
|
||||
func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
||||
c := driverapi.Capability{
|
||||
DataScope: datastore.LocalScope,
|
||||
ConnectivityScope: datastore.LocalScope,
|
||||
}
|
||||
return dc.RegisterDriver(networkType, &driver{}, c)
|
||||
}
|
||||
|
||||
func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {
|
||||
return nil, types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) NetworkFree(id string) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
|
||||
}
|
||||
|
||||
func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
if d.network != "" {
|
||||
return types.ForbiddenErrorf("only one instance of \"%s\" network is allowed", networkType)
|
||||
}
|
||||
|
||||
d.network = id
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) DeleteNetwork(nid string) error {
|
||||
return types.ForbiddenErrorf("network of type \"%s\" cannot be deleted", networkType)
|
||||
}
|
||||
|
||||
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) DeleteEndpoint(nid, eid string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) {
|
||||
return make(map[string]interface{}, 0), nil
|
||||
}
|
||||
|
||||
// Join method is invoked when a Sandbox is attached to an endpoint.
|
||||
func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Leave method is invoked when a Sandbox detaches from an endpoint.
|
||||
func (d *driver) Leave(nid, eid string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) Type() string {
|
||||
return networkType
|
||||
}
|
||||
|
||||
func (d *driver) IsBuiltIn() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster
|
||||
func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster
|
||||
func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||
return nil
|
||||
}
|
115
vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan.go
generated
vendored
115
vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan.go
generated
vendored
|
@ -1,115 +0,0 @@
|
|||
package ipvlan
|
||||
|
||||
import (
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"github.com/docker/libnetwork/datastore"
|
||||
"github.com/docker/libnetwork/discoverapi"
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/osl"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
const (
|
||||
vethLen = 7
|
||||
containerVethPrefix = "eth"
|
||||
vethPrefix = "veth"
|
||||
ipvlanType = "ipvlan" // driver type name
|
||||
modeL2 = "l2" // ipvlan mode l2 is the default
|
||||
modeL3 = "l3" // ipvlan L3 mode
|
||||
parentOpt = "parent" // parent interface -o parent
|
||||
modeOpt = "_mode" // ipvlan mode ux opt suffix
|
||||
)
|
||||
|
||||
var driverModeOpt = ipvlanType + modeOpt // mode -o ipvlan_mode
|
||||
|
||||
type endpointTable map[string]*endpoint
|
||||
|
||||
type networkTable map[string]*network
|
||||
|
||||
type driver struct {
|
||||
networks networkTable
|
||||
sync.Once
|
||||
sync.Mutex
|
||||
store datastore.DataStore
|
||||
}
|
||||
|
||||
type endpoint struct {
|
||||
id string
|
||||
nid string
|
||||
mac net.HardwareAddr
|
||||
addr *net.IPNet
|
||||
addrv6 *net.IPNet
|
||||
srcName string
|
||||
dbIndex uint64
|
||||
dbExists bool
|
||||
}
|
||||
|
||||
type network struct {
|
||||
id string
|
||||
sbox osl.Sandbox
|
||||
endpoints endpointTable
|
||||
driver *driver
|
||||
config *configuration
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// Init initializes and registers the libnetwork ipvlan driver
|
||||
func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
||||
c := driverapi.Capability{
|
||||
DataScope: datastore.LocalScope,
|
||||
ConnectivityScope: datastore.GlobalScope,
|
||||
}
|
||||
d := &driver{
|
||||
networks: networkTable{},
|
||||
}
|
||||
d.initStore(config)
|
||||
|
||||
return dc.RegisterDriver(ipvlanType, d, c)
|
||||
}
|
||||
|
||||
func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {
|
||||
return nil, types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) NetworkFree(id string) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) {
|
||||
return make(map[string]interface{}, 0), nil
|
||||
}
|
||||
|
||||
func (d *driver) Type() string {
|
||||
return ipvlanType
|
||||
}
|
||||
|
||||
func (d *driver) IsBuiltIn() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DiscoverNew is a notification for a new discovery event.
|
||||
func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DiscoverDelete is a notification for a discovery delete event.
|
||||
func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
|
||||
}
|
||||
|
||||
func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
|
||||
return "", nil
|
||||
}
|
89
vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_endpoint.go
generated
vendored
89
vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_endpoint.go
generated
vendored
|
@ -1,89 +0,0 @@
|
|||
package ipvlan
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/ns"
|
||||
"github.com/docker/libnetwork/osl"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// CreateEndpoint assigns the mac, ip and endpoint id for the new container
|
||||
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
|
||||
epOptions map[string]interface{}) error {
|
||||
defer osl.InitOSContext()()
|
||||
|
||||
if err := validateID(nid, eid); err != nil {
|
||||
return err
|
||||
}
|
||||
n, err := d.getNetwork(nid)
|
||||
if err != nil {
|
||||
return fmt.Errorf("network id %q not found", nid)
|
||||
}
|
||||
if ifInfo.MacAddress() != nil {
|
||||
return fmt.Errorf("%s interfaces do not support custom mac address assignment", ipvlanType)
|
||||
}
|
||||
ep := &endpoint{
|
||||
id: eid,
|
||||
nid: nid,
|
||||
addr: ifInfo.Address(),
|
||||
addrv6: ifInfo.AddressIPv6(),
|
||||
}
|
||||
if ep.addr == nil {
|
||||
return fmt.Errorf("create endpoint was not passed an IP address")
|
||||
}
|
||||
// disallow port mapping -p
|
||||
if opt, ok := epOptions[netlabel.PortMap]; ok {
|
||||
if _, ok := opt.([]types.PortBinding); ok {
|
||||
if len(opt.([]types.PortBinding)) > 0 {
|
||||
logrus.Warnf("%s driver does not support port mappings", ipvlanType)
|
||||
}
|
||||
}
|
||||
}
|
||||
// disallow port exposure --expose
|
||||
if opt, ok := epOptions[netlabel.ExposedPorts]; ok {
|
||||
if _, ok := opt.([]types.TransportPort); ok {
|
||||
if len(opt.([]types.TransportPort)) > 0 {
|
||||
logrus.Warnf("%s driver does not support port exposures", ipvlanType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := d.storeUpdate(ep); err != nil {
|
||||
return fmt.Errorf("failed to save ipvlan endpoint %.7s to store: %v", ep.id, err)
|
||||
}
|
||||
|
||||
n.addEndpoint(ep)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteEndpoint remove the endpoint and associated netlink interface
|
||||
func (d *driver) DeleteEndpoint(nid, eid string) error {
|
||||
defer osl.InitOSContext()()
|
||||
if err := validateID(nid, eid); err != nil {
|
||||
return err
|
||||
}
|
||||
n := d.network(nid)
|
||||
if n == nil {
|
||||
return fmt.Errorf("network id %q not found", nid)
|
||||
}
|
||||
ep := n.endpoint(eid)
|
||||
if ep == nil {
|
||||
return fmt.Errorf("endpoint id %q not found", eid)
|
||||
}
|
||||
if link, err := ns.NlHandle().LinkByName(ep.srcName); err == nil {
|
||||
if err := ns.NlHandle().LinkDel(link); err != nil {
|
||||
logrus.WithError(err).Warnf("Failed to delete interface (%s)'s link on endpoint (%s) delete", ep.srcName, ep.id)
|
||||
}
|
||||
}
|
||||
|
||||
if err := d.storeDelete(ep); err != nil {
|
||||
logrus.Warnf("Failed to remove ipvlan endpoint %.7s from store: %v", ep.id, err)
|
||||
}
|
||||
n.deleteEndpoint(ep.id)
|
||||
return nil
|
||||
}
|
210
vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_joinleave.go
generated
vendored
210
vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_joinleave.go
generated
vendored
|
@ -1,210 +0,0 @@
|
|||
package ipvlan
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/ns"
|
||||
"github.com/docker/libnetwork/osl"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type staticRoute struct {
|
||||
Destination *net.IPNet
|
||||
RouteType int
|
||||
NextHop net.IP
|
||||
}
|
||||
|
||||
const (
|
||||
defaultV4RouteCidr = "0.0.0.0/0"
|
||||
defaultV6RouteCidr = "::/0"
|
||||
)
|
||||
|
||||
// Join method is invoked when a Sandbox is attached to an endpoint.
|
||||
func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
||||
defer osl.InitOSContext()()
|
||||
n, err := d.getNetwork(nid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
endpoint := n.endpoint(eid)
|
||||
if endpoint == nil {
|
||||
return fmt.Errorf("could not find endpoint with id %s", eid)
|
||||
}
|
||||
// generate a name for the iface that will be renamed to eth0 in the sbox
|
||||
containerIfName, err := netutils.GenerateIfaceName(ns.NlHandle(), vethPrefix, vethLen)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error generating an interface name: %v", err)
|
||||
}
|
||||
// create the netlink ipvlan interface
|
||||
vethName, err := createIPVlan(containerIfName, n.config.Parent, n.config.IpvlanMode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// bind the generated iface name to the endpoint
|
||||
endpoint.srcName = vethName
|
||||
ep := n.endpoint(eid)
|
||||
if ep == nil {
|
||||
return fmt.Errorf("could not find endpoint with id %s", eid)
|
||||
}
|
||||
if !n.config.Internal {
|
||||
if n.config.IpvlanMode == modeL3 {
|
||||
// disable gateway services to add a default gw using dev eth0 only
|
||||
jinfo.DisableGatewayService()
|
||||
defaultRoute, err := ifaceGateway(defaultV4RouteCidr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := jinfo.AddStaticRoute(defaultRoute.Destination, defaultRoute.RouteType, defaultRoute.NextHop); err != nil {
|
||||
return fmt.Errorf("failed to set an ipvlan l3 mode ipv4 default gateway: %v", err)
|
||||
}
|
||||
logrus.Debugf("Ipvlan Endpoint Joined with IPv4_Addr: %s, Ipvlan_Mode: %s, Parent: %s",
|
||||
ep.addr.IP.String(), n.config.IpvlanMode, n.config.Parent)
|
||||
// If the endpoint has a v6 address, set a v6 default route
|
||||
if ep.addrv6 != nil {
|
||||
default6Route, err := ifaceGateway(defaultV6RouteCidr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = jinfo.AddStaticRoute(default6Route.Destination, default6Route.RouteType, default6Route.NextHop); err != nil {
|
||||
return fmt.Errorf("failed to set an ipvlan l3 mode ipv6 default gateway: %v", err)
|
||||
}
|
||||
logrus.Debugf("Ipvlan Endpoint Joined with IPv6_Addr: %s, Ipvlan_Mode: %s, Parent: %s",
|
||||
ep.addrv6.IP.String(), n.config.IpvlanMode, n.config.Parent)
|
||||
}
|
||||
}
|
||||
if n.config.IpvlanMode == modeL2 {
|
||||
// parse and correlate the endpoint v4 address with the available v4 subnets
|
||||
if len(n.config.Ipv4Subnets) > 0 {
|
||||
s := n.getSubnetforIPv4(ep.addr)
|
||||
if s == nil {
|
||||
return fmt.Errorf("could not find a valid ipv4 subnet for endpoint %s", eid)
|
||||
}
|
||||
v4gw, _, err := net.ParseCIDR(s.GwIP)
|
||||
if err != nil {
|
||||
return fmt.Errorf("gateway %s is not a valid ipv4 address: %v", s.GwIP, err)
|
||||
}
|
||||
err = jinfo.SetGateway(v4gw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.Debugf("Ipvlan Endpoint Joined with IPv4_Addr: %s, Gateway: %s, Ipvlan_Mode: %s, Parent: %s",
|
||||
ep.addr.IP.String(), v4gw.String(), n.config.IpvlanMode, n.config.Parent)
|
||||
}
|
||||
// parse and correlate the endpoint v6 address with the available v6 subnets
|
||||
if len(n.config.Ipv6Subnets) > 0 {
|
||||
s := n.getSubnetforIPv6(ep.addrv6)
|
||||
if s == nil {
|
||||
return fmt.Errorf("could not find a valid ipv6 subnet for endpoint %s", eid)
|
||||
}
|
||||
v6gw, _, err := net.ParseCIDR(s.GwIP)
|
||||
if err != nil {
|
||||
return fmt.Errorf("gateway %s is not a valid ipv6 address: %v", s.GwIP, err)
|
||||
}
|
||||
err = jinfo.SetGatewayIPv6(v6gw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.Debugf("Ipvlan Endpoint Joined with IPv6_Addr: %s, Gateway: %s, Ipvlan_Mode: %s, Parent: %s",
|
||||
ep.addrv6.IP.String(), v6gw.String(), n.config.IpvlanMode, n.config.Parent)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if len(n.config.Ipv4Subnets) > 0 {
|
||||
logrus.Debugf("Ipvlan Endpoint Joined with IPv4_Addr: %s, IpVlan_Mode: %s, Parent: %s",
|
||||
ep.addr.IP.String(), n.config.IpvlanMode, n.config.Parent)
|
||||
}
|
||||
if len(n.config.Ipv6Subnets) > 0 {
|
||||
logrus.Debugf("Ipvlan Endpoint Joined with IPv6_Addr: %s IpVlan_Mode: %s, Parent: %s",
|
||||
ep.addrv6.IP.String(), n.config.IpvlanMode, n.config.Parent)
|
||||
}
|
||||
}
|
||||
iNames := jinfo.InterfaceName()
|
||||
err = iNames.SetNames(vethName, containerVethPrefix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = d.storeUpdate(ep); err != nil {
|
||||
return fmt.Errorf("failed to save ipvlan endpoint %.7s to store: %v", ep.id, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Leave method is invoked when a Sandbox detaches from an endpoint.
|
||||
func (d *driver) Leave(nid, eid string) error {
|
||||
defer osl.InitOSContext()()
|
||||
network, err := d.getNetwork(nid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
endpoint, err := network.getEndpoint(eid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if endpoint == nil {
|
||||
return fmt.Errorf("could not find endpoint with id %s", eid)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ifaceGateway returns a static route for either v4/v6 to be set to the container eth0
|
||||
func ifaceGateway(dfNet string) (*staticRoute, error) {
|
||||
nh, dst, err := net.ParseCIDR(dfNet)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to parse default route %v", err)
|
||||
}
|
||||
defaultRoute := &staticRoute{
|
||||
Destination: dst,
|
||||
RouteType: types.CONNECTED,
|
||||
NextHop: nh,
|
||||
}
|
||||
|
||||
return defaultRoute, nil
|
||||
}
|
||||
|
||||
// getSubnetforIPv4 returns the ipv4 subnet to which the given IP belongs
|
||||
func (n *network) getSubnetforIPv4(ip *net.IPNet) *ipv4Subnet {
|
||||
for _, s := range n.config.Ipv4Subnets {
|
||||
_, snet, err := net.ParseCIDR(s.SubnetIP)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
// first check if the mask lengths are the same
|
||||
i, _ := snet.Mask.Size()
|
||||
j, _ := ip.Mask.Size()
|
||||
if i != j {
|
||||
continue
|
||||
}
|
||||
if snet.Contains(ip.IP) {
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getSubnetforIPv6 returns the ipv6 subnet to which the given IP belongs
|
||||
func (n *network) getSubnetforIPv6(ip *net.IPNet) *ipv6Subnet {
|
||||
for _, s := range n.config.Ipv6Subnets {
|
||||
_, snet, err := net.ParseCIDR(s.SubnetIP)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
// first check if the mask lengths are the same
|
||||
i, _ := snet.Mask.Size()
|
||||
j, _ := ip.Mask.Size()
|
||||
if i != j {
|
||||
continue
|
||||
}
|
||||
if snet.Contains(ip.IP) {
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
260
vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_network.go
generated
vendored
260
vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_network.go
generated
vendored
|
@ -1,260 +0,0 @@
|
|||
package ipvlan
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/docker/pkg/parsers/kernel"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/ns"
|
||||
"github.com/docker/libnetwork/options"
|
||||
"github.com/docker/libnetwork/osl"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// CreateNetwork the network for the specified driver type
|
||||
func (d *driver) CreateNetwork(nid string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
|
||||
defer osl.InitOSContext()()
|
||||
kv, err := kernel.GetKernelVersion()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to check kernel version for %s driver support: %v", ipvlanType, err)
|
||||
}
|
||||
// ensure Kernel version is >= v4.2 for ipvlan support
|
||||
if kv.Kernel < ipvlanKernelVer || (kv.Kernel == ipvlanKernelVer && kv.Major < ipvlanMajorVer) {
|
||||
return fmt.Errorf("kernel version failed to meet the minimum ipvlan kernel requirement of %d.%d, found %d.%d.%d",
|
||||
ipvlanKernelVer, ipvlanMajorVer, kv.Kernel, kv.Major, kv.Minor)
|
||||
}
|
||||
// reject a null v4 network
|
||||
if len(ipV4Data) == 0 || ipV4Data[0].Pool.String() == "0.0.0.0/0" {
|
||||
return fmt.Errorf("ipv4 pool is empty")
|
||||
}
|
||||
// parse and validate the config and bind to networkConfiguration
|
||||
config, err := parseNetworkOptions(nid, option)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
config.ID = nid
|
||||
err = config.processIPAM(nid, ipV4Data, ipV6Data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// verify the ipvlan mode from -o ipvlan_mode option
|
||||
switch config.IpvlanMode {
|
||||
case "", modeL2:
|
||||
// default to ipvlan L2 mode if -o ipvlan_mode is empty
|
||||
config.IpvlanMode = modeL2
|
||||
case modeL3:
|
||||
config.IpvlanMode = modeL3
|
||||
default:
|
||||
return fmt.Errorf("requested ipvlan mode '%s' is not valid, 'l2' mode is the ipvlan driver default", config.IpvlanMode)
|
||||
}
|
||||
// loopback is not a valid parent link
|
||||
if config.Parent == "lo" {
|
||||
return fmt.Errorf("loopback interface is not a valid %s parent link", ipvlanType)
|
||||
}
|
||||
// if parent interface not specified, create a dummy type link to use named dummy+net_id
|
||||
if config.Parent == "" {
|
||||
config.Parent = getDummyName(stringid.TruncateID(config.ID))
|
||||
}
|
||||
foundExisting, err := d.createNetwork(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if foundExisting {
|
||||
return types.InternalMaskableErrorf("restoring existing network %s", config.ID)
|
||||
}
|
||||
// update persistent db, rollback on fail
|
||||
err = d.storeUpdate(config)
|
||||
if err != nil {
|
||||
d.deleteNetwork(config.ID)
|
||||
logrus.Debugf("encountered an error rolling back a network create for %s : %v", config.ID, err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// createNetwork is used by new network callbacks and persistent network cache
|
||||
func (d *driver) createNetwork(config *configuration) (bool, error) {
|
||||
foundExisting := false
|
||||
networkList := d.getNetworks()
|
||||
for _, nw := range networkList {
|
||||
if config.Parent == nw.config.Parent {
|
||||
if config.ID != nw.config.ID {
|
||||
return false, fmt.Errorf("network %s is already using parent interface %s",
|
||||
getDummyName(stringid.TruncateID(nw.config.ID)), config.Parent)
|
||||
}
|
||||
logrus.Debugf("Create Network for the same ID %s\n", config.ID)
|
||||
foundExisting = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !parentExists(config.Parent) {
|
||||
// Create a dummy link if a dummy name is set for parent
|
||||
if dummyName := getDummyName(stringid.TruncateID(config.ID)); dummyName == config.Parent {
|
||||
err := createDummyLink(config.Parent, dummyName)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
config.CreatedSlaveLink = true
|
||||
|
||||
// notify the user in logs they have limited communications
|
||||
logrus.Debugf("Empty -o parent= flags limit communications to other containers inside of network: %s",
|
||||
config.Parent)
|
||||
} else {
|
||||
// if the subinterface parent_iface.vlan_id checks do not pass, return err.
|
||||
// a valid example is 'eth0.10' for a parent iface 'eth0' with a vlan id '10'
|
||||
err := createVlanLink(config.Parent)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
// if driver created the networks slave link, record it for future deletion
|
||||
config.CreatedSlaveLink = true
|
||||
}
|
||||
}
|
||||
if !foundExisting {
|
||||
n := &network{
|
||||
id: config.ID,
|
||||
driver: d,
|
||||
endpoints: endpointTable{},
|
||||
config: config,
|
||||
}
|
||||
// add the network
|
||||
d.addNetwork(n)
|
||||
}
|
||||
|
||||
return foundExisting, nil
|
||||
}
|
||||
|
||||
// DeleteNetwork the network for the specified driver type
|
||||
func (d *driver) DeleteNetwork(nid string) error {
|
||||
defer osl.InitOSContext()()
|
||||
n := d.network(nid)
|
||||
if n == nil {
|
||||
return fmt.Errorf("network id %s not found", nid)
|
||||
}
|
||||
// if the driver created the slave interface, delete it, otherwise leave it
|
||||
if ok := n.config.CreatedSlaveLink; ok {
|
||||
// if the interface exists, only delete if it matches iface.vlan or dummy.net_id naming
|
||||
if ok := parentExists(n.config.Parent); ok {
|
||||
// only delete the link if it is named the net_id
|
||||
if n.config.Parent == getDummyName(stringid.TruncateID(nid)) {
|
||||
err := delDummyLink(n.config.Parent)
|
||||
if err != nil {
|
||||
logrus.Debugf("link %s was not deleted, continuing the delete network operation: %v",
|
||||
n.config.Parent, err)
|
||||
}
|
||||
} else {
|
||||
// only delete the link if it matches iface.vlan naming
|
||||
err := delVlanLink(n.config.Parent)
|
||||
if err != nil {
|
||||
logrus.Debugf("link %s was not deleted, continuing the delete network operation: %v",
|
||||
n.config.Parent, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, ep := range n.endpoints {
|
||||
if link, err := ns.NlHandle().LinkByName(ep.srcName); err == nil {
|
||||
if err := ns.NlHandle().LinkDel(link); err != nil {
|
||||
logrus.WithError(err).Warnf("Failed to delete interface (%s)'s link on endpoint (%s) delete", ep.srcName, ep.id)
|
||||
}
|
||||
}
|
||||
|
||||
if err := d.storeDelete(ep); err != nil {
|
||||
logrus.Warnf("Failed to remove ipvlan endpoint %.7s from store: %v", ep.id, err)
|
||||
}
|
||||
}
|
||||
// delete the *network
|
||||
d.deleteNetwork(nid)
|
||||
// delete the network record from persistent cache
|
||||
err := d.storeDelete(n.config)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error deleting deleting id %s from datastore: %v", nid, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseNetworkOptions parse docker network options
|
||||
func parseNetworkOptions(id string, option options.Generic) (*configuration, error) {
|
||||
var (
|
||||
err error
|
||||
config = &configuration{}
|
||||
)
|
||||
// parse generic labels first
|
||||
if genData, ok := option[netlabel.GenericData]; ok && genData != nil {
|
||||
if config, err = parseNetworkGenericOptions(genData); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if val, ok := option[netlabel.Internal]; ok {
|
||||
if internal, ok := val.(bool); ok && internal {
|
||||
config.Internal = true
|
||||
}
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// parseNetworkGenericOptions parse generic driver docker network options
|
||||
func parseNetworkGenericOptions(data interface{}) (*configuration, error) {
|
||||
var (
|
||||
err error
|
||||
config *configuration
|
||||
)
|
||||
switch opt := data.(type) {
|
||||
case *configuration:
|
||||
config = opt
|
||||
case map[string]string:
|
||||
config = &configuration{}
|
||||
err = config.fromOptions(opt)
|
||||
case options.Generic:
|
||||
var opaqueConfig interface{}
|
||||
if opaqueConfig, err = options.GenerateFromModel(opt, config); err == nil {
|
||||
config = opaqueConfig.(*configuration)
|
||||
}
|
||||
default:
|
||||
err = types.BadRequestErrorf("unrecognized network configuration format: %v", opt)
|
||||
}
|
||||
return config, err
|
||||
}
|
||||
|
||||
// fromOptions binds the generic options to networkConfiguration to cache
|
||||
func (config *configuration) fromOptions(labels map[string]string) error {
|
||||
for label, value := range labels {
|
||||
switch label {
|
||||
case parentOpt:
|
||||
// parse driver option '-o parent'
|
||||
config.Parent = value
|
||||
case driverModeOpt:
|
||||
// parse driver option '-o ipvlan_mode'
|
||||
config.IpvlanMode = value
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// processIPAM parses v4 and v6 IP information and binds it to the network configuration
|
||||
func (config *configuration) processIPAM(id string, ipamV4Data, ipamV6Data []driverapi.IPAMData) error {
|
||||
if len(ipamV4Data) > 0 {
|
||||
for _, ipd := range ipamV4Data {
|
||||
s := &ipv4Subnet{
|
||||
SubnetIP: ipd.Pool.String(),
|
||||
GwIP: ipd.Gateway.String(),
|
||||
}
|
||||
config.Ipv4Subnets = append(config.Ipv4Subnets, s)
|
||||
}
|
||||
}
|
||||
if len(ipamV6Data) > 0 {
|
||||
for _, ipd := range ipamV6Data {
|
||||
s := &ipv6Subnet{
|
||||
SubnetIP: ipd.Pool.String(),
|
||||
GwIP: ipd.Gateway.String(),
|
||||
}
|
||||
config.Ipv6Subnets = append(config.Ipv6Subnets, s)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
205
vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_setup.go
generated
vendored
205
vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_setup.go
generated
vendored
|
@ -1,205 +0,0 @@
|
|||
package ipvlan
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/libnetwork/ns"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
const (
|
||||
dummyPrefix = "di-" // ipvlan prefix for dummy parent interface
|
||||
ipvlanKernelVer = 4 // minimum ipvlan kernel support
|
||||
ipvlanMajorVer = 2 // minimum ipvlan major kernel support
|
||||
)
|
||||
|
||||
// createIPVlan Create the ipvlan slave specifying the source name
|
||||
func createIPVlan(containerIfName, parent, ipvlanMode string) (string, error) {
|
||||
// Set the ipvlan mode. Default is bridge mode
|
||||
mode, err := setIPVlanMode(ipvlanMode)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Unsupported %s ipvlan mode: %v", ipvlanMode, err)
|
||||
}
|
||||
// verify the Docker host interface acting as the macvlan parent iface exists
|
||||
if !parentExists(parent) {
|
||||
return "", fmt.Errorf("the requested parent interface %s was not found on the Docker host", parent)
|
||||
}
|
||||
// Get the link for the master index (Example: the docker host eth iface)
|
||||
parentLink, err := ns.NlHandle().LinkByName(parent)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error occurred looking up the %s parent iface %s error: %s", ipvlanType, parent, err)
|
||||
}
|
||||
// Create an ipvlan link
|
||||
ipvlan := &netlink.IPVlan{
|
||||
LinkAttrs: netlink.LinkAttrs{
|
||||
Name: containerIfName,
|
||||
ParentIndex: parentLink.Attrs().Index,
|
||||
},
|
||||
Mode: mode,
|
||||
}
|
||||
if err := ns.NlHandle().LinkAdd(ipvlan); err != nil {
|
||||
// If a user creates a macvlan and ipvlan on same parent, only one slave iface can be active at a time.
|
||||
return "", fmt.Errorf("failed to create the %s port: %v", ipvlanType, err)
|
||||
}
|
||||
|
||||
return ipvlan.Attrs().Name, nil
|
||||
}
|
||||
|
||||
// setIPVlanMode setter for one of the two ipvlan port types
|
||||
func setIPVlanMode(mode string) (netlink.IPVlanMode, error) {
|
||||
switch mode {
|
||||
case modeL2:
|
||||
return netlink.IPVLAN_MODE_L2, nil
|
||||
case modeL3:
|
||||
return netlink.IPVLAN_MODE_L3, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("Unknown ipvlan mode: %s", mode)
|
||||
}
|
||||
}
|
||||
|
||||
// parentExists check if the specified interface exists in the default namespace
|
||||
func parentExists(ifaceStr string) bool {
|
||||
_, err := ns.NlHandle().LinkByName(ifaceStr)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// createVlanLink parses sub-interfaces and vlan id for creation
|
||||
func createVlanLink(parentName string) error {
|
||||
if strings.Contains(parentName, ".") {
|
||||
parent, vidInt, err := parseVlan(parentName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// VLAN identifier or VID is a 12-bit field specifying the VLAN to which the frame belongs
|
||||
if vidInt > 4094 || vidInt < 1 {
|
||||
return fmt.Errorf("vlan id must be between 1-4094, received: %d", vidInt)
|
||||
}
|
||||
// get the parent link to attach a vlan subinterface
|
||||
parentLink, err := ns.NlHandle().LinkByName(parent)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to find master interface %s on the Docker host: %v", parent, err)
|
||||
}
|
||||
vlanLink := &netlink.Vlan{
|
||||
LinkAttrs: netlink.LinkAttrs{
|
||||
Name: parentName,
|
||||
ParentIndex: parentLink.Attrs().Index,
|
||||
},
|
||||
VlanId: vidInt,
|
||||
}
|
||||
// create the subinterface
|
||||
if err := ns.NlHandle().LinkAdd(vlanLink); err != nil {
|
||||
return fmt.Errorf("failed to create %s vlan link: %v", vlanLink.Name, err)
|
||||
}
|
||||
// Bring the new netlink iface up
|
||||
if err := ns.NlHandle().LinkSetUp(vlanLink); err != nil {
|
||||
return fmt.Errorf("failed to enable %s the ipvlan parent link %v", vlanLink.Name, err)
|
||||
}
|
||||
logrus.Debugf("Added a vlan tagged netlink subinterface: %s with a vlan id: %d", parentName, vidInt)
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("invalid subinterface vlan name %s, example formatting is eth0.10", parentName)
|
||||
}
|
||||
|
||||
// delVlanLink verifies only sub-interfaces with a vlan id get deleted
|
||||
func delVlanLink(linkName string) error {
|
||||
if strings.Contains(linkName, ".") {
|
||||
_, _, err := parseVlan(linkName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// delete the vlan subinterface
|
||||
vlanLink, err := ns.NlHandle().LinkByName(linkName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to find interface %s on the Docker host : %v", linkName, err)
|
||||
}
|
||||
// verify a parent interface isn't being deleted
|
||||
if vlanLink.Attrs().ParentIndex == 0 {
|
||||
return fmt.Errorf("interface %s does not appear to be a slave device: %v", linkName, err)
|
||||
}
|
||||
// delete the ipvlan slave device
|
||||
if err := ns.NlHandle().LinkDel(vlanLink); err != nil {
|
||||
return fmt.Errorf("failed to delete %s link: %v", linkName, err)
|
||||
}
|
||||
logrus.Debugf("Deleted a vlan tagged netlink subinterface: %s", linkName)
|
||||
}
|
||||
// if the subinterface doesn't parse to iface.vlan_id leave the interface in
|
||||
// place since it could be a user specified name not created by the driver.
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseVlan parses and verifies a slave interface name: -o parent=eth0.10
|
||||
func parseVlan(linkName string) (string, int, error) {
|
||||
// parse -o parent=eth0.10
|
||||
splitName := strings.Split(linkName, ".")
|
||||
if len(splitName) != 2 {
|
||||
return "", 0, fmt.Errorf("required interface name format is: name.vlan_id, ex. eth0.10 for vlan 10, instead received %s", linkName)
|
||||
}
|
||||
parent, vidStr := splitName[0], splitName[1]
|
||||
// validate type and convert vlan id to int
|
||||
vidInt, err := strconv.Atoi(vidStr)
|
||||
if err != nil {
|
||||
return "", 0, fmt.Errorf("unable to parse a valid vlan id from: %s (ex. eth0.10 for vlan 10)", vidStr)
|
||||
}
|
||||
// Check if the interface exists
|
||||
if !parentExists(parent) {
|
||||
return "", 0, fmt.Errorf("-o parent interface was not found on the host: %s", parent)
|
||||
}
|
||||
|
||||
return parent, vidInt, nil
|
||||
}
|
||||
|
||||
// createDummyLink creates a dummy0 parent link
|
||||
func createDummyLink(dummyName, truncNetID string) error {
|
||||
// create a parent interface since one was not specified
|
||||
parent := &netlink.Dummy{
|
||||
LinkAttrs: netlink.LinkAttrs{
|
||||
Name: dummyName,
|
||||
},
|
||||
}
|
||||
if err := ns.NlHandle().LinkAdd(parent); err != nil {
|
||||
return err
|
||||
}
|
||||
parentDummyLink, err := ns.NlHandle().LinkByName(dummyName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error occurred looking up the %s parent iface %s error: %s", ipvlanType, dummyName, err)
|
||||
}
|
||||
// bring the new netlink iface up
|
||||
if err := ns.NlHandle().LinkSetUp(parentDummyLink); err != nil {
|
||||
return fmt.Errorf("failed to enable %s the ipvlan parent link: %v", dummyName, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// delDummyLink deletes the link type dummy used when -o parent is not passed
|
||||
func delDummyLink(linkName string) error {
|
||||
// delete the vlan subinterface
|
||||
dummyLink, err := ns.NlHandle().LinkByName(linkName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to find link %s on the Docker host : %v", linkName, err)
|
||||
}
|
||||
// verify a parent interface is being deleted
|
||||
if dummyLink.Attrs().ParentIndex != 0 {
|
||||
return fmt.Errorf("link %s is not a parent dummy interface", linkName)
|
||||
}
|
||||
// delete the ipvlan dummy device
|
||||
if err := ns.NlHandle().LinkDel(dummyLink); err != nil {
|
||||
return fmt.Errorf("failed to delete the dummy %s link: %v", linkName, err)
|
||||
}
|
||||
logrus.Debugf("Deleted a dummy parent link: %s", linkName)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getDummyName returns the name of a dummy parent with truncated net ID and driver prefix
|
||||
func getDummyName(netID string) string {
|
||||
return dummyPrefix + netID
|
||||
}
|
115
vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_state.go
generated
vendored
115
vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_state.go
generated
vendored
|
@ -1,115 +0,0 @@
|
|||
package ipvlan
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/libnetwork/osl"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func (d *driver) network(nid string) *network {
|
||||
d.Lock()
|
||||
n, ok := d.networks[nid]
|
||||
d.Unlock()
|
||||
if !ok {
|
||||
logrus.Errorf("network id %s not found", nid)
|
||||
}
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
func (d *driver) addNetwork(n *network) {
|
||||
d.Lock()
|
||||
d.networks[n.id] = n
|
||||
d.Unlock()
|
||||
}
|
||||
|
||||
func (d *driver) deleteNetwork(nid string) {
|
||||
d.Lock()
|
||||
delete(d.networks, nid)
|
||||
d.Unlock()
|
||||
}
|
||||
|
||||
// getNetworks Safely returns a slice of existing networks
|
||||
func (d *driver) getNetworks() []*network {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
ls := make([]*network, 0, len(d.networks))
|
||||
for _, nw := range d.networks {
|
||||
ls = append(ls, nw)
|
||||
}
|
||||
|
||||
return ls
|
||||
}
|
||||
|
||||
func (n *network) endpoint(eid string) *endpoint {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
||||
return n.endpoints[eid]
|
||||
}
|
||||
|
||||
func (n *network) addEndpoint(ep *endpoint) {
|
||||
n.Lock()
|
||||
n.endpoints[ep.id] = ep
|
||||
n.Unlock()
|
||||
}
|
||||
|
||||
func (n *network) deleteEndpoint(eid string) {
|
||||
n.Lock()
|
||||
delete(n.endpoints, eid)
|
||||
n.Unlock()
|
||||
}
|
||||
|
||||
func (n *network) getEndpoint(eid string) (*endpoint, error) {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
if eid == "" {
|
||||
return nil, fmt.Errorf("endpoint id %s not found", eid)
|
||||
}
|
||||
if ep, ok := n.endpoints[eid]; ok {
|
||||
return ep, nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func validateID(nid, eid string) error {
|
||||
if nid == "" {
|
||||
return fmt.Errorf("invalid network id")
|
||||
}
|
||||
if eid == "" {
|
||||
return fmt.Errorf("invalid endpoint id")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *network) sandbox() osl.Sandbox {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
||||
return n.sbox
|
||||
}
|
||||
|
||||
func (n *network) setSandbox(sbox osl.Sandbox) {
|
||||
n.Lock()
|
||||
n.sbox = sbox
|
||||
n.Unlock()
|
||||
}
|
||||
|
||||
func (d *driver) getNetwork(id string) (*network, error) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
if id == "" {
|
||||
return nil, types.BadRequestErrorf("invalid network id: %s", id)
|
||||
}
|
||||
|
||||
if nw, ok := d.networks[id]; ok {
|
||||
return nw, nil
|
||||
}
|
||||
|
||||
return nil, types.NotFoundErrorf("network not found: %s", id)
|
||||
}
|
356
vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_store.go
generated
vendored
356
vendor/github.com/docker/libnetwork/drivers/ipvlan/ipvlan_store.go
generated
vendored
|
@ -1,356 +0,0 @@
|
|||
package ipvlan
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/docker/libnetwork/datastore"
|
||||
"github.com/docker/libnetwork/discoverapi"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
ipvlanPrefix = "ipvlan"
|
||||
ipvlanNetworkPrefix = ipvlanPrefix + "/network"
|
||||
ipvlanEndpointPrefix = ipvlanPrefix + "/endpoint"
|
||||
)
|
||||
|
||||
// networkConfiguration for this driver's network specific configuration
|
||||
type configuration struct {
|
||||
ID string
|
||||
Mtu int
|
||||
dbIndex uint64
|
||||
dbExists bool
|
||||
Internal bool
|
||||
Parent string
|
||||
IpvlanMode string
|
||||
CreatedSlaveLink bool
|
||||
Ipv4Subnets []*ipv4Subnet
|
||||
Ipv6Subnets []*ipv6Subnet
|
||||
}
|
||||
|
||||
type ipv4Subnet struct {
|
||||
SubnetIP string
|
||||
GwIP string
|
||||
}
|
||||
|
||||
type ipv6Subnet struct {
|
||||
SubnetIP string
|
||||
GwIP string
|
||||
}
|
||||
|
||||
// initStore drivers are responsible for caching their own persistent state
|
||||
func (d *driver) initStore(option map[string]interface{}) error {
|
||||
if data, ok := option[netlabel.LocalKVClient]; ok {
|
||||
var err error
|
||||
dsc, ok := data.(discoverapi.DatastoreConfigData)
|
||||
if !ok {
|
||||
return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
|
||||
}
|
||||
d.store, err = datastore.NewDataStoreFromConfig(dsc)
|
||||
if err != nil {
|
||||
return types.InternalErrorf("ipvlan driver failed to initialize data store: %v", err)
|
||||
}
|
||||
|
||||
err = d.populateNetworks()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = d.populateEndpoints()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// populateNetworks is invoked at driver init to recreate persistently stored networks
|
||||
func (d *driver) populateNetworks() error {
|
||||
kvol, err := d.store.List(datastore.Key(ipvlanNetworkPrefix), &configuration{})
|
||||
if err != nil && err != datastore.ErrKeyNotFound {
|
||||
return fmt.Errorf("failed to get ipvlan network configurations from store: %v", err)
|
||||
}
|
||||
// If empty it simply means no ipvlan networks have been created yet
|
||||
if err == datastore.ErrKeyNotFound {
|
||||
return nil
|
||||
}
|
||||
for _, kvo := range kvol {
|
||||
config := kvo.(*configuration)
|
||||
if _, err = d.createNetwork(config); err != nil {
|
||||
logrus.Warnf("could not create ipvlan network for id %s from persistent state", config.ID)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) populateEndpoints() error {
|
||||
kvol, err := d.store.List(datastore.Key(ipvlanEndpointPrefix), &endpoint{})
|
||||
if err != nil && err != datastore.ErrKeyNotFound {
|
||||
return fmt.Errorf("failed to get ipvlan endpoints from store: %v", err)
|
||||
}
|
||||
|
||||
if err == datastore.ErrKeyNotFound {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, kvo := range kvol {
|
||||
ep := kvo.(*endpoint)
|
||||
n, ok := d.networks[ep.nid]
|
||||
if !ok {
|
||||
logrus.Debugf("Network (%.7s) not found for restored ipvlan endpoint (%.7s)", ep.nid, ep.id)
|
||||
logrus.Debugf("Deleting stale ipvlan endpoint (%.7s) from store", ep.id)
|
||||
if err := d.storeDelete(ep); err != nil {
|
||||
logrus.Debugf("Failed to delete stale ipvlan endpoint (%.7s) from store", ep.id)
|
||||
}
|
||||
continue
|
||||
}
|
||||
n.endpoints[ep.id] = ep
|
||||
logrus.Debugf("Endpoint (%.7s) restored to network (%.7s)", ep.id, ep.nid)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// storeUpdate used to update persistent ipvlan network records as they are created
|
||||
func (d *driver) storeUpdate(kvObject datastore.KVObject) error {
|
||||
if d.store == nil {
|
||||
logrus.Warnf("ipvlan store not initialized. kv object %s is not added to the store", datastore.Key(kvObject.Key()...))
|
||||
return nil
|
||||
}
|
||||
if err := d.store.PutObjectAtomic(kvObject); err != nil {
|
||||
return fmt.Errorf("failed to update ipvlan store for object type %T: %v", kvObject, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// storeDelete used to delete ipvlan network records from persistent cache as they are deleted
|
||||
func (d *driver) storeDelete(kvObject datastore.KVObject) error {
|
||||
if d.store == nil {
|
||||
logrus.Debugf("ipvlan store not initialized. kv object %s is not deleted from store", datastore.Key(kvObject.Key()...))
|
||||
return nil
|
||||
}
|
||||
retry:
|
||||
if err := d.store.DeleteObjectAtomic(kvObject); err != nil {
|
||||
if err == datastore.ErrKeyModified {
|
||||
if err := d.store.GetObject(datastore.Key(kvObject.Key()...), kvObject); err != nil {
|
||||
return fmt.Errorf("could not update the kvobject to latest when trying to delete: %v", err)
|
||||
}
|
||||
goto retry
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (config *configuration) MarshalJSON() ([]byte, error) {
|
||||
nMap := make(map[string]interface{})
|
||||
nMap["ID"] = config.ID
|
||||
nMap["Mtu"] = config.Mtu
|
||||
nMap["Parent"] = config.Parent
|
||||
nMap["IpvlanMode"] = config.IpvlanMode
|
||||
nMap["Internal"] = config.Internal
|
||||
nMap["CreatedSubIface"] = config.CreatedSlaveLink
|
||||
if len(config.Ipv4Subnets) > 0 {
|
||||
iis, err := json.Marshal(config.Ipv4Subnets)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nMap["Ipv4Subnets"] = string(iis)
|
||||
}
|
||||
if len(config.Ipv6Subnets) > 0 {
|
||||
iis, err := json.Marshal(config.Ipv6Subnets)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nMap["Ipv6Subnets"] = string(iis)
|
||||
}
|
||||
|
||||
return json.Marshal(nMap)
|
||||
}
|
||||
|
||||
func (config *configuration) UnmarshalJSON(b []byte) error {
|
||||
var (
|
||||
err error
|
||||
nMap map[string]interface{}
|
||||
)
|
||||
|
||||
if err = json.Unmarshal(b, &nMap); err != nil {
|
||||
return err
|
||||
}
|
||||
config.ID = nMap["ID"].(string)
|
||||
config.Mtu = int(nMap["Mtu"].(float64))
|
||||
config.Parent = nMap["Parent"].(string)
|
||||
config.IpvlanMode = nMap["IpvlanMode"].(string)
|
||||
config.Internal = nMap["Internal"].(bool)
|
||||
config.CreatedSlaveLink = nMap["CreatedSubIface"].(bool)
|
||||
if v, ok := nMap["Ipv4Subnets"]; ok {
|
||||
if err := json.Unmarshal([]byte(v.(string)), &config.Ipv4Subnets); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if v, ok := nMap["Ipv6Subnets"]; ok {
|
||||
if err := json.Unmarshal([]byte(v.(string)), &config.Ipv6Subnets); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (config *configuration) Key() []string {
|
||||
return []string{ipvlanNetworkPrefix, config.ID}
|
||||
}
|
||||
|
||||
func (config *configuration) KeyPrefix() []string {
|
||||
return []string{ipvlanNetworkPrefix}
|
||||
}
|
||||
|
||||
func (config *configuration) Value() []byte {
|
||||
b, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (config *configuration) SetValue(value []byte) error {
|
||||
return json.Unmarshal(value, config)
|
||||
}
|
||||
|
||||
func (config *configuration) Index() uint64 {
|
||||
return config.dbIndex
|
||||
}
|
||||
|
||||
func (config *configuration) SetIndex(index uint64) {
|
||||
config.dbIndex = index
|
||||
config.dbExists = true
|
||||
}
|
||||
|
||||
func (config *configuration) Exists() bool {
|
||||
return config.dbExists
|
||||
}
|
||||
|
||||
func (config *configuration) Skip() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (config *configuration) New() datastore.KVObject {
|
||||
return &configuration{}
|
||||
}
|
||||
|
||||
func (config *configuration) CopyTo(o datastore.KVObject) error {
|
||||
dstNcfg := o.(*configuration)
|
||||
*dstNcfg = *config
|
||||
return nil
|
||||
}
|
||||
|
||||
func (config *configuration) DataScope() string {
|
||||
return datastore.LocalScope
|
||||
}
|
||||
|
||||
func (ep *endpoint) MarshalJSON() ([]byte, error) {
|
||||
epMap := make(map[string]interface{})
|
||||
epMap["id"] = ep.id
|
||||
epMap["nid"] = ep.nid
|
||||
epMap["SrcName"] = ep.srcName
|
||||
if len(ep.mac) != 0 {
|
||||
epMap["MacAddress"] = ep.mac.String()
|
||||
}
|
||||
if ep.addr != nil {
|
||||
epMap["Addr"] = ep.addr.String()
|
||||
}
|
||||
if ep.addrv6 != nil {
|
||||
epMap["Addrv6"] = ep.addrv6.String()
|
||||
}
|
||||
return json.Marshal(epMap)
|
||||
}
|
||||
|
||||
func (ep *endpoint) UnmarshalJSON(b []byte) error {
|
||||
var (
|
||||
err error
|
||||
epMap map[string]interface{}
|
||||
)
|
||||
|
||||
if err = json.Unmarshal(b, &epMap); err != nil {
|
||||
return fmt.Errorf("Failed to unmarshal to ipvlan endpoint: %v", err)
|
||||
}
|
||||
|
||||
if v, ok := epMap["MacAddress"]; ok {
|
||||
if ep.mac, err = net.ParseMAC(v.(string)); err != nil {
|
||||
return types.InternalErrorf("failed to decode ipvlan endpoint MAC address (%s) after json unmarshal: %v", v.(string), err)
|
||||
}
|
||||
}
|
||||
if v, ok := epMap["Addr"]; ok {
|
||||
if ep.addr, err = types.ParseCIDR(v.(string)); err != nil {
|
||||
return types.InternalErrorf("failed to decode ipvlan endpoint IPv4 address (%s) after json unmarshal: %v", v.(string), err)
|
||||
}
|
||||
}
|
||||
if v, ok := epMap["Addrv6"]; ok {
|
||||
if ep.addrv6, err = types.ParseCIDR(v.(string)); err != nil {
|
||||
return types.InternalErrorf("failed to decode ipvlan endpoint IPv6 address (%s) after json unmarshal: %v", v.(string), err)
|
||||
}
|
||||
}
|
||||
ep.id = epMap["id"].(string)
|
||||
ep.nid = epMap["nid"].(string)
|
||||
ep.srcName = epMap["SrcName"].(string)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ep *endpoint) Key() []string {
|
||||
return []string{ipvlanEndpointPrefix, ep.id}
|
||||
}
|
||||
|
||||
func (ep *endpoint) KeyPrefix() []string {
|
||||
return []string{ipvlanEndpointPrefix}
|
||||
}
|
||||
|
||||
func (ep *endpoint) Value() []byte {
|
||||
b, err := json.Marshal(ep)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (ep *endpoint) SetValue(value []byte) error {
|
||||
return json.Unmarshal(value, ep)
|
||||
}
|
||||
|
||||
func (ep *endpoint) Index() uint64 {
|
||||
return ep.dbIndex
|
||||
}
|
||||
|
||||
func (ep *endpoint) SetIndex(index uint64) {
|
||||
ep.dbIndex = index
|
||||
ep.dbExists = true
|
||||
}
|
||||
|
||||
func (ep *endpoint) Exists() bool {
|
||||
return ep.dbExists
|
||||
}
|
||||
|
||||
func (ep *endpoint) Skip() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (ep *endpoint) New() datastore.KVObject {
|
||||
return &endpoint{}
|
||||
}
|
||||
|
||||
func (ep *endpoint) CopyTo(o datastore.KVObject) error {
|
||||
dstEp := o.(*endpoint)
|
||||
*dstEp = *ep
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ep *endpoint) DataScope() string {
|
||||
return datastore.LocalScope
|
||||
}
|
88
vendor/github.com/docker/libnetwork/drivers/ipvlan/ivmanager/ivmanager.go
generated
vendored
88
vendor/github.com/docker/libnetwork/drivers/ipvlan/ivmanager/ivmanager.go
generated
vendored
|
@ -1,88 +0,0 @@
|
|||
package ivmanager
|
||||
|
||||
import (
|
||||
"github.com/docker/libnetwork/datastore"
|
||||
"github.com/docker/libnetwork/discoverapi"
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
const networkType = "ipvlan"
|
||||
|
||||
type driver struct{}
|
||||
|
||||
// Init registers a new instance of ipvlan manager driver
|
||||
func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
||||
c := driverapi.Capability{
|
||||
DataScope: datastore.LocalScope,
|
||||
ConnectivityScope: datastore.GlobalScope,
|
||||
}
|
||||
return dc.RegisterDriver(networkType, &driver{}, c)
|
||||
}
|
||||
|
||||
func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {
|
||||
return nil, types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) NetworkFree(id string) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
|
||||
}
|
||||
|
||||
func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (d *driver) DeleteNetwork(nid string) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) DeleteEndpoint(nid, eid string) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) {
|
||||
return nil, types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) Leave(nid, eid string) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) Type() string {
|
||||
return networkType
|
||||
}
|
||||
|
||||
func (d *driver) IsBuiltIn() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
117
vendor/github.com/docker/libnetwork/drivers/macvlan/macvlan.go
generated
vendored
117
vendor/github.com/docker/libnetwork/drivers/macvlan/macvlan.go
generated
vendored
|
@ -1,117 +0,0 @@
|
|||
package macvlan
|
||||
|
||||
import (
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"github.com/docker/libnetwork/datastore"
|
||||
"github.com/docker/libnetwork/discoverapi"
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/osl"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
const (
|
||||
vethLen = 7
|
||||
containerVethPrefix = "eth"
|
||||
vethPrefix = "veth"
|
||||
macvlanType = "macvlan" // driver type name
|
||||
modePrivate = "private" // macvlan mode private
|
||||
modeVepa = "vepa" // macvlan mode vepa
|
||||
modeBridge = "bridge" // macvlan mode bridge
|
||||
modePassthru = "passthru" // macvlan mode passthrough
|
||||
parentOpt = "parent" // parent interface -o parent
|
||||
modeOpt = "_mode" // macvlan mode ux opt suffix
|
||||
)
|
||||
|
||||
var driverModeOpt = macvlanType + modeOpt // mode --option macvlan_mode
|
||||
|
||||
type endpointTable map[string]*endpoint
|
||||
|
||||
type networkTable map[string]*network
|
||||
|
||||
type driver struct {
|
||||
networks networkTable
|
||||
sync.Once
|
||||
sync.Mutex
|
||||
store datastore.DataStore
|
||||
}
|
||||
|
||||
type endpoint struct {
|
||||
id string
|
||||
nid string
|
||||
mac net.HardwareAddr
|
||||
addr *net.IPNet
|
||||
addrv6 *net.IPNet
|
||||
srcName string
|
||||
dbIndex uint64
|
||||
dbExists bool
|
||||
}
|
||||
|
||||
type network struct {
|
||||
id string
|
||||
sbox osl.Sandbox
|
||||
endpoints endpointTable
|
||||
driver *driver
|
||||
config *configuration
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// Init initializes and registers the libnetwork macvlan driver
|
||||
func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
||||
c := driverapi.Capability{
|
||||
DataScope: datastore.LocalScope,
|
||||
ConnectivityScope: datastore.GlobalScope,
|
||||
}
|
||||
d := &driver{
|
||||
networks: networkTable{},
|
||||
}
|
||||
d.initStore(config)
|
||||
|
||||
return dc.RegisterDriver(macvlanType, d, c)
|
||||
}
|
||||
|
||||
func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {
|
||||
return nil, types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) NetworkFree(id string) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) {
|
||||
return make(map[string]interface{}, 0), nil
|
||||
}
|
||||
|
||||
func (d *driver) Type() string {
|
||||
return macvlanType
|
||||
}
|
||||
|
||||
func (d *driver) IsBuiltIn() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DiscoverNew is a notification for a new discovery event
|
||||
func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DiscoverDelete is a notification for a discovery delete event
|
||||
func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
|
||||
}
|
||||
|
||||
func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
|
||||
return "", nil
|
||||
}
|
96
vendor/github.com/docker/libnetwork/drivers/macvlan/macvlan_endpoint.go
generated
vendored
96
vendor/github.com/docker/libnetwork/drivers/macvlan/macvlan_endpoint.go
generated
vendored
|
@ -1,96 +0,0 @@
|
|||
package macvlan
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/ns"
|
||||
"github.com/docker/libnetwork/osl"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// CreateEndpoint assigns the mac, ip and endpoint id for the new container
|
||||
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
|
||||
epOptions map[string]interface{}) error {
|
||||
defer osl.InitOSContext()()
|
||||
|
||||
if err := validateID(nid, eid); err != nil {
|
||||
return err
|
||||
}
|
||||
n, err := d.getNetwork(nid)
|
||||
if err != nil {
|
||||
return fmt.Errorf("network id %q not found", nid)
|
||||
}
|
||||
ep := &endpoint{
|
||||
id: eid,
|
||||
nid: nid,
|
||||
addr: ifInfo.Address(),
|
||||
addrv6: ifInfo.AddressIPv6(),
|
||||
mac: ifInfo.MacAddress(),
|
||||
}
|
||||
if ep.addr == nil {
|
||||
return fmt.Errorf("create endpoint was not passed an IP address")
|
||||
}
|
||||
if ep.mac == nil {
|
||||
ep.mac = netutils.GenerateMACFromIP(ep.addr.IP)
|
||||
if err := ifInfo.SetMacAddress(ep.mac); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// disallow portmapping -p
|
||||
if opt, ok := epOptions[netlabel.PortMap]; ok {
|
||||
if _, ok := opt.([]types.PortBinding); ok {
|
||||
if len(opt.([]types.PortBinding)) > 0 {
|
||||
logrus.Warnf("%s driver does not support port mappings", macvlanType)
|
||||
}
|
||||
}
|
||||
}
|
||||
// disallow port exposure --expose
|
||||
if opt, ok := epOptions[netlabel.ExposedPorts]; ok {
|
||||
if _, ok := opt.([]types.TransportPort); ok {
|
||||
if len(opt.([]types.TransportPort)) > 0 {
|
||||
logrus.Warnf("%s driver does not support port exposures", macvlanType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := d.storeUpdate(ep); err != nil {
|
||||
return fmt.Errorf("failed to save macvlan endpoint %.7s to store: %v", ep.id, err)
|
||||
}
|
||||
|
||||
n.addEndpoint(ep)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteEndpoint removes the endpoint and associated netlink interface
|
||||
func (d *driver) DeleteEndpoint(nid, eid string) error {
|
||||
defer osl.InitOSContext()()
|
||||
if err := validateID(nid, eid); err != nil {
|
||||
return err
|
||||
}
|
||||
n := d.network(nid)
|
||||
if n == nil {
|
||||
return fmt.Errorf("network id %q not found", nid)
|
||||
}
|
||||
ep := n.endpoint(eid)
|
||||
if ep == nil {
|
||||
return fmt.Errorf("endpoint id %q not found", eid)
|
||||
}
|
||||
if link, err := ns.NlHandle().LinkByName(ep.srcName); err == nil {
|
||||
if err := ns.NlHandle().LinkDel(link); err != nil {
|
||||
logrus.WithError(err).Warnf("Failed to delete interface (%s)'s link on endpoint (%s) delete", ep.srcName, ep.id)
|
||||
}
|
||||
}
|
||||
|
||||
if err := d.storeDelete(ep); err != nil {
|
||||
logrus.Warnf("Failed to remove macvlan endpoint %.7s from store: %v", ep.id, err)
|
||||
}
|
||||
|
||||
n.deleteEndpoint(ep.id)
|
||||
|
||||
return nil
|
||||
}
|
155
vendor/github.com/docker/libnetwork/drivers/macvlan/macvlan_joinleave.go
generated
vendored
155
vendor/github.com/docker/libnetwork/drivers/macvlan/macvlan_joinleave.go
generated
vendored
|
@ -1,155 +0,0 @@
|
|||
package macvlan
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/ns"
|
||||
"github.com/docker/libnetwork/osl"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Join method is invoked when a Sandbox is attached to an endpoint.
|
||||
func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
||||
defer osl.InitOSContext()()
|
||||
n, err := d.getNetwork(nid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
endpoint := n.endpoint(eid)
|
||||
if endpoint == nil {
|
||||
return fmt.Errorf("could not find endpoint with id %s", eid)
|
||||
}
|
||||
// generate a name for the iface that will be renamed to eth0 in the sbox
|
||||
containerIfName, err := netutils.GenerateIfaceName(ns.NlHandle(), vethPrefix, vethLen)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error generating an interface name: %s", err)
|
||||
}
|
||||
// create the netlink macvlan interface
|
||||
vethName, err := createMacVlan(containerIfName, n.config.Parent, n.config.MacvlanMode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// bind the generated iface name to the endpoint
|
||||
endpoint.srcName = vethName
|
||||
ep := n.endpoint(eid)
|
||||
if ep == nil {
|
||||
return fmt.Errorf("could not find endpoint with id %s", eid)
|
||||
}
|
||||
// parse and match the endpoint address with the available v4 subnets
|
||||
if !n.config.Internal {
|
||||
if len(n.config.Ipv4Subnets) > 0 {
|
||||
s := n.getSubnetforIPv4(ep.addr)
|
||||
if s == nil {
|
||||
return fmt.Errorf("could not find a valid ipv4 subnet for endpoint %s", eid)
|
||||
}
|
||||
v4gw, _, err := net.ParseCIDR(s.GwIP)
|
||||
if err != nil {
|
||||
return fmt.Errorf("gateway %s is not a valid ipv4 address: %v", s.GwIP, err)
|
||||
}
|
||||
err = jinfo.SetGateway(v4gw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.Debugf("Macvlan Endpoint Joined with IPv4_Addr: %s, Gateway: %s, MacVlan_Mode: %s, Parent: %s",
|
||||
ep.addr.IP.String(), v4gw.String(), n.config.MacvlanMode, n.config.Parent)
|
||||
}
|
||||
// parse and match the endpoint address with the available v6 subnets
|
||||
if len(n.config.Ipv6Subnets) > 0 {
|
||||
s := n.getSubnetforIPv6(ep.addrv6)
|
||||
if s == nil {
|
||||
return fmt.Errorf("could not find a valid ipv6 subnet for endpoint %s", eid)
|
||||
}
|
||||
v6gw, _, err := net.ParseCIDR(s.GwIP)
|
||||
if err != nil {
|
||||
return fmt.Errorf("gateway %s is not a valid ipv6 address: %v", s.GwIP, err)
|
||||
}
|
||||
err = jinfo.SetGatewayIPv6(v6gw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.Debugf("Macvlan Endpoint Joined with IPv6_Addr: %s Gateway: %s MacVlan_Mode: %s, Parent: %s",
|
||||
ep.addrv6.IP.String(), v6gw.String(), n.config.MacvlanMode, n.config.Parent)
|
||||
}
|
||||
} else {
|
||||
if len(n.config.Ipv4Subnets) > 0 {
|
||||
logrus.Debugf("Macvlan Endpoint Joined with IPv4_Addr: %s, MacVlan_Mode: %s, Parent: %s",
|
||||
ep.addr.IP.String(), n.config.MacvlanMode, n.config.Parent)
|
||||
}
|
||||
if len(n.config.Ipv6Subnets) > 0 {
|
||||
logrus.Debugf("Macvlan Endpoint Joined with IPv6_Addr: %s MacVlan_Mode: %s, Parent: %s",
|
||||
ep.addrv6.IP.String(), n.config.MacvlanMode, n.config.Parent)
|
||||
}
|
||||
}
|
||||
iNames := jinfo.InterfaceName()
|
||||
err = iNames.SetNames(vethName, containerVethPrefix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.storeUpdate(ep); err != nil {
|
||||
return fmt.Errorf("failed to save macvlan endpoint %.7s to store: %v", ep.id, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Leave method is invoked when a Sandbox detaches from an endpoint.
|
||||
func (d *driver) Leave(nid, eid string) error {
|
||||
defer osl.InitOSContext()()
|
||||
network, err := d.getNetwork(nid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
endpoint, err := network.getEndpoint(eid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if endpoint == nil {
|
||||
return fmt.Errorf("could not find endpoint with id %s", eid)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getSubnetforIP returns the ipv4 subnet to which the given IP belongs
|
||||
func (n *network) getSubnetforIPv4(ip *net.IPNet) *ipv4Subnet {
|
||||
for _, s := range n.config.Ipv4Subnets {
|
||||
_, snet, err := net.ParseCIDR(s.SubnetIP)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
// first check if the mask lengths are the same
|
||||
i, _ := snet.Mask.Size()
|
||||
j, _ := ip.Mask.Size()
|
||||
if i != j {
|
||||
continue
|
||||
}
|
||||
if snet.Contains(ip.IP) {
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getSubnetforIPv6 returns the ipv6 subnet to which the given IP belongs
|
||||
func (n *network) getSubnetforIPv6(ip *net.IPNet) *ipv6Subnet {
|
||||
for _, s := range n.config.Ipv6Subnets {
|
||||
_, snet, err := net.ParseCIDR(s.SubnetIP)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
// first check if the mask lengths are the same
|
||||
i, _ := snet.Mask.Size()
|
||||
j, _ := ip.Mask.Size()
|
||||
if i != j {
|
||||
continue
|
||||
}
|
||||
if snet.Contains(ip.IP) {
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
259
vendor/github.com/docker/libnetwork/drivers/macvlan/macvlan_network.go
generated
vendored
259
vendor/github.com/docker/libnetwork/drivers/macvlan/macvlan_network.go
generated
vendored
|
@ -1,259 +0,0 @@
|
|||
package macvlan
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/ns"
|
||||
"github.com/docker/libnetwork/options"
|
||||
"github.com/docker/libnetwork/osl"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// CreateNetwork the network for the specified driver type
|
||||
func (d *driver) CreateNetwork(nid string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
|
||||
defer osl.InitOSContext()()
|
||||
|
||||
// reject a null v4 network
|
||||
if len(ipV4Data) == 0 || ipV4Data[0].Pool.String() == "0.0.0.0/0" {
|
||||
return fmt.Errorf("ipv4 pool is empty")
|
||||
}
|
||||
// parse and validate the config and bind to networkConfiguration
|
||||
config, err := parseNetworkOptions(nid, option)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
config.ID = nid
|
||||
err = config.processIPAM(nid, ipV4Data, ipV6Data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// verify the macvlan mode from -o macvlan_mode option
|
||||
switch config.MacvlanMode {
|
||||
case "", modeBridge:
|
||||
// default to macvlan bridge mode if -o macvlan_mode is empty
|
||||
config.MacvlanMode = modeBridge
|
||||
case modePrivate:
|
||||
config.MacvlanMode = modePrivate
|
||||
case modePassthru:
|
||||
config.MacvlanMode = modePassthru
|
||||
case modeVepa:
|
||||
config.MacvlanMode = modeVepa
|
||||
default:
|
||||
return fmt.Errorf("requested macvlan mode '%s' is not valid, 'bridge' mode is the macvlan driver default", config.MacvlanMode)
|
||||
}
|
||||
// loopback is not a valid parent link
|
||||
if config.Parent == "lo" {
|
||||
return fmt.Errorf("loopback interface is not a valid %s parent link", macvlanType)
|
||||
}
|
||||
// if parent interface not specified, create a dummy type link to use named dummy+net_id
|
||||
if config.Parent == "" {
|
||||
config.Parent = getDummyName(stringid.TruncateID(config.ID))
|
||||
}
|
||||
foundExisting, err := d.createNetwork(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if foundExisting {
|
||||
return types.InternalMaskableErrorf("restoring existing network %s", config.ID)
|
||||
}
|
||||
|
||||
// update persistent db, rollback on fail
|
||||
err = d.storeUpdate(config)
|
||||
if err != nil {
|
||||
d.deleteNetwork(config.ID)
|
||||
logrus.Debugf("encountered an error rolling back a network create for %s : %v", config.ID, err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// createNetwork is used by new network callbacks and persistent network cache
|
||||
func (d *driver) createNetwork(config *configuration) (bool, error) {
|
||||
foundExisting := false
|
||||
networkList := d.getNetworks()
|
||||
for _, nw := range networkList {
|
||||
if config.Parent == nw.config.Parent {
|
||||
if config.ID != nw.config.ID {
|
||||
return false, fmt.Errorf("network %s is already using parent interface %s",
|
||||
getDummyName(stringid.TruncateID(nw.config.ID)), config.Parent)
|
||||
}
|
||||
logrus.Debugf("Create Network for the same ID %s\n", config.ID)
|
||||
foundExisting = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !parentExists(config.Parent) {
|
||||
// Create a dummy link if a dummy name is set for parent
|
||||
if dummyName := getDummyName(stringid.TruncateID(config.ID)); dummyName == config.Parent {
|
||||
err := createDummyLink(config.Parent, dummyName)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
config.CreatedSlaveLink = true
|
||||
// notify the user in logs that they have limited communications
|
||||
logrus.Debugf("Empty -o parent= limit communications to other containers inside of network: %s",
|
||||
config.Parent)
|
||||
} else {
|
||||
// if the subinterface parent_iface.vlan_id checks do not pass, return err.
|
||||
// a valid example is 'eth0.10' for a parent iface 'eth0' with a vlan id '10'
|
||||
err := createVlanLink(config.Parent)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
// if driver created the networks slave link, record it for future deletion
|
||||
config.CreatedSlaveLink = true
|
||||
}
|
||||
}
|
||||
if !foundExisting {
|
||||
n := &network{
|
||||
id: config.ID,
|
||||
driver: d,
|
||||
endpoints: endpointTable{},
|
||||
config: config,
|
||||
}
|
||||
// add the network
|
||||
d.addNetwork(n)
|
||||
}
|
||||
|
||||
return foundExisting, nil
|
||||
}
|
||||
|
||||
// DeleteNetwork deletes the network for the specified driver type
|
||||
func (d *driver) DeleteNetwork(nid string) error {
|
||||
defer osl.InitOSContext()()
|
||||
n := d.network(nid)
|
||||
if n == nil {
|
||||
return fmt.Errorf("network id %s not found", nid)
|
||||
}
|
||||
// if the driver created the slave interface, delete it, otherwise leave it
|
||||
if ok := n.config.CreatedSlaveLink; ok {
|
||||
// if the interface exists, only delete if it matches iface.vlan or dummy.net_id naming
|
||||
if ok := parentExists(n.config.Parent); ok {
|
||||
// only delete the link if it is named the net_id
|
||||
if n.config.Parent == getDummyName(stringid.TruncateID(nid)) {
|
||||
err := delDummyLink(n.config.Parent)
|
||||
if err != nil {
|
||||
logrus.Debugf("link %s was not deleted, continuing the delete network operation: %v",
|
||||
n.config.Parent, err)
|
||||
}
|
||||
} else {
|
||||
// only delete the link if it matches iface.vlan naming
|
||||
err := delVlanLink(n.config.Parent)
|
||||
if err != nil {
|
||||
logrus.Debugf("link %s was not deleted, continuing the delete network operation: %v",
|
||||
n.config.Parent, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, ep := range n.endpoints {
|
||||
if link, err := ns.NlHandle().LinkByName(ep.srcName); err == nil {
|
||||
if err := ns.NlHandle().LinkDel(link); err != nil {
|
||||
logrus.WithError(err).Warnf("Failed to delete interface (%s)'s link on endpoint (%s) delete", ep.srcName, ep.id)
|
||||
}
|
||||
}
|
||||
|
||||
if err := d.storeDelete(ep); err != nil {
|
||||
logrus.Warnf("Failed to remove macvlan endpoint %.7s from store: %v", ep.id, err)
|
||||
}
|
||||
}
|
||||
// delete the *network
|
||||
d.deleteNetwork(nid)
|
||||
// delete the network record from persistent cache
|
||||
err := d.storeDelete(n.config)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error deleting deleting id %s from datastore: %v", nid, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseNetworkOptions parses docker network options
|
||||
func parseNetworkOptions(id string, option options.Generic) (*configuration, error) {
|
||||
var (
|
||||
err error
|
||||
config = &configuration{}
|
||||
)
|
||||
// parse generic labels first
|
||||
if genData, ok := option[netlabel.GenericData]; ok && genData != nil {
|
||||
if config, err = parseNetworkGenericOptions(genData); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if val, ok := option[netlabel.Internal]; ok {
|
||||
if internal, ok := val.(bool); ok && internal {
|
||||
config.Internal = true
|
||||
}
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// parseNetworkGenericOptions parses generic driver docker network options
|
||||
func parseNetworkGenericOptions(data interface{}) (*configuration, error) {
|
||||
var (
|
||||
err error
|
||||
config *configuration
|
||||
)
|
||||
switch opt := data.(type) {
|
||||
case *configuration:
|
||||
config = opt
|
||||
case map[string]string:
|
||||
config = &configuration{}
|
||||
err = config.fromOptions(opt)
|
||||
case options.Generic:
|
||||
var opaqueConfig interface{}
|
||||
if opaqueConfig, err = options.GenerateFromModel(opt, config); err == nil {
|
||||
config = opaqueConfig.(*configuration)
|
||||
}
|
||||
default:
|
||||
err = types.BadRequestErrorf("unrecognized network configuration format: %v", opt)
|
||||
}
|
||||
|
||||
return config, err
|
||||
}
|
||||
|
||||
// fromOptions binds the generic options to networkConfiguration to cache
|
||||
func (config *configuration) fromOptions(labels map[string]string) error {
|
||||
for label, value := range labels {
|
||||
switch label {
|
||||
case parentOpt:
|
||||
// parse driver option '-o parent'
|
||||
config.Parent = value
|
||||
case driverModeOpt:
|
||||
// parse driver option '-o macvlan_mode'
|
||||
config.MacvlanMode = value
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// processIPAM parses v4 and v6 IP information and binds it to the network configuration
|
||||
func (config *configuration) processIPAM(id string, ipamV4Data, ipamV6Data []driverapi.IPAMData) error {
|
||||
if len(ipamV4Data) > 0 {
|
||||
for _, ipd := range ipamV4Data {
|
||||
s := &ipv4Subnet{
|
||||
SubnetIP: ipd.Pool.String(),
|
||||
GwIP: ipd.Gateway.String(),
|
||||
}
|
||||
config.Ipv4Subnets = append(config.Ipv4Subnets, s)
|
||||
}
|
||||
}
|
||||
if len(ipamV6Data) > 0 {
|
||||
for _, ipd := range ipamV6Data {
|
||||
s := &ipv6Subnet{
|
||||
SubnetIP: ipd.Pool.String(),
|
||||
GwIP: ipd.Gateway.String(),
|
||||
}
|
||||
config.Ipv6Subnets = append(config.Ipv6Subnets, s)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
207
vendor/github.com/docker/libnetwork/drivers/macvlan/macvlan_setup.go
generated
vendored
207
vendor/github.com/docker/libnetwork/drivers/macvlan/macvlan_setup.go
generated
vendored
|
@ -1,207 +0,0 @@
|
|||
package macvlan
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/libnetwork/ns"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
const (
|
||||
dummyPrefix = "dm-" // macvlan prefix for dummy parent interface
|
||||
)
|
||||
|
||||
// Create the macvlan slave specifying the source name
|
||||
func createMacVlan(containerIfName, parent, macvlanMode string) (string, error) {
|
||||
// Set the macvlan mode. Default is bridge mode
|
||||
mode, err := setMacVlanMode(macvlanMode)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Unsupported %s macvlan mode: %v", macvlanMode, err)
|
||||
}
|
||||
// verify the Docker host interface acting as the macvlan parent iface exists
|
||||
if !parentExists(parent) {
|
||||
return "", fmt.Errorf("the requested parent interface %s was not found on the Docker host", parent)
|
||||
}
|
||||
// Get the link for the master index (Example: the docker host eth iface)
|
||||
parentLink, err := ns.NlHandle().LinkByName(parent)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error occurred looking up the %s parent iface %s error: %s", macvlanType, parent, err)
|
||||
}
|
||||
// Create a macvlan link
|
||||
macvlan := &netlink.Macvlan{
|
||||
LinkAttrs: netlink.LinkAttrs{
|
||||
Name: containerIfName,
|
||||
ParentIndex: parentLink.Attrs().Index,
|
||||
},
|
||||
Mode: mode,
|
||||
}
|
||||
if err := ns.NlHandle().LinkAdd(macvlan); err != nil {
|
||||
// If a user creates a macvlan and ipvlan on same parent, only one slave iface can be active at a time.
|
||||
return "", fmt.Errorf("failed to create the %s port: %v", macvlanType, err)
|
||||
}
|
||||
|
||||
return macvlan.Attrs().Name, nil
|
||||
}
|
||||
|
||||
// setMacVlanMode setter for one of the four macvlan port types
|
||||
func setMacVlanMode(mode string) (netlink.MacvlanMode, error) {
|
||||
switch mode {
|
||||
case modePrivate:
|
||||
return netlink.MACVLAN_MODE_PRIVATE, nil
|
||||
case modeVepa:
|
||||
return netlink.MACVLAN_MODE_VEPA, nil
|
||||
case modeBridge:
|
||||
return netlink.MACVLAN_MODE_BRIDGE, nil
|
||||
case modePassthru:
|
||||
return netlink.MACVLAN_MODE_PASSTHRU, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("unknown macvlan mode: %s", mode)
|
||||
}
|
||||
}
|
||||
|
||||
// parentExists checks if the specified interface exists in the default namespace
|
||||
func parentExists(ifaceStr string) bool {
|
||||
_, err := ns.NlHandle().LinkByName(ifaceStr)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// createVlanLink parses sub-interfaces and vlan id for creation
|
||||
func createVlanLink(parentName string) error {
|
||||
if strings.Contains(parentName, ".") {
|
||||
parent, vidInt, err := parseVlan(parentName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// VLAN identifier or VID is a 12-bit field specifying the VLAN to which the frame belongs
|
||||
if vidInt > 4094 || vidInt < 1 {
|
||||
return fmt.Errorf("vlan id must be between 1-4094, received: %d", vidInt)
|
||||
}
|
||||
// get the parent link to attach a vlan subinterface
|
||||
parentLink, err := ns.NlHandle().LinkByName(parent)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to find master interface %s on the Docker host: %v", parent, err)
|
||||
}
|
||||
vlanLink := &netlink.Vlan{
|
||||
LinkAttrs: netlink.LinkAttrs{
|
||||
Name: parentName,
|
||||
ParentIndex: parentLink.Attrs().Index,
|
||||
},
|
||||
VlanId: vidInt,
|
||||
}
|
||||
// create the subinterface
|
||||
if err := ns.NlHandle().LinkAdd(vlanLink); err != nil {
|
||||
return fmt.Errorf("failed to create %s vlan link: %v", vlanLink.Name, err)
|
||||
}
|
||||
// Bring the new netlink iface up
|
||||
if err := ns.NlHandle().LinkSetUp(vlanLink); err != nil {
|
||||
return fmt.Errorf("failed to enable %s the macvlan parent link %v", vlanLink.Name, err)
|
||||
}
|
||||
logrus.Debugf("Added a vlan tagged netlink subinterface: %s with a vlan id: %d", parentName, vidInt)
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("invalid subinterface vlan name %s, example formatting is eth0.10", parentName)
|
||||
}
|
||||
|
||||
// delVlanLink verifies only sub-interfaces with a vlan id get deleted
|
||||
func delVlanLink(linkName string) error {
|
||||
if strings.Contains(linkName, ".") {
|
||||
_, _, err := parseVlan(linkName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// delete the vlan subinterface
|
||||
vlanLink, err := ns.NlHandle().LinkByName(linkName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to find interface %s on the Docker host : %v", linkName, err)
|
||||
}
|
||||
// verify a parent interface isn't being deleted
|
||||
if vlanLink.Attrs().ParentIndex == 0 {
|
||||
return fmt.Errorf("interface %s does not appear to be a slave device: %v", linkName, err)
|
||||
}
|
||||
// delete the macvlan slave device
|
||||
if err := ns.NlHandle().LinkDel(vlanLink); err != nil {
|
||||
return fmt.Errorf("failed to delete %s link: %v", linkName, err)
|
||||
}
|
||||
logrus.Debugf("Deleted a vlan tagged netlink subinterface: %s", linkName)
|
||||
}
|
||||
// if the subinterface doesn't parse to iface.vlan_id leave the interface in
|
||||
// place since it could be a user specified name not created by the driver.
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseVlan parses and verifies a slave interface name: -o parent=eth0.10
|
||||
func parseVlan(linkName string) (string, int, error) {
|
||||
// parse -o parent=eth0.10
|
||||
splitName := strings.Split(linkName, ".")
|
||||
if len(splitName) != 2 {
|
||||
return "", 0, fmt.Errorf("required interface name format is: name.vlan_id, ex. eth0.10 for vlan 10, instead received %s", linkName)
|
||||
}
|
||||
parent, vidStr := splitName[0], splitName[1]
|
||||
// validate type and convert vlan id to int
|
||||
vidInt, err := strconv.Atoi(vidStr)
|
||||
if err != nil {
|
||||
return "", 0, fmt.Errorf("unable to parse a valid vlan id from: %s (ex. eth0.10 for vlan 10)", vidStr)
|
||||
}
|
||||
// Check if the interface exists
|
||||
if !parentExists(parent) {
|
||||
return "", 0, fmt.Errorf("-o parent interface does was not found on the host: %s", parent)
|
||||
}
|
||||
|
||||
return parent, vidInt, nil
|
||||
}
|
||||
|
||||
// createDummyLink creates a dummy0 parent link
|
||||
func createDummyLink(dummyName, truncNetID string) error {
|
||||
// create a parent interface since one was not specified
|
||||
parent := &netlink.Dummy{
|
||||
LinkAttrs: netlink.LinkAttrs{
|
||||
Name: dummyName,
|
||||
},
|
||||
}
|
||||
if err := ns.NlHandle().LinkAdd(parent); err != nil {
|
||||
return err
|
||||
}
|
||||
parentDummyLink, err := ns.NlHandle().LinkByName(dummyName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error occurred looking up the %s parent iface %s error: %s", macvlanType, dummyName, err)
|
||||
}
|
||||
// bring the new netlink iface up
|
||||
if err := ns.NlHandle().LinkSetUp(parentDummyLink); err != nil {
|
||||
return fmt.Errorf("failed to enable %s the macvlan parent link: %v", dummyName, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// delDummyLink deletes the link type dummy used when -o parent is not passed
|
||||
func delDummyLink(linkName string) error {
|
||||
// delete the vlan subinterface
|
||||
dummyLink, err := ns.NlHandle().LinkByName(linkName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to find link %s on the Docker host : %v", linkName, err)
|
||||
}
|
||||
// verify a parent interface is being deleted
|
||||
if dummyLink.Attrs().ParentIndex != 0 {
|
||||
return fmt.Errorf("link %s is not a parent dummy interface", linkName)
|
||||
}
|
||||
// delete the macvlan dummy device
|
||||
if err := ns.NlHandle().LinkDel(dummyLink); err != nil {
|
||||
return fmt.Errorf("failed to delete the dummy %s link: %v", linkName, err)
|
||||
}
|
||||
logrus.Debugf("Deleted a dummy parent link: %s", linkName)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getDummyName returns the name of a dummy parent with truncated net ID and driver prefix
|
||||
func getDummyName(netID string) string {
|
||||
return dummyPrefix + netID
|
||||
}
|
113
vendor/github.com/docker/libnetwork/drivers/macvlan/macvlan_state.go
generated
vendored
113
vendor/github.com/docker/libnetwork/drivers/macvlan/macvlan_state.go
generated
vendored
|
@ -1,113 +0,0 @@
|
|||
package macvlan
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/libnetwork/osl"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func (d *driver) network(nid string) *network {
|
||||
d.Lock()
|
||||
n, ok := d.networks[nid]
|
||||
d.Unlock()
|
||||
if !ok {
|
||||
logrus.Errorf("network id %s not found", nid)
|
||||
}
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
func (d *driver) addNetwork(n *network) {
|
||||
d.Lock()
|
||||
d.networks[n.id] = n
|
||||
d.Unlock()
|
||||
}
|
||||
|
||||
func (d *driver) deleteNetwork(nid string) {
|
||||
d.Lock()
|
||||
delete(d.networks, nid)
|
||||
d.Unlock()
|
||||
}
|
||||
|
||||
// getNetworks Safely returns a slice of existing networks
|
||||
func (d *driver) getNetworks() []*network {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
ls := make([]*network, 0, len(d.networks))
|
||||
for _, nw := range d.networks {
|
||||
ls = append(ls, nw)
|
||||
}
|
||||
|
||||
return ls
|
||||
}
|
||||
|
||||
func (n *network) endpoint(eid string) *endpoint {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
||||
return n.endpoints[eid]
|
||||
}
|
||||
|
||||
func (n *network) addEndpoint(ep *endpoint) {
|
||||
n.Lock()
|
||||
n.endpoints[ep.id] = ep
|
||||
n.Unlock()
|
||||
}
|
||||
|
||||
func (n *network) deleteEndpoint(eid string) {
|
||||
n.Lock()
|
||||
delete(n.endpoints, eid)
|
||||
n.Unlock()
|
||||
}
|
||||
|
||||
func (n *network) getEndpoint(eid string) (*endpoint, error) {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
if eid == "" {
|
||||
return nil, fmt.Errorf("endpoint id %s not found", eid)
|
||||
}
|
||||
if ep, ok := n.endpoints[eid]; ok {
|
||||
return ep, nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func validateID(nid, eid string) error {
|
||||
if nid == "" {
|
||||
return fmt.Errorf("invalid network id")
|
||||
}
|
||||
if eid == "" {
|
||||
return fmt.Errorf("invalid endpoint id")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *network) sandbox() osl.Sandbox {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
||||
return n.sbox
|
||||
}
|
||||
|
||||
func (n *network) setSandbox(sbox osl.Sandbox) {
|
||||
n.Lock()
|
||||
n.sbox = sbox
|
||||
n.Unlock()
|
||||
}
|
||||
|
||||
func (d *driver) getNetwork(id string) (*network, error) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
if id == "" {
|
||||
return nil, types.BadRequestErrorf("invalid network id: %s", id)
|
||||
}
|
||||
if nw, ok := d.networks[id]; ok {
|
||||
return nw, nil
|
||||
}
|
||||
|
||||
return nil, types.NotFoundErrorf("network not found: %s", id)
|
||||
}
|
359
vendor/github.com/docker/libnetwork/drivers/macvlan/macvlan_store.go
generated
vendored
359
vendor/github.com/docker/libnetwork/drivers/macvlan/macvlan_store.go
generated
vendored
|
@ -1,359 +0,0 @@
|
|||
package macvlan
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/docker/libnetwork/datastore"
|
||||
"github.com/docker/libnetwork/discoverapi"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
macvlanPrefix = "macvlan"
|
||||
macvlanNetworkPrefix = macvlanPrefix + "/network"
|
||||
macvlanEndpointPrefix = macvlanPrefix + "/endpoint"
|
||||
)
|
||||
|
||||
// networkConfiguration for this driver's network specific configuration
|
||||
type configuration struct {
|
||||
ID string
|
||||
Mtu int
|
||||
dbIndex uint64
|
||||
dbExists bool
|
||||
Internal bool
|
||||
Parent string
|
||||
MacvlanMode string
|
||||
CreatedSlaveLink bool
|
||||
Ipv4Subnets []*ipv4Subnet
|
||||
Ipv6Subnets []*ipv6Subnet
|
||||
}
|
||||
|
||||
type ipv4Subnet struct {
|
||||
SubnetIP string
|
||||
GwIP string
|
||||
}
|
||||
|
||||
type ipv6Subnet struct {
|
||||
SubnetIP string
|
||||
GwIP string
|
||||
}
|
||||
|
||||
// initStore drivers are responsible for caching their own persistent state
|
||||
func (d *driver) initStore(option map[string]interface{}) error {
|
||||
if data, ok := option[netlabel.LocalKVClient]; ok {
|
||||
var err error
|
||||
dsc, ok := data.(discoverapi.DatastoreConfigData)
|
||||
if !ok {
|
||||
return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
|
||||
}
|
||||
d.store, err = datastore.NewDataStoreFromConfig(dsc)
|
||||
if err != nil {
|
||||
return types.InternalErrorf("macvlan driver failed to initialize data store: %v", err)
|
||||
}
|
||||
|
||||
err = d.populateNetworks()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = d.populateEndpoints()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// populateNetworks is invoked at driver init to recreate persistently stored networks
|
||||
func (d *driver) populateNetworks() error {
|
||||
kvol, err := d.store.List(datastore.Key(macvlanPrefix), &configuration{})
|
||||
if err != nil && err != datastore.ErrKeyNotFound {
|
||||
return fmt.Errorf("failed to get macvlan network configurations from store: %v", err)
|
||||
}
|
||||
// If empty it simply means no macvlan networks have been created yet
|
||||
if err == datastore.ErrKeyNotFound {
|
||||
return nil
|
||||
}
|
||||
for _, kvo := range kvol {
|
||||
config := kvo.(*configuration)
|
||||
if _, err = d.createNetwork(config); err != nil {
|
||||
logrus.Warnf("Could not create macvlan network for id %s from persistent state", config.ID)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) populateEndpoints() error {
|
||||
kvol, err := d.store.List(datastore.Key(macvlanEndpointPrefix), &endpoint{})
|
||||
if err != nil && err != datastore.ErrKeyNotFound {
|
||||
return fmt.Errorf("failed to get macvlan endpoints from store: %v", err)
|
||||
}
|
||||
|
||||
if err == datastore.ErrKeyNotFound {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, kvo := range kvol {
|
||||
ep := kvo.(*endpoint)
|
||||
n, ok := d.networks[ep.nid]
|
||||
if !ok {
|
||||
logrus.Debugf("Network (%.7s) not found for restored macvlan endpoint (%.7s)", ep.nid, ep.id)
|
||||
logrus.Debugf("Deleting stale macvlan endpoint (%.7s) from store", ep.id)
|
||||
if err := d.storeDelete(ep); err != nil {
|
||||
logrus.Debugf("Failed to delete stale macvlan endpoint (%.7s) from store", ep.id)
|
||||
}
|
||||
continue
|
||||
}
|
||||
n.endpoints[ep.id] = ep
|
||||
logrus.Debugf("Endpoint (%.7s) restored to network (%.7s)", ep.id, ep.nid)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// storeUpdate used to update persistent macvlan network records as they are created
|
||||
func (d *driver) storeUpdate(kvObject datastore.KVObject) error {
|
||||
if d.store == nil {
|
||||
logrus.Warnf("macvlan store not initialized. kv object %s is not added to the store", datastore.Key(kvObject.Key()...))
|
||||
return nil
|
||||
}
|
||||
if err := d.store.PutObjectAtomic(kvObject); err != nil {
|
||||
return fmt.Errorf("failed to update macvlan store for object type %T: %v", kvObject, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// storeDelete used to delete macvlan records from persistent cache as they are deleted
|
||||
func (d *driver) storeDelete(kvObject datastore.KVObject) error {
|
||||
if d.store == nil {
|
||||
logrus.Debugf("macvlan store not initialized. kv object %s is not deleted from store", datastore.Key(kvObject.Key()...))
|
||||
return nil
|
||||
}
|
||||
retry:
|
||||
if err := d.store.DeleteObjectAtomic(kvObject); err != nil {
|
||||
if err == datastore.ErrKeyModified {
|
||||
if err := d.store.GetObject(datastore.Key(kvObject.Key()...), kvObject); err != nil {
|
||||
return fmt.Errorf("could not update the kvobject to latest when trying to delete: %v", err)
|
||||
}
|
||||
goto retry
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (config *configuration) MarshalJSON() ([]byte, error) {
|
||||
nMap := make(map[string]interface{})
|
||||
nMap["ID"] = config.ID
|
||||
nMap["Mtu"] = config.Mtu
|
||||
nMap["Parent"] = config.Parent
|
||||
nMap["MacvlanMode"] = config.MacvlanMode
|
||||
nMap["Internal"] = config.Internal
|
||||
nMap["CreatedSubIface"] = config.CreatedSlaveLink
|
||||
if len(config.Ipv4Subnets) > 0 {
|
||||
iis, err := json.Marshal(config.Ipv4Subnets)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nMap["Ipv4Subnets"] = string(iis)
|
||||
}
|
||||
if len(config.Ipv6Subnets) > 0 {
|
||||
iis, err := json.Marshal(config.Ipv6Subnets)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nMap["Ipv6Subnets"] = string(iis)
|
||||
}
|
||||
|
||||
return json.Marshal(nMap)
|
||||
}
|
||||
|
||||
func (config *configuration) UnmarshalJSON(b []byte) error {
|
||||
var (
|
||||
err error
|
||||
nMap map[string]interface{}
|
||||
)
|
||||
|
||||
if err = json.Unmarshal(b, &nMap); err != nil {
|
||||
return err
|
||||
}
|
||||
config.ID = nMap["ID"].(string)
|
||||
config.Mtu = int(nMap["Mtu"].(float64))
|
||||
config.Parent = nMap["Parent"].(string)
|
||||
config.MacvlanMode = nMap["MacvlanMode"].(string)
|
||||
config.Internal = nMap["Internal"].(bool)
|
||||
config.CreatedSlaveLink = nMap["CreatedSubIface"].(bool)
|
||||
if v, ok := nMap["Ipv4Subnets"]; ok {
|
||||
if err := json.Unmarshal([]byte(v.(string)), &config.Ipv4Subnets); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if v, ok := nMap["Ipv6Subnets"]; ok {
|
||||
if err := json.Unmarshal([]byte(v.(string)), &config.Ipv6Subnets); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (config *configuration) Key() []string {
|
||||
return []string{macvlanNetworkPrefix, config.ID}
|
||||
}
|
||||
|
||||
func (config *configuration) KeyPrefix() []string {
|
||||
return []string{macvlanNetworkPrefix}
|
||||
}
|
||||
|
||||
func (config *configuration) Value() []byte {
|
||||
b, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func (config *configuration) SetValue(value []byte) error {
|
||||
return json.Unmarshal(value, config)
|
||||
}
|
||||
|
||||
func (config *configuration) Index() uint64 {
|
||||
return config.dbIndex
|
||||
}
|
||||
|
||||
func (config *configuration) SetIndex(index uint64) {
|
||||
config.dbIndex = index
|
||||
config.dbExists = true
|
||||
}
|
||||
|
||||
func (config *configuration) Exists() bool {
|
||||
return config.dbExists
|
||||
}
|
||||
|
||||
func (config *configuration) Skip() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (config *configuration) New() datastore.KVObject {
|
||||
return &configuration{}
|
||||
}
|
||||
|
||||
func (config *configuration) CopyTo(o datastore.KVObject) error {
|
||||
dstNcfg := o.(*configuration)
|
||||
*dstNcfg = *config
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (config *configuration) DataScope() string {
|
||||
return datastore.LocalScope
|
||||
}
|
||||
|
||||
func (ep *endpoint) MarshalJSON() ([]byte, error) {
|
||||
epMap := make(map[string]interface{})
|
||||
epMap["id"] = ep.id
|
||||
epMap["nid"] = ep.nid
|
||||
epMap["SrcName"] = ep.srcName
|
||||
if len(ep.mac) != 0 {
|
||||
epMap["MacAddress"] = ep.mac.String()
|
||||
}
|
||||
if ep.addr != nil {
|
||||
epMap["Addr"] = ep.addr.String()
|
||||
}
|
||||
if ep.addrv6 != nil {
|
||||
epMap["Addrv6"] = ep.addrv6.String()
|
||||
}
|
||||
return json.Marshal(epMap)
|
||||
}
|
||||
|
||||
func (ep *endpoint) UnmarshalJSON(b []byte) error {
|
||||
var (
|
||||
err error
|
||||
epMap map[string]interface{}
|
||||
)
|
||||
|
||||
if err = json.Unmarshal(b, &epMap); err != nil {
|
||||
return fmt.Errorf("Failed to unmarshal to macvlan endpoint: %v", err)
|
||||
}
|
||||
|
||||
if v, ok := epMap["MacAddress"]; ok {
|
||||
if ep.mac, err = net.ParseMAC(v.(string)); err != nil {
|
||||
return types.InternalErrorf("failed to decode macvlan endpoint MAC address (%s) after json unmarshal: %v", v.(string), err)
|
||||
}
|
||||
}
|
||||
if v, ok := epMap["Addr"]; ok {
|
||||
if ep.addr, err = types.ParseCIDR(v.(string)); err != nil {
|
||||
return types.InternalErrorf("failed to decode macvlan endpoint IPv4 address (%s) after json unmarshal: %v", v.(string), err)
|
||||
}
|
||||
}
|
||||
if v, ok := epMap["Addrv6"]; ok {
|
||||
if ep.addrv6, err = types.ParseCIDR(v.(string)); err != nil {
|
||||
return types.InternalErrorf("failed to decode macvlan endpoint IPv6 address (%s) after json unmarshal: %v", v.(string), err)
|
||||
}
|
||||
}
|
||||
ep.id = epMap["id"].(string)
|
||||
ep.nid = epMap["nid"].(string)
|
||||
ep.srcName = epMap["SrcName"].(string)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ep *endpoint) Key() []string {
|
||||
return []string{macvlanEndpointPrefix, ep.id}
|
||||
}
|
||||
|
||||
func (ep *endpoint) KeyPrefix() []string {
|
||||
return []string{macvlanEndpointPrefix}
|
||||
}
|
||||
|
||||
func (ep *endpoint) Value() []byte {
|
||||
b, err := json.Marshal(ep)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (ep *endpoint) SetValue(value []byte) error {
|
||||
return json.Unmarshal(value, ep)
|
||||
}
|
||||
|
||||
func (ep *endpoint) Index() uint64 {
|
||||
return ep.dbIndex
|
||||
}
|
||||
|
||||
func (ep *endpoint) SetIndex(index uint64) {
|
||||
ep.dbIndex = index
|
||||
ep.dbExists = true
|
||||
}
|
||||
|
||||
func (ep *endpoint) Exists() bool {
|
||||
return ep.dbExists
|
||||
}
|
||||
|
||||
func (ep *endpoint) Skip() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (ep *endpoint) New() datastore.KVObject {
|
||||
return &endpoint{}
|
||||
}
|
||||
|
||||
func (ep *endpoint) CopyTo(o datastore.KVObject) error {
|
||||
dstEp := o.(*endpoint)
|
||||
*dstEp = *ep
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ep *endpoint) DataScope() string {
|
||||
return datastore.LocalScope
|
||||
}
|
88
vendor/github.com/docker/libnetwork/drivers/macvlan/mvmanager/mvmanager.go
generated
vendored
88
vendor/github.com/docker/libnetwork/drivers/macvlan/mvmanager/mvmanager.go
generated
vendored
|
@ -1,88 +0,0 @@
|
|||
package mvmanager
|
||||
|
||||
import (
|
||||
"github.com/docker/libnetwork/datastore"
|
||||
"github.com/docker/libnetwork/discoverapi"
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
const networkType = "macvlan"
|
||||
|
||||
type driver struct{}
|
||||
|
||||
// Init registers a new instance of macvlan manager driver
|
||||
func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
||||
c := driverapi.Capability{
|
||||
DataScope: datastore.LocalScope,
|
||||
ConnectivityScope: datastore.GlobalScope,
|
||||
}
|
||||
return dc.RegisterDriver(networkType, &driver{}, c)
|
||||
}
|
||||
|
||||
func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {
|
||||
return nil, types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) NetworkFree(id string) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
|
||||
}
|
||||
|
||||
func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (d *driver) DeleteNetwork(nid string) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) DeleteEndpoint(nid, eid string) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) {
|
||||
return nil, types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) Leave(nid, eid string) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) Type() string {
|
||||
return networkType
|
||||
}
|
||||
|
||||
func (d *driver) IsBuiltIn() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
105
vendor/github.com/docker/libnetwork/drivers/null/null.go
generated
vendored
105
vendor/github.com/docker/libnetwork/drivers/null/null.go
generated
vendored
|
@ -1,105 +0,0 @@
|
|||
package null
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/docker/libnetwork/datastore"
|
||||
"github.com/docker/libnetwork/discoverapi"
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
const networkType = "null"
|
||||
|
||||
type driver struct {
|
||||
network string
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// Init registers a new instance of null driver
|
||||
func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
||||
c := driverapi.Capability{
|
||||
DataScope: datastore.LocalScope,
|
||||
}
|
||||
return dc.RegisterDriver(networkType, &driver{}, c)
|
||||
}
|
||||
|
||||
func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {
|
||||
return nil, types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) NetworkFree(id string) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
|
||||
}
|
||||
|
||||
func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
if d.network != "" {
|
||||
return types.ForbiddenErrorf("only one instance of \"%s\" network is allowed", networkType)
|
||||
}
|
||||
|
||||
d.network = id
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) DeleteNetwork(nid string) error {
|
||||
return types.ForbiddenErrorf("network of type \"%s\" cannot be deleted", networkType)
|
||||
}
|
||||
|
||||
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) DeleteEndpoint(nid, eid string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) {
|
||||
return make(map[string]interface{}, 0), nil
|
||||
}
|
||||
|
||||
// Join method is invoked when a Sandbox is attached to an endpoint.
|
||||
func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Leave method is invoked when a Sandbox detaches from an endpoint.
|
||||
func (d *driver) Leave(nid, eid string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) Type() string {
|
||||
return networkType
|
||||
}
|
||||
|
||||
func (d *driver) IsBuiltIn() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster
|
||||
func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster
|
||||
func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||
return nil
|
||||
}
|
646
vendor/github.com/docker/libnetwork/drivers/overlay/encryption.go
generated
vendored
646
vendor/github.com/docker/libnetwork/drivers/overlay/encryption.go
generated
vendored
|
@ -1,646 +0,0 @@
|
|||
package overlay
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"hash/fnv"
|
||||
"net"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"strconv"
|
||||
|
||||
"github.com/docker/libnetwork/drivers/overlay/overlayutils"
|
||||
"github.com/docker/libnetwork/iptables"
|
||||
"github.com/docker/libnetwork/ns"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
const (
|
||||
r = 0xD0C4E3
|
||||
pktExpansion = 26 // SPI(4) + SeqN(4) + IV(8) + PadLength(1) + NextHeader(1) + ICV(8)
|
||||
)
|
||||
|
||||
const (
|
||||
forward = iota + 1
|
||||
reverse
|
||||
bidir
|
||||
)
|
||||
|
||||
var spMark = netlink.XfrmMark{Value: uint32(r), Mask: 0xffffffff}
|
||||
|
||||
type key struct {
|
||||
value []byte
|
||||
tag uint32
|
||||
}
|
||||
|
||||
func (k *key) String() string {
|
||||
if k != nil {
|
||||
return fmt.Sprintf("(key: %s, tag: 0x%x)", hex.EncodeToString(k.value)[0:5], k.tag)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type spi struct {
|
||||
forward int
|
||||
reverse int
|
||||
}
|
||||
|
||||
func (s *spi) String() string {
|
||||
return fmt.Sprintf("SPI(FWD: 0x%x, REV: 0x%x)", uint32(s.forward), uint32(s.reverse))
|
||||
}
|
||||
|
||||
type encrMap struct {
|
||||
nodes map[string][]*spi
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
func (e *encrMap) String() string {
|
||||
e.Lock()
|
||||
defer e.Unlock()
|
||||
b := new(bytes.Buffer)
|
||||
for k, v := range e.nodes {
|
||||
b.WriteString("\n")
|
||||
b.WriteString(k)
|
||||
b.WriteString(":")
|
||||
b.WriteString("[")
|
||||
for _, s := range v {
|
||||
b.WriteString(s.String())
|
||||
b.WriteString(",")
|
||||
}
|
||||
b.WriteString("]")
|
||||
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func (d *driver) checkEncryption(nid string, rIP net.IP, vxlanID uint32, isLocal, add bool) error {
|
||||
logrus.Debugf("checkEncryption(%.7s, %v, %d, %t)", nid, rIP, vxlanID, isLocal)
|
||||
|
||||
n := d.network(nid)
|
||||
if n == nil || !n.secure {
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(d.keys) == 0 {
|
||||
return types.ForbiddenErrorf("encryption key is not present")
|
||||
}
|
||||
|
||||
lIP := net.ParseIP(d.bindAddress)
|
||||
aIP := net.ParseIP(d.advertiseAddress)
|
||||
nodes := map[string]net.IP{}
|
||||
|
||||
switch {
|
||||
case isLocal:
|
||||
if err := d.peerDbNetworkWalk(nid, func(pKey *peerKey, pEntry *peerEntry) bool {
|
||||
if !aIP.Equal(pEntry.vtep) {
|
||||
nodes[pEntry.vtep.String()] = pEntry.vtep
|
||||
}
|
||||
return false
|
||||
}); err != nil {
|
||||
logrus.Warnf("Failed to retrieve list of participating nodes in overlay network %.5s: %v", nid, err)
|
||||
}
|
||||
default:
|
||||
if len(d.network(nid).endpoints) > 0 {
|
||||
nodes[rIP.String()] = rIP
|
||||
}
|
||||
}
|
||||
|
||||
logrus.Debugf("List of nodes: %s", nodes)
|
||||
|
||||
if add {
|
||||
for _, rIP := range nodes {
|
||||
if err := setupEncryption(lIP, aIP, rIP, vxlanID, d.secMap, d.keys); err != nil {
|
||||
logrus.Warnf("Failed to program network encryption between %s and %s: %v", lIP, rIP, err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if len(nodes) == 0 {
|
||||
if err := removeEncryption(lIP, rIP, d.secMap); err != nil {
|
||||
logrus.Warnf("Failed to remove network encryption between %s and %s: %v", lIP, rIP, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setupEncryption(localIP, advIP, remoteIP net.IP, vni uint32, em *encrMap, keys []*key) error {
|
||||
logrus.Debugf("Programming encryption for vxlan %d between %s and %s", vni, localIP, remoteIP)
|
||||
rIPs := remoteIP.String()
|
||||
|
||||
indices := make([]*spi, 0, len(keys))
|
||||
|
||||
err := programMangle(vni, true)
|
||||
if err != nil {
|
||||
logrus.Warn(err)
|
||||
}
|
||||
|
||||
err = programInput(vni, true)
|
||||
if err != nil {
|
||||
logrus.Warn(err)
|
||||
}
|
||||
|
||||
for i, k := range keys {
|
||||
spis := &spi{buildSPI(advIP, remoteIP, k.tag), buildSPI(remoteIP, advIP, k.tag)}
|
||||
dir := reverse
|
||||
if i == 0 {
|
||||
dir = bidir
|
||||
}
|
||||
fSA, rSA, err := programSA(localIP, remoteIP, spis, k, dir, true)
|
||||
if err != nil {
|
||||
logrus.Warn(err)
|
||||
}
|
||||
indices = append(indices, spis)
|
||||
if i != 0 {
|
||||
continue
|
||||
}
|
||||
err = programSP(fSA, rSA, true)
|
||||
if err != nil {
|
||||
logrus.Warn(err)
|
||||
}
|
||||
}
|
||||
|
||||
em.Lock()
|
||||
em.nodes[rIPs] = indices
|
||||
em.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func removeEncryption(localIP, remoteIP net.IP, em *encrMap) error {
|
||||
em.Lock()
|
||||
indices, ok := em.nodes[remoteIP.String()]
|
||||
em.Unlock()
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
for i, idxs := range indices {
|
||||
dir := reverse
|
||||
if i == 0 {
|
||||
dir = bidir
|
||||
}
|
||||
fSA, rSA, err := programSA(localIP, remoteIP, idxs, nil, dir, false)
|
||||
if err != nil {
|
||||
logrus.Warn(err)
|
||||
}
|
||||
if i != 0 {
|
||||
continue
|
||||
}
|
||||
err = programSP(fSA, rSA, false)
|
||||
if err != nil {
|
||||
logrus.Warn(err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func programMangle(vni uint32, add bool) (err error) {
|
||||
var (
|
||||
p = strconv.FormatUint(uint64(overlayutils.VXLANUDPPort()), 10)
|
||||
c = fmt.Sprintf("0>>22&0x3C@12&0xFFFFFF00=%d", int(vni)<<8)
|
||||
m = strconv.FormatUint(uint64(r), 10)
|
||||
chain = "OUTPUT"
|
||||
rule = []string{"-p", "udp", "--dport", p, "-m", "u32", "--u32", c, "-j", "MARK", "--set-mark", m}
|
||||
a = "-A"
|
||||
action = "install"
|
||||
)
|
||||
|
||||
// TODO IPv6 support
|
||||
iptable := iptables.GetIptable(iptables.IPv4)
|
||||
|
||||
if add == iptable.Exists(iptables.Mangle, chain, rule...) {
|
||||
return
|
||||
}
|
||||
|
||||
if !add {
|
||||
a = "-D"
|
||||
action = "remove"
|
||||
}
|
||||
|
||||
if err = iptable.RawCombinedOutput(append([]string{"-t", string(iptables.Mangle), a, chain}, rule...)...); err != nil {
|
||||
logrus.Warnf("could not %s mangle rule: %v", action, err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func programInput(vni uint32, add bool) (err error) {
|
||||
var (
|
||||
port = strconv.FormatUint(uint64(overlayutils.VXLANUDPPort()), 10)
|
||||
vniMatch = fmt.Sprintf("0>>22&0x3C@12&0xFFFFFF00=%d", int(vni)<<8)
|
||||
plainVxlan = []string{"-p", "udp", "--dport", port, "-m", "u32", "--u32", vniMatch, "-j"}
|
||||
ipsecVxlan = append([]string{"-m", "policy", "--dir", "in", "--pol", "ipsec"}, plainVxlan...)
|
||||
block = append(plainVxlan, "DROP")
|
||||
accept = append(ipsecVxlan, "ACCEPT")
|
||||
chain = "INPUT"
|
||||
action = iptables.Append
|
||||
msg = "add"
|
||||
)
|
||||
|
||||
// TODO IPv6 support
|
||||
iptable := iptables.GetIptable(iptables.IPv4)
|
||||
|
||||
if !add {
|
||||
action = iptables.Delete
|
||||
msg = "remove"
|
||||
}
|
||||
|
||||
if err := iptable.ProgramRule(iptables.Filter, chain, action, accept); err != nil {
|
||||
logrus.Errorf("could not %s input rule: %v. Please do it manually.", msg, err)
|
||||
}
|
||||
|
||||
if err := iptable.ProgramRule(iptables.Filter, chain, action, block); err != nil {
|
||||
logrus.Errorf("could not %s input rule: %v. Please do it manually.", msg, err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func programSA(localIP, remoteIP net.IP, spi *spi, k *key, dir int, add bool) (fSA *netlink.XfrmState, rSA *netlink.XfrmState, err error) {
|
||||
var (
|
||||
action = "Removing"
|
||||
xfrmProgram = ns.NlHandle().XfrmStateDel
|
||||
)
|
||||
|
||||
if add {
|
||||
action = "Adding"
|
||||
xfrmProgram = ns.NlHandle().XfrmStateAdd
|
||||
}
|
||||
|
||||
if dir&reverse > 0 {
|
||||
rSA = &netlink.XfrmState{
|
||||
Src: remoteIP,
|
||||
Dst: localIP,
|
||||
Proto: netlink.XFRM_PROTO_ESP,
|
||||
Spi: spi.reverse,
|
||||
Mode: netlink.XFRM_MODE_TRANSPORT,
|
||||
Reqid: r,
|
||||
}
|
||||
if add {
|
||||
rSA.Aead = buildAeadAlgo(k, spi.reverse)
|
||||
}
|
||||
|
||||
exists, err := saExists(rSA)
|
||||
if err != nil {
|
||||
exists = !add
|
||||
}
|
||||
|
||||
if add != exists {
|
||||
logrus.Debugf("%s: rSA{%s}", action, rSA)
|
||||
if err := xfrmProgram(rSA); err != nil {
|
||||
logrus.Warnf("Failed %s rSA{%s}: %v", action, rSA, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if dir&forward > 0 {
|
||||
fSA = &netlink.XfrmState{
|
||||
Src: localIP,
|
||||
Dst: remoteIP,
|
||||
Proto: netlink.XFRM_PROTO_ESP,
|
||||
Spi: spi.forward,
|
||||
Mode: netlink.XFRM_MODE_TRANSPORT,
|
||||
Reqid: r,
|
||||
}
|
||||
if add {
|
||||
fSA.Aead = buildAeadAlgo(k, spi.forward)
|
||||
}
|
||||
|
||||
exists, err := saExists(fSA)
|
||||
if err != nil {
|
||||
exists = !add
|
||||
}
|
||||
|
||||
if add != exists {
|
||||
logrus.Debugf("%s fSA{%s}", action, fSA)
|
||||
if err := xfrmProgram(fSA); err != nil {
|
||||
logrus.Warnf("Failed %s fSA{%s}: %v.", action, fSA, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func programSP(fSA *netlink.XfrmState, rSA *netlink.XfrmState, add bool) error {
|
||||
action := "Removing"
|
||||
xfrmProgram := ns.NlHandle().XfrmPolicyDel
|
||||
if add {
|
||||
action = "Adding"
|
||||
xfrmProgram = ns.NlHandle().XfrmPolicyAdd
|
||||
}
|
||||
|
||||
// Create a congruent cidr
|
||||
s := types.GetMinimalIP(fSA.Src)
|
||||
d := types.GetMinimalIP(fSA.Dst)
|
||||
fullMask := net.CIDRMask(8*len(s), 8*len(s))
|
||||
|
||||
fPol := &netlink.XfrmPolicy{
|
||||
Src: &net.IPNet{IP: s, Mask: fullMask},
|
||||
Dst: &net.IPNet{IP: d, Mask: fullMask},
|
||||
Dir: netlink.XFRM_DIR_OUT,
|
||||
Proto: 17,
|
||||
DstPort: 4789,
|
||||
Mark: &spMark,
|
||||
Tmpls: []netlink.XfrmPolicyTmpl{
|
||||
{
|
||||
Src: fSA.Src,
|
||||
Dst: fSA.Dst,
|
||||
Proto: netlink.XFRM_PROTO_ESP,
|
||||
Mode: netlink.XFRM_MODE_TRANSPORT,
|
||||
Spi: fSA.Spi,
|
||||
Reqid: r,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
exists, err := spExists(fPol)
|
||||
if err != nil {
|
||||
exists = !add
|
||||
}
|
||||
|
||||
if add != exists {
|
||||
logrus.Debugf("%s fSP{%s}", action, fPol)
|
||||
if err := xfrmProgram(fPol); err != nil {
|
||||
logrus.Warnf("%s fSP{%s}: %v", action, fPol, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func saExists(sa *netlink.XfrmState) (bool, error) {
|
||||
_, err := ns.NlHandle().XfrmStateGet(sa)
|
||||
switch err {
|
||||
case nil:
|
||||
return true, nil
|
||||
case syscall.ESRCH:
|
||||
return false, nil
|
||||
default:
|
||||
err = fmt.Errorf("Error while checking for SA existence: %v", err)
|
||||
logrus.Warn(err)
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
func spExists(sp *netlink.XfrmPolicy) (bool, error) {
|
||||
_, err := ns.NlHandle().XfrmPolicyGet(sp)
|
||||
switch err {
|
||||
case nil:
|
||||
return true, nil
|
||||
case syscall.ENOENT:
|
||||
return false, nil
|
||||
default:
|
||||
err = fmt.Errorf("Error while checking for SP existence: %v", err)
|
||||
logrus.Warn(err)
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
func buildSPI(src, dst net.IP, st uint32) int {
|
||||
b := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(b, st)
|
||||
h := fnv.New32a()
|
||||
h.Write(src)
|
||||
h.Write(b)
|
||||
h.Write(dst)
|
||||
return int(binary.BigEndian.Uint32(h.Sum(nil)))
|
||||
}
|
||||
|
||||
func buildAeadAlgo(k *key, s int) *netlink.XfrmStateAlgo {
|
||||
salt := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(salt, uint32(s))
|
||||
return &netlink.XfrmStateAlgo{
|
||||
Name: "rfc4106(gcm(aes))",
|
||||
Key: append(k.value, salt...),
|
||||
ICVLen: 64,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *driver) secMapWalk(f func(string, []*spi) ([]*spi, bool)) error {
|
||||
d.secMap.Lock()
|
||||
for node, indices := range d.secMap.nodes {
|
||||
idxs, stop := f(node, indices)
|
||||
if idxs != nil {
|
||||
d.secMap.nodes[node] = idxs
|
||||
}
|
||||
if stop {
|
||||
break
|
||||
}
|
||||
}
|
||||
d.secMap.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) setKeys(keys []*key) error {
|
||||
// Remove any stale policy, state
|
||||
clearEncryptionStates()
|
||||
// Accept the encryption keys and clear any stale encryption map
|
||||
d.Lock()
|
||||
d.keys = keys
|
||||
d.secMap = &encrMap{nodes: map[string][]*spi{}}
|
||||
d.Unlock()
|
||||
logrus.Debugf("Initial encryption keys: %v", keys)
|
||||
return nil
|
||||
}
|
||||
|
||||
// updateKeys allows to add a new key and/or change the primary key and/or prune an existing key
|
||||
// The primary key is the key used in transmission and will go in first position in the list.
|
||||
func (d *driver) updateKeys(newKey, primary, pruneKey *key) error {
|
||||
logrus.Debugf("Updating Keys. New: %v, Primary: %v, Pruned: %v", newKey, primary, pruneKey)
|
||||
|
||||
logrus.Debugf("Current: %v", d.keys)
|
||||
|
||||
var (
|
||||
newIdx = -1
|
||||
priIdx = -1
|
||||
delIdx = -1
|
||||
lIP = net.ParseIP(d.bindAddress)
|
||||
aIP = net.ParseIP(d.advertiseAddress)
|
||||
)
|
||||
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
// add new
|
||||
if newKey != nil {
|
||||
d.keys = append(d.keys, newKey)
|
||||
newIdx += len(d.keys)
|
||||
}
|
||||
for i, k := range d.keys {
|
||||
if primary != nil && k.tag == primary.tag {
|
||||
priIdx = i
|
||||
}
|
||||
if pruneKey != nil && k.tag == pruneKey.tag {
|
||||
delIdx = i
|
||||
}
|
||||
}
|
||||
|
||||
if (newKey != nil && newIdx == -1) ||
|
||||
(primary != nil && priIdx == -1) ||
|
||||
(pruneKey != nil && delIdx == -1) {
|
||||
return types.BadRequestErrorf("cannot find proper key indices while processing key update:"+
|
||||
"(newIdx,priIdx,delIdx):(%d, %d, %d)", newIdx, priIdx, delIdx)
|
||||
}
|
||||
|
||||
if priIdx != -1 && priIdx == delIdx {
|
||||
return types.BadRequestErrorf("attempting to both make a key (index %d) primary and delete it", priIdx)
|
||||
}
|
||||
|
||||
d.secMapWalk(func(rIPs string, spis []*spi) ([]*spi, bool) {
|
||||
rIP := net.ParseIP(rIPs)
|
||||
return updateNodeKey(lIP, aIP, rIP, spis, d.keys, newIdx, priIdx, delIdx), false
|
||||
})
|
||||
|
||||
// swap primary
|
||||
if priIdx != -1 {
|
||||
d.keys[0], d.keys[priIdx] = d.keys[priIdx], d.keys[0]
|
||||
}
|
||||
// prune
|
||||
if delIdx != -1 {
|
||||
if delIdx == 0 {
|
||||
delIdx = priIdx
|
||||
}
|
||||
d.keys = append(d.keys[:delIdx], d.keys[delIdx+1:]...)
|
||||
}
|
||||
|
||||
logrus.Debugf("Updated: %v", d.keys)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
/********************************************************
|
||||
* Steady state: rSA0, rSA1, rSA2, fSA1, fSP1
|
||||
* Rotation --> -rSA0, +rSA3, +fSA2, +fSP2/-fSP1, -fSA1
|
||||
* Steady state: rSA1, rSA2, rSA3, fSA2, fSP2
|
||||
*********************************************************/
|
||||
|
||||
// Spis and keys are sorted in such away the one in position 0 is the primary
|
||||
func updateNodeKey(lIP, aIP, rIP net.IP, idxs []*spi, curKeys []*key, newIdx, priIdx, delIdx int) []*spi {
|
||||
logrus.Debugf("Updating keys for node: %s (%d,%d,%d)", rIP, newIdx, priIdx, delIdx)
|
||||
|
||||
spis := idxs
|
||||
logrus.Debugf("Current: %v", spis)
|
||||
|
||||
// add new
|
||||
if newIdx != -1 {
|
||||
spis = append(spis, &spi{
|
||||
forward: buildSPI(aIP, rIP, curKeys[newIdx].tag),
|
||||
reverse: buildSPI(rIP, aIP, curKeys[newIdx].tag),
|
||||
})
|
||||
}
|
||||
|
||||
if delIdx != -1 {
|
||||
// -rSA0
|
||||
programSA(lIP, rIP, spis[delIdx], nil, reverse, false)
|
||||
}
|
||||
|
||||
if newIdx > -1 {
|
||||
// +rSA2
|
||||
programSA(lIP, rIP, spis[newIdx], curKeys[newIdx], reverse, true)
|
||||
}
|
||||
|
||||
if priIdx > 0 {
|
||||
// +fSA2
|
||||
fSA2, _, _ := programSA(lIP, rIP, spis[priIdx], curKeys[priIdx], forward, true)
|
||||
|
||||
// +fSP2, -fSP1
|
||||
s := types.GetMinimalIP(fSA2.Src)
|
||||
d := types.GetMinimalIP(fSA2.Dst)
|
||||
fullMask := net.CIDRMask(8*len(s), 8*len(s))
|
||||
|
||||
fSP1 := &netlink.XfrmPolicy{
|
||||
Src: &net.IPNet{IP: s, Mask: fullMask},
|
||||
Dst: &net.IPNet{IP: d, Mask: fullMask},
|
||||
Dir: netlink.XFRM_DIR_OUT,
|
||||
Proto: 17,
|
||||
DstPort: 4789,
|
||||
Mark: &spMark,
|
||||
Tmpls: []netlink.XfrmPolicyTmpl{
|
||||
{
|
||||
Src: fSA2.Src,
|
||||
Dst: fSA2.Dst,
|
||||
Proto: netlink.XFRM_PROTO_ESP,
|
||||
Mode: netlink.XFRM_MODE_TRANSPORT,
|
||||
Spi: fSA2.Spi,
|
||||
Reqid: r,
|
||||
},
|
||||
},
|
||||
}
|
||||
logrus.Debugf("Updating fSP{%s}", fSP1)
|
||||
if err := ns.NlHandle().XfrmPolicyUpdate(fSP1); err != nil {
|
||||
logrus.Warnf("Failed to update fSP{%s}: %v", fSP1, err)
|
||||
}
|
||||
|
||||
// -fSA1
|
||||
programSA(lIP, rIP, spis[0], nil, forward, false)
|
||||
}
|
||||
|
||||
// swap
|
||||
if priIdx > 0 {
|
||||
swp := spis[0]
|
||||
spis[0] = spis[priIdx]
|
||||
spis[priIdx] = swp
|
||||
}
|
||||
// prune
|
||||
if delIdx != -1 {
|
||||
if delIdx == 0 {
|
||||
delIdx = priIdx
|
||||
}
|
||||
spis = append(spis[:delIdx], spis[delIdx+1:]...)
|
||||
}
|
||||
|
||||
logrus.Debugf("Updated: %v", spis)
|
||||
|
||||
return spis
|
||||
}
|
||||
|
||||
func (n *network) maxMTU() int {
|
||||
mtu := 1500
|
||||
if n.mtu != 0 {
|
||||
mtu = n.mtu
|
||||
}
|
||||
mtu -= vxlanEncap
|
||||
if n.secure {
|
||||
// In case of encryption account for the
|
||||
// esp packet expansion and padding
|
||||
mtu -= pktExpansion
|
||||
mtu -= (mtu % 4)
|
||||
}
|
||||
return mtu
|
||||
}
|
||||
|
||||
func clearEncryptionStates() {
|
||||
nlh := ns.NlHandle()
|
||||
spList, err := nlh.XfrmPolicyList(netlink.FAMILY_ALL)
|
||||
if err != nil {
|
||||
logrus.Warnf("Failed to retrieve SP list for cleanup: %v", err)
|
||||
}
|
||||
saList, err := nlh.XfrmStateList(netlink.FAMILY_ALL)
|
||||
if err != nil {
|
||||
logrus.Warnf("Failed to retrieve SA list for cleanup: %v", err)
|
||||
}
|
||||
for _, sp := range spList {
|
||||
if sp.Mark != nil && sp.Mark.Value == spMark.Value {
|
||||
if err := nlh.XfrmPolicyDel(&sp); err != nil {
|
||||
logrus.Warnf("Failed to delete stale SP %s: %v", sp, err)
|
||||
continue
|
||||
}
|
||||
logrus.Debugf("Removed stale SP: %s", sp)
|
||||
}
|
||||
}
|
||||
for _, sa := range saList {
|
||||
if sa.Reqid == r {
|
||||
if err := nlh.XfrmStateDel(&sa); err != nil {
|
||||
logrus.Warnf("Failed to delete stale SA %s: %v", sa, err)
|
||||
continue
|
||||
}
|
||||
logrus.Debugf("Removed stale SA: %s", sa)
|
||||
}
|
||||
}
|
||||
}
|
150
vendor/github.com/docker/libnetwork/drivers/overlay/filter.go
generated
vendored
150
vendor/github.com/docker/libnetwork/drivers/overlay/filter.go
generated
vendored
|
@ -1,150 +0,0 @@
|
|||
package overlay
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/docker/libnetwork/iptables"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const globalChain = "DOCKER-OVERLAY"
|
||||
|
||||
var filterOnce sync.Once
|
||||
|
||||
var filterChan = make(chan struct{}, 1)
|
||||
|
||||
func filterWait() func() {
|
||||
filterChan <- struct{}{}
|
||||
return func() { <-filterChan }
|
||||
}
|
||||
|
||||
func chainExists(cname string) bool {
|
||||
// TODO IPv6 support
|
||||
iptable := iptables.GetIptable(iptables.IPv4)
|
||||
if _, err := iptable.Raw("-L", cname); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func setupGlobalChain() {
|
||||
// TODO IPv6 support
|
||||
iptable := iptables.GetIptable(iptables.IPv4)
|
||||
// Because of an ungraceful shutdown, chain could already be present
|
||||
if !chainExists(globalChain) {
|
||||
if err := iptable.RawCombinedOutput("-N", globalChain); err != nil {
|
||||
logrus.Errorf("could not create global overlay chain: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if !iptable.Exists(iptables.Filter, globalChain, "-j", "RETURN") {
|
||||
if err := iptable.RawCombinedOutput("-A", globalChain, "-j", "RETURN"); err != nil {
|
||||
logrus.Errorf("could not install default return chain in the overlay global chain: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setNetworkChain(cname string, remove bool) error {
|
||||
// TODO IPv6 support
|
||||
iptable := iptables.GetIptable(iptables.IPv4)
|
||||
// Initialize the onetime global overlay chain
|
||||
filterOnce.Do(setupGlobalChain)
|
||||
|
||||
exists := chainExists(cname)
|
||||
|
||||
opt := "-N"
|
||||
// In case of remove, make sure to flush the rules in the chain
|
||||
if remove && exists {
|
||||
if err := iptable.RawCombinedOutput("-F", cname); err != nil {
|
||||
return fmt.Errorf("failed to flush overlay network chain %s rules: %v", cname, err)
|
||||
}
|
||||
opt = "-X"
|
||||
}
|
||||
|
||||
if (!remove && !exists) || (remove && exists) {
|
||||
if err := iptable.RawCombinedOutput(opt, cname); err != nil {
|
||||
return fmt.Errorf("failed network chain operation %q for chain %s: %v", opt, cname, err)
|
||||
}
|
||||
}
|
||||
|
||||
if !remove {
|
||||
if !iptable.Exists(iptables.Filter, cname, "-j", "DROP") {
|
||||
if err := iptable.RawCombinedOutput("-A", cname, "-j", "DROP"); err != nil {
|
||||
return fmt.Errorf("failed adding default drop rule to overlay network chain %s: %v", cname, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func addNetworkChain(cname string) error {
|
||||
defer filterWait()()
|
||||
|
||||
return setNetworkChain(cname, false)
|
||||
}
|
||||
|
||||
func removeNetworkChain(cname string) error {
|
||||
defer filterWait()()
|
||||
|
||||
return setNetworkChain(cname, true)
|
||||
}
|
||||
|
||||
func setFilters(cname, brName string, remove bool) error {
|
||||
opt := "-I"
|
||||
if remove {
|
||||
opt = "-D"
|
||||
}
|
||||
// TODO IPv6 support
|
||||
iptable := iptables.GetIptable(iptables.IPv4)
|
||||
|
||||
// Every time we set filters for a new subnet make sure to move the global overlay hook to the top of the both the OUTPUT and forward chains
|
||||
if !remove {
|
||||
for _, chain := range []string{"OUTPUT", "FORWARD"} {
|
||||
exists := iptable.Exists(iptables.Filter, chain, "-j", globalChain)
|
||||
if exists {
|
||||
if err := iptable.RawCombinedOutput("-D", chain, "-j", globalChain); err != nil {
|
||||
return fmt.Errorf("failed to delete overlay hook in chain %s while moving the hook: %v", chain, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := iptable.RawCombinedOutput("-I", chain, "-j", globalChain); err != nil {
|
||||
return fmt.Errorf("failed to insert overlay hook in chain %s: %v", chain, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Insert/Delete the rule to jump to per-bridge chain
|
||||
exists := iptable.Exists(iptables.Filter, globalChain, "-o", brName, "-j", cname)
|
||||
if (!remove && !exists) || (remove && exists) {
|
||||
if err := iptable.RawCombinedOutput(opt, globalChain, "-o", brName, "-j", cname); err != nil {
|
||||
return fmt.Errorf("failed to add per-bridge filter rule for bridge %s, network chain %s: %v", brName, cname, err)
|
||||
}
|
||||
}
|
||||
|
||||
exists = iptable.Exists(iptables.Filter, cname, "-i", brName, "-j", "ACCEPT")
|
||||
if (!remove && exists) || (remove && !exists) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := iptable.RawCombinedOutput(opt, cname, "-i", brName, "-j", "ACCEPT"); err != nil {
|
||||
return fmt.Errorf("failed to add overlay filter rile for network chain %s, bridge %s: %v", cname, brName, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func addFilters(cname, brName string) error {
|
||||
defer filterWait()()
|
||||
|
||||
return setFilters(cname, brName, false)
|
||||
}
|
||||
|
||||
func removeFilters(cname, brName string) error {
|
||||
defer filterWait()()
|
||||
|
||||
return setFilters(cname, brName, true)
|
||||
}
|
232
vendor/github.com/docker/libnetwork/drivers/overlay/joinleave.go
generated
vendored
232
vendor/github.com/docker/libnetwork/drivers/overlay/joinleave.go
generated
vendored
|
@ -1,232 +0,0 @@
|
|||
package overlay
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"syscall"
|
||||
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/ns"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Join method is invoked when a Sandbox is attached to an endpoint.
|
||||
func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
||||
if err := validateID(nid, eid); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n := d.network(nid)
|
||||
if n == nil {
|
||||
return fmt.Errorf("could not find network with id %s", nid)
|
||||
}
|
||||
|
||||
ep := n.endpoint(eid)
|
||||
if ep == nil {
|
||||
return fmt.Errorf("could not find endpoint with id %s", eid)
|
||||
}
|
||||
|
||||
if n.secure && len(d.keys) == 0 {
|
||||
return fmt.Errorf("cannot join secure network: encryption keys not present")
|
||||
}
|
||||
|
||||
nlh := ns.NlHandle()
|
||||
|
||||
if n.secure && !nlh.SupportsNetlinkFamily(syscall.NETLINK_XFRM) {
|
||||
return fmt.Errorf("cannot join secure network: required modules to install IPSEC rules are missing on host")
|
||||
}
|
||||
|
||||
s := n.getSubnetforIP(ep.addr)
|
||||
if s == nil {
|
||||
return fmt.Errorf("could not find subnet for endpoint %s", eid)
|
||||
}
|
||||
|
||||
if err := n.obtainVxlanID(s); err != nil {
|
||||
return fmt.Errorf("couldn't get vxlan id for %q: %v", s.subnetIP.String(), err)
|
||||
}
|
||||
|
||||
if err := n.joinSandbox(s, false, true); err != nil {
|
||||
return fmt.Errorf("network sandbox join failed: %v", err)
|
||||
}
|
||||
|
||||
sbox := n.sandbox()
|
||||
|
||||
overlayIfName, containerIfName, err := createVethPair()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ep.ifName = containerIfName
|
||||
|
||||
if err = d.writeEndpointToStore(ep); err != nil {
|
||||
return fmt.Errorf("failed to update overlay endpoint %.7s to local data store: %v", ep.id, err)
|
||||
}
|
||||
|
||||
// Set the container interface and its peer MTU to 1450 to allow
|
||||
// for 50 bytes vxlan encap (inner eth header(14) + outer IP(20) +
|
||||
// outer UDP(8) + vxlan header(8))
|
||||
mtu := n.maxMTU()
|
||||
|
||||
veth, err := nlh.LinkByName(overlayIfName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cound not find link by name %s: %v", overlayIfName, err)
|
||||
}
|
||||
err = nlh.LinkSetMTU(veth, mtu)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = sbox.AddInterface(overlayIfName, "veth",
|
||||
sbox.InterfaceOptions().Master(s.brName)); err != nil {
|
||||
return fmt.Errorf("could not add veth pair inside the network sandbox: %v", err)
|
||||
}
|
||||
|
||||
veth, err = nlh.LinkByName(containerIfName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not find link by name %s: %v", containerIfName, err)
|
||||
}
|
||||
err = nlh.LinkSetMTU(veth, mtu)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = nlh.LinkSetHardwareAddr(veth, ep.mac); err != nil {
|
||||
return fmt.Errorf("could not set mac address (%v) to the container interface: %v", ep.mac, err)
|
||||
}
|
||||
|
||||
for _, sub := range n.subnets {
|
||||
if sub == s {
|
||||
continue
|
||||
}
|
||||
if err = jinfo.AddStaticRoute(sub.subnetIP, types.NEXTHOP, s.gwIP.IP); err != nil {
|
||||
logrus.Errorf("Adding subnet %s static route in network %q failed\n", s.subnetIP, n.id)
|
||||
}
|
||||
}
|
||||
|
||||
if iNames := jinfo.InterfaceName(); iNames != nil {
|
||||
err = iNames.SetNames(containerIfName, "eth")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
d.peerAdd(nid, eid, ep.addr.IP, ep.addr.Mask, ep.mac, net.ParseIP(d.advertiseAddress), false, false, true)
|
||||
|
||||
if err = d.checkEncryption(nid, nil, n.vxlanID(s), true, true); err != nil {
|
||||
logrus.Warn(err)
|
||||
}
|
||||
|
||||
buf, err := proto.Marshal(&PeerRecord{
|
||||
EndpointIP: ep.addr.String(),
|
||||
EndpointMAC: ep.mac.String(),
|
||||
TunnelEndpointIP: d.advertiseAddress,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := jinfo.AddTableEntry(ovPeerTable, eid, buf); err != nil {
|
||||
logrus.Errorf("overlay: Failed adding table entry to joininfo: %v", err)
|
||||
}
|
||||
|
||||
d.pushLocalEndpointEvent("join", nid, eid)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
|
||||
if tablename != ovPeerTable {
|
||||
logrus.Errorf("DecodeTableEntry: unexpected table name %s", tablename)
|
||||
return "", nil
|
||||
}
|
||||
|
||||
var peer PeerRecord
|
||||
if err := proto.Unmarshal(value, &peer); err != nil {
|
||||
logrus.Errorf("DecodeTableEntry: failed to unmarshal peer record for key %s: %v", key, err)
|
||||
return "", nil
|
||||
}
|
||||
|
||||
return key, map[string]string{
|
||||
"Host IP": peer.TunnelEndpointIP,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
|
||||
if tableName != ovPeerTable {
|
||||
logrus.Errorf("Unexpected table notification for table %s received", tableName)
|
||||
return
|
||||
}
|
||||
|
||||
eid := key
|
||||
|
||||
var peer PeerRecord
|
||||
if err := proto.Unmarshal(value, &peer); err != nil {
|
||||
logrus.Errorf("Failed to unmarshal peer record: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Ignore local peers. We already know about them and they
|
||||
// should not be added to vxlan fdb.
|
||||
if peer.TunnelEndpointIP == d.advertiseAddress {
|
||||
return
|
||||
}
|
||||
|
||||
addr, err := types.ParseCIDR(peer.EndpointIP)
|
||||
if err != nil {
|
||||
logrus.Errorf("Invalid peer IP %s received in event notify", peer.EndpointIP)
|
||||
return
|
||||
}
|
||||
|
||||
mac, err := net.ParseMAC(peer.EndpointMAC)
|
||||
if err != nil {
|
||||
logrus.Errorf("Invalid mac %s received in event notify", peer.EndpointMAC)
|
||||
return
|
||||
}
|
||||
|
||||
vtep := net.ParseIP(peer.TunnelEndpointIP)
|
||||
if vtep == nil {
|
||||
logrus.Errorf("Invalid VTEP %s received in event notify", peer.TunnelEndpointIP)
|
||||
return
|
||||
}
|
||||
|
||||
if etype == driverapi.Delete {
|
||||
d.peerDelete(nid, eid, addr.IP, addr.Mask, mac, vtep, false)
|
||||
return
|
||||
}
|
||||
|
||||
d.peerAdd(nid, eid, addr.IP, addr.Mask, mac, vtep, false, false, false)
|
||||
}
|
||||
|
||||
// Leave method is invoked when a Sandbox detaches from an endpoint.
|
||||
func (d *driver) Leave(nid, eid string) error {
|
||||
if err := validateID(nid, eid); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n := d.network(nid)
|
||||
if n == nil {
|
||||
return fmt.Errorf("could not find network with id %s", nid)
|
||||
}
|
||||
|
||||
ep := n.endpoint(eid)
|
||||
|
||||
if ep == nil {
|
||||
return types.InternalMaskableErrorf("could not find endpoint with id %s", eid)
|
||||
}
|
||||
|
||||
if d.notifyCh != nil {
|
||||
d.notifyCh <- ovNotify{
|
||||
action: "leave",
|
||||
nw: n,
|
||||
ep: ep,
|
||||
}
|
||||
}
|
||||
|
||||
d.peerDelete(nid, eid, ep.addr.IP, ep.addr.Mask, ep.mac, net.ParseIP(d.advertiseAddress), true)
|
||||
|
||||
n.leaveSandbox()
|
||||
|
||||
return nil
|
||||
}
|
23
vendor/github.com/docker/libnetwork/drivers/overlay/ostweaks_linux.go
generated
vendored
23
vendor/github.com/docker/libnetwork/drivers/overlay/ostweaks_linux.go
generated
vendored
|
@ -1,23 +0,0 @@
|
|||
package overlay
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/docker/libnetwork/osl/kernel"
|
||||
)
|
||||
|
||||
var ovConfig = map[string]*kernel.OSValue{
|
||||
"net.ipv4.neigh.default.gc_thresh1": {Value: "8192", CheckFn: checkHigher},
|
||||
"net.ipv4.neigh.default.gc_thresh2": {Value: "49152", CheckFn: checkHigher},
|
||||
"net.ipv4.neigh.default.gc_thresh3": {Value: "65536", CheckFn: checkHigher},
|
||||
}
|
||||
|
||||
func checkHigher(val1, val2 string) bool {
|
||||
val1Int, _ := strconv.ParseInt(val1, 10, 32)
|
||||
val2Int, _ := strconv.ParseInt(val2, 10, 32)
|
||||
return val1Int < val2Int
|
||||
}
|
||||
|
||||
func applyOStweaks() {
|
||||
kernel.ApplyOSTweaks(ovConfig)
|
||||
}
|
5
vendor/github.com/docker/libnetwork/drivers/overlay/ostweaks_unsupported.go
generated
vendored
5
vendor/github.com/docker/libnetwork/drivers/overlay/ostweaks_unsupported.go
generated
vendored
|
@ -1,5 +0,0 @@
|
|||
// +build !linux
|
||||
|
||||
package overlay
|
||||
|
||||
func applyOStweaks() {}
|
252
vendor/github.com/docker/libnetwork/drivers/overlay/ov_endpoint.go
generated
vendored
252
vendor/github.com/docker/libnetwork/drivers/overlay/ov_endpoint.go
generated
vendored
|
@ -1,252 +0,0 @@
|
|||
package overlay
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/docker/libnetwork/datastore"
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/ns"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type endpointTable map[string]*endpoint
|
||||
|
||||
const overlayEndpointPrefix = "overlay/endpoint"
|
||||
|
||||
type endpoint struct {
|
||||
id string
|
||||
nid string
|
||||
ifName string
|
||||
mac net.HardwareAddr
|
||||
addr *net.IPNet
|
||||
dbExists bool
|
||||
dbIndex uint64
|
||||
}
|
||||
|
||||
func (n *network) endpoint(eid string) *endpoint {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
||||
return n.endpoints[eid]
|
||||
}
|
||||
|
||||
func (n *network) addEndpoint(ep *endpoint) {
|
||||
n.Lock()
|
||||
n.endpoints[ep.id] = ep
|
||||
n.Unlock()
|
||||
}
|
||||
|
||||
func (n *network) deleteEndpoint(eid string) {
|
||||
n.Lock()
|
||||
delete(n.endpoints, eid)
|
||||
n.Unlock()
|
||||
}
|
||||
|
||||
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
|
||||
epOptions map[string]interface{}) error {
|
||||
var err error
|
||||
|
||||
if err = validateID(nid, eid); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Since we perform lazy configuration make sure we try
|
||||
// configuring the driver when we enter CreateEndpoint since
|
||||
// CreateNetwork may not be called in every node.
|
||||
if err := d.configure(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n := d.network(nid)
|
||||
if n == nil {
|
||||
return fmt.Errorf("network id %q not found", nid)
|
||||
}
|
||||
|
||||
ep := &endpoint{
|
||||
id: eid,
|
||||
nid: n.id,
|
||||
addr: ifInfo.Address(),
|
||||
mac: ifInfo.MacAddress(),
|
||||
}
|
||||
if ep.addr == nil {
|
||||
return fmt.Errorf("create endpoint was not passed interface IP address")
|
||||
}
|
||||
|
||||
if s := n.getSubnetforIP(ep.addr); s == nil {
|
||||
return fmt.Errorf("no matching subnet for IP %q in network %q", ep.addr, nid)
|
||||
}
|
||||
|
||||
if ep.mac == nil {
|
||||
ep.mac = netutils.GenerateMACFromIP(ep.addr.IP)
|
||||
if err := ifInfo.SetMacAddress(ep.mac); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
n.addEndpoint(ep)
|
||||
|
||||
if err := d.writeEndpointToStore(ep); err != nil {
|
||||
return fmt.Errorf("failed to update overlay endpoint %.7s to local store: %v", ep.id, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) DeleteEndpoint(nid, eid string) error {
|
||||
nlh := ns.NlHandle()
|
||||
|
||||
if err := validateID(nid, eid); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n := d.network(nid)
|
||||
if n == nil {
|
||||
return fmt.Errorf("network id %q not found", nid)
|
||||
}
|
||||
|
||||
ep := n.endpoint(eid)
|
||||
if ep == nil {
|
||||
return fmt.Errorf("endpoint id %q not found", eid)
|
||||
}
|
||||
|
||||
n.deleteEndpoint(eid)
|
||||
|
||||
if err := d.deleteEndpointFromStore(ep); err != nil {
|
||||
logrus.Warnf("Failed to delete overlay endpoint %.7s from local store: %v", ep.id, err)
|
||||
}
|
||||
|
||||
if ep.ifName == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
link, err := nlh.LinkByName(ep.ifName)
|
||||
if err != nil {
|
||||
logrus.Debugf("Failed to retrieve interface (%s)'s link on endpoint (%s) delete: %v", ep.ifName, ep.id, err)
|
||||
return nil
|
||||
}
|
||||
if err := nlh.LinkDel(link); err != nil {
|
||||
logrus.Debugf("Failed to delete interface (%s)'s link on endpoint (%s) delete: %v", ep.ifName, ep.id, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) {
|
||||
return make(map[string]interface{}, 0), nil
|
||||
}
|
||||
|
||||
func (d *driver) deleteEndpointFromStore(e *endpoint) error {
|
||||
if d.localStore == nil {
|
||||
return fmt.Errorf("overlay local store not initialized, ep not deleted")
|
||||
}
|
||||
|
||||
return d.localStore.DeleteObjectAtomic(e)
|
||||
}
|
||||
|
||||
func (d *driver) writeEndpointToStore(e *endpoint) error {
|
||||
if d.localStore == nil {
|
||||
return fmt.Errorf("overlay local store not initialized, ep not added")
|
||||
}
|
||||
|
||||
return d.localStore.PutObjectAtomic(e)
|
||||
}
|
||||
|
||||
func (ep *endpoint) DataScope() string {
|
||||
return datastore.LocalScope
|
||||
}
|
||||
|
||||
func (ep *endpoint) New() datastore.KVObject {
|
||||
return &endpoint{}
|
||||
}
|
||||
|
||||
func (ep *endpoint) CopyTo(o datastore.KVObject) error {
|
||||
dstep := o.(*endpoint)
|
||||
*dstep = *ep
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ep *endpoint) Key() []string {
|
||||
return []string{overlayEndpointPrefix, ep.id}
|
||||
}
|
||||
|
||||
func (ep *endpoint) KeyPrefix() []string {
|
||||
return []string{overlayEndpointPrefix}
|
||||
}
|
||||
|
||||
func (ep *endpoint) Index() uint64 {
|
||||
return ep.dbIndex
|
||||
}
|
||||
|
||||
func (ep *endpoint) SetIndex(index uint64) {
|
||||
ep.dbIndex = index
|
||||
ep.dbExists = true
|
||||
}
|
||||
|
||||
func (ep *endpoint) Exists() bool {
|
||||
return ep.dbExists
|
||||
}
|
||||
|
||||
func (ep *endpoint) Skip() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (ep *endpoint) Value() []byte {
|
||||
b, err := json.Marshal(ep)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (ep *endpoint) SetValue(value []byte) error {
|
||||
return json.Unmarshal(value, ep)
|
||||
}
|
||||
|
||||
func (ep *endpoint) MarshalJSON() ([]byte, error) {
|
||||
epMap := make(map[string]interface{})
|
||||
|
||||
epMap["id"] = ep.id
|
||||
epMap["nid"] = ep.nid
|
||||
if ep.ifName != "" {
|
||||
epMap["ifName"] = ep.ifName
|
||||
}
|
||||
if ep.addr != nil {
|
||||
epMap["addr"] = ep.addr.String()
|
||||
}
|
||||
if len(ep.mac) != 0 {
|
||||
epMap["mac"] = ep.mac.String()
|
||||
}
|
||||
|
||||
return json.Marshal(epMap)
|
||||
}
|
||||
|
||||
func (ep *endpoint) UnmarshalJSON(value []byte) error {
|
||||
var (
|
||||
err error
|
||||
epMap map[string]interface{}
|
||||
)
|
||||
|
||||
json.Unmarshal(value, &epMap)
|
||||
|
||||
ep.id = epMap["id"].(string)
|
||||
ep.nid = epMap["nid"].(string)
|
||||
if v, ok := epMap["mac"]; ok {
|
||||
if ep.mac, err = net.ParseMAC(v.(string)); err != nil {
|
||||
return types.InternalErrorf("failed to decode endpoint interface mac address after json unmarshal: %s", v.(string))
|
||||
}
|
||||
}
|
||||
if v, ok := epMap["addr"]; ok {
|
||||
if ep.addr, err = types.ParseCIDR(v.(string)); err != nil {
|
||||
return types.InternalErrorf("failed to decode endpoint interface ipv4 address after json unmarshal: %v", err)
|
||||
}
|
||||
}
|
||||
if v, ok := epMap["ifName"]; ok {
|
||||
ep.ifName = v.(string)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
1155
vendor/github.com/docker/libnetwork/drivers/overlay/ov_network.go
generated
vendored
1155
vendor/github.com/docker/libnetwork/drivers/overlay/ov_network.go
generated
vendored
File diff suppressed because it is too large
Load diff
229
vendor/github.com/docker/libnetwork/drivers/overlay/ov_serf.go
generated
vendored
229
vendor/github.com/docker/libnetwork/drivers/overlay/ov_serf.go
generated
vendored
|
@ -1,229 +0,0 @@
|
|||
package overlay
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/serf/serf"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type ovNotify struct {
|
||||
action string
|
||||
ep *endpoint
|
||||
nw *network
|
||||
}
|
||||
|
||||
type logWriter struct{}
|
||||
|
||||
func (l *logWriter) Write(p []byte) (int, error) {
|
||||
str := string(p)
|
||||
|
||||
switch {
|
||||
case strings.Contains(str, "[WARN]"):
|
||||
logrus.Warn(str)
|
||||
case strings.Contains(str, "[DEBUG]"):
|
||||
logrus.Debug(str)
|
||||
case strings.Contains(str, "[INFO]"):
|
||||
logrus.Info(str)
|
||||
case strings.Contains(str, "[ERR]"):
|
||||
logrus.Error(str)
|
||||
}
|
||||
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func (d *driver) serfInit() error {
|
||||
var err error
|
||||
|
||||
config := serf.DefaultConfig()
|
||||
config.Init()
|
||||
config.MemberlistConfig.BindAddr = d.advertiseAddress
|
||||
|
||||
d.eventCh = make(chan serf.Event, 4)
|
||||
config.EventCh = d.eventCh
|
||||
config.UserCoalescePeriod = 1 * time.Second
|
||||
config.UserQuiescentPeriod = 50 * time.Millisecond
|
||||
|
||||
config.LogOutput = &logWriter{}
|
||||
config.MemberlistConfig.LogOutput = config.LogOutput
|
||||
|
||||
s, err := serf.Create(config)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create cluster node: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
s.Shutdown()
|
||||
}
|
||||
}()
|
||||
|
||||
d.serfInstance = s
|
||||
|
||||
d.notifyCh = make(chan ovNotify)
|
||||
d.exitCh = make(chan chan struct{})
|
||||
|
||||
go d.startSerfLoop(d.eventCh, d.notifyCh, d.exitCh)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) serfJoin(neighIP string) error {
|
||||
if neighIP == "" {
|
||||
return fmt.Errorf("no neighbor to join")
|
||||
}
|
||||
if _, err := d.serfInstance.Join([]string{neighIP}, true); err != nil {
|
||||
return fmt.Errorf("Failed to join the cluster at neigh IP %s: %v",
|
||||
neighIP, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) notifyEvent(event ovNotify) {
|
||||
ep := event.ep
|
||||
|
||||
ePayload := fmt.Sprintf("%s %s %s %s", event.action, ep.addr.IP.String(),
|
||||
net.IP(ep.addr.Mask).String(), ep.mac.String())
|
||||
eName := fmt.Sprintf("jl %s %s %s", d.serfInstance.LocalMember().Addr.String(),
|
||||
event.nw.id, ep.id)
|
||||
|
||||
if err := d.serfInstance.UserEvent(eName, []byte(ePayload), true); err != nil {
|
||||
logrus.Errorf("Sending user event failed: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *driver) processEvent(u serf.UserEvent) {
|
||||
logrus.Debugf("Received user event name:%s, payload:%s LTime:%d \n", u.Name,
|
||||
string(u.Payload), uint64(u.LTime))
|
||||
|
||||
var dummy, action, vtepStr, nid, eid, ipStr, maskStr, macStr string
|
||||
if _, err := fmt.Sscan(u.Name, &dummy, &vtepStr, &nid, &eid); err != nil {
|
||||
fmt.Printf("Failed to scan name string: %v\n", err)
|
||||
}
|
||||
|
||||
if _, err := fmt.Sscan(string(u.Payload), &action,
|
||||
&ipStr, &maskStr, &macStr); err != nil {
|
||||
fmt.Printf("Failed to scan value string: %v\n", err)
|
||||
}
|
||||
|
||||
logrus.Debugf("Parsed data = %s/%s/%s/%s/%s/%s\n", nid, eid, vtepStr, ipStr, maskStr, macStr)
|
||||
|
||||
mac, err := net.ParseMAC(macStr)
|
||||
if err != nil {
|
||||
logrus.Errorf("Failed to parse mac: %v\n", err)
|
||||
}
|
||||
|
||||
if d.serfInstance.LocalMember().Addr.String() == vtepStr {
|
||||
return
|
||||
}
|
||||
|
||||
switch action {
|
||||
case "join":
|
||||
d.peerAdd(nid, eid, net.ParseIP(ipStr), net.IPMask(net.ParseIP(maskStr).To4()), mac, net.ParseIP(vtepStr), false, false, false)
|
||||
case "leave":
|
||||
d.peerDelete(nid, eid, net.ParseIP(ipStr), net.IPMask(net.ParseIP(maskStr).To4()), mac, net.ParseIP(vtepStr), false)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *driver) processQuery(q *serf.Query) {
|
||||
logrus.Debugf("Received query name:%s, payload:%s\n", q.Name,
|
||||
string(q.Payload))
|
||||
|
||||
var nid, ipStr string
|
||||
if _, err := fmt.Sscan(string(q.Payload), &nid, &ipStr); err != nil {
|
||||
fmt.Printf("Failed to scan query payload string: %v\n", err)
|
||||
}
|
||||
|
||||
pKey, pEntry, err := d.peerDbSearch(nid, net.ParseIP(ipStr))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
logrus.Debugf("Sending peer query resp mac %v, mask %s, vtep %s", pKey.peerMac, net.IP(pEntry.peerIPMask).String(), pEntry.vtep)
|
||||
q.Respond([]byte(fmt.Sprintf("%s %s %s", pKey.peerMac.String(), net.IP(pEntry.peerIPMask).String(), pEntry.vtep.String())))
|
||||
}
|
||||
|
||||
func (d *driver) resolvePeer(nid string, peerIP net.IP) (net.HardwareAddr, net.IPMask, net.IP, error) {
|
||||
if d.serfInstance == nil {
|
||||
return nil, nil, nil, fmt.Errorf("could not resolve peer: serf instance not initialized")
|
||||
}
|
||||
|
||||
qPayload := fmt.Sprintf("%s %s", string(nid), peerIP.String())
|
||||
resp, err := d.serfInstance.Query("peerlookup", []byte(qPayload), nil)
|
||||
if err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("resolving peer by querying the cluster failed: %v", err)
|
||||
}
|
||||
|
||||
respCh := resp.ResponseCh()
|
||||
select {
|
||||
case r := <-respCh:
|
||||
var macStr, maskStr, vtepStr string
|
||||
if _, err := fmt.Sscan(string(r.Payload), &macStr, &maskStr, &vtepStr); err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("bad response %q for the resolve query: %v", string(r.Payload), err)
|
||||
}
|
||||
|
||||
mac, err := net.ParseMAC(macStr)
|
||||
if err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("failed to parse mac: %v", err)
|
||||
}
|
||||
|
||||
logrus.Debugf("Received peer query response, mac %s, vtep %s, mask %s", macStr, vtepStr, maskStr)
|
||||
return mac, net.IPMask(net.ParseIP(maskStr).To4()), net.ParseIP(vtepStr), nil
|
||||
|
||||
case <-time.After(time.Second):
|
||||
return nil, nil, nil, fmt.Errorf("timed out resolving peer by querying the cluster")
|
||||
}
|
||||
}
|
||||
|
||||
func (d *driver) startSerfLoop(eventCh chan serf.Event, notifyCh chan ovNotify,
|
||||
exitCh chan chan struct{}) {
|
||||
|
||||
for {
|
||||
select {
|
||||
case notify, ok := <-notifyCh:
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
|
||||
d.notifyEvent(notify)
|
||||
case ch, ok := <-exitCh:
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
|
||||
if err := d.serfInstance.Leave(); err != nil {
|
||||
logrus.Errorf("failed leaving the cluster: %v\n", err)
|
||||
}
|
||||
|
||||
d.serfInstance.Shutdown()
|
||||
close(ch)
|
||||
return
|
||||
case e, ok := <-eventCh:
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
|
||||
if e.EventType() == serf.EventQuery {
|
||||
d.processQuery(e.(*serf.Query))
|
||||
break
|
||||
}
|
||||
|
||||
u, ok := e.(serf.UserEvent)
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
d.processEvent(u)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (d *driver) isSerfAlive() bool {
|
||||
d.Lock()
|
||||
serfInstance := d.serfInstance
|
||||
d.Unlock()
|
||||
if serfInstance == nil || serfInstance.State() != serf.SerfAlive {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
162
vendor/github.com/docker/libnetwork/drivers/overlay/ov_utils.go
generated
vendored
162
vendor/github.com/docker/libnetwork/drivers/overlay/ov_utils.go
generated
vendored
|
@ -1,162 +0,0 @@
|
|||
package overlay
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/docker/libnetwork/drivers/overlay/overlayutils"
|
||||
"github.com/docker/libnetwork/netutils"
|
||||
"github.com/docker/libnetwork/ns"
|
||||
"github.com/docker/libnetwork/osl"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vishvananda/netlink"
|
||||
"github.com/vishvananda/netns"
|
||||
)
|
||||
|
||||
var soTimeout = ns.NetlinkSocketsTimeout
|
||||
|
||||
func validateID(nid, eid string) error {
|
||||
if nid == "" {
|
||||
return fmt.Errorf("invalid network id")
|
||||
}
|
||||
|
||||
if eid == "" {
|
||||
return fmt.Errorf("invalid endpoint id")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createVethPair() (string, string, error) {
|
||||
defer osl.InitOSContext()()
|
||||
nlh := ns.NlHandle()
|
||||
|
||||
// Generate a name for what will be the host side pipe interface
|
||||
name1, err := netutils.GenerateIfaceName(nlh, vethPrefix, vethLen)
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("error generating veth name1: %v", err)
|
||||
}
|
||||
|
||||
// Generate a name for what will be the sandbox side pipe interface
|
||||
name2, err := netutils.GenerateIfaceName(nlh, vethPrefix, vethLen)
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("error generating veth name2: %v", err)
|
||||
}
|
||||
|
||||
// Generate and add the interface pipe host <-> sandbox
|
||||
veth := &netlink.Veth{
|
||||
LinkAttrs: netlink.LinkAttrs{Name: name1, TxQLen: 0},
|
||||
PeerName: name2}
|
||||
if err := nlh.LinkAdd(veth); err != nil {
|
||||
return "", "", fmt.Errorf("error creating veth pair: %v", err)
|
||||
}
|
||||
|
||||
return name1, name2, nil
|
||||
}
|
||||
|
||||
func createVxlan(name string, vni uint32, mtu int) error {
|
||||
defer osl.InitOSContext()()
|
||||
|
||||
vxlan := &netlink.Vxlan{
|
||||
LinkAttrs: netlink.LinkAttrs{Name: name, MTU: mtu},
|
||||
VxlanId: int(vni),
|
||||
Learning: true,
|
||||
Port: int(overlayutils.VXLANUDPPort()),
|
||||
Proxy: true,
|
||||
L3miss: true,
|
||||
L2miss: true,
|
||||
}
|
||||
|
||||
if err := ns.NlHandle().LinkAdd(vxlan); err != nil {
|
||||
return fmt.Errorf("error creating vxlan interface: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteInterfaceBySubnet(brPrefix string, s *subnet) error {
|
||||
defer osl.InitOSContext()()
|
||||
|
||||
nlh := ns.NlHandle()
|
||||
links, err := nlh.LinkList()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list interfaces while deleting bridge interface by subnet: %v", err)
|
||||
}
|
||||
|
||||
for _, l := range links {
|
||||
name := l.Attrs().Name
|
||||
if _, ok := l.(*netlink.Bridge); ok && strings.HasPrefix(name, brPrefix) {
|
||||
addrList, err := nlh.AddrList(l, netlink.FAMILY_V4)
|
||||
if err != nil {
|
||||
logrus.Errorf("error getting AddressList for bridge %s", name)
|
||||
continue
|
||||
}
|
||||
for _, addr := range addrList {
|
||||
if netutils.NetworkOverlaps(addr.IPNet, s.subnetIP) {
|
||||
err = nlh.LinkDel(l)
|
||||
if err != nil {
|
||||
logrus.Errorf("error deleting bridge (%s) with subnet %v: %v", name, addr.IPNet, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func deleteInterface(name string) error {
|
||||
defer osl.InitOSContext()()
|
||||
|
||||
link, err := ns.NlHandle().LinkByName(name)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to find interface with name %s: %v", name, err)
|
||||
}
|
||||
|
||||
if err := ns.NlHandle().LinkDel(link); err != nil {
|
||||
return fmt.Errorf("error deleting interface with name %s: %v", name, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteVxlanByVNI(path string, vni uint32) error {
|
||||
defer osl.InitOSContext()()
|
||||
|
||||
nlh := ns.NlHandle()
|
||||
if path != "" {
|
||||
ns, err := netns.GetFromPath(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get ns handle for %s: %v", path, err)
|
||||
}
|
||||
defer ns.Close()
|
||||
|
||||
nlh, err = netlink.NewHandleAt(ns, syscall.NETLINK_ROUTE)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get netlink handle for ns %s: %v", path, err)
|
||||
}
|
||||
defer nlh.Delete()
|
||||
err = nlh.SetSocketTimeout(soTimeout)
|
||||
if err != nil {
|
||||
logrus.Warnf("Failed to set the timeout on the netlink handle sockets for vxlan deletion: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
links, err := nlh.LinkList()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list interfaces while deleting vxlan interface by vni: %v", err)
|
||||
}
|
||||
|
||||
for _, l := range links {
|
||||
if l.Type() == "vxlan" && (vni == 0 || l.(*netlink.Vxlan).VxlanId == int(vni)) {
|
||||
err = nlh.LinkDel(l)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error deleting vxlan interface with id %d: %v", vni, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("could not find a vxlan interface to delete with id %d", vni)
|
||||
}
|
391
vendor/github.com/docker/libnetwork/drivers/overlay/overlay.go
generated
vendored
391
vendor/github.com/docker/libnetwork/drivers/overlay/overlay.go
generated
vendored
|
@ -1,391 +0,0 @@
|
|||
package overlay
|
||||
|
||||
//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
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"github.com/docker/libnetwork/datastore"
|
||||
"github.com/docker/libnetwork/discoverapi"
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/idm"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/osl"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/hashicorp/serf/serf"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
networkType = "overlay"
|
||||
vethPrefix = "veth"
|
||||
vethLen = 7
|
||||
vxlanIDStart = 256
|
||||
vxlanIDEnd = (1 << 24) - 1
|
||||
vxlanEncap = 50
|
||||
secureOption = "encrypted"
|
||||
)
|
||||
|
||||
var initVxlanIdm = make(chan (bool), 1)
|
||||
|
||||
type driver struct {
|
||||
eventCh chan serf.Event
|
||||
notifyCh chan ovNotify
|
||||
exitCh chan chan struct{}
|
||||
bindAddress string
|
||||
advertiseAddress string
|
||||
neighIP string
|
||||
config map[string]interface{}
|
||||
peerDb peerNetworkMap
|
||||
secMap *encrMap
|
||||
serfInstance *serf.Serf
|
||||
networks networkTable
|
||||
store datastore.DataStore
|
||||
localStore datastore.DataStore
|
||||
vxlanIdm *idm.Idm
|
||||
initOS sync.Once
|
||||
joinOnce sync.Once
|
||||
localJoinOnce sync.Once
|
||||
keys []*key
|
||||
peerOpCh chan *peerOperation
|
||||
peerOpCancel context.CancelFunc
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// Init registers a new instance of overlay driver
|
||||
func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
||||
c := driverapi.Capability{
|
||||
DataScope: datastore.GlobalScope,
|
||||
ConnectivityScope: datastore.GlobalScope,
|
||||
}
|
||||
d := &driver{
|
||||
networks: networkTable{},
|
||||
peerDb: peerNetworkMap{
|
||||
mp: map[string]*peerMap{},
|
||||
},
|
||||
secMap: &encrMap{nodes: map[string][]*spi{}},
|
||||
config: config,
|
||||
peerOpCh: make(chan *peerOperation),
|
||||
}
|
||||
|
||||
// Launch the go routine for processing peer operations
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
d.peerOpCancel = cancel
|
||||
go d.peerOpRoutine(ctx, d.peerOpCh)
|
||||
|
||||
if data, ok := config[netlabel.GlobalKVClient]; ok {
|
||||
var err error
|
||||
dsc, ok := data.(discoverapi.DatastoreConfigData)
|
||||
if !ok {
|
||||
return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
|
||||
}
|
||||
d.store, err = datastore.NewDataStoreFromConfig(dsc)
|
||||
if err != nil {
|
||||
return types.InternalErrorf("failed to initialize data store: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if data, ok := config[netlabel.LocalKVClient]; ok {
|
||||
var err error
|
||||
dsc, ok := data.(discoverapi.DatastoreConfigData)
|
||||
if !ok {
|
||||
return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
|
||||
}
|
||||
d.localStore, err = datastore.NewDataStoreFromConfig(dsc)
|
||||
if err != nil {
|
||||
return types.InternalErrorf("failed to initialize local data store: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := d.restoreEndpoints(); err != nil {
|
||||
logrus.Warnf("Failure during overlay endpoints restore: %v", err)
|
||||
}
|
||||
|
||||
return dc.RegisterDriver(networkType, d, c)
|
||||
}
|
||||
|
||||
// Endpoints are stored in the local store. Restore them and reconstruct the overlay sandbox
|
||||
func (d *driver) restoreEndpoints() error {
|
||||
if d.localStore == nil {
|
||||
logrus.Warn("Cannot restore overlay endpoints because local datastore is missing")
|
||||
return nil
|
||||
}
|
||||
kvol, err := d.localStore.List(datastore.Key(overlayEndpointPrefix), &endpoint{})
|
||||
if err != nil && err != datastore.ErrKeyNotFound {
|
||||
return fmt.Errorf("failed to read overlay endpoint from store: %v", err)
|
||||
}
|
||||
|
||||
if err == datastore.ErrKeyNotFound {
|
||||
return nil
|
||||
}
|
||||
for _, kvo := range kvol {
|
||||
ep := kvo.(*endpoint)
|
||||
n := d.network(ep.nid)
|
||||
if n == nil {
|
||||
logrus.Debugf("Network (%.7s) not found for restored endpoint (%.7s)", ep.nid, ep.id)
|
||||
logrus.Debugf("Deleting stale overlay endpoint (%.7s) from store", ep.id)
|
||||
if err := d.deleteEndpointFromStore(ep); err != nil {
|
||||
logrus.Debugf("Failed to delete stale overlay endpoint (%.7s) from store", ep.id)
|
||||
}
|
||||
continue
|
||||
}
|
||||
n.addEndpoint(ep)
|
||||
|
||||
s := n.getSubnetforIP(ep.addr)
|
||||
if s == nil {
|
||||
return fmt.Errorf("could not find subnet for endpoint %s", ep.id)
|
||||
}
|
||||
|
||||
if err := n.joinSandbox(s, true, true); err != nil {
|
||||
return fmt.Errorf("restore network sandbox failed: %v", err)
|
||||
}
|
||||
|
||||
Ifaces := make(map[string][]osl.IfaceOption)
|
||||
vethIfaceOption := make([]osl.IfaceOption, 1)
|
||||
vethIfaceOption = append(vethIfaceOption, n.sbox.InterfaceOptions().Master(s.brName))
|
||||
Ifaces["veth+veth"] = vethIfaceOption
|
||||
|
||||
err := n.sbox.Restore(Ifaces, nil, nil, nil)
|
||||
if err != nil {
|
||||
n.leaveSandbox()
|
||||
return fmt.Errorf("failed to restore overlay sandbox: %v", err)
|
||||
}
|
||||
|
||||
d.peerAdd(ep.nid, ep.id, ep.addr.IP, ep.addr.Mask, ep.mac, net.ParseIP(d.advertiseAddress), false, false, true)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Fini cleans up the driver resources
|
||||
func Fini(drv driverapi.Driver) {
|
||||
d := drv.(*driver)
|
||||
|
||||
// Notify the peer go routine to return
|
||||
if d.peerOpCancel != nil {
|
||||
d.peerOpCancel()
|
||||
}
|
||||
|
||||
if d.exitCh != nil {
|
||||
waitCh := make(chan struct{})
|
||||
|
||||
d.exitCh <- waitCh
|
||||
|
||||
<-waitCh
|
||||
}
|
||||
}
|
||||
|
||||
func (d *driver) configure() error {
|
||||
|
||||
// Apply OS specific kernel configs if needed
|
||||
d.initOS.Do(applyOStweaks)
|
||||
|
||||
if d.store == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if d.vxlanIdm == nil {
|
||||
return d.initializeVxlanIdm()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) initializeVxlanIdm() error {
|
||||
var err error
|
||||
|
||||
initVxlanIdm <- true
|
||||
defer func() { <-initVxlanIdm }()
|
||||
|
||||
if d.vxlanIdm != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
d.vxlanIdm, err = idm.New(d.store, "vxlan-id", vxlanIDStart, vxlanIDEnd)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to initialize vxlan id manager: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) Type() string {
|
||||
return networkType
|
||||
}
|
||||
|
||||
func (d *driver) IsBuiltIn() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func validateSelf(node string) error {
|
||||
advIP := net.ParseIP(node)
|
||||
if advIP == nil {
|
||||
return fmt.Errorf("invalid self address (%s)", node)
|
||||
}
|
||||
|
||||
addrs, err := net.InterfaceAddrs()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to get interface addresses %v", err)
|
||||
}
|
||||
for _, addr := range addrs {
|
||||
ip, _, err := net.ParseCIDR(addr.String())
|
||||
if err == nil && ip.Equal(advIP) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
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())
|
||||
}
|
||||
|
||||
func (d *driver) nodeJoin(advertiseAddress, bindAddress string, self bool) {
|
||||
if self && !d.isSerfAlive() {
|
||||
d.Lock()
|
||||
d.advertiseAddress = advertiseAddress
|
||||
d.bindAddress = bindAddress
|
||||
d.Unlock()
|
||||
|
||||
// If containers are already running on this network update the
|
||||
// advertise address in the peerDB
|
||||
d.localJoinOnce.Do(func() {
|
||||
d.peerDBUpdateSelf()
|
||||
})
|
||||
|
||||
// If there is no cluster store there is no need to start serf.
|
||||
if d.store != nil {
|
||||
if err := validateSelf(advertiseAddress); err != nil {
|
||||
logrus.Warn(err.Error())
|
||||
}
|
||||
err := d.serfInit()
|
||||
if err != nil {
|
||||
logrus.Errorf("initializing serf instance failed: %v", err)
|
||||
d.Lock()
|
||||
d.advertiseAddress = ""
|
||||
d.bindAddress = ""
|
||||
d.Unlock()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
d.Lock()
|
||||
if !self {
|
||||
d.neighIP = advertiseAddress
|
||||
}
|
||||
neighIP := d.neighIP
|
||||
d.Unlock()
|
||||
|
||||
if d.serfInstance != nil && neighIP != "" {
|
||||
var err error
|
||||
d.joinOnce.Do(func() {
|
||||
err = d.serfJoin(neighIP)
|
||||
if err == nil {
|
||||
d.pushLocalDb()
|
||||
}
|
||||
})
|
||||
if err != nil {
|
||||
logrus.Errorf("joining serf neighbor %s failed: %v", advertiseAddress, err)
|
||||
d.Lock()
|
||||
d.joinOnce = sync.Once{}
|
||||
d.Unlock()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (d *driver) pushLocalEndpointEvent(action, nid, eid string) {
|
||||
n := d.network(nid)
|
||||
if n == nil {
|
||||
logrus.Debugf("Error pushing local endpoint event for network %s", nid)
|
||||
return
|
||||
}
|
||||
ep := n.endpoint(eid)
|
||||
if ep == nil {
|
||||
logrus.Debugf("Error pushing local endpoint event for ep %s / %s", nid, eid)
|
||||
return
|
||||
}
|
||||
|
||||
if !d.isSerfAlive() {
|
||||
return
|
||||
}
|
||||
d.notifyCh <- ovNotify{
|
||||
action: "join",
|
||||
nw: n,
|
||||
ep: ep,
|
||||
}
|
||||
}
|
||||
|
||||
// DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster
|
||||
func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||
var err error
|
||||
switch dType {
|
||||
case discoverapi.NodeDiscovery:
|
||||
nodeData, ok := data.(discoverapi.NodeDiscoveryData)
|
||||
if !ok || nodeData.Address == "" {
|
||||
return fmt.Errorf("invalid discovery data")
|
||||
}
|
||||
d.nodeJoin(nodeData.Address, nodeData.BindAddress, nodeData.Self)
|
||||
case discoverapi.DatastoreConfig:
|
||||
if d.store != nil {
|
||||
return types.ForbiddenErrorf("cannot accept datastore configuration: Overlay driver has a datastore configured already")
|
||||
}
|
||||
dsc, ok := data.(discoverapi.DatastoreConfigData)
|
||||
if !ok {
|
||||
return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
|
||||
}
|
||||
d.store, err = datastore.NewDataStoreFromConfig(dsc)
|
||||
if err != nil {
|
||||
return types.InternalErrorf("failed to initialize data store: %v", err)
|
||||
}
|
||||
case discoverapi.EncryptionKeysConfig:
|
||||
encrData, ok := data.(discoverapi.DriverEncryptionConfig)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid encryption key notification data")
|
||||
}
|
||||
keys := make([]*key, 0, len(encrData.Keys))
|
||||
for i := 0; i < len(encrData.Keys); i++ {
|
||||
k := &key{
|
||||
value: encrData.Keys[i],
|
||||
tag: uint32(encrData.Tags[i]),
|
||||
}
|
||||
keys = append(keys, k)
|
||||
}
|
||||
if err := d.setKeys(keys); err != nil {
|
||||
logrus.Warn(err)
|
||||
}
|
||||
case discoverapi.EncryptionKeysUpdate:
|
||||
var newKey, delKey, priKey *key
|
||||
encrData, ok := data.(discoverapi.DriverEncryptionUpdate)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid encryption key notification data")
|
||||
}
|
||||
if encrData.Key != nil {
|
||||
newKey = &key{
|
||||
value: encrData.Key,
|
||||
tag: uint32(encrData.Tag),
|
||||
}
|
||||
}
|
||||
if encrData.Primary != nil {
|
||||
priKey = &key{
|
||||
value: encrData.Primary,
|
||||
tag: uint32(encrData.PrimaryTag),
|
||||
}
|
||||
}
|
||||
if encrData.Prune != nil {
|
||||
delKey = &key{
|
||||
value: encrData.Prune,
|
||||
tag: uint32(encrData.PruneTag),
|
||||
}
|
||||
}
|
||||
if err := d.updateKeys(newKey, priKey, delKey); err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster
|
||||
func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||
return nil
|
||||
}
|
455
vendor/github.com/docker/libnetwork/drivers/overlay/overlay.pb.go
generated
vendored
455
vendor/github.com/docker/libnetwork/drivers/overlay/overlay.pb.go
generated
vendored
|
@ -1,455 +0,0 @@
|
|||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: drivers/overlay/overlay.proto
|
||||
|
||||
/*
|
||||
Package overlay is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
drivers/overlay/overlay.proto
|
||||
|
||||
It has these top-level messages:
|
||||
PeerRecord
|
||||
*/
|
||||
package overlay
|
||||
|
||||
import proto "github.com/gogo/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import _ "github.com/gogo/protobuf/gogoproto"
|
||||
|
||||
import strings "strings"
|
||||
import reflect "reflect"
|
||||
|
||||
import io "io"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
// PeerRecord defines the information corresponding to a peer
|
||||
// container in the overlay network.
|
||||
type PeerRecord struct {
|
||||
// Endpoint IP is the IP of the container attachment on the
|
||||
// given overlay network.
|
||||
EndpointIP string `protobuf:"bytes,1,opt,name=endpoint_ip,json=endpointIp,proto3" json:"endpoint_ip,omitempty"`
|
||||
// Endpoint MAC is the mac address of the container attachment
|
||||
// on the given overlay network.
|
||||
EndpointMAC string `protobuf:"bytes,2,opt,name=endpoint_mac,json=endpointMac,proto3" json:"endpoint_mac,omitempty"`
|
||||
// Tunnel Endpoint IP defines the host IP for the host in
|
||||
// which this container is running and can be reached by
|
||||
// building a tunnel to that host IP.
|
||||
TunnelEndpointIP string `protobuf:"bytes,3,opt,name=tunnel_endpoint_ip,json=tunnelEndpointIp,proto3" json:"tunnel_endpoint_ip,omitempty"`
|
||||
}
|
||||
|
||||
func (m *PeerRecord) Reset() { *m = PeerRecord{} }
|
||||
func (*PeerRecord) ProtoMessage() {}
|
||||
func (*PeerRecord) Descriptor() ([]byte, []int) { return fileDescriptorOverlay, []int{0} }
|
||||
|
||||
func (m *PeerRecord) GetEndpointIP() string {
|
||||
if m != nil {
|
||||
return m.EndpointIP
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *PeerRecord) GetEndpointMAC() string {
|
||||
if m != nil {
|
||||
return m.EndpointMAC
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *PeerRecord) GetTunnelEndpointIP() string {
|
||||
if m != nil {
|
||||
return m.TunnelEndpointIP
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*PeerRecord)(nil), "overlay.PeerRecord")
|
||||
}
|
||||
func (this *PeerRecord) GoString() string {
|
||||
if this == nil {
|
||||
return "nil"
|
||||
}
|
||||
s := make([]string, 0, 7)
|
||||
s = append(s, "&overlay.PeerRecord{")
|
||||
s = append(s, "EndpointIP: "+fmt.Sprintf("%#v", this.EndpointIP)+",\n")
|
||||
s = append(s, "EndpointMAC: "+fmt.Sprintf("%#v", this.EndpointMAC)+",\n")
|
||||
s = append(s, "TunnelEndpointIP: "+fmt.Sprintf("%#v", this.TunnelEndpointIP)+",\n")
|
||||
s = append(s, "}")
|
||||
return strings.Join(s, "")
|
||||
}
|
||||
func valueToGoStringOverlay(v interface{}, typ string) string {
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.IsNil() {
|
||||
return "nil"
|
||||
}
|
||||
pv := reflect.Indirect(rv).Interface()
|
||||
return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
|
||||
}
|
||||
func (m *PeerRecord) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *PeerRecord) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.EndpointIP) > 0 {
|
||||
dAtA[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintOverlay(dAtA, i, uint64(len(m.EndpointIP)))
|
||||
i += copy(dAtA[i:], m.EndpointIP)
|
||||
}
|
||||
if len(m.EndpointMAC) > 0 {
|
||||
dAtA[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintOverlay(dAtA, i, uint64(len(m.EndpointMAC)))
|
||||
i += copy(dAtA[i:], m.EndpointMAC)
|
||||
}
|
||||
if len(m.TunnelEndpointIP) > 0 {
|
||||
dAtA[i] = 0x1a
|
||||
i++
|
||||
i = encodeVarintOverlay(dAtA, i, uint64(len(m.TunnelEndpointIP)))
|
||||
i += copy(dAtA[i:], m.TunnelEndpointIP)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func encodeVarintOverlay(dAtA []byte, offset int, v uint64) int {
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return offset + 1
|
||||
}
|
||||
func (m *PeerRecord) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.EndpointIP)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovOverlay(uint64(l))
|
||||
}
|
||||
l = len(m.EndpointMAC)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovOverlay(uint64(l))
|
||||
}
|
||||
l = len(m.TunnelEndpointIP)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovOverlay(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovOverlay(x uint64) (n int) {
|
||||
for {
|
||||
n++
|
||||
x >>= 7
|
||||
if x == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
func sozOverlay(x uint64) (n int) {
|
||||
return sovOverlay(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (this *PeerRecord) String() string {
|
||||
if this == nil {
|
||||
return "nil"
|
||||
}
|
||||
s := strings.Join([]string{`&PeerRecord{`,
|
||||
`EndpointIP:` + fmt.Sprintf("%v", this.EndpointIP) + `,`,
|
||||
`EndpointMAC:` + fmt.Sprintf("%v", this.EndpointMAC) + `,`,
|
||||
`TunnelEndpointIP:` + fmt.Sprintf("%v", this.TunnelEndpointIP) + `,`,
|
||||
`}`,
|
||||
}, "")
|
||||
return s
|
||||
}
|
||||
func valueToStringOverlay(v interface{}) string {
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.IsNil() {
|
||||
return "nil"
|
||||
}
|
||||
pv := reflect.Indirect(rv).Interface()
|
||||
return fmt.Sprintf("*%v", pv)
|
||||
}
|
||||
func (m *PeerRecord) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowOverlay
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: PeerRecord: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: PeerRecord: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field EndpointIP", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowOverlay
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthOverlay
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.EndpointIP = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field EndpointMAC", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowOverlay
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthOverlay
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.EndpointMAC = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field TunnelEndpointIP", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowOverlay
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthOverlay
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.TunnelEndpointIP = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipOverlay(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthOverlay
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipOverlay(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowOverlay
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowOverlay
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
return iNdEx, nil
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowOverlay
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
iNdEx += length
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthOverlay
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 3:
|
||||
for {
|
||||
var innerWire uint64
|
||||
var start int = iNdEx
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowOverlay
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
innerWire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
innerWireType := int(innerWire & 0x7)
|
||||
if innerWireType == 4 {
|
||||
break
|
||||
}
|
||||
next, err := skipOverlay(dAtA[start:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
iNdEx = start + next
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 4:
|
||||
return iNdEx, nil
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
return iNdEx, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthOverlay = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowOverlay = fmt.Errorf("proto: integer overflow")
|
||||
)
|
||||
|
||||
func init() { proto.RegisterFile("drivers/overlay/overlay.proto", fileDescriptorOverlay) }
|
||||
|
||||
var fileDescriptorOverlay = []byte{
|
||||
// 212 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4d, 0x29, 0xca, 0x2c,
|
||||
0x4b, 0x2d, 0x2a, 0xd6, 0xcf, 0x2f, 0x4b, 0x2d, 0xca, 0x49, 0xac, 0x84, 0xd1, 0x7a, 0x05, 0x45,
|
||||
0xf9, 0x25, 0xf9, 0x42, 0xec, 0x50, 0xae, 0x94, 0x48, 0x7a, 0x7e, 0x7a, 0x3e, 0x58, 0x4c, 0x1f,
|
||||
0xc4, 0x82, 0x48, 0x2b, 0x6d, 0x65, 0xe4, 0xe2, 0x0a, 0x48, 0x4d, 0x2d, 0x0a, 0x4a, 0x4d, 0xce,
|
||||
0x2f, 0x4a, 0x11, 0xd2, 0xe7, 0xe2, 0x4e, 0xcd, 0x4b, 0x29, 0xc8, 0xcf, 0xcc, 0x2b, 0x89, 0xcf,
|
||||
0x2c, 0x90, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x74, 0xe2, 0x7b, 0x74, 0x4f, 0x9e, 0xcb, 0x15, 0x2a,
|
||||
0xec, 0x19, 0x10, 0xc4, 0x05, 0x53, 0xe2, 0x59, 0x20, 0x64, 0xc4, 0xc5, 0x03, 0xd7, 0x90, 0x9b,
|
||||
0x98, 0x2c, 0xc1, 0x04, 0xd6, 0xc1, 0xff, 0xe8, 0x9e, 0x3c, 0x37, 0x4c, 0x87, 0xaf, 0xa3, 0x73,
|
||||
0x10, 0xdc, 0x54, 0xdf, 0xc4, 0x64, 0x21, 0x27, 0x2e, 0xa1, 0x92, 0xd2, 0xbc, 0xbc, 0xd4, 0x9c,
|
||||
0x78, 0x64, 0xbb, 0x98, 0xc1, 0x3a, 0x45, 0x1e, 0xdd, 0x93, 0x17, 0x08, 0x01, 0xcb, 0x22, 0xd9,
|
||||
0x28, 0x50, 0x82, 0x2a, 0x52, 0xe0, 0x24, 0x71, 0xe3, 0xa1, 0x1c, 0xc3, 0x87, 0x87, 0x72, 0x8c,
|
||||
0x0d, 0x8f, 0xe4, 0x18, 0x4f, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39,
|
||||
0xc6, 0x24, 0x36, 0xb0, 0xc7, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x48, 0x07, 0xf6, 0xf3,
|
||||
0x18, 0x01, 0x00, 0x00,
|
||||
}
|
27
vendor/github.com/docker/libnetwork/drivers/overlay/overlay.proto
generated
vendored
27
vendor/github.com/docker/libnetwork/drivers/overlay/overlay.proto
generated
vendored
|
@ -1,27 +0,0 @@
|
|||
syntax = "proto3";
|
||||
|
||||
import "gogoproto/gogo.proto";
|
||||
|
||||
package overlay;
|
||||
|
||||
option (gogoproto.marshaler_all) = true;
|
||||
option (gogoproto.unmarshaler_all) = true;
|
||||
option (gogoproto.stringer_all) = true;
|
||||
option (gogoproto.gostring_all) = true;
|
||||
option (gogoproto.sizer_all) = true;
|
||||
option (gogoproto.goproto_stringer_all) = false;
|
||||
|
||||
// PeerRecord defines the information corresponding to a peer
|
||||
// container in the overlay network.
|
||||
message PeerRecord {
|
||||
// Endpoint IP is the IP of the container attachment on the
|
||||
// given overlay network.
|
||||
string endpoint_ip = 1 [(gogoproto.customname) = "EndpointIP"];
|
||||
// Endpoint MAC is the mac address of the container attachment
|
||||
// on the given overlay network.
|
||||
string endpoint_mac = 2 [(gogoproto.customname) = "EndpointMAC"];
|
||||
// Tunnel Endpoint IP defines the host IP for the host in
|
||||
// which this container is running and can be reached by
|
||||
// building a tunnel to that host IP.
|
||||
string tunnel_endpoint_ip = 3 [(gogoproto.customname) = "TunnelEndpointIP"];
|
||||
}
|
46
vendor/github.com/docker/libnetwork/drivers/overlay/overlayutils/utils.go
generated
vendored
46
vendor/github.com/docker/libnetwork/drivers/overlay/overlayutils/utils.go
generated
vendored
|
@ -1,46 +0,0 @@
|
|||
// Package overlayutils provides utility functions for overlay networks
|
||||
package overlayutils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
mutex sync.RWMutex
|
||||
vxlanUDPPort uint32
|
||||
)
|
||||
|
||||
const defaultVXLANUDPPort = 4789
|
||||
|
||||
func init() {
|
||||
vxlanUDPPort = defaultVXLANUDPPort
|
||||
}
|
||||
|
||||
// ConfigVXLANUDPPort configures the VXLAN UDP port (data path port) number.
|
||||
// If no port is set, the default (4789) is returned. Valid port numbers are
|
||||
// between 1024 and 49151.
|
||||
func ConfigVXLANUDPPort(vxlanPort uint32) error {
|
||||
if vxlanPort == 0 {
|
||||
vxlanPort = defaultVXLANUDPPort
|
||||
}
|
||||
// IANA procedures for each range in detail
|
||||
// The Well Known Ports, aka the System Ports, from 0-1023
|
||||
// The Registered Ports, aka the User Ports, from 1024-49151
|
||||
// The Dynamic Ports, aka the Private Ports, from 49152-65535
|
||||
// So we can allow range between 1024 to 49151
|
||||
if vxlanPort < 1024 || vxlanPort > 49151 {
|
||||
return fmt.Errorf("VXLAN UDP port number is not in valid range (1024-49151): %d", vxlanPort)
|
||||
}
|
||||
mutex.Lock()
|
||||
vxlanUDPPort = vxlanPort
|
||||
mutex.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
// VXLANUDPPort returns Vxlan UDP port number
|
||||
func VXLANUDPPort() uint32 {
|
||||
mutex.RLock()
|
||||
defer mutex.RUnlock()
|
||||
return vxlanUDPPort
|
||||
}
|
259
vendor/github.com/docker/libnetwork/drivers/overlay/ovmanager/ovmanager.go
generated
vendored
259
vendor/github.com/docker/libnetwork/drivers/overlay/ovmanager/ovmanager.go
generated
vendored
|
@ -1,259 +0,0 @@
|
|||
package ovmanager
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/docker/libnetwork/datastore"
|
||||
"github.com/docker/libnetwork/discoverapi"
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/idm"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
networkType = "overlay"
|
||||
vxlanIDStart = 4096
|
||||
vxlanIDEnd = (1 << 24) - 1
|
||||
)
|
||||
|
||||
type networkTable map[string]*network
|
||||
|
||||
type driver struct {
|
||||
config map[string]interface{}
|
||||
networks networkTable
|
||||
store datastore.DataStore
|
||||
vxlanIdm *idm.Idm
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
type subnet struct {
|
||||
subnetIP *net.IPNet
|
||||
gwIP *net.IPNet
|
||||
vni uint32
|
||||
}
|
||||
|
||||
type network struct {
|
||||
id string
|
||||
driver *driver
|
||||
subnets []*subnet
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// Init registers a new instance of overlay driver
|
||||
func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
||||
var err error
|
||||
c := driverapi.Capability{
|
||||
DataScope: datastore.GlobalScope,
|
||||
ConnectivityScope: datastore.GlobalScope,
|
||||
}
|
||||
|
||||
d := &driver{
|
||||
networks: networkTable{},
|
||||
config: config,
|
||||
}
|
||||
|
||||
d.vxlanIdm, err = idm.New(nil, "vxlan-id", 0, vxlanIDEnd)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to initialize vxlan id manager: %v", err)
|
||||
}
|
||||
|
||||
return dc.RegisterDriver(networkType, d, c)
|
||||
}
|
||||
|
||||
func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {
|
||||
if id == "" {
|
||||
return nil, fmt.Errorf("invalid network id for overlay network")
|
||||
}
|
||||
|
||||
if ipV4Data == nil {
|
||||
return nil, fmt.Errorf("empty ipv4 data passed during overlay network creation")
|
||||
}
|
||||
|
||||
n := &network{
|
||||
id: id,
|
||||
driver: d,
|
||||
subnets: []*subnet{},
|
||||
}
|
||||
|
||||
opts := make(map[string]string)
|
||||
vxlanIDList := make([]uint32, 0, len(ipV4Data))
|
||||
for key, val := range option {
|
||||
if key == netlabel.OverlayVxlanIDList {
|
||||
logrus.Debugf("overlay network option: %s", val)
|
||||
valStrList := strings.Split(val, ",")
|
||||
for _, idStr := range valStrList {
|
||||
vni, err := strconv.Atoi(idStr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid vxlan id value %q passed", idStr)
|
||||
}
|
||||
|
||||
vxlanIDList = append(vxlanIDList, uint32(vni))
|
||||
}
|
||||
} else {
|
||||
opts[key] = val
|
||||
}
|
||||
}
|
||||
|
||||
for i, ipd := range ipV4Data {
|
||||
s := &subnet{
|
||||
subnetIP: ipd.Pool,
|
||||
gwIP: ipd.Gateway,
|
||||
}
|
||||
|
||||
if len(vxlanIDList) > i {
|
||||
s.vni = vxlanIDList[i]
|
||||
}
|
||||
|
||||
if err := n.obtainVxlanID(s); err != nil {
|
||||
n.releaseVxlanID()
|
||||
return nil, fmt.Errorf("could not obtain vxlan id for pool %s: %v", s.subnetIP, err)
|
||||
}
|
||||
|
||||
n.subnets = append(n.subnets, s)
|
||||
}
|
||||
|
||||
val := fmt.Sprintf("%d", n.subnets[0].vni)
|
||||
for _, s := range n.subnets[1:] {
|
||||
val = val + fmt.Sprintf(",%d", s.vni)
|
||||
}
|
||||
opts[netlabel.OverlayVxlanIDList] = val
|
||||
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
if _, ok := d.networks[id]; ok {
|
||||
n.releaseVxlanID()
|
||||
return nil, fmt.Errorf("network %s already exists", id)
|
||||
}
|
||||
d.networks[id] = n
|
||||
|
||||
return opts, nil
|
||||
}
|
||||
|
||||
func (d *driver) NetworkFree(id string) error {
|
||||
if id == "" {
|
||||
return fmt.Errorf("invalid network id passed while freeing overlay network")
|
||||
}
|
||||
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
n, ok := d.networks[id]
|
||||
|
||||
if !ok {
|
||||
return fmt.Errorf("overlay network with id %s not found", id)
|
||||
}
|
||||
|
||||
// Release all vxlan IDs in one shot.
|
||||
n.releaseVxlanID()
|
||||
|
||||
delete(d.networks, id)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *network) obtainVxlanID(s *subnet) error {
|
||||
var (
|
||||
err error
|
||||
vni uint64
|
||||
)
|
||||
|
||||
n.Lock()
|
||||
vni = uint64(s.vni)
|
||||
n.Unlock()
|
||||
|
||||
if vni == 0 {
|
||||
vni, err = n.driver.vxlanIdm.GetIDInRange(vxlanIDStart, vxlanIDEnd, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n.Lock()
|
||||
s.vni = uint32(vni)
|
||||
n.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
return n.driver.vxlanIdm.GetSpecificID(vni)
|
||||
}
|
||||
|
||||
func (n *network) releaseVxlanID() {
|
||||
n.Lock()
|
||||
vnis := make([]uint32, 0, len(n.subnets))
|
||||
for _, s := range n.subnets {
|
||||
vnis = append(vnis, s.vni)
|
||||
s.vni = 0
|
||||
}
|
||||
n.Unlock()
|
||||
|
||||
for _, vni := range vnis {
|
||||
n.driver.vxlanIdm.Release(uint64(vni))
|
||||
}
|
||||
}
|
||||
|
||||
func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
|
||||
}
|
||||
|
||||
func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (d *driver) DeleteNetwork(nid string) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) DeleteEndpoint(nid, eid string) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) {
|
||||
return nil, types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
// Join method is invoked when a Sandbox is attached to an endpoint.
|
||||
func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
// Leave method is invoked when a Sandbox detaches from an endpoint.
|
||||
func (d *driver) Leave(nid, eid string) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) Type() string {
|
||||
return networkType
|
||||
}
|
||||
|
||||
func (d *driver) IsBuiltIn() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster
|
||||
func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
// DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster
|
||||
func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
526
vendor/github.com/docker/libnetwork/drivers/overlay/peerdb.go
generated
vendored
526
vendor/github.com/docker/libnetwork/drivers/overlay/peerdb.go
generated
vendored
|
@ -1,526 +0,0 @@
|
|||
package overlay
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/docker/libnetwork/internal/caller"
|
||||
"github.com/docker/libnetwork/internal/setmatrix"
|
||||
"github.com/docker/libnetwork/osl"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const ovPeerTable = "overlay_peer_table"
|
||||
|
||||
type peerKey struct {
|
||||
peerIP net.IP
|
||||
peerMac net.HardwareAddr
|
||||
}
|
||||
|
||||
type peerEntry struct {
|
||||
eid string
|
||||
vtep net.IP
|
||||
peerIPMask net.IPMask
|
||||
isLocal bool
|
||||
}
|
||||
|
||||
func (p *peerEntry) MarshalDB() peerEntryDB {
|
||||
ones, bits := p.peerIPMask.Size()
|
||||
return peerEntryDB{
|
||||
eid: p.eid,
|
||||
vtep: p.vtep.String(),
|
||||
peerIPMaskOnes: ones,
|
||||
peerIPMaskBits: bits,
|
||||
isLocal: p.isLocal,
|
||||
}
|
||||
}
|
||||
|
||||
// This the structure saved into the set (SetMatrix), due to the implementation of it
|
||||
// the value inserted in the set has to be Hashable so the []byte had to be converted into
|
||||
// strings
|
||||
type peerEntryDB struct {
|
||||
eid string
|
||||
vtep string
|
||||
peerIPMaskOnes int
|
||||
peerIPMaskBits int
|
||||
isLocal bool
|
||||
}
|
||||
|
||||
func (p *peerEntryDB) UnMarshalDB() peerEntry {
|
||||
return peerEntry{
|
||||
eid: p.eid,
|
||||
vtep: net.ParseIP(p.vtep),
|
||||
peerIPMask: net.CIDRMask(p.peerIPMaskOnes, p.peerIPMaskBits),
|
||||
isLocal: p.isLocal,
|
||||
}
|
||||
}
|
||||
|
||||
type peerMap struct {
|
||||
// set of peerEntry, note they have to be objects and not pointers to maintain the proper equality checks
|
||||
mp setmatrix.SetMatrix
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
type peerNetworkMap struct {
|
||||
// map with key peerKey
|
||||
mp map[string]*peerMap
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
func (pKey peerKey) String() string {
|
||||
return fmt.Sprintf("%s %s", pKey.peerIP, pKey.peerMac)
|
||||
}
|
||||
|
||||
func (pKey *peerKey) Scan(state fmt.ScanState, verb rune) error {
|
||||
ipB, err := state.Token(true, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pKey.peerIP = net.ParseIP(string(ipB))
|
||||
|
||||
macB, err := state.Token(true, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pKey.peerMac, err = net.ParseMAC(string(macB))
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *driver) peerDbWalk(f func(string, *peerKey, *peerEntry) bool) error {
|
||||
d.peerDb.Lock()
|
||||
nids := []string{}
|
||||
for nid := range d.peerDb.mp {
|
||||
nids = append(nids, nid)
|
||||
}
|
||||
d.peerDb.Unlock()
|
||||
|
||||
for _, nid := range nids {
|
||||
d.peerDbNetworkWalk(nid, func(pKey *peerKey, pEntry *peerEntry) bool {
|
||||
return f(nid, pKey, pEntry)
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) peerDbNetworkWalk(nid string, f func(*peerKey, *peerEntry) bool) error {
|
||||
d.peerDb.Lock()
|
||||
pMap, ok := d.peerDb.mp[nid]
|
||||
d.peerDb.Unlock()
|
||||
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
mp := map[string]peerEntry{}
|
||||
pMap.Lock()
|
||||
for _, pKeyStr := range pMap.mp.Keys() {
|
||||
entryDBList, ok := pMap.mp.Get(pKeyStr)
|
||||
if ok {
|
||||
peerEntryDB := entryDBList[0].(peerEntryDB)
|
||||
mp[pKeyStr] = peerEntryDB.UnMarshalDB()
|
||||
}
|
||||
}
|
||||
pMap.Unlock()
|
||||
|
||||
for pKeyStr, pEntry := range mp {
|
||||
var pKey peerKey
|
||||
if _, err := fmt.Sscan(pKeyStr, &pKey); err != nil {
|
||||
logrus.Warnf("Peer key scan on network %s failed: %v", nid, err)
|
||||
}
|
||||
if f(&pKey, &pEntry) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) peerDbSearch(nid string, peerIP net.IP) (*peerKey, *peerEntry, error) {
|
||||
var pKeyMatched *peerKey
|
||||
var pEntryMatched *peerEntry
|
||||
err := d.peerDbNetworkWalk(nid, func(pKey *peerKey, pEntry *peerEntry) bool {
|
||||
if pKey.peerIP.Equal(peerIP) {
|
||||
pKeyMatched = pKey
|
||||
pEntryMatched = pEntry
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("peerdb search for peer ip %q failed: %v", peerIP, err)
|
||||
}
|
||||
|
||||
if pKeyMatched == nil || pEntryMatched == nil {
|
||||
return nil, nil, fmt.Errorf("peer ip %q not found in peerdb", peerIP)
|
||||
}
|
||||
|
||||
return pKeyMatched, pEntryMatched, nil
|
||||
}
|
||||
|
||||
func (d *driver) peerDbAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask,
|
||||
peerMac net.HardwareAddr, vtep net.IP, isLocal bool) (bool, int) {
|
||||
|
||||
d.peerDb.Lock()
|
||||
pMap, ok := d.peerDb.mp[nid]
|
||||
if !ok {
|
||||
d.peerDb.mp[nid] = &peerMap{
|
||||
mp: setmatrix.NewSetMatrix(),
|
||||
}
|
||||
|
||||
pMap = d.peerDb.mp[nid]
|
||||
}
|
||||
d.peerDb.Unlock()
|
||||
|
||||
pKey := peerKey{
|
||||
peerIP: peerIP,
|
||||
peerMac: peerMac,
|
||||
}
|
||||
|
||||
pEntry := peerEntry{
|
||||
eid: eid,
|
||||
vtep: vtep,
|
||||
peerIPMask: peerIPMask,
|
||||
isLocal: isLocal,
|
||||
}
|
||||
|
||||
pMap.Lock()
|
||||
defer pMap.Unlock()
|
||||
b, i := pMap.mp.Insert(pKey.String(), pEntry.MarshalDB())
|
||||
if i != 1 {
|
||||
// Transient case, there is more than one endpoint that is using the same IP,MAC pair
|
||||
s, _ := pMap.mp.String(pKey.String())
|
||||
logrus.Warnf("peerDbAdd transient condition - Key:%s cardinality:%d db state:%s", pKey.String(), i, s)
|
||||
}
|
||||
return b, i
|
||||
}
|
||||
|
||||
func (d *driver) peerDbDelete(nid, eid string, peerIP net.IP, peerIPMask net.IPMask,
|
||||
peerMac net.HardwareAddr, vtep net.IP, isLocal bool) (bool, int) {
|
||||
|
||||
d.peerDb.Lock()
|
||||
pMap, ok := d.peerDb.mp[nid]
|
||||
if !ok {
|
||||
d.peerDb.Unlock()
|
||||
return false, 0
|
||||
}
|
||||
d.peerDb.Unlock()
|
||||
|
||||
pKey := peerKey{
|
||||
peerIP: peerIP,
|
||||
peerMac: peerMac,
|
||||
}
|
||||
|
||||
pEntry := peerEntry{
|
||||
eid: eid,
|
||||
vtep: vtep,
|
||||
peerIPMask: peerIPMask,
|
||||
isLocal: isLocal,
|
||||
}
|
||||
|
||||
pMap.Lock()
|
||||
defer pMap.Unlock()
|
||||
b, i := pMap.mp.Remove(pKey.String(), pEntry.MarshalDB())
|
||||
if i != 0 {
|
||||
// Transient case, there is more than one endpoint that is using the same IP,MAC pair
|
||||
s, _ := pMap.mp.String(pKey.String())
|
||||
logrus.Warnf("peerDbDelete transient condition - Key:%s cardinality:%d db state:%s", pKey.String(), i, s)
|
||||
}
|
||||
return b, i
|
||||
}
|
||||
|
||||
// The overlay uses a lazy initialization approach, this means that when a network is created
|
||||
// and the driver registered the overlay does not allocate resources till the moment that a
|
||||
// sandbox is actually created.
|
||||
// At the moment of this call, that happens when a sandbox is initialized, is possible that
|
||||
// networkDB has already delivered some events of peers already available on remote nodes,
|
||||
// these peers are saved into the peerDB and this function is used to properly configure
|
||||
// the network sandbox with all those peers that got previously notified.
|
||||
// Note also that this method sends a single message on the channel and the go routine on the
|
||||
// other side, will atomically loop on the whole table of peers and will program their state
|
||||
// in one single atomic operation. This is fundamental to guarantee consistency, and avoid that
|
||||
// new peerAdd or peerDelete gets reordered during the sandbox init.
|
||||
func (d *driver) initSandboxPeerDB(nid string) {
|
||||
d.peerInit(nid)
|
||||
}
|
||||
|
||||
type peerOperationType int32
|
||||
|
||||
const (
|
||||
peerOperationINIT peerOperationType = iota
|
||||
peerOperationADD
|
||||
peerOperationDELETE
|
||||
peerOperationFLUSH
|
||||
)
|
||||
|
||||
type peerOperation struct {
|
||||
opType peerOperationType
|
||||
networkID string
|
||||
endpointID string
|
||||
peerIP net.IP
|
||||
peerIPMask net.IPMask
|
||||
peerMac net.HardwareAddr
|
||||
vtepIP net.IP
|
||||
l2Miss bool
|
||||
l3Miss bool
|
||||
localPeer bool
|
||||
callerName string
|
||||
}
|
||||
|
||||
func (d *driver) peerOpRoutine(ctx context.Context, ch chan *peerOperation) {
|
||||
var err error
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case op := <-ch:
|
||||
switch op.opType {
|
||||
case peerOperationINIT:
|
||||
err = d.peerInitOp(op.networkID)
|
||||
case peerOperationADD:
|
||||
err = d.peerAddOp(op.networkID, op.endpointID, op.peerIP, op.peerIPMask, op.peerMac, op.vtepIP, op.l2Miss, op.l3Miss, true, op.localPeer)
|
||||
case peerOperationDELETE:
|
||||
err = d.peerDeleteOp(op.networkID, op.endpointID, op.peerIP, op.peerIPMask, op.peerMac, op.vtepIP, op.localPeer)
|
||||
case peerOperationFLUSH:
|
||||
err = d.peerFlushOp(op.networkID)
|
||||
}
|
||||
if err != nil {
|
||||
logrus.Warnf("Peer operation failed:%s op:%v", err, op)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (d *driver) peerInit(nid string) {
|
||||
callerName := caller.Name(1)
|
||||
d.peerOpCh <- &peerOperation{
|
||||
opType: peerOperationINIT,
|
||||
networkID: nid,
|
||||
callerName: callerName,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *driver) peerInitOp(nid string) error {
|
||||
return d.peerDbNetworkWalk(nid, func(pKey *peerKey, pEntry *peerEntry) bool {
|
||||
// Local entries do not need to be added
|
||||
if pEntry.isLocal {
|
||||
return false
|
||||
}
|
||||
|
||||
d.peerAddOp(nid, pEntry.eid, pKey.peerIP, pEntry.peerIPMask, pKey.peerMac, pEntry.vtep, false, false, false, pEntry.isLocal)
|
||||
// return false to loop on all entries
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
func (d *driver) peerAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask,
|
||||
peerMac net.HardwareAddr, vtep net.IP, l2Miss, l3Miss, localPeer bool) {
|
||||
d.peerOpCh <- &peerOperation{
|
||||
opType: peerOperationADD,
|
||||
networkID: nid,
|
||||
endpointID: eid,
|
||||
peerIP: peerIP,
|
||||
peerIPMask: peerIPMask,
|
||||
peerMac: peerMac,
|
||||
vtepIP: vtep,
|
||||
l2Miss: l2Miss,
|
||||
l3Miss: l3Miss,
|
||||
localPeer: localPeer,
|
||||
callerName: caller.Name(1),
|
||||
}
|
||||
}
|
||||
|
||||
func (d *driver) peerAddOp(nid, eid string, peerIP net.IP, peerIPMask net.IPMask,
|
||||
peerMac net.HardwareAddr, vtep net.IP, l2Miss, l3Miss, updateDB, localPeer bool) error {
|
||||
|
||||
if err := validateID(nid, eid); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var dbEntries int
|
||||
var inserted bool
|
||||
if updateDB {
|
||||
inserted, dbEntries = d.peerDbAdd(nid, eid, peerIP, peerIPMask, peerMac, vtep, localPeer)
|
||||
if !inserted {
|
||||
logrus.Warnf("Entry already present in db: nid:%s eid:%s peerIP:%v peerMac:%v isLocal:%t vtep:%v",
|
||||
nid, eid, peerIP, peerMac, localPeer, vtep)
|
||||
}
|
||||
}
|
||||
|
||||
// Local peers do not need any further configuration
|
||||
if localPeer {
|
||||
return nil
|
||||
}
|
||||
|
||||
n := d.network(nid)
|
||||
if n == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
sbox := n.sandbox()
|
||||
if sbox == nil {
|
||||
// We are hitting this case for all the events that are arriving before that the sandbox
|
||||
// is being created. The peer got already added into the database and the sanbox init will
|
||||
// call the peerDbUpdateSandbox that will configure all these peers from the database
|
||||
return nil
|
||||
}
|
||||
|
||||
IP := &net.IPNet{
|
||||
IP: peerIP,
|
||||
Mask: peerIPMask,
|
||||
}
|
||||
|
||||
s := n.getSubnetforIP(IP)
|
||||
if s == nil {
|
||||
return fmt.Errorf("couldn't find the subnet %q in network %q", IP.String(), n.id)
|
||||
}
|
||||
|
||||
if err := n.obtainVxlanID(s); err != nil {
|
||||
return fmt.Errorf("couldn't get vxlan id for %q: %v", s.subnetIP.String(), err)
|
||||
}
|
||||
|
||||
if err := n.joinSandbox(s, false, false); err != nil {
|
||||
return fmt.Errorf("subnet sandbox join failed for %q: %v", s.subnetIP.String(), err)
|
||||
}
|
||||
|
||||
if err := d.checkEncryption(nid, vtep, n.vxlanID(s), false, true); err != nil {
|
||||
logrus.Warn(err)
|
||||
}
|
||||
|
||||
// Add neighbor entry for the peer IP
|
||||
if err := sbox.AddNeighbor(peerIP, peerMac, l3Miss, sbox.NeighborOptions().LinkName(s.vxlanName)); err != nil {
|
||||
if _, ok := err.(osl.NeighborSearchError); ok && dbEntries > 1 {
|
||||
// We are in the transient case so only the first configuration is programmed into the kernel
|
||||
// Upon deletion if the active configuration is deleted the next one from the database will be restored
|
||||
// Note we are skipping also the next configuration
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("could not add neighbor entry for nid:%s eid:%s into the sandbox:%v", nid, eid, err)
|
||||
}
|
||||
|
||||
// Add fdb entry to the bridge for the peer mac
|
||||
if err := sbox.AddNeighbor(vtep, peerMac, l2Miss, sbox.NeighborOptions().LinkName(s.vxlanName),
|
||||
sbox.NeighborOptions().Family(syscall.AF_BRIDGE)); err != nil {
|
||||
return fmt.Errorf("could not add fdb entry for nid:%s eid:%s into the sandbox:%v", nid, eid, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) peerDelete(nid, eid string, peerIP net.IP, peerIPMask net.IPMask,
|
||||
peerMac net.HardwareAddr, vtep net.IP, localPeer bool) {
|
||||
d.peerOpCh <- &peerOperation{
|
||||
opType: peerOperationDELETE,
|
||||
networkID: nid,
|
||||
endpointID: eid,
|
||||
peerIP: peerIP,
|
||||
peerIPMask: peerIPMask,
|
||||
peerMac: peerMac,
|
||||
vtepIP: vtep,
|
||||
callerName: caller.Name(1),
|
||||
localPeer: localPeer,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *driver) peerDeleteOp(nid, eid string, peerIP net.IP, peerIPMask net.IPMask,
|
||||
peerMac net.HardwareAddr, vtep net.IP, localPeer bool) error {
|
||||
|
||||
if err := validateID(nid, eid); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
deleted, dbEntries := d.peerDbDelete(nid, eid, peerIP, peerIPMask, peerMac, vtep, localPeer)
|
||||
if !deleted {
|
||||
logrus.Warnf("Entry was not in db: nid:%s eid:%s peerIP:%v peerMac:%v isLocal:%t vtep:%v",
|
||||
nid, eid, peerIP, peerMac, localPeer, vtep)
|
||||
}
|
||||
|
||||
n := d.network(nid)
|
||||
if n == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
sbox := n.sandbox()
|
||||
if sbox == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := d.checkEncryption(nid, vtep, 0, localPeer, false); err != nil {
|
||||
logrus.Warn(err)
|
||||
}
|
||||
|
||||
// Local peers do not have any local configuration to delete
|
||||
if !localPeer {
|
||||
// Remove fdb entry to the bridge for the peer mac
|
||||
if err := sbox.DeleteNeighbor(vtep, peerMac, true); err != nil {
|
||||
if _, ok := err.(osl.NeighborSearchError); ok && dbEntries > 0 {
|
||||
// We fall in here if there is a transient state and if the neighbor that is being deleted
|
||||
// was never been configured into the kernel (we allow only 1 configuration at the time per <ip,mac> mapping)
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("could not delete fdb entry for nid:%s eid:%s into the sandbox:%v", nid, eid, err)
|
||||
}
|
||||
|
||||
// Delete neighbor entry for the peer IP
|
||||
if err := sbox.DeleteNeighbor(peerIP, peerMac, true); err != nil {
|
||||
return fmt.Errorf("could not delete neighbor entry for nid:%s eid:%s into the sandbox:%v", nid, eid, err)
|
||||
}
|
||||
}
|
||||
|
||||
if dbEntries == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// If there is still an entry into the database and the deletion went through without errors means that there is now no
|
||||
// configuration active in the kernel.
|
||||
// Restore one configuration for the <ip,mac> directly from the database, note that is guaranteed that there is one
|
||||
peerKey, peerEntry, err := d.peerDbSearch(nid, peerIP)
|
||||
if err != nil {
|
||||
logrus.Errorf("peerDeleteOp unable to restore a configuration for nid:%s ip:%v mac:%v err:%s", nid, peerIP, peerMac, err)
|
||||
return err
|
||||
}
|
||||
return d.peerAddOp(nid, peerEntry.eid, peerIP, peerEntry.peerIPMask, peerKey.peerMac, peerEntry.vtep, false, false, false, peerEntry.isLocal)
|
||||
}
|
||||
|
||||
func (d *driver) peerFlush(nid string) {
|
||||
d.peerOpCh <- &peerOperation{
|
||||
opType: peerOperationFLUSH,
|
||||
networkID: nid,
|
||||
callerName: caller.Name(1),
|
||||
}
|
||||
}
|
||||
|
||||
func (d *driver) peerFlushOp(nid string) error {
|
||||
d.peerDb.Lock()
|
||||
defer d.peerDb.Unlock()
|
||||
_, ok := d.peerDb.mp[nid]
|
||||
if !ok {
|
||||
return fmt.Errorf("Unable to find the peerDB for nid:%s", nid)
|
||||
}
|
||||
delete(d.peerDb.mp, nid)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) pushLocalDb() {
|
||||
d.peerDbWalk(func(nid string, pKey *peerKey, pEntry *peerEntry) bool {
|
||||
if pEntry.isLocal {
|
||||
d.pushLocalEndpointEvent("join", nid, pEntry.eid)
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
func (d *driver) peerDBUpdateSelf() {
|
||||
d.peerDbWalk(func(nid string, pkey *peerKey, pEntry *peerEntry) bool {
|
||||
if pEntry.isLocal {
|
||||
pEntry.vtep = net.ParseIP(d.advertiseAddress)
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
221
vendor/github.com/docker/libnetwork/drivers/remote/api/api.go
generated
vendored
221
vendor/github.com/docker/libnetwork/drivers/remote/api/api.go
generated
vendored
|
@ -1,221 +0,0 @@
|
|||
/*
|
||||
Package api represents all requests and responses suitable for conversation
|
||||
with a remote driver.
|
||||
*/
|
||||
package api
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/docker/libnetwork/discoverapi"
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
)
|
||||
|
||||
// Response is the basic response structure used in all responses.
|
||||
type Response struct {
|
||||
Err string
|
||||
}
|
||||
|
||||
// GetError returns the error from the response, if any.
|
||||
func (r *Response) GetError() string {
|
||||
return r.Err
|
||||
}
|
||||
|
||||
// GetCapabilityResponse is the response of GetCapability request
|
||||
type GetCapabilityResponse struct {
|
||||
Response
|
||||
Scope string
|
||||
ConnectivityScope string
|
||||
}
|
||||
|
||||
// AllocateNetworkRequest requests allocation of new network by manager
|
||||
type AllocateNetworkRequest struct {
|
||||
// A network ID that remote plugins are expected to store for future
|
||||
// reference.
|
||||
NetworkID string
|
||||
|
||||
// A free form map->object interface for communication of options.
|
||||
Options map[string]string
|
||||
|
||||
// IPAMData contains the address pool information for this network
|
||||
IPv4Data, IPv6Data []driverapi.IPAMData
|
||||
}
|
||||
|
||||
// AllocateNetworkResponse is the response to the AllocateNetworkRequest.
|
||||
type AllocateNetworkResponse struct {
|
||||
Response
|
||||
// A free form plugin specific string->string object to be sent in
|
||||
// CreateNetworkRequest call in the libnetwork agents
|
||||
Options map[string]string
|
||||
}
|
||||
|
||||
// FreeNetworkRequest is the request to free allocated network in the manager
|
||||
type FreeNetworkRequest struct {
|
||||
// The ID of the network to be freed.
|
||||
NetworkID string
|
||||
}
|
||||
|
||||
// FreeNetworkResponse is the response to a request for freeing a network.
|
||||
type FreeNetworkResponse struct {
|
||||
Response
|
||||
}
|
||||
|
||||
// CreateNetworkRequest requests a new network.
|
||||
type CreateNetworkRequest struct {
|
||||
// A network ID that remote plugins are expected to store for future
|
||||
// reference.
|
||||
NetworkID string
|
||||
|
||||
// A free form map->object interface for communication of options.
|
||||
Options map[string]interface{}
|
||||
|
||||
// IPAMData contains the address pool information for this network
|
||||
IPv4Data, IPv6Data []driverapi.IPAMData
|
||||
}
|
||||
|
||||
// CreateNetworkResponse is the response to the CreateNetworkRequest.
|
||||
type CreateNetworkResponse struct {
|
||||
Response
|
||||
}
|
||||
|
||||
// DeleteNetworkRequest is the request to delete an existing network.
|
||||
type DeleteNetworkRequest struct {
|
||||
// The ID of the network to delete.
|
||||
NetworkID string
|
||||
}
|
||||
|
||||
// DeleteNetworkResponse is the response to a request for deleting a network.
|
||||
type DeleteNetworkResponse struct {
|
||||
Response
|
||||
}
|
||||
|
||||
// CreateEndpointRequest is the request to create an endpoint within a network.
|
||||
type CreateEndpointRequest struct {
|
||||
// Provided at create time, this will be the network id referenced.
|
||||
NetworkID string
|
||||
// The ID of the endpoint for later reference.
|
||||
EndpointID string
|
||||
Interface *EndpointInterface
|
||||
Options map[string]interface{}
|
||||
}
|
||||
|
||||
// EndpointInterface represents an interface endpoint.
|
||||
type EndpointInterface struct {
|
||||
Address string
|
||||
AddressIPv6 string
|
||||
MacAddress string
|
||||
}
|
||||
|
||||
// CreateEndpointResponse is the response to the CreateEndpoint action.
|
||||
type CreateEndpointResponse struct {
|
||||
Response
|
||||
Interface *EndpointInterface
|
||||
}
|
||||
|
||||
// Interface is the representation of a linux interface.
|
||||
type Interface struct {
|
||||
Address *net.IPNet
|
||||
AddressIPv6 *net.IPNet
|
||||
MacAddress net.HardwareAddr
|
||||
}
|
||||
|
||||
// DeleteEndpointRequest describes the API for deleting an endpoint.
|
||||
type DeleteEndpointRequest struct {
|
||||
NetworkID string
|
||||
EndpointID string
|
||||
}
|
||||
|
||||
// DeleteEndpointResponse is the response to the DeleteEndpoint action.
|
||||
type DeleteEndpointResponse struct {
|
||||
Response
|
||||
}
|
||||
|
||||
// EndpointInfoRequest retrieves information about the endpoint from the network driver.
|
||||
type EndpointInfoRequest struct {
|
||||
NetworkID string
|
||||
EndpointID string
|
||||
}
|
||||
|
||||
// EndpointInfoResponse is the response to an EndpointInfoRequest.
|
||||
type EndpointInfoResponse struct {
|
||||
Response
|
||||
Value map[string]interface{}
|
||||
}
|
||||
|
||||
// JoinRequest describes the API for joining an endpoint to a sandbox.
|
||||
type JoinRequest struct {
|
||||
NetworkID string
|
||||
EndpointID string
|
||||
SandboxKey string
|
||||
Options map[string]interface{}
|
||||
}
|
||||
|
||||
// InterfaceName is the struct representation of a pair of devices with source
|
||||
// and destination, for the purposes of putting an endpoint into a container.
|
||||
type InterfaceName struct {
|
||||
SrcName string
|
||||
DstName string
|
||||
DstPrefix string
|
||||
}
|
||||
|
||||
// StaticRoute is the plain JSON representation of a static route.
|
||||
type StaticRoute struct {
|
||||
Destination string
|
||||
RouteType int
|
||||
NextHop string
|
||||
}
|
||||
|
||||
// JoinResponse is the response to a JoinRequest.
|
||||
type JoinResponse struct {
|
||||
Response
|
||||
InterfaceName *InterfaceName
|
||||
Gateway string
|
||||
GatewayIPv6 string
|
||||
StaticRoutes []StaticRoute
|
||||
DisableGatewayService bool
|
||||
}
|
||||
|
||||
// LeaveRequest describes the API for detaching an endpoint from a sandbox.
|
||||
type LeaveRequest struct {
|
||||
NetworkID string
|
||||
EndpointID string
|
||||
}
|
||||
|
||||
// LeaveResponse is the answer to LeaveRequest.
|
||||
type LeaveResponse struct {
|
||||
Response
|
||||
}
|
||||
|
||||
// ProgramExternalConnectivityRequest describes the API for programming the external connectivity for the given endpoint.
|
||||
type ProgramExternalConnectivityRequest struct {
|
||||
NetworkID string
|
||||
EndpointID string
|
||||
Options map[string]interface{}
|
||||
}
|
||||
|
||||
// ProgramExternalConnectivityResponse is the answer to ProgramExternalConnectivityRequest.
|
||||
type ProgramExternalConnectivityResponse struct {
|
||||
Response
|
||||
}
|
||||
|
||||
// RevokeExternalConnectivityRequest describes the API for revoking the external connectivity for the given endpoint.
|
||||
type RevokeExternalConnectivityRequest struct {
|
||||
NetworkID string
|
||||
EndpointID string
|
||||
}
|
||||
|
||||
// RevokeExternalConnectivityResponse is the answer to RevokeExternalConnectivityRequest.
|
||||
type RevokeExternalConnectivityResponse struct {
|
||||
Response
|
||||
}
|
||||
|
||||
// DiscoveryNotification represents a discovery notification
|
||||
type DiscoveryNotification struct {
|
||||
DiscoveryType discoverapi.DiscoveryType
|
||||
DiscoveryData interface{}
|
||||
}
|
||||
|
||||
// DiscoveryResponse is used by libnetwork to log any plugin error processing the discovery notifications
|
||||
type DiscoveryResponse struct {
|
||||
Response
|
||||
}
|
436
vendor/github.com/docker/libnetwork/drivers/remote/driver.go
generated
vendored
436
vendor/github.com/docker/libnetwork/drivers/remote/driver.go
generated
vendored
|
@ -1,436 +0,0 @@
|
|||
package remote
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/docker/docker/pkg/plugingetter"
|
||||
"github.com/docker/docker/pkg/plugins"
|
||||
"github.com/docker/libnetwork/datastore"
|
||||
"github.com/docker/libnetwork/discoverapi"
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/drivers/remote/api"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type driver struct {
|
||||
endpoint *plugins.Client
|
||||
networkType string
|
||||
}
|
||||
|
||||
type maybeError interface {
|
||||
GetError() string
|
||||
}
|
||||
|
||||
func newDriver(name string, client *plugins.Client) driverapi.Driver {
|
||||
return &driver{networkType: name, endpoint: client}
|
||||
}
|
||||
|
||||
// Init makes sure a remote driver is registered when a network driver
|
||||
// plugin is activated.
|
||||
func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
||||
newPluginHandler := func(name string, client *plugins.Client) {
|
||||
// negotiate driver capability with client
|
||||
d := newDriver(name, client)
|
||||
c, err := d.(*driver).getCapabilities()
|
||||
if err != nil {
|
||||
logrus.Errorf("error getting capability for %s due to %v", name, err)
|
||||
return
|
||||
}
|
||||
if err = dc.RegisterDriver(name, d, *c); err != nil {
|
||||
logrus.Errorf("error registering driver for %s due to %v", name, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Unit test code is unaware of a true PluginStore. So we fall back to v1 plugins.
|
||||
handleFunc := plugins.Handle
|
||||
if pg := dc.GetPluginGetter(); pg != nil {
|
||||
handleFunc = pg.Handle
|
||||
activePlugins := pg.GetAllManagedPluginsByCap(driverapi.NetworkPluginEndpointType)
|
||||
for _, ap := range activePlugins {
|
||||
client, err := getPluginClient(ap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newPluginHandler(ap.Name(), client)
|
||||
}
|
||||
}
|
||||
handleFunc(driverapi.NetworkPluginEndpointType, newPluginHandler)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getPluginClient(p plugingetter.CompatPlugin) (*plugins.Client, error) {
|
||||
if v1, ok := p.(plugingetter.PluginWithV1Client); ok {
|
||||
return v1.Client(), nil
|
||||
}
|
||||
|
||||
pa, ok := p.(plugingetter.PluginAddr)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("unknown plugin type %T", p)
|
||||
}
|
||||
|
||||
if pa.Protocol() != plugins.ProtocolSchemeHTTPV1 {
|
||||
return nil, errors.Errorf("unsupported plugin protocol %s", pa.Protocol())
|
||||
}
|
||||
|
||||
addr := pa.Addr()
|
||||
client, err := plugins.NewClientWithTimeout(addr.Network()+"://"+addr.String(), nil, pa.Timeout())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error creating plugin client")
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// Get capability from client
|
||||
func (d *driver) getCapabilities() (*driverapi.Capability, error) {
|
||||
var capResp api.GetCapabilityResponse
|
||||
if err := d.call("GetCapabilities", nil, &capResp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c := &driverapi.Capability{}
|
||||
switch capResp.Scope {
|
||||
case "global":
|
||||
c.DataScope = datastore.GlobalScope
|
||||
case "local":
|
||||
c.DataScope = datastore.LocalScope
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid capability: expecting 'local' or 'global', got %s", capResp.Scope)
|
||||
}
|
||||
|
||||
switch capResp.ConnectivityScope {
|
||||
case "global":
|
||||
c.ConnectivityScope = datastore.GlobalScope
|
||||
case "local":
|
||||
c.ConnectivityScope = datastore.LocalScope
|
||||
case "":
|
||||
c.ConnectivityScope = c.DataScope
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid capability: expecting 'local' or 'global', got %s", capResp.Scope)
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// Config is not implemented for remote drivers, since it is assumed
|
||||
// to be supplied to the remote process out-of-band (e.g., as command
|
||||
// line arguments).
|
||||
func (d *driver) Config(option map[string]interface{}) error {
|
||||
return &driverapi.ErrNotImplemented{}
|
||||
}
|
||||
|
||||
func (d *driver) call(methodName string, arg interface{}, retVal maybeError) error {
|
||||
method := driverapi.NetworkPluginEndpointType + "." + methodName
|
||||
err := d.endpoint.Call(method, arg, retVal)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if e := retVal.GetError(); e != "" {
|
||||
return fmt.Errorf("remote: %s", e)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) NetworkAllocate(id string, options map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {
|
||||
create := &api.AllocateNetworkRequest{
|
||||
NetworkID: id,
|
||||
Options: options,
|
||||
IPv4Data: ipV4Data,
|
||||
IPv6Data: ipV6Data,
|
||||
}
|
||||
retVal := api.AllocateNetworkResponse{}
|
||||
err := d.call("AllocateNetwork", create, &retVal)
|
||||
return retVal.Options, err
|
||||
}
|
||||
|
||||
func (d *driver) NetworkFree(id string) error {
|
||||
fr := &api.FreeNetworkRequest{NetworkID: id}
|
||||
return d.call("FreeNetwork", fr, &api.FreeNetworkResponse{})
|
||||
}
|
||||
|
||||
func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
|
||||
}
|
||||
|
||||
func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (d *driver) CreateNetwork(id string, options map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
|
||||
create := &api.CreateNetworkRequest{
|
||||
NetworkID: id,
|
||||
Options: options,
|
||||
IPv4Data: ipV4Data,
|
||||
IPv6Data: ipV6Data,
|
||||
}
|
||||
return d.call("CreateNetwork", create, &api.CreateNetworkResponse{})
|
||||
}
|
||||
|
||||
func (d *driver) DeleteNetwork(nid string) error {
|
||||
delete := &api.DeleteNetworkRequest{NetworkID: nid}
|
||||
return d.call("DeleteNetwork", delete, &api.DeleteNetworkResponse{})
|
||||
}
|
||||
|
||||
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error {
|
||||
if ifInfo == nil {
|
||||
return errors.New("must not be called with nil InterfaceInfo")
|
||||
}
|
||||
|
||||
reqIface := &api.EndpointInterface{}
|
||||
if ifInfo.Address() != nil {
|
||||
reqIface.Address = ifInfo.Address().String()
|
||||
}
|
||||
if ifInfo.AddressIPv6() != nil {
|
||||
reqIface.AddressIPv6 = ifInfo.AddressIPv6().String()
|
||||
}
|
||||
if ifInfo.MacAddress() != nil {
|
||||
reqIface.MacAddress = ifInfo.MacAddress().String()
|
||||
}
|
||||
|
||||
create := &api.CreateEndpointRequest{
|
||||
NetworkID: nid,
|
||||
EndpointID: eid,
|
||||
Interface: reqIface,
|
||||
Options: epOptions,
|
||||
}
|
||||
var res api.CreateEndpointResponse
|
||||
if err := d.call("CreateEndpoint", create, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
inIface, err := parseInterface(res)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if inIface == nil {
|
||||
// Remote driver did not set any field
|
||||
return nil
|
||||
}
|
||||
|
||||
if inIface.MacAddress != nil {
|
||||
if err := ifInfo.SetMacAddress(inIface.MacAddress); err != nil {
|
||||
return errorWithRollback(fmt.Sprintf("driver modified interface MAC address: %v", err), d.DeleteEndpoint(nid, eid))
|
||||
}
|
||||
}
|
||||
if inIface.Address != nil {
|
||||
if err := ifInfo.SetIPAddress(inIface.Address); err != nil {
|
||||
return errorWithRollback(fmt.Sprintf("driver modified interface address: %v", err), d.DeleteEndpoint(nid, eid))
|
||||
}
|
||||
}
|
||||
if inIface.AddressIPv6 != nil {
|
||||
if err := ifInfo.SetIPAddress(inIface.AddressIPv6); err != nil {
|
||||
return errorWithRollback(fmt.Sprintf("driver modified interface address: %v", err), d.DeleteEndpoint(nid, eid))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func errorWithRollback(msg string, err error) error {
|
||||
rollback := "rolled back"
|
||||
if err != nil {
|
||||
rollback = "failed to roll back: " + err.Error()
|
||||
}
|
||||
return fmt.Errorf("%s; %s", msg, rollback)
|
||||
}
|
||||
|
||||
func (d *driver) DeleteEndpoint(nid, eid string) error {
|
||||
delete := &api.DeleteEndpointRequest{
|
||||
NetworkID: nid,
|
||||
EndpointID: eid,
|
||||
}
|
||||
return d.call("DeleteEndpoint", delete, &api.DeleteEndpointResponse{})
|
||||
}
|
||||
|
||||
func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) {
|
||||
info := &api.EndpointInfoRequest{
|
||||
NetworkID: nid,
|
||||
EndpointID: eid,
|
||||
}
|
||||
var res api.EndpointInfoResponse
|
||||
if err := d.call("EndpointOperInfo", info, &res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res.Value, nil
|
||||
}
|
||||
|
||||
// Join method is invoked when a Sandbox is attached to an endpoint.
|
||||
func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
||||
join := &api.JoinRequest{
|
||||
NetworkID: nid,
|
||||
EndpointID: eid,
|
||||
SandboxKey: sboxKey,
|
||||
Options: options,
|
||||
}
|
||||
var (
|
||||
res api.JoinResponse
|
||||
err error
|
||||
)
|
||||
if err = d.call("Join", join, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ifaceName := res.InterfaceName
|
||||
if iface := jinfo.InterfaceName(); iface != nil && ifaceName != nil {
|
||||
if err := iface.SetNames(ifaceName.SrcName, ifaceName.DstPrefix); err != nil {
|
||||
return errorWithRollback(fmt.Sprintf("failed to set interface name: %s", err), d.Leave(nid, eid))
|
||||
}
|
||||
}
|
||||
|
||||
var addr net.IP
|
||||
if res.Gateway != "" {
|
||||
if addr = net.ParseIP(res.Gateway); addr == nil {
|
||||
return fmt.Errorf(`unable to parse Gateway "%s"`, res.Gateway)
|
||||
}
|
||||
if jinfo.SetGateway(addr) != nil {
|
||||
return errorWithRollback(fmt.Sprintf("failed to set gateway: %v", addr), d.Leave(nid, eid))
|
||||
}
|
||||
}
|
||||
if res.GatewayIPv6 != "" {
|
||||
if addr = net.ParseIP(res.GatewayIPv6); addr == nil {
|
||||
return fmt.Errorf(`unable to parse GatewayIPv6 "%s"`, res.GatewayIPv6)
|
||||
}
|
||||
if jinfo.SetGatewayIPv6(addr) != nil {
|
||||
return errorWithRollback(fmt.Sprintf("failed to set gateway IPv6: %v", addr), d.Leave(nid, eid))
|
||||
}
|
||||
}
|
||||
if len(res.StaticRoutes) > 0 {
|
||||
routes, err := parseStaticRoutes(res)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, route := range routes {
|
||||
if jinfo.AddStaticRoute(route.Destination, route.RouteType, route.NextHop) != nil {
|
||||
return errorWithRollback(fmt.Sprintf("failed to set static route: %v", route), d.Leave(nid, eid))
|
||||
}
|
||||
}
|
||||
}
|
||||
if res.DisableGatewayService {
|
||||
jinfo.DisableGatewayService()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Leave method is invoked when a Sandbox detaches from an endpoint.
|
||||
func (d *driver) Leave(nid, eid string) error {
|
||||
leave := &api.LeaveRequest{
|
||||
NetworkID: nid,
|
||||
EndpointID: eid,
|
||||
}
|
||||
return d.call("Leave", leave, &api.LeaveResponse{})
|
||||
}
|
||||
|
||||
// ProgramExternalConnectivity is invoked to program the rules to allow external connectivity for the endpoint.
|
||||
func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
||||
data := &api.ProgramExternalConnectivityRequest{
|
||||
NetworkID: nid,
|
||||
EndpointID: eid,
|
||||
Options: options,
|
||||
}
|
||||
err := d.call("ProgramExternalConnectivity", data, &api.ProgramExternalConnectivityResponse{})
|
||||
if err != nil && plugins.IsNotFound(err) {
|
||||
// It is not mandatory yet to support this method
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// RevokeExternalConnectivity method is invoked to remove any external connectivity programming related to the endpoint.
|
||||
func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
||||
data := &api.RevokeExternalConnectivityRequest{
|
||||
NetworkID: nid,
|
||||
EndpointID: eid,
|
||||
}
|
||||
err := d.call("RevokeExternalConnectivity", data, &api.RevokeExternalConnectivityResponse{})
|
||||
if err != nil && plugins.IsNotFound(err) {
|
||||
// It is not mandatory yet to support this method
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *driver) Type() string {
|
||||
return d.networkType
|
||||
}
|
||||
|
||||
func (d *driver) IsBuiltIn() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster
|
||||
func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||
if dType != discoverapi.NodeDiscovery {
|
||||
return nil
|
||||
}
|
||||
notif := &api.DiscoveryNotification{
|
||||
DiscoveryType: dType,
|
||||
DiscoveryData: data,
|
||||
}
|
||||
return d.call("DiscoverNew", notif, &api.DiscoveryResponse{})
|
||||
}
|
||||
|
||||
// DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster
|
||||
func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||
if dType != discoverapi.NodeDiscovery {
|
||||
return nil
|
||||
}
|
||||
notif := &api.DiscoveryNotification{
|
||||
DiscoveryType: dType,
|
||||
DiscoveryData: data,
|
||||
}
|
||||
return d.call("DiscoverDelete", notif, &api.DiscoveryResponse{})
|
||||
}
|
||||
|
||||
func parseStaticRoutes(r api.JoinResponse) ([]*types.StaticRoute, error) {
|
||||
var routes = make([]*types.StaticRoute, len(r.StaticRoutes))
|
||||
for i, inRoute := range r.StaticRoutes {
|
||||
var err error
|
||||
outRoute := &types.StaticRoute{RouteType: inRoute.RouteType}
|
||||
|
||||
if inRoute.Destination != "" {
|
||||
if outRoute.Destination, err = types.ParseCIDR(inRoute.Destination); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if inRoute.NextHop != "" {
|
||||
outRoute.NextHop = net.ParseIP(inRoute.NextHop)
|
||||
if outRoute.NextHop == nil {
|
||||
return nil, fmt.Errorf("failed to parse nexthop IP %s", inRoute.NextHop)
|
||||
}
|
||||
}
|
||||
|
||||
routes[i] = outRoute
|
||||
}
|
||||
return routes, nil
|
||||
}
|
||||
|
||||
// parseInterfaces validates all the parameters of an Interface and returns them.
|
||||
func parseInterface(r api.CreateEndpointResponse) (*api.Interface, error) {
|
||||
var outIf *api.Interface
|
||||
|
||||
inIf := r.Interface
|
||||
if inIf != nil {
|
||||
var err error
|
||||
outIf = &api.Interface{}
|
||||
if inIf.Address != "" {
|
||||
if outIf.Address, err = types.ParseCIDR(inIf.Address); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if inIf.AddressIPv6 != "" {
|
||||
if outIf.AddressIPv6, err = types.ParseCIDR(inIf.AddressIPv6); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if inIf.MacAddress != "" {
|
||||
if outIf.MacAddress, err = net.ParseMAC(inIf.MacAddress); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outIf, nil
|
||||
}
|
51
vendor/github.com/docker/libnetwork/drivers/windows/labels.go
generated
vendored
51
vendor/github.com/docker/libnetwork/drivers/windows/labels.go
generated
vendored
|
@ -1,51 +0,0 @@
|
|||
package windows
|
||||
|
||||
const (
|
||||
// NetworkName label for bridge driver
|
||||
NetworkName = "com.docker.network.windowsshim.networkname"
|
||||
|
||||
// HNSID of the discovered network
|
||||
HNSID = "com.docker.network.windowsshim.hnsid"
|
||||
|
||||
// RoutingDomain of the network
|
||||
RoutingDomain = "com.docker.network.windowsshim.routingdomain"
|
||||
|
||||
// Interface of the network
|
||||
Interface = "com.docker.network.windowsshim.interface"
|
||||
|
||||
// QosPolicies of the endpoint
|
||||
QosPolicies = "com.docker.endpoint.windowsshim.qospolicies"
|
||||
|
||||
// VLAN of the network
|
||||
VLAN = "com.docker.network.windowsshim.vlanid"
|
||||
|
||||
// VSID of the network
|
||||
VSID = "com.docker.network.windowsshim.vsid"
|
||||
|
||||
// DNSSuffix of the network
|
||||
DNSSuffix = "com.docker.network.windowsshim.dnssuffix"
|
||||
|
||||
// DNSServers of the network
|
||||
DNSServers = "com.docker.network.windowsshim.dnsservers"
|
||||
|
||||
// MacPool of the network
|
||||
MacPool = "com.docker.network.windowsshim.macpool"
|
||||
|
||||
// SourceMac of the network
|
||||
SourceMac = "com.docker.network.windowsshim.sourcemac"
|
||||
|
||||
// DisableICC label
|
||||
DisableICC = "com.docker.network.windowsshim.disableicc"
|
||||
|
||||
// DisableDNS label
|
||||
DisableDNS = "com.docker.network.windowsshim.disable_dns"
|
||||
|
||||
// DisableGatewayDNS label
|
||||
DisableGatewayDNS = "com.docker.network.windowsshim.disable_gatewaydns"
|
||||
|
||||
// EnableOutboundNat label
|
||||
EnableOutboundNat = "com.docker.network.windowsshim.enable_outboundnat"
|
||||
|
||||
// OutboundNatExceptions label
|
||||
OutboundNatExceptions = "com.docker.network.windowsshim.outboundnat_exceptions"
|
||||
)
|
115
vendor/github.com/docker/libnetwork/drivers/windows/overlay/joinleave_windows.go
generated
vendored
115
vendor/github.com/docker/libnetwork/drivers/windows/overlay/joinleave_windows.go
generated
vendored
|
@ -1,115 +0,0 @@
|
|||
package overlay
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Join method is invoked when a Sandbox is attached to an endpoint.
|
||||
func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
||||
if err := validateID(nid, eid); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n := d.network(nid)
|
||||
if n == nil {
|
||||
return fmt.Errorf("could not find network with id %s", nid)
|
||||
}
|
||||
|
||||
ep := n.endpoint(eid)
|
||||
if ep == nil {
|
||||
return fmt.Errorf("could not find endpoint with id %s", eid)
|
||||
}
|
||||
|
||||
buf, err := proto.Marshal(&PeerRecord{
|
||||
EndpointIP: ep.addr.String(),
|
||||
EndpointMAC: ep.mac.String(),
|
||||
TunnelEndpointIP: n.providerAddress,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := jinfo.AddTableEntry(ovPeerTable, eid, buf); err != nil {
|
||||
logrus.Errorf("overlay: Failed adding table entry to joininfo: %v", err)
|
||||
}
|
||||
|
||||
if ep.disablegateway {
|
||||
jinfo.DisableGatewayService()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
|
||||
if tableName != ovPeerTable {
|
||||
logrus.Errorf("Unexpected table notification for table %s received", tableName)
|
||||
return
|
||||
}
|
||||
|
||||
eid := key
|
||||
|
||||
var peer PeerRecord
|
||||
if err := proto.Unmarshal(value, &peer); err != nil {
|
||||
logrus.Errorf("Failed to unmarshal peer record: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
n := d.network(nid)
|
||||
if n == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Ignore local peers. We already know about them and they
|
||||
// should not be added to vxlan fdb.
|
||||
if peer.TunnelEndpointIP == n.providerAddress {
|
||||
return
|
||||
}
|
||||
|
||||
addr, err := types.ParseCIDR(peer.EndpointIP)
|
||||
if err != nil {
|
||||
logrus.Errorf("Invalid peer IP %s received in event notify", peer.EndpointIP)
|
||||
return
|
||||
}
|
||||
|
||||
mac, err := net.ParseMAC(peer.EndpointMAC)
|
||||
if err != nil {
|
||||
logrus.Errorf("Invalid mac %s received in event notify", peer.EndpointMAC)
|
||||
return
|
||||
}
|
||||
|
||||
vtep := net.ParseIP(peer.TunnelEndpointIP)
|
||||
if vtep == nil {
|
||||
logrus.Errorf("Invalid VTEP %s received in event notify", peer.TunnelEndpointIP)
|
||||
return
|
||||
}
|
||||
|
||||
if etype == driverapi.Delete {
|
||||
d.peerDelete(nid, eid, addr.IP, addr.Mask, mac, vtep, true)
|
||||
return
|
||||
}
|
||||
|
||||
err = d.peerAdd(nid, eid, addr.IP, addr.Mask, mac, vtep, true)
|
||||
if err != nil {
|
||||
logrus.Errorf("peerAdd failed (%v) for ip %s with mac %s", err, addr.IP.String(), mac.String())
|
||||
}
|
||||
}
|
||||
|
||||
func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// Leave method is invoked when a Sandbox detaches from an endpoint.
|
||||
func (d *driver) Leave(nid, eid string) error {
|
||||
if err := validateID(nid, eid); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
296
vendor/github.com/docker/libnetwork/drivers/windows/overlay/ov_endpoint_windows.go
generated
vendored
296
vendor/github.com/docker/libnetwork/drivers/windows/overlay/ov_endpoint_windows.go
generated
vendored
|
@ -1,296 +0,0 @@
|
|||
package overlay
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"github.com/Microsoft/hcsshim"
|
||||
"github.com/Microsoft/hcsshim/osversion"
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/drivers/windows"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type endpointTable map[string]*endpoint
|
||||
|
||||
const overlayEndpointPrefix = "overlay/endpoint"
|
||||
|
||||
type endpoint struct {
|
||||
id string
|
||||
nid string
|
||||
profileID string
|
||||
remote bool
|
||||
mac net.HardwareAddr
|
||||
addr *net.IPNet
|
||||
disablegateway bool
|
||||
portMapping []types.PortBinding // Operation port bindings
|
||||
}
|
||||
|
||||
var (
|
||||
//Server 2016 (RS1) does not support concurrent add/delete of endpoints. Therefore, we need
|
||||
//to use this mutex and serialize the add/delete of endpoints on RS1.
|
||||
endpointMu sync.Mutex
|
||||
windowsBuild = osversion.Build()
|
||||
)
|
||||
|
||||
func validateID(nid, eid string) error {
|
||||
if nid == "" {
|
||||
return fmt.Errorf("invalid network id")
|
||||
}
|
||||
|
||||
if eid == "" {
|
||||
return fmt.Errorf("invalid endpoint id")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *network) endpoint(eid string) *endpoint {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
||||
return n.endpoints[eid]
|
||||
}
|
||||
|
||||
func (n *network) addEndpoint(ep *endpoint) {
|
||||
n.Lock()
|
||||
n.endpoints[ep.id] = ep
|
||||
n.Unlock()
|
||||
}
|
||||
|
||||
func (n *network) deleteEndpoint(eid string) {
|
||||
n.Lock()
|
||||
delete(n.endpoints, eid)
|
||||
n.Unlock()
|
||||
}
|
||||
|
||||
func (n *network) removeEndpointWithAddress(addr *net.IPNet) {
|
||||
var networkEndpoint *endpoint
|
||||
n.Lock()
|
||||
for _, ep := range n.endpoints {
|
||||
if ep.addr.IP.Equal(addr.IP) {
|
||||
networkEndpoint = ep
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if networkEndpoint != nil {
|
||||
delete(n.endpoints, networkEndpoint.id)
|
||||
}
|
||||
n.Unlock()
|
||||
|
||||
if networkEndpoint != nil {
|
||||
logrus.Debugf("Removing stale endpoint from HNS")
|
||||
_, err := endpointRequest("DELETE", networkEndpoint.profileID, "")
|
||||
if err != nil {
|
||||
logrus.Debugf("Failed to delete stale overlay endpoint (%.7s) from hns", networkEndpoint.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
|
||||
epOptions map[string]interface{}) error {
|
||||
var err error
|
||||
if err = validateID(nid, eid); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n := d.network(nid)
|
||||
if n == nil {
|
||||
return fmt.Errorf("network id %q not found", nid)
|
||||
}
|
||||
|
||||
ep := n.endpoint(eid)
|
||||
if ep != nil {
|
||||
logrus.Debugf("Deleting stale endpoint %s", eid)
|
||||
n.deleteEndpoint(eid)
|
||||
_, err := endpointRequest("DELETE", ep.profileID, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
ep = &endpoint{
|
||||
id: eid,
|
||||
nid: n.id,
|
||||
addr: ifInfo.Address(),
|
||||
mac: ifInfo.MacAddress(),
|
||||
}
|
||||
|
||||
if ep.addr == nil {
|
||||
return fmt.Errorf("create endpoint was not passed interface IP address")
|
||||
}
|
||||
|
||||
s := n.getSubnetforIP(ep.addr)
|
||||
if s == nil {
|
||||
return fmt.Errorf("no matching subnet for IP %q in network %q", ep.addr, nid)
|
||||
}
|
||||
|
||||
// Todo: Add port bindings and qos policies here
|
||||
|
||||
hnsEndpoint := &hcsshim.HNSEndpoint{
|
||||
Name: eid,
|
||||
VirtualNetwork: n.hnsID,
|
||||
IPAddress: ep.addr.IP,
|
||||
EnableInternalDNS: true,
|
||||
GatewayAddress: s.gwIP.String(),
|
||||
}
|
||||
|
||||
if ep.mac != nil {
|
||||
hnsEndpoint.MacAddress = ep.mac.String()
|
||||
}
|
||||
|
||||
paPolicy, err := json.Marshal(hcsshim.PaPolicy{
|
||||
Type: "PA",
|
||||
PA: n.providerAddress,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hnsEndpoint.Policies = append(hnsEndpoint.Policies, paPolicy)
|
||||
|
||||
if osversion.Build() > 16236 {
|
||||
natPolicy, err := json.Marshal(hcsshim.PaPolicy{
|
||||
Type: "OutBoundNAT",
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hnsEndpoint.Policies = append(hnsEndpoint.Policies, natPolicy)
|
||||
|
||||
epConnectivity, err := windows.ParseEndpointConnectivity(epOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ep.portMapping = epConnectivity.PortBindings
|
||||
ep.portMapping, err = windows.AllocatePorts(n.portMapper, ep.portMapping, ep.addr.IP)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
windows.ReleasePorts(n.portMapper, ep.portMapping)
|
||||
}
|
||||
}()
|
||||
|
||||
pbPolicy, err := windows.ConvertPortBindings(ep.portMapping)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hnsEndpoint.Policies = append(hnsEndpoint.Policies, pbPolicy...)
|
||||
|
||||
ep.disablegateway = true
|
||||
}
|
||||
|
||||
configurationb, err := json.Marshal(hnsEndpoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hnsresponse, err := endpointRequest("POST", "", string(configurationb))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ep.profileID = hnsresponse.Id
|
||||
|
||||
if ep.mac == nil {
|
||||
ep.mac, err = net.ParseMAC(hnsresponse.MacAddress)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := ifInfo.SetMacAddress(ep.mac); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
ep.portMapping, err = windows.ParsePortBindingPolicies(hnsresponse.Policies)
|
||||
if err != nil {
|
||||
endpointRequest("DELETE", hnsresponse.Id, "")
|
||||
return err
|
||||
}
|
||||
|
||||
n.addEndpoint(ep)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) DeleteEndpoint(nid, eid string) error {
|
||||
if err := validateID(nid, eid); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n := d.network(nid)
|
||||
if n == nil {
|
||||
return fmt.Errorf("network id %q not found", nid)
|
||||
}
|
||||
|
||||
ep := n.endpoint(eid)
|
||||
if ep == nil {
|
||||
return fmt.Errorf("endpoint id %q not found", eid)
|
||||
}
|
||||
|
||||
windows.ReleasePorts(n.portMapper, ep.portMapping)
|
||||
|
||||
n.deleteEndpoint(eid)
|
||||
|
||||
_, err := endpointRequest("DELETE", ep.profileID, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) {
|
||||
if err := validateID(nid, eid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
n := d.network(nid)
|
||||
if n == nil {
|
||||
return nil, fmt.Errorf("network id %q not found", nid)
|
||||
}
|
||||
|
||||
ep := n.endpoint(eid)
|
||||
if ep == nil {
|
||||
return nil, fmt.Errorf("endpoint id %q not found", eid)
|
||||
}
|
||||
|
||||
data := make(map[string]interface{}, 1)
|
||||
data["hnsid"] = ep.profileID
|
||||
data["AllowUnqualifiedDNSQuery"] = true
|
||||
|
||||
if ep.portMapping != nil {
|
||||
// Return a copy of the operational data
|
||||
pmc := make([]types.PortBinding, 0, len(ep.portMapping))
|
||||
for _, pm := range ep.portMapping {
|
||||
pmc = append(pmc, pm.GetCopy())
|
||||
}
|
||||
data[netlabel.PortMap] = pmc
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func endpointRequest(method, path, request string) (*hcsshim.HNSEndpoint, error) {
|
||||
if windowsBuild == 14393 {
|
||||
endpointMu.Lock()
|
||||
}
|
||||
hnsresponse, err := hcsshim.HNSEndpointRequest(method, path, request)
|
||||
if windowsBuild == 14393 {
|
||||
endpointMu.Unlock()
|
||||
}
|
||||
return hnsresponse, err
|
||||
}
|
384
vendor/github.com/docker/libnetwork/drivers/windows/overlay/ov_network_windows.go
generated
vendored
384
vendor/github.com/docker/libnetwork/drivers/windows/overlay/ov_network_windows.go
generated
vendored
|
@ -1,384 +0,0 @@
|
|||
package overlay
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/Microsoft/hcsshim"
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/portmapper"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var (
|
||||
hostMode bool
|
||||
networkMu sync.Mutex
|
||||
)
|
||||
|
||||
type networkTable map[string]*network
|
||||
|
||||
type subnet struct {
|
||||
vni uint32
|
||||
subnetIP *net.IPNet
|
||||
gwIP *net.IP
|
||||
}
|
||||
|
||||
type subnetJSON struct {
|
||||
SubnetIP string
|
||||
GwIP string
|
||||
Vni uint32
|
||||
}
|
||||
|
||||
type network struct {
|
||||
id string
|
||||
name string
|
||||
hnsID string
|
||||
providerAddress string
|
||||
interfaceName string
|
||||
endpoints endpointTable
|
||||
driver *driver
|
||||
initEpoch int
|
||||
initErr error
|
||||
subnets []*subnet
|
||||
secure bool
|
||||
portMapper *portmapper.PortMapper
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {
|
||||
return nil, types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) NetworkFree(id string) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
|
||||
var (
|
||||
networkName string
|
||||
interfaceName string
|
||||
staleNetworks []string
|
||||
)
|
||||
|
||||
if id == "" {
|
||||
return fmt.Errorf("invalid network id")
|
||||
}
|
||||
|
||||
if nInfo == nil {
|
||||
return fmt.Errorf("invalid network info structure")
|
||||
}
|
||||
|
||||
if len(ipV4Data) == 0 || ipV4Data[0].Pool.String() == "0.0.0.0/0" {
|
||||
return types.BadRequestErrorf("ipv4 pool is empty")
|
||||
}
|
||||
|
||||
staleNetworks = make([]string, 0)
|
||||
vnis := make([]uint32, 0, len(ipV4Data))
|
||||
|
||||
existingNetwork := d.network(id)
|
||||
if existingNetwork != nil {
|
||||
logrus.Debugf("Network preexists. Deleting %s", id)
|
||||
err := d.DeleteNetwork(id)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error deleting stale network %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
n := &network{
|
||||
id: id,
|
||||
driver: d,
|
||||
endpoints: endpointTable{},
|
||||
subnets: []*subnet{},
|
||||
portMapper: portmapper.New(""),
|
||||
}
|
||||
|
||||
genData, ok := option[netlabel.GenericData].(map[string]string)
|
||||
|
||||
if !ok {
|
||||
return fmt.Errorf("Unknown generic data option")
|
||||
}
|
||||
|
||||
for label, value := range genData {
|
||||
switch label {
|
||||
case "com.docker.network.windowsshim.networkname":
|
||||
networkName = value
|
||||
case "com.docker.network.windowsshim.interface":
|
||||
interfaceName = value
|
||||
case "com.docker.network.windowsshim.hnsid":
|
||||
n.hnsID = value
|
||||
case netlabel.OverlayVxlanIDList:
|
||||
vniStrings := strings.Split(value, ",")
|
||||
for _, vniStr := range vniStrings {
|
||||
vni, err := strconv.Atoi(vniStr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid vxlan id value %q passed", vniStr)
|
||||
}
|
||||
|
||||
vnis = append(vnis, uint32(vni))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we are getting vnis from libnetwork, either we get for
|
||||
// all subnets or none.
|
||||
if len(vnis) < len(ipV4Data) {
|
||||
return fmt.Errorf("insufficient vnis(%d) passed to overlay. Windows driver requires VNIs to be prepopulated", len(vnis))
|
||||
}
|
||||
|
||||
for i, ipd := range ipV4Data {
|
||||
s := &subnet{
|
||||
subnetIP: ipd.Pool,
|
||||
gwIP: &ipd.Gateway.IP,
|
||||
}
|
||||
|
||||
if len(vnis) != 0 {
|
||||
s.vni = vnis[i]
|
||||
}
|
||||
|
||||
d.Lock()
|
||||
for _, network := range d.networks {
|
||||
found := false
|
||||
for _, sub := range network.subnets {
|
||||
if sub.vni == s.vni {
|
||||
staleNetworks = append(staleNetworks, network.id)
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if found {
|
||||
break
|
||||
}
|
||||
}
|
||||
d.Unlock()
|
||||
|
||||
n.subnets = append(n.subnets, s)
|
||||
}
|
||||
|
||||
for _, staleNetwork := range staleNetworks {
|
||||
d.DeleteNetwork(staleNetwork)
|
||||
}
|
||||
|
||||
n.name = networkName
|
||||
if n.name == "" {
|
||||
n.name = id
|
||||
}
|
||||
|
||||
n.interfaceName = interfaceName
|
||||
|
||||
if nInfo != nil {
|
||||
if err := nInfo.TableEventRegister(ovPeerTable, driverapi.EndpointObject); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
d.addNetwork(n)
|
||||
|
||||
err := d.createHnsNetwork(n)
|
||||
|
||||
if err != nil {
|
||||
d.deleteNetwork(id)
|
||||
} else {
|
||||
genData["com.docker.network.windowsshim.hnsid"] = n.hnsID
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *driver) DeleteNetwork(nid string) error {
|
||||
if nid == "" {
|
||||
return fmt.Errorf("invalid network id")
|
||||
}
|
||||
|
||||
n := d.network(nid)
|
||||
if n == nil {
|
||||
return types.ForbiddenErrorf("could not find network with id %s", nid)
|
||||
}
|
||||
|
||||
_, err := hcsshim.HNSNetworkRequest("DELETE", n.hnsID, "")
|
||||
if err != nil {
|
||||
return types.ForbiddenErrorf(err.Error())
|
||||
}
|
||||
|
||||
d.deleteNetwork(nid)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) addNetwork(n *network) {
|
||||
d.Lock()
|
||||
d.networks[n.id] = n
|
||||
d.Unlock()
|
||||
}
|
||||
|
||||
func (d *driver) deleteNetwork(nid string) {
|
||||
d.Lock()
|
||||
delete(d.networks, nid)
|
||||
d.Unlock()
|
||||
}
|
||||
|
||||
func (d *driver) network(nid string) *network {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
return d.networks[nid]
|
||||
}
|
||||
|
||||
// func (n *network) restoreNetworkEndpoints() error {
|
||||
// logrus.Infof("Restoring endpoints for overlay network: %s", n.id)
|
||||
|
||||
// hnsresponse, err := hcsshim.HNSListEndpointRequest("GET", "", "")
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// for _, endpoint := range hnsresponse {
|
||||
// if endpoint.VirtualNetwork != n.hnsID {
|
||||
// continue
|
||||
// }
|
||||
|
||||
// ep := n.convertToOverlayEndpoint(&endpoint)
|
||||
|
||||
// if ep != nil {
|
||||
// logrus.Debugf("Restored endpoint:%s Remote:%t", ep.id, ep.remote)
|
||||
// n.addEndpoint(ep)
|
||||
// }
|
||||
// }
|
||||
|
||||
// return nil
|
||||
// }
|
||||
|
||||
func (n *network) convertToOverlayEndpoint(v *hcsshim.HNSEndpoint) *endpoint {
|
||||
ep := &endpoint{
|
||||
id: v.Name,
|
||||
profileID: v.Id,
|
||||
nid: n.id,
|
||||
remote: v.IsRemoteEndpoint,
|
||||
}
|
||||
|
||||
mac, err := net.ParseMAC(v.MacAddress)
|
||||
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
ep.mac = mac
|
||||
ep.addr = &net.IPNet{
|
||||
IP: v.IPAddress,
|
||||
Mask: net.CIDRMask(32, 32),
|
||||
}
|
||||
|
||||
return ep
|
||||
}
|
||||
|
||||
func (d *driver) createHnsNetwork(n *network) error {
|
||||
|
||||
subnets := []hcsshim.Subnet{}
|
||||
|
||||
for _, s := range n.subnets {
|
||||
subnet := hcsshim.Subnet{
|
||||
AddressPrefix: s.subnetIP.String(),
|
||||
}
|
||||
|
||||
if s.gwIP != nil {
|
||||
subnet.GatewayAddress = s.gwIP.String()
|
||||
}
|
||||
|
||||
vsidPolicy, err := json.Marshal(hcsshim.VsidPolicy{
|
||||
Type: "VSID",
|
||||
VSID: uint(s.vni),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
subnet.Policies = append(subnet.Policies, vsidPolicy)
|
||||
subnets = append(subnets, subnet)
|
||||
}
|
||||
|
||||
network := &hcsshim.HNSNetwork{
|
||||
Name: n.name,
|
||||
Type: d.Type(),
|
||||
Subnets: subnets,
|
||||
NetworkAdapterName: n.interfaceName,
|
||||
AutomaticDNS: true,
|
||||
}
|
||||
|
||||
configurationb, err := json.Marshal(network)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
configuration := string(configurationb)
|
||||
logrus.Infof("HNSNetwork Request =%v", configuration)
|
||||
|
||||
hnsresponse, err := hcsshim.HNSNetworkRequest("POST", "", configuration)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n.hnsID = hnsresponse.Id
|
||||
n.providerAddress = hnsresponse.ManagementIP
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// contains return true if the passed ip belongs to one the network's
|
||||
// subnets
|
||||
func (n *network) contains(ip net.IP) bool {
|
||||
for _, s := range n.subnets {
|
||||
if s.subnetIP.Contains(ip) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// getSubnetforIP returns the subnet to which the given IP belongs
|
||||
func (n *network) getSubnetforIP(ip *net.IPNet) *subnet {
|
||||
for _, s := range n.subnets {
|
||||
// first check if the mask lengths are the same
|
||||
i, _ := s.subnetIP.Mask.Size()
|
||||
j, _ := ip.Mask.Size()
|
||||
if i != j {
|
||||
continue
|
||||
}
|
||||
if s.subnetIP.Contains(ip.IP) {
|
||||
return s
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// getMatchingSubnet return the network's subnet that matches the input
|
||||
func (n *network) getMatchingSubnet(ip *net.IPNet) *subnet {
|
||||
if ip == nil {
|
||||
return nil
|
||||
}
|
||||
for _, s := range n.subnets {
|
||||
// first check if the mask lengths are the same
|
||||
i, _ := s.subnetIP.Mask.Size()
|
||||
j, _ := ip.Mask.Size()
|
||||
if i != j {
|
||||
continue
|
||||
}
|
||||
if s.subnetIP.IP.Equal(ip.IP) {
|
||||
return s
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
455
vendor/github.com/docker/libnetwork/drivers/windows/overlay/overlay.pb.go
generated
vendored
455
vendor/github.com/docker/libnetwork/drivers/windows/overlay/overlay.pb.go
generated
vendored
|
@ -1,455 +0,0 @@
|
|||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: drivers/windows/overlay/overlay.proto
|
||||
|
||||
/*
|
||||
Package overlay is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
drivers/windows/overlay/overlay.proto
|
||||
|
||||
It has these top-level messages:
|
||||
PeerRecord
|
||||
*/
|
||||
package overlay
|
||||
|
||||
import proto "github.com/gogo/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import _ "github.com/gogo/protobuf/gogoproto"
|
||||
|
||||
import strings "strings"
|
||||
import reflect "reflect"
|
||||
|
||||
import io "io"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
// PeerRecord defines the information corresponding to a peer
|
||||
// container in the overlay network.
|
||||
type PeerRecord struct {
|
||||
// Endpoint IP is the IP of the container attachment on the
|
||||
// given overlay network.
|
||||
EndpointIP string `protobuf:"bytes,1,opt,name=endpoint_ip,json=endpointIp,proto3" json:"endpoint_ip,omitempty"`
|
||||
// Endpoint MAC is the mac address of the container attachment
|
||||
// on the given overlay network.
|
||||
EndpointMAC string `protobuf:"bytes,2,opt,name=endpoint_mac,json=endpointMac,proto3" json:"endpoint_mac,omitempty"`
|
||||
// Tunnel Endpoint IP defines the host IP for the host in
|
||||
// which this container is running and can be reached by
|
||||
// building a tunnel to that host IP.
|
||||
TunnelEndpointIP string `protobuf:"bytes,3,opt,name=tunnel_endpoint_ip,json=tunnelEndpointIp,proto3" json:"tunnel_endpoint_ip,omitempty"`
|
||||
}
|
||||
|
||||
func (m *PeerRecord) Reset() { *m = PeerRecord{} }
|
||||
func (*PeerRecord) ProtoMessage() {}
|
||||
func (*PeerRecord) Descriptor() ([]byte, []int) { return fileDescriptorOverlay, []int{0} }
|
||||
|
||||
func (m *PeerRecord) GetEndpointIP() string {
|
||||
if m != nil {
|
||||
return m.EndpointIP
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *PeerRecord) GetEndpointMAC() string {
|
||||
if m != nil {
|
||||
return m.EndpointMAC
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *PeerRecord) GetTunnelEndpointIP() string {
|
||||
if m != nil {
|
||||
return m.TunnelEndpointIP
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*PeerRecord)(nil), "overlay.PeerRecord")
|
||||
}
|
||||
func (this *PeerRecord) GoString() string {
|
||||
if this == nil {
|
||||
return "nil"
|
||||
}
|
||||
s := make([]string, 0, 7)
|
||||
s = append(s, "&overlay.PeerRecord{")
|
||||
s = append(s, "EndpointIP: "+fmt.Sprintf("%#v", this.EndpointIP)+",\n")
|
||||
s = append(s, "EndpointMAC: "+fmt.Sprintf("%#v", this.EndpointMAC)+",\n")
|
||||
s = append(s, "TunnelEndpointIP: "+fmt.Sprintf("%#v", this.TunnelEndpointIP)+",\n")
|
||||
s = append(s, "}")
|
||||
return strings.Join(s, "")
|
||||
}
|
||||
func valueToGoStringOverlay(v interface{}, typ string) string {
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.IsNil() {
|
||||
return "nil"
|
||||
}
|
||||
pv := reflect.Indirect(rv).Interface()
|
||||
return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
|
||||
}
|
||||
func (m *PeerRecord) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *PeerRecord) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.EndpointIP) > 0 {
|
||||
dAtA[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintOverlay(dAtA, i, uint64(len(m.EndpointIP)))
|
||||
i += copy(dAtA[i:], m.EndpointIP)
|
||||
}
|
||||
if len(m.EndpointMAC) > 0 {
|
||||
dAtA[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintOverlay(dAtA, i, uint64(len(m.EndpointMAC)))
|
||||
i += copy(dAtA[i:], m.EndpointMAC)
|
||||
}
|
||||
if len(m.TunnelEndpointIP) > 0 {
|
||||
dAtA[i] = 0x1a
|
||||
i++
|
||||
i = encodeVarintOverlay(dAtA, i, uint64(len(m.TunnelEndpointIP)))
|
||||
i += copy(dAtA[i:], m.TunnelEndpointIP)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func encodeVarintOverlay(dAtA []byte, offset int, v uint64) int {
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return offset + 1
|
||||
}
|
||||
func (m *PeerRecord) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.EndpointIP)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovOverlay(uint64(l))
|
||||
}
|
||||
l = len(m.EndpointMAC)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovOverlay(uint64(l))
|
||||
}
|
||||
l = len(m.TunnelEndpointIP)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovOverlay(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovOverlay(x uint64) (n int) {
|
||||
for {
|
||||
n++
|
||||
x >>= 7
|
||||
if x == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
func sozOverlay(x uint64) (n int) {
|
||||
return sovOverlay(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (this *PeerRecord) String() string {
|
||||
if this == nil {
|
||||
return "nil"
|
||||
}
|
||||
s := strings.Join([]string{`&PeerRecord{`,
|
||||
`EndpointIP:` + fmt.Sprintf("%v", this.EndpointIP) + `,`,
|
||||
`EndpointMAC:` + fmt.Sprintf("%v", this.EndpointMAC) + `,`,
|
||||
`TunnelEndpointIP:` + fmt.Sprintf("%v", this.TunnelEndpointIP) + `,`,
|
||||
`}`,
|
||||
}, "")
|
||||
return s
|
||||
}
|
||||
func valueToStringOverlay(v interface{}) string {
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.IsNil() {
|
||||
return "nil"
|
||||
}
|
||||
pv := reflect.Indirect(rv).Interface()
|
||||
return fmt.Sprintf("*%v", pv)
|
||||
}
|
||||
func (m *PeerRecord) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowOverlay
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: PeerRecord: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: PeerRecord: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field EndpointIP", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowOverlay
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthOverlay
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.EndpointIP = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field EndpointMAC", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowOverlay
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthOverlay
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.EndpointMAC = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field TunnelEndpointIP", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowOverlay
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthOverlay
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.TunnelEndpointIP = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipOverlay(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthOverlay
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipOverlay(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowOverlay
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowOverlay
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
return iNdEx, nil
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowOverlay
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
iNdEx += length
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthOverlay
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 3:
|
||||
for {
|
||||
var innerWire uint64
|
||||
var start int = iNdEx
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowOverlay
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
innerWire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
innerWireType := int(innerWire & 0x7)
|
||||
if innerWireType == 4 {
|
||||
break
|
||||
}
|
||||
next, err := skipOverlay(dAtA[start:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
iNdEx = start + next
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 4:
|
||||
return iNdEx, nil
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
return iNdEx, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthOverlay = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowOverlay = fmt.Errorf("proto: integer overflow")
|
||||
)
|
||||
|
||||
func init() { proto.RegisterFile("drivers/windows/overlay/overlay.proto", fileDescriptorOverlay) }
|
||||
|
||||
var fileDescriptorOverlay = []byte{
|
||||
// 220 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4d, 0x29, 0xca, 0x2c,
|
||||
0x4b, 0x2d, 0x2a, 0xd6, 0x2f, 0xcf, 0xcc, 0x4b, 0xc9, 0x2f, 0x2f, 0xd6, 0xcf, 0x2f, 0x4b, 0x2d,
|
||||
0xca, 0x49, 0xac, 0x84, 0xd1, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, 0xec, 0x50, 0xae, 0x94,
|
||||
0x48, 0x7a, 0x7e, 0x7a, 0x3e, 0x58, 0x4c, 0x1f, 0xc4, 0x82, 0x48, 0x2b, 0x6d, 0x65, 0xe4, 0xe2,
|
||||
0x0a, 0x48, 0x4d, 0x2d, 0x0a, 0x4a, 0x4d, 0xce, 0x2f, 0x4a, 0x11, 0xd2, 0xe7, 0xe2, 0x4e, 0xcd,
|
||||
0x4b, 0x29, 0xc8, 0xcf, 0xcc, 0x2b, 0x89, 0xcf, 0x2c, 0x90, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x74,
|
||||
0xe2, 0x7b, 0x74, 0x4f, 0x9e, 0xcb, 0x15, 0x2a, 0xec, 0x19, 0x10, 0xc4, 0x05, 0x53, 0xe2, 0x59,
|
||||
0x20, 0x64, 0xc4, 0xc5, 0x03, 0xd7, 0x90, 0x9b, 0x98, 0x2c, 0xc1, 0x04, 0xd6, 0xc1, 0xff, 0xe8,
|
||||
0x9e, 0x3c, 0x37, 0x4c, 0x87, 0xaf, 0xa3, 0x73, 0x10, 0xdc, 0x54, 0xdf, 0xc4, 0x64, 0x21, 0x27,
|
||||
0x2e, 0xa1, 0x92, 0xd2, 0xbc, 0xbc, 0xd4, 0x9c, 0x78, 0x64, 0xbb, 0x98, 0xc1, 0x3a, 0x45, 0x1e,
|
||||
0xdd, 0x93, 0x17, 0x08, 0x01, 0xcb, 0x22, 0xd9, 0x28, 0x50, 0x82, 0x2a, 0x52, 0xe0, 0x24, 0x71,
|
||||
0xe3, 0xa1, 0x1c, 0xc3, 0x87, 0x87, 0x72, 0x8c, 0x0d, 0x8f, 0xe4, 0x18, 0x4f, 0x3c, 0x92, 0x63,
|
||||
0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x24, 0x36, 0xb0, 0xc7, 0x8c, 0x01, 0x01,
|
||||
0x00, 0x00, 0xff, 0xff, 0xc0, 0x48, 0xd1, 0xc0, 0x20, 0x01, 0x00, 0x00,
|
||||
}
|
27
vendor/github.com/docker/libnetwork/drivers/windows/overlay/overlay.proto
generated
vendored
27
vendor/github.com/docker/libnetwork/drivers/windows/overlay/overlay.proto
generated
vendored
|
@ -1,27 +0,0 @@
|
|||
syntax = "proto3";
|
||||
|
||||
import "gogoproto/gogo.proto";
|
||||
|
||||
package overlay;
|
||||
|
||||
option (gogoproto.marshaler_all) = true;
|
||||
option (gogoproto.unmarshaler_all) = true;
|
||||
option (gogoproto.stringer_all) = true;
|
||||
option (gogoproto.gostring_all) = true;
|
||||
option (gogoproto.sizer_all) = true;
|
||||
option (gogoproto.goproto_stringer_all) = false;
|
||||
|
||||
// PeerRecord defines the information corresponding to a peer
|
||||
// container in the overlay network.
|
||||
message PeerRecord {
|
||||
// Endpoint IP is the IP of the container attachment on the
|
||||
// given overlay network.
|
||||
string endpoint_ip = 1 [(gogoproto.customname) = "EndpointIP"];
|
||||
// Endpoint MAC is the mac address of the container attachment
|
||||
// on the given overlay network.
|
||||
string endpoint_mac = 2 [(gogoproto.customname) = "EndpointMAC"];
|
||||
// Tunnel Endpoint IP defines the host IP for the host in
|
||||
// which this container is running and can be reached by
|
||||
// building a tunnel to that host IP.
|
||||
string tunnel_endpoint_ip = 3 [(gogoproto.customname) = "TunnelEndpointIP"];
|
||||
}
|
159
vendor/github.com/docker/libnetwork/drivers/windows/overlay/overlay_windows.go
generated
vendored
159
vendor/github.com/docker/libnetwork/drivers/windows/overlay/overlay_windows.go
generated
vendored
|
@ -1,159 +0,0 @@
|
|||
package overlay
|
||||
|
||||
//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
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"github.com/Microsoft/hcsshim"
|
||||
"github.com/docker/libnetwork/datastore"
|
||||
"github.com/docker/libnetwork/discoverapi"
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
networkType = "overlay"
|
||||
vethPrefix = "veth"
|
||||
vethLen = 7
|
||||
secureOption = "encrypted"
|
||||
)
|
||||
|
||||
type driver struct {
|
||||
config map[string]interface{}
|
||||
networks networkTable
|
||||
store datastore.DataStore
|
||||
localStore datastore.DataStore
|
||||
once sync.Once
|
||||
joinOnce sync.Once
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// Init registers a new instance of overlay driver
|
||||
func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
||||
c := driverapi.Capability{
|
||||
DataScope: datastore.GlobalScope,
|
||||
ConnectivityScope: datastore.GlobalScope,
|
||||
}
|
||||
|
||||
d := &driver{
|
||||
networks: networkTable{},
|
||||
config: config,
|
||||
}
|
||||
|
||||
if data, ok := config[netlabel.GlobalKVClient]; ok {
|
||||
var err error
|
||||
dsc, ok := data.(discoverapi.DatastoreConfigData)
|
||||
if !ok {
|
||||
return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
|
||||
}
|
||||
d.store, err = datastore.NewDataStoreFromConfig(dsc)
|
||||
if err != nil {
|
||||
return types.InternalErrorf("failed to initialize data store: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if data, ok := config[netlabel.LocalKVClient]; ok {
|
||||
var err error
|
||||
dsc, ok := data.(discoverapi.DatastoreConfigData)
|
||||
if !ok {
|
||||
return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
|
||||
}
|
||||
d.localStore, err = datastore.NewDataStoreFromConfig(dsc)
|
||||
if err != nil {
|
||||
return types.InternalErrorf("failed to initialize local data store: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
d.restoreHNSNetworks()
|
||||
|
||||
return dc.RegisterDriver(networkType, d, c)
|
||||
}
|
||||
|
||||
func (d *driver) restoreHNSNetworks() error {
|
||||
logrus.Infof("Restoring existing overlay networks from HNS into docker")
|
||||
|
||||
hnsresponse, err := hcsshim.HNSListNetworkRequest("GET", "", "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, v := range hnsresponse {
|
||||
if v.Type != networkType {
|
||||
continue
|
||||
}
|
||||
|
||||
logrus.Infof("Restoring overlay network: %s", v.Name)
|
||||
n := d.convertToOverlayNetwork(&v)
|
||||
d.addNetwork(n)
|
||||
|
||||
//
|
||||
// We assume that any network will be recreated on daemon restart
|
||||
// and therefore don't restore hns endpoints for now
|
||||
//
|
||||
//n.restoreNetworkEndpoints()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) convertToOverlayNetwork(v *hcsshim.HNSNetwork) *network {
|
||||
n := &network{
|
||||
id: v.Name,
|
||||
hnsID: v.Id,
|
||||
driver: d,
|
||||
endpoints: endpointTable{},
|
||||
subnets: []*subnet{},
|
||||
providerAddress: v.ManagementIP,
|
||||
}
|
||||
|
||||
for _, hnsSubnet := range v.Subnets {
|
||||
vsidPolicy := &hcsshim.VsidPolicy{}
|
||||
for _, policy := range hnsSubnet.Policies {
|
||||
if err := json.Unmarshal([]byte(policy), &vsidPolicy); err == nil && vsidPolicy.Type == "VSID" {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
gwIP := net.ParseIP(hnsSubnet.GatewayAddress)
|
||||
localsubnet := &subnet{
|
||||
vni: uint32(vsidPolicy.VSID),
|
||||
gwIP: &gwIP,
|
||||
}
|
||||
|
||||
_, subnetIP, err := net.ParseCIDR(hnsSubnet.AddressPrefix)
|
||||
|
||||
if err != nil {
|
||||
logrus.Errorf("Error parsing subnet address %s ", hnsSubnet.AddressPrefix)
|
||||
continue
|
||||
}
|
||||
|
||||
localsubnet.subnetIP = subnetIP
|
||||
|
||||
n.subnets = append(n.subnets, localsubnet)
|
||||
}
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
func (d *driver) Type() string {
|
||||
return networkType
|
||||
}
|
||||
|
||||
func (d *driver) IsBuiltIn() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster
|
||||
func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
// DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster
|
||||
func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
119
vendor/github.com/docker/libnetwork/drivers/windows/overlay/peerdb_windows.go
generated
vendored
119
vendor/github.com/docker/libnetwork/drivers/windows/overlay/peerdb_windows.go
generated
vendored
|
@ -1,119 +0,0 @@
|
|||
package overlay
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"encoding/json"
|
||||
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/Microsoft/hcsshim"
|
||||
)
|
||||
|
||||
const ovPeerTable = "overlay_peer_table"
|
||||
|
||||
func (d *driver) peerAdd(nid, eid string, peerIP net.IP, peerIPMask net.IPMask,
|
||||
peerMac net.HardwareAddr, vtep net.IP, updateDb bool) error {
|
||||
|
||||
logrus.Debugf("WINOVERLAY: Enter peerAdd for ca ip %s with ca mac %s", peerIP.String(), peerMac.String())
|
||||
|
||||
if err := validateID(nid, eid); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n := d.network(nid)
|
||||
if n == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if updateDb {
|
||||
logrus.Info("WINOVERLAY: peerAdd: notifying HNS of the REMOTE endpoint")
|
||||
|
||||
hnsEndpoint := &hcsshim.HNSEndpoint{
|
||||
Name: eid,
|
||||
VirtualNetwork: n.hnsID,
|
||||
MacAddress: peerMac.String(),
|
||||
IPAddress: peerIP,
|
||||
IsRemoteEndpoint: true,
|
||||
}
|
||||
|
||||
paPolicy, err := json.Marshal(hcsshim.PaPolicy{
|
||||
Type: "PA",
|
||||
PA: vtep.String(),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hnsEndpoint.Policies = append(hnsEndpoint.Policies, paPolicy)
|
||||
|
||||
configurationb, err := json.Marshal(hnsEndpoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Temp: We have to create an endpoint object to keep track of the HNS ID for
|
||||
// this endpoint so that we can retrieve it later when the endpoint is deleted.
|
||||
// This seems unnecessary when we already have dockers EID. See if we can pass
|
||||
// the global EID to HNS to use as it's ID, rather than having each HNS assign
|
||||
// it's own local ID for the endpoint
|
||||
|
||||
addr, err := types.ParseCIDR(peerIP.String() + "/32")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n.removeEndpointWithAddress(addr)
|
||||
hnsresponse, err := endpointRequest("POST", "", string(configurationb))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ep := &endpoint{
|
||||
id: eid,
|
||||
nid: nid,
|
||||
addr: addr,
|
||||
mac: peerMac,
|
||||
profileID: hnsresponse.Id,
|
||||
remote: true,
|
||||
}
|
||||
|
||||
n.addEndpoint(ep)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) peerDelete(nid, eid string, peerIP net.IP, peerIPMask net.IPMask,
|
||||
peerMac net.HardwareAddr, vtep net.IP, updateDb bool) error {
|
||||
|
||||
logrus.Infof("WINOVERLAY: Enter peerDelete for endpoint %s and peer ip %s", eid, peerIP.String())
|
||||
|
||||
if err := validateID(nid, eid); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n := d.network(nid)
|
||||
if n == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
ep := n.endpoint(eid)
|
||||
if ep == nil {
|
||||
return fmt.Errorf("could not find endpoint with id %s", eid)
|
||||
}
|
||||
|
||||
if updateDb {
|
||||
_, err := endpointRequest("DELETE", ep.profileID, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n.deleteEndpoint(eid)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
131
vendor/github.com/docker/libnetwork/drivers/windows/port_mapping.go
generated
vendored
131
vendor/github.com/docker/libnetwork/drivers/windows/port_mapping.go
generated
vendored
|
@ -1,131 +0,0 @@
|
|||
// +build windows
|
||||
|
||||
package windows
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/docker/libnetwork/portmapper"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/ishidawataru/sctp"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
maxAllocatePortAttempts = 10
|
||||
)
|
||||
|
||||
// ErrUnsupportedAddressType is returned when the specified address type is not supported.
|
||||
type ErrUnsupportedAddressType string
|
||||
|
||||
func (uat ErrUnsupportedAddressType) Error() string {
|
||||
return fmt.Sprintf("unsupported address type: %s", string(uat))
|
||||
}
|
||||
|
||||
// AllocatePorts allocates ports specified in bindings from the portMapper
|
||||
func AllocatePorts(portMapper *portmapper.PortMapper, bindings []types.PortBinding, containerIP net.IP) ([]types.PortBinding, error) {
|
||||
bs := make([]types.PortBinding, 0, len(bindings))
|
||||
for _, c := range bindings {
|
||||
b := c.GetCopy()
|
||||
if err := allocatePort(portMapper, &b, containerIP); err != nil {
|
||||
// On allocation failure, release previously allocated ports. On cleanup error, just log a warning message
|
||||
if cuErr := ReleasePorts(portMapper, bs); cuErr != nil {
|
||||
logrus.Warnf("Upon allocation failure for %v, failed to clear previously allocated port bindings: %v", b, cuErr)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
bs = append(bs, b)
|
||||
}
|
||||
return bs, nil
|
||||
}
|
||||
|
||||
func allocatePort(portMapper *portmapper.PortMapper, bnd *types.PortBinding, containerIP net.IP) error {
|
||||
var (
|
||||
host net.Addr
|
||||
err error
|
||||
)
|
||||
|
||||
// Windows does not support a host ip for port bindings (this is validated in ConvertPortBindings()).
|
||||
// If the HostIP is nil, force it to be 0.0.0.0 for use as the key in portMapper.
|
||||
if bnd.HostIP == nil {
|
||||
bnd.HostIP = net.IPv4zero
|
||||
}
|
||||
|
||||
// Store the container interface address in the operational binding
|
||||
bnd.IP = containerIP
|
||||
|
||||
// Adjust HostPortEnd if this is not a range.
|
||||
if bnd.HostPortEnd == 0 {
|
||||
bnd.HostPortEnd = bnd.HostPort
|
||||
}
|
||||
|
||||
// Construct the container side transport address
|
||||
container, err := bnd.ContainerAddr()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Try up to maxAllocatePortAttempts times to get a port that's not already allocated.
|
||||
for i := 0; i < maxAllocatePortAttempts; i++ {
|
||||
if host, err = portMapper.MapRange(container, bnd.HostIP, int(bnd.HostPort), int(bnd.HostPortEnd), false); err == nil {
|
||||
break
|
||||
}
|
||||
// There is no point in immediately retrying to map an explicitly chosen port.
|
||||
if bnd.HostPort != 0 {
|
||||
logrus.Warnf("Failed to allocate and map port %d-%d: %s", bnd.HostPort, bnd.HostPortEnd, err)
|
||||
break
|
||||
}
|
||||
logrus.Warnf("Failed to allocate and map port: %s, retry: %d", err, i+1)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Save the host port (regardless it was or not specified in the binding)
|
||||
switch netAddr := host.(type) {
|
||||
case *net.TCPAddr:
|
||||
bnd.HostPort = uint16(host.(*net.TCPAddr).Port)
|
||||
break
|
||||
case *net.UDPAddr:
|
||||
bnd.HostPort = uint16(host.(*net.UDPAddr).Port)
|
||||
break
|
||||
case *sctp.SCTPAddr:
|
||||
bnd.HostPort = uint16(host.(*sctp.SCTPAddr).Port)
|
||||
break
|
||||
default:
|
||||
// For completeness
|
||||
return ErrUnsupportedAddressType(fmt.Sprintf("%T", netAddr))
|
||||
}
|
||||
//Windows does not support host port ranges.
|
||||
bnd.HostPortEnd = bnd.HostPort
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReleasePorts releases ports specified in bindings from the portMapper
|
||||
func ReleasePorts(portMapper *portmapper.PortMapper, bindings []types.PortBinding) error {
|
||||
var errorBuf bytes.Buffer
|
||||
|
||||
// Attempt to release all port bindings, do not stop on failure
|
||||
for _, m := range bindings {
|
||||
if err := releasePort(portMapper, m); err != nil {
|
||||
errorBuf.WriteString(fmt.Sprintf("\ncould not release %v because of %v", m, err))
|
||||
}
|
||||
}
|
||||
|
||||
if errorBuf.Len() != 0 {
|
||||
return errors.New(errorBuf.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func releasePort(portMapper *portmapper.PortMapper, bnd types.PortBinding) error {
|
||||
// Construct the host side transport address
|
||||
host, err := bnd.HostAddr()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return portMapper.Unmap(host)
|
||||
}
|
920
vendor/github.com/docker/libnetwork/drivers/windows/windows.go
generated
vendored
920
vendor/github.com/docker/libnetwork/drivers/windows/windows.go
generated
vendored
|
@ -1,920 +0,0 @@
|
|||
// +build windows
|
||||
|
||||
// Shim for the Host Network Service (HNS) to manage networking for
|
||||
// Windows Server containers and Hyper-V containers. This module
|
||||
// is a basic libnetwork driver that passes all the calls to HNS
|
||||
// It implements the 4 networking modes supported by HNS L2Bridge,
|
||||
// L2Tunnel, NAT and Transparent(DHCP)
|
||||
//
|
||||
// The network are stored in memory and docker daemon ensures discovering
|
||||
// and loading these networks on startup
|
||||
|
||||
package windows
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/Microsoft/hcsshim"
|
||||
"github.com/Microsoft/hcsshim/osversion"
|
||||
"github.com/docker/libnetwork/datastore"
|
||||
"github.com/docker/libnetwork/discoverapi"
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/portmapper"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// networkConfiguration for network specific configuration
|
||||
type networkConfiguration struct {
|
||||
ID string
|
||||
Type string
|
||||
Name string
|
||||
HnsID string
|
||||
RDID string
|
||||
VLAN uint
|
||||
VSID uint
|
||||
DNSServers string
|
||||
MacPools []hcsshim.MacPool
|
||||
DNSSuffix string
|
||||
SourceMac string
|
||||
NetworkAdapterName string
|
||||
dbIndex uint64
|
||||
dbExists bool
|
||||
DisableGatewayDNS bool
|
||||
EnableOutboundNat bool
|
||||
OutboundNatExceptions []string
|
||||
}
|
||||
|
||||
// endpointConfiguration represents the user specified configuration for the sandbox endpoint
|
||||
type endpointOption struct {
|
||||
MacAddress net.HardwareAddr
|
||||
QosPolicies []types.QosPolicy
|
||||
DNSServers []string
|
||||
DisableDNS bool
|
||||
DisableICC bool
|
||||
}
|
||||
|
||||
// EndpointConnectivity stores the port bindings and exposed ports that the user has specified in epOptions.
|
||||
type EndpointConnectivity struct {
|
||||
PortBindings []types.PortBinding
|
||||
ExposedPorts []types.TransportPort
|
||||
}
|
||||
|
||||
type hnsEndpoint struct {
|
||||
id string
|
||||
nid string
|
||||
profileID string
|
||||
Type string
|
||||
//Note: Currently, the sandboxID is the same as the containerID since windows does
|
||||
//not expose the sandboxID.
|
||||
//In the future, windows will support a proper sandboxID that is different
|
||||
//than the containerID.
|
||||
//Therefore, we are using sandboxID now, so that we won't have to change this code
|
||||
//when windows properly supports a sandboxID.
|
||||
sandboxID string
|
||||
macAddress net.HardwareAddr
|
||||
epOption *endpointOption // User specified parameters
|
||||
epConnectivity *EndpointConnectivity // User specified parameters
|
||||
portMapping []types.PortBinding // Operation port bindings
|
||||
addr *net.IPNet
|
||||
gateway net.IP
|
||||
dbIndex uint64
|
||||
dbExists bool
|
||||
}
|
||||
|
||||
type hnsNetwork struct {
|
||||
id string
|
||||
created bool
|
||||
config *networkConfiguration
|
||||
endpoints map[string]*hnsEndpoint // key: endpoint id
|
||||
driver *driver // The network's driver
|
||||
portMapper *portmapper.PortMapper
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
type driver struct {
|
||||
name string
|
||||
networks map[string]*hnsNetwork
|
||||
store datastore.DataStore
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
const (
|
||||
errNotFound = "HNS failed with error : The object identifier does not represent a valid object. "
|
||||
)
|
||||
|
||||
// IsBuiltinLocalDriver validates if network-type is a builtin local-scoped driver
|
||||
func IsBuiltinLocalDriver(networkType string) bool {
|
||||
if "l2bridge" == networkType || "l2tunnel" == networkType ||
|
||||
"nat" == networkType || "ics" == networkType ||
|
||||
"transparent" == networkType || "internal" == networkType ||
|
||||
"private" == networkType {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// New constructs a new bridge driver
|
||||
func newDriver(networkType string) *driver {
|
||||
return &driver{name: networkType, networks: map[string]*hnsNetwork{}}
|
||||
}
|
||||
|
||||
// GetInit returns an initializer for the given network type
|
||||
func GetInit(networkType string) func(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
||||
return func(dc driverapi.DriverCallback, config map[string]interface{}) error {
|
||||
if !IsBuiltinLocalDriver(networkType) {
|
||||
return types.BadRequestErrorf("Network type not supported: %s", networkType)
|
||||
}
|
||||
|
||||
d := newDriver(networkType)
|
||||
|
||||
err := d.initStore(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return dc.RegisterDriver(networkType, d, driverapi.Capability{
|
||||
DataScope: datastore.LocalScope,
|
||||
ConnectivityScope: datastore.LocalScope,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (d *driver) getNetwork(id string) (*hnsNetwork, error) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
|
||||
if nw, ok := d.networks[id]; ok {
|
||||
return nw, nil
|
||||
}
|
||||
|
||||
return nil, types.NotFoundErrorf("network not found: %s", id)
|
||||
}
|
||||
|
||||
func (n *hnsNetwork) getEndpoint(eid string) (*hnsEndpoint, error) {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
||||
if ep, ok := n.endpoints[eid]; ok {
|
||||
return ep, nil
|
||||
}
|
||||
|
||||
return nil, types.NotFoundErrorf("Endpoint not found: %s", eid)
|
||||
}
|
||||
|
||||
func (d *driver) parseNetworkOptions(id string, genericOptions map[string]string) (*networkConfiguration, error) {
|
||||
config := &networkConfiguration{Type: d.name}
|
||||
|
||||
for label, value := range genericOptions {
|
||||
switch label {
|
||||
case NetworkName:
|
||||
config.Name = value
|
||||
case HNSID:
|
||||
config.HnsID = value
|
||||
case RoutingDomain:
|
||||
config.RDID = value
|
||||
case Interface:
|
||||
config.NetworkAdapterName = value
|
||||
case DNSSuffix:
|
||||
config.DNSSuffix = value
|
||||
case DNSServers:
|
||||
config.DNSServers = value
|
||||
case DisableGatewayDNS:
|
||||
b, err := strconv.ParseBool(value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.DisableGatewayDNS = b
|
||||
case MacPool:
|
||||
config.MacPools = make([]hcsshim.MacPool, 0)
|
||||
s := strings.Split(value, ",")
|
||||
if len(s)%2 != 0 {
|
||||
return nil, types.BadRequestErrorf("Invalid mac pool. You must specify both a start range and an end range")
|
||||
}
|
||||
for i := 0; i < len(s)-1; i += 2 {
|
||||
config.MacPools = append(config.MacPools, hcsshim.MacPool{
|
||||
StartMacAddress: s[i],
|
||||
EndMacAddress: s[i+1],
|
||||
})
|
||||
}
|
||||
case VLAN:
|
||||
vlan, err := strconv.ParseUint(value, 10, 32)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.VLAN = uint(vlan)
|
||||
case VSID:
|
||||
vsid, err := strconv.ParseUint(value, 10, 32)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.VSID = uint(vsid)
|
||||
case EnableOutboundNat:
|
||||
if osversion.Build() <= 16236 {
|
||||
return nil, fmt.Errorf("Invalid network option. OutboundNat is not supported on this OS version")
|
||||
}
|
||||
b, err := strconv.ParseBool(value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.EnableOutboundNat = b
|
||||
case OutboundNatExceptions:
|
||||
s := strings.Split(value, ",")
|
||||
config.OutboundNatExceptions = s
|
||||
}
|
||||
}
|
||||
|
||||
config.ID = id
|
||||
config.Type = d.name
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func (c *networkConfiguration) processIPAM(id string, ipamV4Data, ipamV6Data []driverapi.IPAMData) error {
|
||||
if len(ipamV6Data) > 0 {
|
||||
return types.ForbiddenErrorf("windowsshim driver doesn't support v6 subnets")
|
||||
}
|
||||
|
||||
if len(ipamV4Data) == 0 {
|
||||
return types.BadRequestErrorf("network %s requires ipv4 configuration", id)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) EventNotify(etype driverapi.EventType, nid, tableName, key string, value []byte) {
|
||||
}
|
||||
|
||||
func (d *driver) DecodeTableEntry(tablename string, key string, value []byte) (string, map[string]string) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (d *driver) createNetwork(config *networkConfiguration) *hnsNetwork {
|
||||
network := &hnsNetwork{
|
||||
id: config.ID,
|
||||
endpoints: make(map[string]*hnsEndpoint),
|
||||
config: config,
|
||||
driver: d,
|
||||
portMapper: portmapper.New(""),
|
||||
}
|
||||
|
||||
d.Lock()
|
||||
d.networks[config.ID] = network
|
||||
d.Unlock()
|
||||
|
||||
return network
|
||||
}
|
||||
|
||||
// Create a new network
|
||||
func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
|
||||
if _, err := d.getNetwork(id); err == nil {
|
||||
return types.ForbiddenErrorf("network %s exists", id)
|
||||
}
|
||||
|
||||
genData, ok := option[netlabel.GenericData].(map[string]string)
|
||||
if !ok {
|
||||
return fmt.Errorf("Unknown generic data option")
|
||||
}
|
||||
|
||||
// Parse and validate the config. It should not conflict with existing networks' config
|
||||
config, err := d.parseNetworkOptions(id, genData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = config.processIPAM(id, ipV4Data, ipV6Data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n := d.createNetwork(config)
|
||||
|
||||
// A non blank hnsid indicates that the network was discovered
|
||||
// from HNS. No need to call HNS if this network was discovered
|
||||
// from HNS
|
||||
if config.HnsID == "" {
|
||||
subnets := []hcsshim.Subnet{}
|
||||
|
||||
for _, ipData := range ipV4Data {
|
||||
subnet := hcsshim.Subnet{
|
||||
AddressPrefix: ipData.Pool.String(),
|
||||
}
|
||||
|
||||
if ipData.Gateway != nil {
|
||||
subnet.GatewayAddress = ipData.Gateway.IP.String()
|
||||
}
|
||||
|
||||
subnets = append(subnets, subnet)
|
||||
}
|
||||
|
||||
network := &hcsshim.HNSNetwork{
|
||||
Name: config.Name,
|
||||
Type: d.name,
|
||||
Subnets: subnets,
|
||||
DNSServerList: config.DNSServers,
|
||||
DNSSuffix: config.DNSSuffix,
|
||||
MacPools: config.MacPools,
|
||||
SourceMac: config.SourceMac,
|
||||
NetworkAdapterName: config.NetworkAdapterName,
|
||||
}
|
||||
|
||||
if config.VLAN != 0 {
|
||||
vlanPolicy, err := json.Marshal(hcsshim.VlanPolicy{
|
||||
Type: "VLAN",
|
||||
VLAN: config.VLAN,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
network.Policies = append(network.Policies, vlanPolicy)
|
||||
}
|
||||
|
||||
if config.VSID != 0 {
|
||||
vsidPolicy, err := json.Marshal(hcsshim.VsidPolicy{
|
||||
Type: "VSID",
|
||||
VSID: config.VSID,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
network.Policies = append(network.Policies, vsidPolicy)
|
||||
}
|
||||
|
||||
if network.Name == "" {
|
||||
network.Name = id
|
||||
}
|
||||
|
||||
configurationb, err := json.Marshal(network)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
configuration := string(configurationb)
|
||||
logrus.Debugf("HNSNetwork Request =%v Address Space=%v", configuration, subnets)
|
||||
|
||||
hnsresponse, err := hcsshim.HNSNetworkRequest("POST", "", configuration)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config.HnsID = hnsresponse.Id
|
||||
genData[HNSID] = config.HnsID
|
||||
n.created = true
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
d.DeleteNetwork(n.id)
|
||||
}
|
||||
}()
|
||||
|
||||
hnsIPv4Data := make([]driverapi.IPAMData, len(hnsresponse.Subnets))
|
||||
|
||||
for i, subnet := range hnsresponse.Subnets {
|
||||
var gwIP, subnetIP *net.IPNet
|
||||
|
||||
//The gateway returned from HNS is an IPAddress.
|
||||
//We need to convert it to an IPNet to use as the Gateway of driverapi.IPAMData struct
|
||||
gwCIDR := subnet.GatewayAddress + "/32"
|
||||
_, gwIP, err = net.ParseCIDR(gwCIDR)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hnsIPv4Data[i].Gateway = gwIP
|
||||
_, subnetIP, err = net.ParseCIDR(subnet.AddressPrefix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hnsIPv4Data[i].Pool = subnetIP
|
||||
}
|
||||
|
||||
nInfo.UpdateIpamConfig(hnsIPv4Data)
|
||||
|
||||
} else {
|
||||
// Delete any stale HNS endpoints for this network.
|
||||
if endpoints, err := hcsshim.HNSListEndpointRequest(); err == nil {
|
||||
for _, ep := range endpoints {
|
||||
if ep.VirtualNetwork == config.HnsID {
|
||||
logrus.Infof("Removing stale HNS endpoint %s", ep.Id)
|
||||
_, err = hcsshim.HNSEndpointRequest("DELETE", ep.Id, "")
|
||||
if err != nil {
|
||||
logrus.Warnf("Error removing HNS endpoint %s", ep.Id)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logrus.Warnf("Error listing HNS endpoints for network %s", config.HnsID)
|
||||
}
|
||||
|
||||
n.created = true
|
||||
}
|
||||
|
||||
return d.storeUpdate(config)
|
||||
}
|
||||
|
||||
func (d *driver) DeleteNetwork(nid string) error {
|
||||
n, err := d.getNetwork(nid)
|
||||
if err != nil {
|
||||
return types.InternalMaskableErrorf("%s", err)
|
||||
}
|
||||
|
||||
n.Lock()
|
||||
config := n.config
|
||||
n.Unlock()
|
||||
|
||||
if n.created {
|
||||
_, err = hcsshim.HNSNetworkRequest("DELETE", config.HnsID, "")
|
||||
if err != nil && err.Error() != errNotFound {
|
||||
return types.ForbiddenErrorf(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
d.Lock()
|
||||
delete(d.networks, nid)
|
||||
d.Unlock()
|
||||
|
||||
// delele endpoints belong to this network
|
||||
for _, ep := range n.endpoints {
|
||||
if err := d.storeDelete(ep); err != nil {
|
||||
logrus.Warnf("Failed to remove bridge endpoint %.7s from store: %v", ep.id, err)
|
||||
}
|
||||
}
|
||||
|
||||
return d.storeDelete(config)
|
||||
}
|
||||
|
||||
func convertQosPolicies(qosPolicies []types.QosPolicy) ([]json.RawMessage, error) {
|
||||
var qps []json.RawMessage
|
||||
|
||||
// Enumerate through the qos policies specified by the user and convert
|
||||
// them into the internal structure matching the JSON blob that can be
|
||||
// understood by the HCS.
|
||||
for _, elem := range qosPolicies {
|
||||
encodedPolicy, err := json.Marshal(hcsshim.QosPolicy{
|
||||
Type: "QOS",
|
||||
MaximumOutgoingBandwidthInBytes: elem.MaxEgressBandwidth,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
qps = append(qps, encodedPolicy)
|
||||
}
|
||||
return qps, nil
|
||||
}
|
||||
|
||||
// ConvertPortBindings converts PortBindings to JSON for HNS request
|
||||
func ConvertPortBindings(portBindings []types.PortBinding) ([]json.RawMessage, error) {
|
||||
var pbs []json.RawMessage
|
||||
|
||||
// Enumerate through the port bindings specified by the user and convert
|
||||
// them into the internal structure matching the JSON blob that can be
|
||||
// understood by the HCS.
|
||||
for _, elem := range portBindings {
|
||||
proto := strings.ToUpper(elem.Proto.String())
|
||||
if proto != "TCP" && proto != "UDP" {
|
||||
return nil, fmt.Errorf("invalid protocol %s", elem.Proto.String())
|
||||
}
|
||||
|
||||
if elem.HostPort != elem.HostPortEnd {
|
||||
return nil, fmt.Errorf("Windows does not support more than one host port in NAT settings")
|
||||
}
|
||||
|
||||
if len(elem.HostIP) != 0 && !elem.HostIP.IsUnspecified() {
|
||||
return nil, fmt.Errorf("Windows does not support host IP addresses in NAT settings")
|
||||
}
|
||||
|
||||
encodedPolicy, err := json.Marshal(hcsshim.NatPolicy{
|
||||
Type: "NAT",
|
||||
ExternalPort: elem.HostPort,
|
||||
InternalPort: elem.Port,
|
||||
Protocol: elem.Proto.String(),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pbs = append(pbs, encodedPolicy)
|
||||
}
|
||||
return pbs, nil
|
||||
}
|
||||
|
||||
// ParsePortBindingPolicies parses HNS endpoint response message to PortBindings
|
||||
func ParsePortBindingPolicies(policies []json.RawMessage) ([]types.PortBinding, error) {
|
||||
var bindings []types.PortBinding
|
||||
hcsPolicy := &hcsshim.NatPolicy{}
|
||||
|
||||
for _, elem := range policies {
|
||||
|
||||
if err := json.Unmarshal([]byte(elem), &hcsPolicy); err != nil || hcsPolicy.Type != "NAT" {
|
||||
continue
|
||||
}
|
||||
|
||||
binding := types.PortBinding{
|
||||
HostPort: hcsPolicy.ExternalPort,
|
||||
HostPortEnd: hcsPolicy.ExternalPort,
|
||||
Port: hcsPolicy.InternalPort,
|
||||
Proto: types.ParseProtocol(hcsPolicy.Protocol),
|
||||
HostIP: net.IPv4(0, 0, 0, 0),
|
||||
}
|
||||
|
||||
bindings = append(bindings, binding)
|
||||
}
|
||||
|
||||
return bindings, nil
|
||||
}
|
||||
|
||||
func parseEndpointOptions(epOptions map[string]interface{}) (*endpointOption, error) {
|
||||
if epOptions == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
ec := &endpointOption{}
|
||||
|
||||
if opt, ok := epOptions[netlabel.MacAddress]; ok {
|
||||
if mac, ok := opt.(net.HardwareAddr); ok {
|
||||
ec.MacAddress = mac
|
||||
} else {
|
||||
return nil, fmt.Errorf("Invalid endpoint configuration")
|
||||
}
|
||||
}
|
||||
|
||||
if opt, ok := epOptions[QosPolicies]; ok {
|
||||
if policies, ok := opt.([]types.QosPolicy); ok {
|
||||
ec.QosPolicies = policies
|
||||
} else {
|
||||
return nil, fmt.Errorf("Invalid endpoint configuration")
|
||||
}
|
||||
}
|
||||
|
||||
if opt, ok := epOptions[netlabel.DNSServers]; ok {
|
||||
if dns, ok := opt.([]string); ok {
|
||||
ec.DNSServers = dns
|
||||
} else {
|
||||
return nil, fmt.Errorf("Invalid endpoint configuration")
|
||||
}
|
||||
}
|
||||
|
||||
if opt, ok := epOptions[DisableICC]; ok {
|
||||
if disableICC, ok := opt.(bool); ok {
|
||||
ec.DisableICC = disableICC
|
||||
} else {
|
||||
return nil, fmt.Errorf("Invalid endpoint configuration")
|
||||
}
|
||||
}
|
||||
|
||||
if opt, ok := epOptions[DisableDNS]; ok {
|
||||
if disableDNS, ok := opt.(bool); ok {
|
||||
ec.DisableDNS = disableDNS
|
||||
} else {
|
||||
return nil, fmt.Errorf("Invalid endpoint configuration")
|
||||
}
|
||||
}
|
||||
|
||||
return ec, nil
|
||||
}
|
||||
|
||||
// ParseEndpointConnectivity parses options passed to CreateEndpoint, specifically port bindings, and store in a endpointConnectivity object.
|
||||
func ParseEndpointConnectivity(epOptions map[string]interface{}) (*EndpointConnectivity, error) {
|
||||
if epOptions == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
ec := &EndpointConnectivity{}
|
||||
|
||||
if opt, ok := epOptions[netlabel.PortMap]; ok {
|
||||
if bs, ok := opt.([]types.PortBinding); ok {
|
||||
ec.PortBindings = bs
|
||||
} else {
|
||||
return nil, fmt.Errorf("Invalid endpoint configuration")
|
||||
}
|
||||
}
|
||||
|
||||
if opt, ok := epOptions[netlabel.ExposedPorts]; ok {
|
||||
if ports, ok := opt.([]types.TransportPort); ok {
|
||||
ec.ExposedPorts = ports
|
||||
} else {
|
||||
return nil, fmt.Errorf("Invalid endpoint configuration")
|
||||
}
|
||||
}
|
||||
return ec, nil
|
||||
}
|
||||
|
||||
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error {
|
||||
n, err := d.getNetwork(nid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check if endpoint id is good and retrieve corresponding endpoint
|
||||
ep, err := n.getEndpoint(eid)
|
||||
if err == nil && ep != nil {
|
||||
return driverapi.ErrEndpointExists(eid)
|
||||
}
|
||||
|
||||
endpointStruct := &hcsshim.HNSEndpoint{
|
||||
VirtualNetwork: n.config.HnsID,
|
||||
}
|
||||
|
||||
epOption, err := parseEndpointOptions(epOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
epConnectivity, err := ParseEndpointConnectivity(epOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
macAddress := ifInfo.MacAddress()
|
||||
// Use the macaddress if it was provided
|
||||
if macAddress != nil {
|
||||
endpointStruct.MacAddress = strings.Replace(macAddress.String(), ":", "-", -1)
|
||||
}
|
||||
|
||||
portMapping := epConnectivity.PortBindings
|
||||
|
||||
if n.config.Type == "l2bridge" || n.config.Type == "l2tunnel" {
|
||||
ip := net.IPv4(0, 0, 0, 0)
|
||||
if ifInfo.Address() != nil {
|
||||
ip = ifInfo.Address().IP
|
||||
}
|
||||
|
||||
portMapping, err = AllocatePorts(n.portMapper, portMapping, ip)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
ReleasePorts(n.portMapper, portMapping)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
endpointStruct.Policies, err = ConvertPortBindings(portMapping)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
qosPolicies, err := convertQosPolicies(epOption.QosPolicies)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
endpointStruct.Policies = append(endpointStruct.Policies, qosPolicies...)
|
||||
|
||||
if ifInfo.Address() != nil {
|
||||
endpointStruct.IPAddress = ifInfo.Address().IP
|
||||
}
|
||||
|
||||
endpointStruct.DNSServerList = strings.Join(epOption.DNSServers, ",")
|
||||
|
||||
// overwrite the ep DisableDNS option if DisableGatewayDNS was set to true during the network creation option
|
||||
if n.config.DisableGatewayDNS {
|
||||
logrus.Debugf("n.config.DisableGatewayDNS[%v] overwrites epOption.DisableDNS[%v]", n.config.DisableGatewayDNS, epOption.DisableDNS)
|
||||
epOption.DisableDNS = n.config.DisableGatewayDNS
|
||||
}
|
||||
|
||||
if n.driver.name == "nat" && !epOption.DisableDNS {
|
||||
logrus.Debugf("endpointStruct.EnableInternalDNS =[%v]", endpointStruct.EnableInternalDNS)
|
||||
endpointStruct.EnableInternalDNS = true
|
||||
}
|
||||
|
||||
endpointStruct.DisableICC = epOption.DisableICC
|
||||
|
||||
// Inherit OutboundNat policy from the network
|
||||
if n.config.EnableOutboundNat {
|
||||
outboundNatPolicy, err := json.Marshal(hcsshim.OutboundNatPolicy{
|
||||
Policy: hcsshim.Policy{Type: hcsshim.OutboundNat},
|
||||
Exceptions: n.config.OutboundNatExceptions,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
endpointStruct.Policies = append(endpointStruct.Policies, outboundNatPolicy)
|
||||
}
|
||||
|
||||
configurationb, err := json.Marshal(endpointStruct)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hnsresponse, err := hcsshim.HNSEndpointRequest("POST", "", string(configurationb))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mac, err := net.ParseMAC(hnsresponse.MacAddress)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO For now the ip mask is not in the info generated by HNS
|
||||
endpoint := &hnsEndpoint{
|
||||
id: eid,
|
||||
nid: n.id,
|
||||
Type: d.name,
|
||||
addr: &net.IPNet{IP: hnsresponse.IPAddress, Mask: hnsresponse.IPAddress.DefaultMask()},
|
||||
macAddress: mac,
|
||||
}
|
||||
|
||||
if hnsresponse.GatewayAddress != "" {
|
||||
endpoint.gateway = net.ParseIP(hnsresponse.GatewayAddress)
|
||||
}
|
||||
|
||||
endpoint.profileID = hnsresponse.Id
|
||||
endpoint.epConnectivity = epConnectivity
|
||||
endpoint.epOption = epOption
|
||||
endpoint.portMapping, err = ParsePortBindingPolicies(hnsresponse.Policies)
|
||||
|
||||
if err != nil {
|
||||
hcsshim.HNSEndpointRequest("DELETE", hnsresponse.Id, "")
|
||||
return err
|
||||
}
|
||||
|
||||
n.Lock()
|
||||
n.endpoints[eid] = endpoint
|
||||
n.Unlock()
|
||||
|
||||
if ifInfo.Address() == nil {
|
||||
ifInfo.SetIPAddress(endpoint.addr)
|
||||
}
|
||||
|
||||
if macAddress == nil {
|
||||
ifInfo.SetMacAddress(endpoint.macAddress)
|
||||
}
|
||||
|
||||
if err = d.storeUpdate(endpoint); err != nil {
|
||||
logrus.Errorf("Failed to save endpoint %.7s to store: %v", endpoint.id, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) DeleteEndpoint(nid, eid string) error {
|
||||
n, err := d.getNetwork(nid)
|
||||
if err != nil {
|
||||
return types.InternalMaskableErrorf("%s", err)
|
||||
}
|
||||
|
||||
ep, err := n.getEndpoint(eid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if n.config.Type == "l2bridge" || n.config.Type == "l2tunnel" {
|
||||
ReleasePorts(n.portMapper, ep.portMapping)
|
||||
}
|
||||
|
||||
n.Lock()
|
||||
delete(n.endpoints, eid)
|
||||
n.Unlock()
|
||||
|
||||
_, err = hcsshim.HNSEndpointRequest("DELETE", ep.profileID, "")
|
||||
if err != nil && err.Error() != errNotFound {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := d.storeDelete(ep); err != nil {
|
||||
logrus.Warnf("Failed to remove bridge endpoint %.7s from store: %v", ep.id, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) {
|
||||
network, err := d.getNetwork(nid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ep, err := network.getEndpoint(eid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := make(map[string]interface{}, 1)
|
||||
if network.driver.name == "nat" {
|
||||
data["AllowUnqualifiedDNSQuery"] = true
|
||||
}
|
||||
|
||||
data["hnsid"] = ep.profileID
|
||||
if ep.epConnectivity.ExposedPorts != nil {
|
||||
// Return a copy of the config data
|
||||
epc := make([]types.TransportPort, 0, len(ep.epConnectivity.ExposedPorts))
|
||||
for _, tp := range ep.epConnectivity.ExposedPorts {
|
||||
epc = append(epc, tp.GetCopy())
|
||||
}
|
||||
data[netlabel.ExposedPorts] = epc
|
||||
}
|
||||
|
||||
if ep.portMapping != nil {
|
||||
// Return a copy of the operational data
|
||||
pmc := make([]types.PortBinding, 0, len(ep.portMapping))
|
||||
for _, pm := range ep.portMapping {
|
||||
pmc = append(pmc, pm.GetCopy())
|
||||
}
|
||||
data[netlabel.PortMap] = pmc
|
||||
}
|
||||
|
||||
if len(ep.macAddress) != 0 {
|
||||
data[netlabel.MacAddress] = ep.macAddress
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// Join method is invoked when a Sandbox is attached to an endpoint.
|
||||
func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error {
|
||||
network, err := d.getNetwork(nid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Ensure that the endpoint exists
|
||||
endpoint, err := network.getEndpoint(eid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = jinfo.SetGateway(endpoint.gateway)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
endpoint.sandboxID = sboxKey
|
||||
|
||||
err = hcsshim.HotAttachEndpoint(endpoint.sandboxID, endpoint.profileID)
|
||||
if err != nil {
|
||||
// If container doesn't exists in hcs, do not throw error for hot add/remove
|
||||
if err != hcsshim.ErrComputeSystemDoesNotExist {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
jinfo.DisableGatewayService()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Leave method is invoked when a Sandbox detaches from an endpoint.
|
||||
func (d *driver) Leave(nid, eid string) error {
|
||||
network, err := d.getNetwork(nid)
|
||||
if err != nil {
|
||||
return types.InternalMaskableErrorf("%s", err)
|
||||
}
|
||||
|
||||
// Ensure that the endpoint exists
|
||||
endpoint, err := network.getEndpoint(eid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = hcsshim.HotDetachEndpoint(endpoint.sandboxID, endpoint.profileID)
|
||||
if err != nil {
|
||||
// If container doesn't exists in hcs, do not throw error for hot add/remove
|
||||
if err != hcsshim.ErrComputeSystemDoesNotExist {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) ProgramExternalConnectivity(nid, eid string, options map[string]interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) RevokeExternalConnectivity(nid, eid string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {
|
||||
return nil, types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) NetworkFree(id string) error {
|
||||
return types.NotImplementedErrorf("not implemented")
|
||||
}
|
||||
|
||||
func (d *driver) Type() string {
|
||||
return d.name
|
||||
}
|
||||
|
||||
func (d *driver) IsBuiltIn() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// DiscoverNew is a notification for a new discovery event, such as a new node joining a cluster
|
||||
func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DiscoverDelete is a notification for a discovery delete event, such as a node leaving a cluster
|
||||
func (d *driver) DiscoverDelete(dType discoverapi.DiscoveryType, data interface{}) error {
|
||||
return nil
|
||||
}
|
337
vendor/github.com/docker/libnetwork/drivers/windows/windows_store.go
generated
vendored
337
vendor/github.com/docker/libnetwork/drivers/windows/windows_store.go
generated
vendored
|
@ -1,337 +0,0 @@
|
|||
// +build windows
|
||||
|
||||
package windows
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/docker/libnetwork/datastore"
|
||||
"github.com/docker/libnetwork/discoverapi"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
windowsPrefix = "windows"
|
||||
windowsEndpointPrefix = "windows-endpoint"
|
||||
)
|
||||
|
||||
func (d *driver) initStore(option map[string]interface{}) error {
|
||||
if data, ok := option[netlabel.LocalKVClient]; ok {
|
||||
var err error
|
||||
dsc, ok := data.(discoverapi.DatastoreConfigData)
|
||||
if !ok {
|
||||
return types.InternalErrorf("incorrect data in datastore configuration: %v", data)
|
||||
}
|
||||
d.store, err = datastore.NewDataStoreFromConfig(dsc)
|
||||
if err != nil {
|
||||
return types.InternalErrorf("windows driver failed to initialize data store: %v", err)
|
||||
}
|
||||
|
||||
err = d.populateNetworks()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = d.populateEndpoints()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) populateNetworks() error {
|
||||
kvol, err := d.store.List(datastore.Key(windowsPrefix), &networkConfiguration{Type: d.name})
|
||||
if err != nil && err != datastore.ErrKeyNotFound {
|
||||
return fmt.Errorf("failed to get windows network configurations from store: %v", err)
|
||||
}
|
||||
|
||||
// It's normal for network configuration state to be empty. Just return.
|
||||
if err == datastore.ErrKeyNotFound {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, kvo := range kvol {
|
||||
ncfg := kvo.(*networkConfiguration)
|
||||
if ncfg.Type != d.name {
|
||||
continue
|
||||
}
|
||||
d.createNetwork(ncfg)
|
||||
logrus.Debugf("Network %v (%.7s) restored", d.name, ncfg.ID)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) populateEndpoints() error {
|
||||
kvol, err := d.store.List(datastore.Key(windowsEndpointPrefix), &hnsEndpoint{Type: d.name})
|
||||
if err != nil && err != datastore.ErrKeyNotFound {
|
||||
return fmt.Errorf("failed to get endpoints from store: %v", err)
|
||||
}
|
||||
|
||||
if err == datastore.ErrKeyNotFound {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, kvo := range kvol {
|
||||
ep := kvo.(*hnsEndpoint)
|
||||
if ep.Type != d.name {
|
||||
continue
|
||||
}
|
||||
n, ok := d.networks[ep.nid]
|
||||
if !ok {
|
||||
logrus.Debugf("Network (%.7s) not found for restored endpoint (%.7s)", ep.nid, ep.id)
|
||||
logrus.Debugf("Deleting stale endpoint (%.7s) from store", ep.id)
|
||||
if err := d.storeDelete(ep); err != nil {
|
||||
logrus.Debugf("Failed to delete stale endpoint (%.7s) from store", ep.id)
|
||||
}
|
||||
continue
|
||||
}
|
||||
n.endpoints[ep.id] = ep
|
||||
logrus.Debugf("Endpoint (%.7s) restored to network (%.7s)", ep.id, ep.nid)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) storeUpdate(kvObject datastore.KVObject) error {
|
||||
if d.store == nil {
|
||||
logrus.Warnf("store not initialized. kv object %s is not added to the store", datastore.Key(kvObject.Key()...))
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := d.store.PutObjectAtomic(kvObject); err != nil {
|
||||
return fmt.Errorf("failed to update store for object type %T: %v", kvObject, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) storeDelete(kvObject datastore.KVObject) error {
|
||||
if d.store == nil {
|
||||
logrus.Debugf("store not initialized. kv object %s is not deleted from store", datastore.Key(kvObject.Key()...))
|
||||
return nil
|
||||
}
|
||||
|
||||
retry:
|
||||
if err := d.store.DeleteObjectAtomic(kvObject); err != nil {
|
||||
if err == datastore.ErrKeyModified {
|
||||
if err := d.store.GetObject(datastore.Key(kvObject.Key()...), kvObject); err != nil {
|
||||
return fmt.Errorf("could not update the kvobject to latest when trying to delete: %v", err)
|
||||
}
|
||||
goto retry
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) MarshalJSON() ([]byte, error) {
|
||||
nMap := make(map[string]interface{})
|
||||
|
||||
nMap["ID"] = ncfg.ID
|
||||
nMap["Type"] = ncfg.Type
|
||||
nMap["Name"] = ncfg.Name
|
||||
nMap["HnsID"] = ncfg.HnsID
|
||||
nMap["VLAN"] = ncfg.VLAN
|
||||
nMap["VSID"] = ncfg.VSID
|
||||
nMap["DNSServers"] = ncfg.DNSServers
|
||||
nMap["DNSSuffix"] = ncfg.DNSSuffix
|
||||
nMap["SourceMac"] = ncfg.SourceMac
|
||||
nMap["NetworkAdapterName"] = ncfg.NetworkAdapterName
|
||||
|
||||
return json.Marshal(nMap)
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) UnmarshalJSON(b []byte) error {
|
||||
var (
|
||||
err error
|
||||
nMap map[string]interface{}
|
||||
)
|
||||
|
||||
if err = json.Unmarshal(b, &nMap); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ncfg.ID = nMap["ID"].(string)
|
||||
ncfg.Type = nMap["Type"].(string)
|
||||
ncfg.Name = nMap["Name"].(string)
|
||||
ncfg.HnsID = nMap["HnsID"].(string)
|
||||
ncfg.VLAN = uint(nMap["VLAN"].(float64))
|
||||
ncfg.VSID = uint(nMap["VSID"].(float64))
|
||||
ncfg.DNSServers = nMap["DNSServers"].(string)
|
||||
ncfg.DNSSuffix = nMap["DNSSuffix"].(string)
|
||||
ncfg.SourceMac = nMap["SourceMac"].(string)
|
||||
ncfg.NetworkAdapterName = nMap["NetworkAdapterName"].(string)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) Key() []string {
|
||||
return []string{windowsPrefix + ncfg.Type, ncfg.ID}
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) KeyPrefix() []string {
|
||||
return []string{windowsPrefix + ncfg.Type}
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) Value() []byte {
|
||||
b, err := json.Marshal(ncfg)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) SetValue(value []byte) error {
|
||||
return json.Unmarshal(value, ncfg)
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) Index() uint64 {
|
||||
return ncfg.dbIndex
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) SetIndex(index uint64) {
|
||||
ncfg.dbIndex = index
|
||||
ncfg.dbExists = true
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) Exists() bool {
|
||||
return ncfg.dbExists
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) Skip() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) New() datastore.KVObject {
|
||||
return &networkConfiguration{Type: ncfg.Type}
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) CopyTo(o datastore.KVObject) error {
|
||||
dstNcfg := o.(*networkConfiguration)
|
||||
*dstNcfg = *ncfg
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ncfg *networkConfiguration) DataScope() string {
|
||||
return datastore.LocalScope
|
||||
}
|
||||
|
||||
func (ep *hnsEndpoint) MarshalJSON() ([]byte, error) {
|
||||
epMap := make(map[string]interface{})
|
||||
epMap["id"] = ep.id
|
||||
epMap["nid"] = ep.nid
|
||||
epMap["Type"] = ep.Type
|
||||
epMap["profileID"] = ep.profileID
|
||||
epMap["MacAddress"] = ep.macAddress.String()
|
||||
if ep.addr.IP != nil {
|
||||
epMap["Addr"] = ep.addr.String()
|
||||
}
|
||||
if ep.gateway != nil {
|
||||
epMap["gateway"] = ep.gateway.String()
|
||||
}
|
||||
epMap["epOption"] = ep.epOption
|
||||
epMap["epConnectivity"] = ep.epConnectivity
|
||||
epMap["PortMapping"] = ep.portMapping
|
||||
|
||||
return json.Marshal(epMap)
|
||||
}
|
||||
|
||||
func (ep *hnsEndpoint) UnmarshalJSON(b []byte) error {
|
||||
var (
|
||||
err error
|
||||
epMap map[string]interface{}
|
||||
)
|
||||
|
||||
if err = json.Unmarshal(b, &epMap); err != nil {
|
||||
return fmt.Errorf("Failed to unmarshal to endpoint: %v", err)
|
||||
}
|
||||
if v, ok := epMap["MacAddress"]; ok {
|
||||
if ep.macAddress, err = net.ParseMAC(v.(string)); err != nil {
|
||||
return types.InternalErrorf("failed to decode endpoint MAC address (%s) after json unmarshal: %v", v.(string), err)
|
||||
}
|
||||
}
|
||||
if v, ok := epMap["Addr"]; ok {
|
||||
if ep.addr, err = types.ParseCIDR(v.(string)); err != nil {
|
||||
logrus.Warnf("failed to decode endpoint IPv4 address (%s) after json unmarshal: %v", v.(string), err)
|
||||
}
|
||||
}
|
||||
if v, ok := epMap["gateway"]; ok {
|
||||
ep.gateway = net.ParseIP(v.(string))
|
||||
}
|
||||
ep.id = epMap["id"].(string)
|
||||
ep.Type = epMap["Type"].(string)
|
||||
ep.nid = epMap["nid"].(string)
|
||||
ep.profileID = epMap["profileID"].(string)
|
||||
d, _ := json.Marshal(epMap["epOption"])
|
||||
if err := json.Unmarshal(d, &ep.epOption); err != nil {
|
||||
logrus.Warnf("Failed to decode endpoint container config %v", err)
|
||||
}
|
||||
d, _ = json.Marshal(epMap["epConnectivity"])
|
||||
if err := json.Unmarshal(d, &ep.epConnectivity); err != nil {
|
||||
logrus.Warnf("Failed to decode endpoint external connectivity configuration %v", err)
|
||||
}
|
||||
d, _ = json.Marshal(epMap["PortMapping"])
|
||||
if err := json.Unmarshal(d, &ep.portMapping); err != nil {
|
||||
logrus.Warnf("Failed to decode endpoint port mapping %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ep *hnsEndpoint) Key() []string {
|
||||
return []string{windowsEndpointPrefix + ep.Type, ep.id}
|
||||
}
|
||||
|
||||
func (ep *hnsEndpoint) KeyPrefix() []string {
|
||||
return []string{windowsEndpointPrefix + ep.Type}
|
||||
}
|
||||
|
||||
func (ep *hnsEndpoint) Value() []byte {
|
||||
b, err := json.Marshal(ep)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (ep *hnsEndpoint) SetValue(value []byte) error {
|
||||
return json.Unmarshal(value, ep)
|
||||
}
|
||||
|
||||
func (ep *hnsEndpoint) Index() uint64 {
|
||||
return ep.dbIndex
|
||||
}
|
||||
|
||||
func (ep *hnsEndpoint) SetIndex(index uint64) {
|
||||
ep.dbIndex = index
|
||||
ep.dbExists = true
|
||||
}
|
||||
|
||||
func (ep *hnsEndpoint) Exists() bool {
|
||||
return ep.dbExists
|
||||
}
|
||||
|
||||
func (ep *hnsEndpoint) Skip() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (ep *hnsEndpoint) New() datastore.KVObject {
|
||||
return &hnsEndpoint{Type: ep.Type}
|
||||
}
|
||||
|
||||
func (ep *hnsEndpoint) CopyTo(o datastore.KVObject) error {
|
||||
dstEp := o.(*hnsEndpoint)
|
||||
*dstEp = *ep
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ep *hnsEndpoint) DataScope() string {
|
||||
return datastore.LocalScope
|
||||
}
|
13
vendor/github.com/docker/libnetwork/drivers_freebsd.go
generated
vendored
13
vendor/github.com/docker/libnetwork/drivers_freebsd.go
generated
vendored
|
@ -1,13 +0,0 @@
|
|||
package libnetwork
|
||||
|
||||
import (
|
||||
"github.com/docker/libnetwork/drivers/null"
|
||||
"github.com/docker/libnetwork/drivers/remote"
|
||||
)
|
||||
|
||||
func getInitializers(experimental bool) []initializer {
|
||||
return []initializer{
|
||||
{null.Init, "null"},
|
||||
{remote.Init, "remote"},
|
||||
}
|
||||
}
|
25
vendor/github.com/docker/libnetwork/drivers_ipam.go
generated
vendored
25
vendor/github.com/docker/libnetwork/drivers_ipam.go
generated
vendored
|
@ -1,25 +0,0 @@
|
|||
package libnetwork
|
||||
|
||||
import (
|
||||
"github.com/docker/libnetwork/drvregistry"
|
||||
"github.com/docker/libnetwork/ipamapi"
|
||||
builtinIpam "github.com/docker/libnetwork/ipams/builtin"
|
||||
nullIpam "github.com/docker/libnetwork/ipams/null"
|
||||
remoteIpam "github.com/docker/libnetwork/ipams/remote"
|
||||
"github.com/docker/libnetwork/ipamutils"
|
||||
)
|
||||
|
||||
func initIPAMDrivers(r *drvregistry.DrvRegistry, lDs, gDs interface{}, addressPool []*ipamutils.NetworkToSplit) error {
|
||||
builtinIpam.SetDefaultIPAddressPool(addressPool)
|
||||
for _, fn := range [](func(ipamapi.Callback, interface{}, interface{}) error){
|
||||
builtinIpam.Init,
|
||||
remoteIpam.Init,
|
||||
nullIpam.Init,
|
||||
} {
|
||||
if err := fn(r, lDs, gDs); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
24
vendor/github.com/docker/libnetwork/drivers_linux.go
generated
vendored
24
vendor/github.com/docker/libnetwork/drivers_linux.go
generated
vendored
|
@ -1,24 +0,0 @@
|
|||
package libnetwork
|
||||
|
||||
import (
|
||||
"github.com/docker/libnetwork/drivers/bridge"
|
||||
"github.com/docker/libnetwork/drivers/host"
|
||||
"github.com/docker/libnetwork/drivers/ipvlan"
|
||||
"github.com/docker/libnetwork/drivers/macvlan"
|
||||
"github.com/docker/libnetwork/drivers/null"
|
||||
"github.com/docker/libnetwork/drivers/overlay"
|
||||
"github.com/docker/libnetwork/drivers/remote"
|
||||
)
|
||||
|
||||
func getInitializers(experimental bool) []initializer {
|
||||
in := []initializer{
|
||||
{bridge.Init, "bridge"},
|
||||
{host.Init, "host"},
|
||||
{ipvlan.Init, "ipvlan"},
|
||||
{macvlan.Init, "macvlan"},
|
||||
{null.Init, "null"},
|
||||
{overlay.Init, "overlay"},
|
||||
{remote.Init, "remote"},
|
||||
}
|
||||
return in
|
||||
}
|
23
vendor/github.com/docker/libnetwork/drivers_windows.go
generated
vendored
23
vendor/github.com/docker/libnetwork/drivers_windows.go
generated
vendored
|
@ -1,23 +0,0 @@
|
|||
package libnetwork
|
||||
|
||||
import (
|
||||
"github.com/docker/libnetwork/drivers/null"
|
||||
"github.com/docker/libnetwork/drivers/remote"
|
||||
"github.com/docker/libnetwork/drivers/windows"
|
||||
"github.com/docker/libnetwork/drivers/windows/overlay"
|
||||
)
|
||||
|
||||
func getInitializers(experimental bool) []initializer {
|
||||
return []initializer{
|
||||
{null.Init, "null"},
|
||||
{overlay.Init, "overlay"},
|
||||
{remote.Init, "remote"},
|
||||
{windows.GetInit("transparent"), "transparent"},
|
||||
{windows.GetInit("l2bridge"), "l2bridge"},
|
||||
{windows.GetInit("l2tunnel"), "l2tunnel"},
|
||||
{windows.GetInit("nat"), "nat"},
|
||||
{windows.GetInit("internal"), "internal"},
|
||||
{windows.GetInit("private"), "private"},
|
||||
{windows.GetInit("ics"), "ics"},
|
||||
}
|
||||
}
|
228
vendor/github.com/docker/libnetwork/drvregistry/drvregistry.go
generated
vendored
228
vendor/github.com/docker/libnetwork/drvregistry/drvregistry.go
generated
vendored
|
@ -1,228 +0,0 @@
|
|||
package drvregistry
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/docker/docker/pkg/plugingetter"
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/ipamapi"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
type driverData struct {
|
||||
driver driverapi.Driver
|
||||
capability driverapi.Capability
|
||||
}
|
||||
|
||||
type ipamData struct {
|
||||
driver ipamapi.Ipam
|
||||
capability *ipamapi.Capability
|
||||
// default address spaces are provided by ipam driver at registration time
|
||||
defaultLocalAddressSpace, defaultGlobalAddressSpace string
|
||||
}
|
||||
|
||||
type driverTable map[string]*driverData
|
||||
type ipamTable map[string]*ipamData
|
||||
|
||||
// DrvRegistry holds the registry of all network drivers and IPAM drivers that it knows about.
|
||||
type DrvRegistry struct {
|
||||
sync.Mutex
|
||||
drivers driverTable
|
||||
ipamDrivers ipamTable
|
||||
dfn DriverNotifyFunc
|
||||
ifn IPAMNotifyFunc
|
||||
pluginGetter plugingetter.PluginGetter
|
||||
}
|
||||
|
||||
// Functors definition
|
||||
|
||||
// InitFunc defines the driver initialization function signature.
|
||||
type InitFunc func(driverapi.DriverCallback, map[string]interface{}) error
|
||||
|
||||
// IPAMWalkFunc defines the IPAM driver table walker function signature.
|
||||
type IPAMWalkFunc func(name string, driver ipamapi.Ipam, cap *ipamapi.Capability) bool
|
||||
|
||||
// DriverWalkFunc defines the network driver table walker function signature.
|
||||
type DriverWalkFunc func(name string, driver driverapi.Driver, capability driverapi.Capability) bool
|
||||
|
||||
// IPAMNotifyFunc defines the notify function signature when a new IPAM driver gets registered.
|
||||
type IPAMNotifyFunc func(name string, driver ipamapi.Ipam, cap *ipamapi.Capability) error
|
||||
|
||||
// DriverNotifyFunc defines the notify function signature when a new network driver gets registered.
|
||||
type DriverNotifyFunc func(name string, driver driverapi.Driver, capability driverapi.Capability) error
|
||||
|
||||
// New returns a new driver registry handle.
|
||||
func New(lDs, gDs interface{}, dfn DriverNotifyFunc, ifn IPAMNotifyFunc, pg plugingetter.PluginGetter) (*DrvRegistry, error) {
|
||||
r := &DrvRegistry{
|
||||
drivers: make(driverTable),
|
||||
ipamDrivers: make(ipamTable),
|
||||
dfn: dfn,
|
||||
ifn: ifn,
|
||||
pluginGetter: pg,
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// AddDriver adds a network driver to the registry.
|
||||
func (r *DrvRegistry) AddDriver(ntype string, fn InitFunc, config map[string]interface{}) error {
|
||||
return fn(r, config)
|
||||
}
|
||||
|
||||
// WalkIPAMs walks the IPAM drivers registered in the registry and invokes the passed walk function and each one of them.
|
||||
func (r *DrvRegistry) WalkIPAMs(ifn IPAMWalkFunc) {
|
||||
type ipamVal struct {
|
||||
name string
|
||||
data *ipamData
|
||||
}
|
||||
|
||||
r.Lock()
|
||||
ivl := make([]ipamVal, 0, len(r.ipamDrivers))
|
||||
for k, v := range r.ipamDrivers {
|
||||
ivl = append(ivl, ipamVal{name: k, data: v})
|
||||
}
|
||||
r.Unlock()
|
||||
|
||||
for _, iv := range ivl {
|
||||
if ifn(iv.name, iv.data.driver, iv.data.capability) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WalkDrivers walks the network drivers registered in the registry and invokes the passed walk function and each one of them.
|
||||
func (r *DrvRegistry) WalkDrivers(dfn DriverWalkFunc) {
|
||||
type driverVal struct {
|
||||
name string
|
||||
data *driverData
|
||||
}
|
||||
|
||||
r.Lock()
|
||||
dvl := make([]driverVal, 0, len(r.drivers))
|
||||
for k, v := range r.drivers {
|
||||
dvl = append(dvl, driverVal{name: k, data: v})
|
||||
}
|
||||
r.Unlock()
|
||||
|
||||
for _, dv := range dvl {
|
||||
if dfn(dv.name, dv.data.driver, dv.data.capability) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Driver returns the actual network driver instance and its capability which registered with the passed name.
|
||||
func (r *DrvRegistry) Driver(name string) (driverapi.Driver, *driverapi.Capability) {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
d, ok := r.drivers[name]
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return d.driver, &d.capability
|
||||
}
|
||||
|
||||
// IPAM returns the actual IPAM driver instance and its capability which registered with the passed name.
|
||||
func (r *DrvRegistry) IPAM(name string) (ipamapi.Ipam, *ipamapi.Capability) {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
i, ok := r.ipamDrivers[name]
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return i.driver, i.capability
|
||||
}
|
||||
|
||||
// IPAMDefaultAddressSpaces returns the default address space strings for the passed IPAM driver name.
|
||||
func (r *DrvRegistry) IPAMDefaultAddressSpaces(name string) (string, string, error) {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
i, ok := r.ipamDrivers[name]
|
||||
if !ok {
|
||||
return "", "", fmt.Errorf("ipam %s not found", name)
|
||||
}
|
||||
|
||||
return i.defaultLocalAddressSpace, i.defaultGlobalAddressSpace, nil
|
||||
}
|
||||
|
||||
// GetPluginGetter returns the plugingetter
|
||||
func (r *DrvRegistry) GetPluginGetter() plugingetter.PluginGetter {
|
||||
return r.pluginGetter
|
||||
}
|
||||
|
||||
// RegisterDriver registers the network driver when it gets discovered.
|
||||
func (r *DrvRegistry) RegisterDriver(ntype string, driver driverapi.Driver, capability driverapi.Capability) error {
|
||||
if strings.TrimSpace(ntype) == "" {
|
||||
return errors.New("network type string cannot be empty")
|
||||
}
|
||||
|
||||
r.Lock()
|
||||
dd, ok := r.drivers[ntype]
|
||||
r.Unlock()
|
||||
|
||||
if ok && dd.driver.IsBuiltIn() {
|
||||
return driverapi.ErrActiveRegistration(ntype)
|
||||
}
|
||||
|
||||
if r.dfn != nil {
|
||||
if err := r.dfn(ntype, driver, capability); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
dData := &driverData{driver, capability}
|
||||
|
||||
r.Lock()
|
||||
r.drivers[ntype] = dData
|
||||
r.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *DrvRegistry) registerIpamDriver(name string, driver ipamapi.Ipam, caps *ipamapi.Capability) error {
|
||||
if strings.TrimSpace(name) == "" {
|
||||
return errors.New("ipam driver name string cannot be empty")
|
||||
}
|
||||
|
||||
r.Lock()
|
||||
dd, ok := r.ipamDrivers[name]
|
||||
r.Unlock()
|
||||
if ok && dd.driver.IsBuiltIn() {
|
||||
return types.ForbiddenErrorf("ipam driver %q already registered", name)
|
||||
}
|
||||
|
||||
locAS, glbAS, err := driver.GetDefaultAddressSpaces()
|
||||
if err != nil {
|
||||
return types.InternalErrorf("ipam driver %q failed to return default address spaces: %v", name, err)
|
||||
}
|
||||
|
||||
if r.ifn != nil {
|
||||
if err := r.ifn(name, driver, caps); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
r.Lock()
|
||||
r.ipamDrivers[name] = &ipamData{driver: driver, defaultLocalAddressSpace: locAS, defaultGlobalAddressSpace: glbAS, capability: caps}
|
||||
r.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegisterIpamDriver registers the IPAM driver discovered with default capabilities.
|
||||
func (r *DrvRegistry) RegisterIpamDriver(name string, driver ipamapi.Ipam) error {
|
||||
return r.registerIpamDriver(name, driver, &ipamapi.Capability{})
|
||||
}
|
||||
|
||||
// RegisterIpamDriverWithCapabilities registers the IPAM driver discovered with specified capabilities.
|
||||
func (r *DrvRegistry) RegisterIpamDriverWithCapabilities(name string, driver ipamapi.Ipam, caps *ipamapi.Capability) error {
|
||||
return r.registerIpamDriver(name, driver, caps)
|
||||
}
|
1232
vendor/github.com/docker/libnetwork/endpoint.go
generated
vendored
1232
vendor/github.com/docker/libnetwork/endpoint.go
generated
vendored
File diff suppressed because it is too large
Load diff
182
vendor/github.com/docker/libnetwork/endpoint_cnt.go
generated
vendored
182
vendor/github.com/docker/libnetwork/endpoint_cnt.go
generated
vendored
|
@ -1,182 +0,0 @@
|
|||
package libnetwork
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/docker/libnetwork/datastore"
|
||||
)
|
||||
|
||||
type endpointCnt struct {
|
||||
n *network
|
||||
Count uint64
|
||||
dbIndex uint64
|
||||
dbExists bool
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
const epCntKeyPrefix = "endpoint_count"
|
||||
|
||||
func (ec *endpointCnt) Key() []string {
|
||||
ec.Lock()
|
||||
defer ec.Unlock()
|
||||
|
||||
return []string{epCntKeyPrefix, ec.n.id}
|
||||
}
|
||||
|
||||
func (ec *endpointCnt) KeyPrefix() []string {
|
||||
ec.Lock()
|
||||
defer ec.Unlock()
|
||||
|
||||
return []string{epCntKeyPrefix, ec.n.id}
|
||||
}
|
||||
|
||||
func (ec *endpointCnt) Value() []byte {
|
||||
ec.Lock()
|
||||
defer ec.Unlock()
|
||||
|
||||
b, err := json.Marshal(ec)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (ec *endpointCnt) SetValue(value []byte) error {
|
||||
ec.Lock()
|
||||
defer ec.Unlock()
|
||||
|
||||
return json.Unmarshal(value, &ec)
|
||||
}
|
||||
|
||||
func (ec *endpointCnt) Index() uint64 {
|
||||
ec.Lock()
|
||||
defer ec.Unlock()
|
||||
return ec.dbIndex
|
||||
}
|
||||
|
||||
func (ec *endpointCnt) SetIndex(index uint64) {
|
||||
ec.Lock()
|
||||
ec.dbIndex = index
|
||||
ec.dbExists = true
|
||||
ec.Unlock()
|
||||
}
|
||||
|
||||
func (ec *endpointCnt) Exists() bool {
|
||||
ec.Lock()
|
||||
defer ec.Unlock()
|
||||
return ec.dbExists
|
||||
}
|
||||
|
||||
func (ec *endpointCnt) Skip() bool {
|
||||
ec.Lock()
|
||||
defer ec.Unlock()
|
||||
return !ec.n.persist
|
||||
}
|
||||
|
||||
func (ec *endpointCnt) New() datastore.KVObject {
|
||||
ec.Lock()
|
||||
defer ec.Unlock()
|
||||
|
||||
return &endpointCnt{
|
||||
n: ec.n,
|
||||
}
|
||||
}
|
||||
|
||||
func (ec *endpointCnt) CopyTo(o datastore.KVObject) error {
|
||||
ec.Lock()
|
||||
defer ec.Unlock()
|
||||
|
||||
dstEc := o.(*endpointCnt)
|
||||
dstEc.n = ec.n
|
||||
dstEc.Count = ec.Count
|
||||
dstEc.dbExists = ec.dbExists
|
||||
dstEc.dbIndex = ec.dbIndex
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ec *endpointCnt) DataScope() string {
|
||||
return ec.n.DataScope()
|
||||
}
|
||||
|
||||
func (ec *endpointCnt) EndpointCnt() uint64 {
|
||||
ec.Lock()
|
||||
defer ec.Unlock()
|
||||
|
||||
return ec.Count
|
||||
}
|
||||
|
||||
func (ec *endpointCnt) updateStore() error {
|
||||
store := ec.n.getController().getStore(ec.DataScope())
|
||||
if store == nil {
|
||||
return fmt.Errorf("store not found for scope %s on endpoint count update", ec.DataScope())
|
||||
}
|
||||
// make a copy of count and n to avoid being overwritten by store.GetObject
|
||||
count := ec.EndpointCnt()
|
||||
n := ec.n
|
||||
for {
|
||||
if err := ec.n.getController().updateToStore(ec); err == nil || err != datastore.ErrKeyModified {
|
||||
return err
|
||||
}
|
||||
if err := store.GetObject(datastore.Key(ec.Key()...), ec); err != nil {
|
||||
return fmt.Errorf("could not update the kvobject to latest on endpoint count update: %v", err)
|
||||
}
|
||||
ec.Lock()
|
||||
ec.Count = count
|
||||
ec.n = n
|
||||
ec.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
func (ec *endpointCnt) setCnt(cnt uint64) error {
|
||||
ec.Lock()
|
||||
ec.Count = cnt
|
||||
ec.Unlock()
|
||||
return ec.updateStore()
|
||||
}
|
||||
|
||||
func (ec *endpointCnt) atomicIncDecEpCnt(inc bool) error {
|
||||
store := ec.n.getController().getStore(ec.DataScope())
|
||||
if store == nil {
|
||||
return fmt.Errorf("store not found for scope %s", ec.DataScope())
|
||||
}
|
||||
|
||||
tmp := &endpointCnt{n: ec.n}
|
||||
if err := store.GetObject(datastore.Key(ec.Key()...), tmp); err != nil {
|
||||
return err
|
||||
}
|
||||
retry:
|
||||
ec.Lock()
|
||||
if inc {
|
||||
ec.Count++
|
||||
} else {
|
||||
if ec.Count > 0 {
|
||||
ec.Count--
|
||||
}
|
||||
}
|
||||
ec.Unlock()
|
||||
|
||||
if err := ec.n.getController().updateToStore(ec); err != nil {
|
||||
if err == datastore.ErrKeyModified {
|
||||
if err := store.GetObject(datastore.Key(ec.Key()...), ec); err != nil {
|
||||
return fmt.Errorf("could not update the kvobject to latest when trying to atomic add endpoint count: %v", err)
|
||||
}
|
||||
|
||||
goto retry
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ec *endpointCnt) IncEndpointCnt() error {
|
||||
return ec.atomicIncDecEpCnt(true)
|
||||
}
|
||||
|
||||
func (ec *endpointCnt) DecEndpointCnt() error {
|
||||
return ec.atomicIncDecEpCnt(false)
|
||||
}
|
459
vendor/github.com/docker/libnetwork/endpoint_info.go
generated
vendored
459
vendor/github.com/docker/libnetwork/endpoint_info.go
generated
vendored
|
@ -1,459 +0,0 @@
|
|||
package libnetwork
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
"github.com/docker/libnetwork/types"
|
||||
)
|
||||
|
||||
// EndpointInfo provides an interface to retrieve network resources bound to the endpoint.
|
||||
type EndpointInfo interface {
|
||||
// Iface returns InterfaceInfo, go interface that can be used
|
||||
// to get more information on the interface which was assigned to
|
||||
// the endpoint by the driver. This can be used after the
|
||||
// endpoint has been created.
|
||||
Iface() InterfaceInfo
|
||||
|
||||
// Gateway returns the IPv4 gateway assigned by the driver.
|
||||
// This will only return a valid value if a container has joined the endpoint.
|
||||
Gateway() net.IP
|
||||
|
||||
// GatewayIPv6 returns the IPv6 gateway assigned by the driver.
|
||||
// This will only return a valid value if a container has joined the endpoint.
|
||||
GatewayIPv6() net.IP
|
||||
|
||||
// StaticRoutes returns the list of static routes configured by the network
|
||||
// driver when the container joins a network
|
||||
StaticRoutes() []*types.StaticRoute
|
||||
|
||||
// Sandbox returns the attached sandbox if there, nil otherwise.
|
||||
Sandbox() Sandbox
|
||||
|
||||
// LoadBalancer returns whether the endpoint is the load balancer endpoint for the network.
|
||||
LoadBalancer() bool
|
||||
}
|
||||
|
||||
// InterfaceInfo provides an interface to retrieve interface addresses bound to the endpoint.
|
||||
type InterfaceInfo interface {
|
||||
// MacAddress returns the MAC address assigned to the endpoint.
|
||||
MacAddress() net.HardwareAddr
|
||||
|
||||
// Address returns the IPv4 address assigned to the endpoint.
|
||||
Address() *net.IPNet
|
||||
|
||||
// AddressIPv6 returns the IPv6 address assigned to the endpoint.
|
||||
AddressIPv6() *net.IPNet
|
||||
|
||||
// LinkLocalAddresses returns the list of link-local (IPv4/IPv6) addresses assigned to the endpoint.
|
||||
LinkLocalAddresses() []*net.IPNet
|
||||
|
||||
// SrcName returns the name of the interface w/in the container
|
||||
SrcName() string
|
||||
}
|
||||
|
||||
type endpointInterface struct {
|
||||
mac net.HardwareAddr
|
||||
addr *net.IPNet
|
||||
addrv6 *net.IPNet
|
||||
llAddrs []*net.IPNet
|
||||
srcName string
|
||||
dstPrefix string
|
||||
routes []*net.IPNet
|
||||
v4PoolID string
|
||||
v6PoolID string
|
||||
}
|
||||
|
||||
func (epi *endpointInterface) MarshalJSON() ([]byte, error) {
|
||||
epMap := make(map[string]interface{})
|
||||
if epi.mac != nil {
|
||||
epMap["mac"] = epi.mac.String()
|
||||
}
|
||||
if epi.addr != nil {
|
||||
epMap["addr"] = epi.addr.String()
|
||||
}
|
||||
if epi.addrv6 != nil {
|
||||
epMap["addrv6"] = epi.addrv6.String()
|
||||
}
|
||||
if len(epi.llAddrs) != 0 {
|
||||
list := make([]string, 0, len(epi.llAddrs))
|
||||
for _, ll := range epi.llAddrs {
|
||||
list = append(list, ll.String())
|
||||
}
|
||||
epMap["llAddrs"] = list
|
||||
}
|
||||
epMap["srcName"] = epi.srcName
|
||||
epMap["dstPrefix"] = epi.dstPrefix
|
||||
var routes []string
|
||||
for _, route := range epi.routes {
|
||||
routes = append(routes, route.String())
|
||||
}
|
||||
epMap["routes"] = routes
|
||||
epMap["v4PoolID"] = epi.v4PoolID
|
||||
epMap["v6PoolID"] = epi.v6PoolID
|
||||
return json.Marshal(epMap)
|
||||
}
|
||||
|
||||
func (epi *endpointInterface) UnmarshalJSON(b []byte) error {
|
||||
var (
|
||||
err error
|
||||
epMap map[string]interface{}
|
||||
)
|
||||
if err = json.Unmarshal(b, &epMap); err != nil {
|
||||
return err
|
||||
}
|
||||
if v, ok := epMap["mac"]; ok {
|
||||
if epi.mac, err = net.ParseMAC(v.(string)); err != nil {
|
||||
return types.InternalErrorf("failed to decode endpoint interface mac address after json unmarshal: %s", v.(string))
|
||||
}
|
||||
}
|
||||
if v, ok := epMap["addr"]; ok {
|
||||
if epi.addr, err = types.ParseCIDR(v.(string)); err != nil {
|
||||
return types.InternalErrorf("failed to decode endpoint interface ipv4 address after json unmarshal: %v", err)
|
||||
}
|
||||
}
|
||||
if v, ok := epMap["addrv6"]; ok {
|
||||
if epi.addrv6, err = types.ParseCIDR(v.(string)); err != nil {
|
||||
return types.InternalErrorf("failed to decode endpoint interface ipv6 address after json unmarshal: %v", err)
|
||||
}
|
||||
}
|
||||
if v, ok := epMap["llAddrs"]; ok {
|
||||
list := v.([]interface{})
|
||||
epi.llAddrs = make([]*net.IPNet, 0, len(list))
|
||||
for _, llS := range list {
|
||||
ll, err := types.ParseCIDR(llS.(string))
|
||||
if err != nil {
|
||||
return types.InternalErrorf("failed to decode endpoint interface link-local address (%v) after json unmarshal: %v", llS, err)
|
||||
}
|
||||
epi.llAddrs = append(epi.llAddrs, ll)
|
||||
}
|
||||
}
|
||||
epi.srcName = epMap["srcName"].(string)
|
||||
epi.dstPrefix = epMap["dstPrefix"].(string)
|
||||
|
||||
rb, _ := json.Marshal(epMap["routes"])
|
||||
var routes []string
|
||||
json.Unmarshal(rb, &routes)
|
||||
epi.routes = make([]*net.IPNet, 0)
|
||||
for _, route := range routes {
|
||||
ip, ipr, err := net.ParseCIDR(route)
|
||||
if err == nil {
|
||||
ipr.IP = ip
|
||||
epi.routes = append(epi.routes, ipr)
|
||||
}
|
||||
}
|
||||
epi.v4PoolID = epMap["v4PoolID"].(string)
|
||||
epi.v6PoolID = epMap["v6PoolID"].(string)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (epi *endpointInterface) CopyTo(dstEpi *endpointInterface) error {
|
||||
dstEpi.mac = types.GetMacCopy(epi.mac)
|
||||
dstEpi.addr = types.GetIPNetCopy(epi.addr)
|
||||
dstEpi.addrv6 = types.GetIPNetCopy(epi.addrv6)
|
||||
dstEpi.srcName = epi.srcName
|
||||
dstEpi.dstPrefix = epi.dstPrefix
|
||||
dstEpi.v4PoolID = epi.v4PoolID
|
||||
dstEpi.v6PoolID = epi.v6PoolID
|
||||
if len(epi.llAddrs) != 0 {
|
||||
dstEpi.llAddrs = make([]*net.IPNet, 0, len(epi.llAddrs))
|
||||
dstEpi.llAddrs = append(dstEpi.llAddrs, epi.llAddrs...)
|
||||
}
|
||||
|
||||
for _, route := range epi.routes {
|
||||
dstEpi.routes = append(dstEpi.routes, types.GetIPNetCopy(route))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type endpointJoinInfo struct {
|
||||
gw net.IP
|
||||
gw6 net.IP
|
||||
StaticRoutes []*types.StaticRoute
|
||||
driverTableEntries []*tableEntry
|
||||
disableGatewayService bool
|
||||
}
|
||||
|
||||
type tableEntry struct {
|
||||
tableName string
|
||||
key string
|
||||
value []byte
|
||||
}
|
||||
|
||||
func (ep *endpoint) Info() EndpointInfo {
|
||||
if ep.sandboxID != "" {
|
||||
return ep
|
||||
}
|
||||
n, err := ep.getNetworkFromStore()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
ep, err = n.getEndpointFromStore(ep.ID())
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
sb, ok := ep.getSandbox()
|
||||
if !ok {
|
||||
// endpoint hasn't joined any sandbox.
|
||||
// Just return the endpoint
|
||||
return ep
|
||||
}
|
||||
|
||||
return sb.getEndpoint(ep.ID())
|
||||
}
|
||||
|
||||
func (ep *endpoint) Iface() InterfaceInfo {
|
||||
ep.Lock()
|
||||
defer ep.Unlock()
|
||||
|
||||
if ep.iface != nil {
|
||||
return ep.iface
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ep *endpoint) Interface() driverapi.InterfaceInfo {
|
||||
ep.Lock()
|
||||
defer ep.Unlock()
|
||||
|
||||
if ep.iface != nil {
|
||||
return ep.iface
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (epi *endpointInterface) SetMacAddress(mac net.HardwareAddr) error {
|
||||
if epi.mac != nil {
|
||||
return types.ForbiddenErrorf("endpoint interface MAC address present (%s). Cannot be modified with %s.", epi.mac, mac)
|
||||
}
|
||||
if mac == nil {
|
||||
return types.BadRequestErrorf("tried to set nil MAC address to endpoint interface")
|
||||
}
|
||||
epi.mac = types.GetMacCopy(mac)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (epi *endpointInterface) SetIPAddress(address *net.IPNet) error {
|
||||
if address.IP == nil {
|
||||
return types.BadRequestErrorf("tried to set nil IP address to endpoint interface")
|
||||
}
|
||||
if address.IP.To4() == nil {
|
||||
return setAddress(&epi.addrv6, address)
|
||||
}
|
||||
return setAddress(&epi.addr, address)
|
||||
}
|
||||
|
||||
func setAddress(ifaceAddr **net.IPNet, address *net.IPNet) error {
|
||||
if *ifaceAddr != nil {
|
||||
return types.ForbiddenErrorf("endpoint interface IP present (%s). Cannot be modified with (%s).", *ifaceAddr, address)
|
||||
}
|
||||
*ifaceAddr = types.GetIPNetCopy(address)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (epi *endpointInterface) MacAddress() net.HardwareAddr {
|
||||
return types.GetMacCopy(epi.mac)
|
||||
}
|
||||
|
||||
func (epi *endpointInterface) Address() *net.IPNet {
|
||||
return types.GetIPNetCopy(epi.addr)
|
||||
}
|
||||
|
||||
func (epi *endpointInterface) AddressIPv6() *net.IPNet {
|
||||
return types.GetIPNetCopy(epi.addrv6)
|
||||
}
|
||||
|
||||
func (epi *endpointInterface) LinkLocalAddresses() []*net.IPNet {
|
||||
return epi.llAddrs
|
||||
}
|
||||
|
||||
func (epi *endpointInterface) SrcName() string {
|
||||
return epi.srcName
|
||||
}
|
||||
|
||||
func (epi *endpointInterface) SetNames(srcName string, dstPrefix string) error {
|
||||
epi.srcName = srcName
|
||||
epi.dstPrefix = dstPrefix
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ep *endpoint) InterfaceName() driverapi.InterfaceNameInfo {
|
||||
ep.Lock()
|
||||
defer ep.Unlock()
|
||||
|
||||
if ep.iface != nil {
|
||||
return ep.iface
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ep *endpoint) AddStaticRoute(destination *net.IPNet, routeType int, nextHop net.IP) error {
|
||||
ep.Lock()
|
||||
defer ep.Unlock()
|
||||
|
||||
r := types.StaticRoute{Destination: destination, RouteType: routeType, NextHop: nextHop}
|
||||
|
||||
if routeType == types.NEXTHOP {
|
||||
// If the route specifies a next-hop, then it's loosely routed (i.e. not bound to a particular interface).
|
||||
ep.joinInfo.StaticRoutes = append(ep.joinInfo.StaticRoutes, &r)
|
||||
} else {
|
||||
// If the route doesn't specify a next-hop, it must be a connected route, bound to an interface.
|
||||
ep.iface.routes = append(ep.iface.routes, r.Destination)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ep *endpoint) AddTableEntry(tableName, key string, value []byte) error {
|
||||
ep.Lock()
|
||||
defer ep.Unlock()
|
||||
|
||||
ep.joinInfo.driverTableEntries = append(ep.joinInfo.driverTableEntries, &tableEntry{
|
||||
tableName: tableName,
|
||||
key: key,
|
||||
value: value,
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ep *endpoint) Sandbox() Sandbox {
|
||||
cnt, ok := ep.getSandbox()
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return cnt
|
||||
}
|
||||
|
||||
func (ep *endpoint) LoadBalancer() bool {
|
||||
ep.Lock()
|
||||
defer ep.Unlock()
|
||||
return ep.loadBalancer
|
||||
}
|
||||
|
||||
func (ep *endpoint) StaticRoutes() []*types.StaticRoute {
|
||||
ep.Lock()
|
||||
defer ep.Unlock()
|
||||
|
||||
if ep.joinInfo == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return ep.joinInfo.StaticRoutes
|
||||
}
|
||||
|
||||
func (ep *endpoint) Gateway() net.IP {
|
||||
ep.Lock()
|
||||
defer ep.Unlock()
|
||||
|
||||
if ep.joinInfo == nil {
|
||||
return net.IP{}
|
||||
}
|
||||
|
||||
return types.GetIPCopy(ep.joinInfo.gw)
|
||||
}
|
||||
|
||||
func (ep *endpoint) GatewayIPv6() net.IP {
|
||||
ep.Lock()
|
||||
defer ep.Unlock()
|
||||
|
||||
if ep.joinInfo == nil {
|
||||
return net.IP{}
|
||||
}
|
||||
|
||||
return types.GetIPCopy(ep.joinInfo.gw6)
|
||||
}
|
||||
|
||||
func (ep *endpoint) SetGateway(gw net.IP) error {
|
||||
ep.Lock()
|
||||
defer ep.Unlock()
|
||||
|
||||
ep.joinInfo.gw = types.GetIPCopy(gw)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ep *endpoint) SetGatewayIPv6(gw6 net.IP) error {
|
||||
ep.Lock()
|
||||
defer ep.Unlock()
|
||||
|
||||
ep.joinInfo.gw6 = types.GetIPCopy(gw6)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ep *endpoint) retrieveFromStore() (*endpoint, error) {
|
||||
n, err := ep.getNetworkFromStore()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not find network in store to get latest endpoint %s: %v", ep.Name(), err)
|
||||
}
|
||||
return n.getEndpointFromStore(ep.ID())
|
||||
}
|
||||
|
||||
func (ep *endpoint) DisableGatewayService() {
|
||||
ep.Lock()
|
||||
defer ep.Unlock()
|
||||
|
||||
ep.joinInfo.disableGatewayService = true
|
||||
}
|
||||
|
||||
func (epj *endpointJoinInfo) MarshalJSON() ([]byte, error) {
|
||||
epMap := make(map[string]interface{})
|
||||
if epj.gw != nil {
|
||||
epMap["gw"] = epj.gw.String()
|
||||
}
|
||||
if epj.gw6 != nil {
|
||||
epMap["gw6"] = epj.gw6.String()
|
||||
}
|
||||
epMap["disableGatewayService"] = epj.disableGatewayService
|
||||
epMap["StaticRoutes"] = epj.StaticRoutes
|
||||
return json.Marshal(epMap)
|
||||
}
|
||||
|
||||
func (epj *endpointJoinInfo) UnmarshalJSON(b []byte) error {
|
||||
var (
|
||||
err error
|
||||
epMap map[string]interface{}
|
||||
)
|
||||
if err = json.Unmarshal(b, &epMap); err != nil {
|
||||
return err
|
||||
}
|
||||
if v, ok := epMap["gw"]; ok {
|
||||
epj.gw = net.ParseIP(v.(string))
|
||||
}
|
||||
if v, ok := epMap["gw6"]; ok {
|
||||
epj.gw6 = net.ParseIP(v.(string))
|
||||
}
|
||||
epj.disableGatewayService = epMap["disableGatewayService"].(bool)
|
||||
|
||||
var tStaticRoute []types.StaticRoute
|
||||
if v, ok := epMap["StaticRoutes"]; ok {
|
||||
tb, _ := json.Marshal(v)
|
||||
var tStaticRoute []types.StaticRoute
|
||||
json.Unmarshal(tb, &tStaticRoute)
|
||||
}
|
||||
var StaticRoutes []*types.StaticRoute
|
||||
for _, r := range tStaticRoute {
|
||||
StaticRoutes = append(StaticRoutes, &r)
|
||||
}
|
||||
epj.StaticRoutes = StaticRoutes
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (epj *endpointJoinInfo) CopyTo(dstEpj *endpointJoinInfo) error {
|
||||
dstEpj.disableGatewayService = epj.disableGatewayService
|
||||
dstEpj.StaticRoutes = make([]*types.StaticRoute, len(epj.StaticRoutes))
|
||||
copy(dstEpj.StaticRoutes, epj.StaticRoutes)
|
||||
dstEpj.driverTableEntries = make([]*tableEntry, len(epj.driverTableEntries))
|
||||
copy(dstEpj.driverTableEntries, epj.driverTableEntries)
|
||||
dstEpj.gw = types.GetIPCopy(epj.gw)
|
||||
dstEpj.gw6 = types.GetIPCopy(epj.gw6)
|
||||
return nil
|
||||
}
|
30
vendor/github.com/docker/libnetwork/endpoint_info_unix.go
generated
vendored
30
vendor/github.com/docker/libnetwork/endpoint_info_unix.go
generated
vendored
|
@ -1,30 +0,0 @@
|
|||
// +build !windows
|
||||
|
||||
package libnetwork
|
||||
|
||||
import "fmt"
|
||||
|
||||
func (ep *endpoint) DriverInfo() (map[string]interface{}, error) {
|
||||
ep, err := ep.retrieveFromStore()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if sb, ok := ep.getSandbox(); ok {
|
||||
if gwep := sb.getEndpointInGWNetwork(); gwep != nil && gwep.ID() != ep.ID() {
|
||||
return gwep.DriverInfo()
|
||||
}
|
||||
}
|
||||
|
||||
n, err := ep.getNetworkFromStore()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not find network in store for driver info: %v", err)
|
||||
}
|
||||
|
||||
driver, err := n.driver(true)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get driver info: %v", err)
|
||||
}
|
||||
|
||||
return driver.EndpointOperInfo(n.ID(), ep.ID())
|
||||
}
|
45
vendor/github.com/docker/libnetwork/endpoint_info_windows.go
generated
vendored
45
vendor/github.com/docker/libnetwork/endpoint_info_windows.go
generated
vendored
|
@ -1,45 +0,0 @@
|
|||
// +build windows
|
||||
|
||||
package libnetwork
|
||||
|
||||
import "fmt"
|
||||
|
||||
func (ep *endpoint) DriverInfo() (map[string]interface{}, error) {
|
||||
ep, err := ep.retrieveFromStore()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var gwDriverInfo map[string]interface{}
|
||||
if sb, ok := ep.getSandbox(); ok {
|
||||
if gwep := sb.getEndpointInGWNetwork(); gwep != nil && gwep.ID() != ep.ID() {
|
||||
|
||||
gwDriverInfo, err = gwep.DriverInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
n, err := ep.getNetworkFromStore()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not find network in store for driver info: %v", err)
|
||||
}
|
||||
|
||||
driver, err := n.driver(true)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get driver info: %v", err)
|
||||
}
|
||||
|
||||
epInfo, err := driver.EndpointOperInfo(n.ID(), ep.ID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if epInfo != nil {
|
||||
epInfo["GW_INFO"] = gwDriverInfo
|
||||
return epInfo, nil
|
||||
}
|
||||
|
||||
return gwDriverInfo, nil
|
||||
}
|
193
vendor/github.com/docker/libnetwork/error.go
generated
vendored
193
vendor/github.com/docker/libnetwork/error.go
generated
vendored
|
@ -1,193 +0,0 @@
|
|||
package libnetwork
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// ErrNoSuchNetwork is returned when a network query finds no result
|
||||
type ErrNoSuchNetwork string
|
||||
|
||||
func (nsn ErrNoSuchNetwork) Error() string {
|
||||
return fmt.Sprintf("network %s not found", string(nsn))
|
||||
}
|
||||
|
||||
// NotFound denotes the type of this error
|
||||
func (nsn ErrNoSuchNetwork) NotFound() {}
|
||||
|
||||
// ErrNoSuchEndpoint is returned when an endpoint query finds no result
|
||||
type ErrNoSuchEndpoint string
|
||||
|
||||
func (nse ErrNoSuchEndpoint) Error() string {
|
||||
return fmt.Sprintf("endpoint %s not found", string(nse))
|
||||
}
|
||||
|
||||
// NotFound denotes the type of this error
|
||||
func (nse ErrNoSuchEndpoint) NotFound() {}
|
||||
|
||||
// ErrInvalidNetworkDriver is returned if an invalid driver
|
||||
// name is passed.
|
||||
type ErrInvalidNetworkDriver string
|
||||
|
||||
func (ind ErrInvalidNetworkDriver) Error() string {
|
||||
return fmt.Sprintf("invalid driver bound to network: %s", string(ind))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (ind ErrInvalidNetworkDriver) BadRequest() {}
|
||||
|
||||
// ErrInvalidJoin is returned if a join is attempted on an endpoint
|
||||
// which already has a container joined.
|
||||
type ErrInvalidJoin struct{}
|
||||
|
||||
func (ij ErrInvalidJoin) Error() string {
|
||||
return "a container has already joined the endpoint"
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (ij ErrInvalidJoin) BadRequest() {}
|
||||
|
||||
// ErrNoContainer is returned when the endpoint has no container
|
||||
// attached to it.
|
||||
type ErrNoContainer struct{}
|
||||
|
||||
func (nc ErrNoContainer) Error() string {
|
||||
return "no container is attached to the endpoint"
|
||||
}
|
||||
|
||||
// Maskable denotes the type of this error
|
||||
func (nc ErrNoContainer) Maskable() {}
|
||||
|
||||
// ErrInvalidID is returned when a query-by-id method is being invoked
|
||||
// with an empty id parameter
|
||||
type ErrInvalidID string
|
||||
|
||||
func (ii ErrInvalidID) Error() string {
|
||||
return fmt.Sprintf("invalid id: %s", string(ii))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (ii ErrInvalidID) BadRequest() {}
|
||||
|
||||
// ErrInvalidName is returned when a query-by-name or resource create method is
|
||||
// invoked with an empty name parameter
|
||||
type ErrInvalidName string
|
||||
|
||||
func (in ErrInvalidName) Error() string {
|
||||
return fmt.Sprintf("invalid name: %s", string(in))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (in ErrInvalidName) BadRequest() {}
|
||||
|
||||
// ErrInvalidConfigFile type is returned when an invalid LibNetwork config file is detected
|
||||
type ErrInvalidConfigFile string
|
||||
|
||||
func (cf ErrInvalidConfigFile) Error() string {
|
||||
return fmt.Sprintf("Invalid Config file %q", string(cf))
|
||||
}
|
||||
|
||||
// NetworkTypeError type is returned when the network type string is not
|
||||
// known to libnetwork.
|
||||
type NetworkTypeError string
|
||||
|
||||
func (nt NetworkTypeError) Error() string {
|
||||
return fmt.Sprintf("unknown driver %q", string(nt))
|
||||
}
|
||||
|
||||
// NotFound denotes the type of this error
|
||||
func (nt NetworkTypeError) NotFound() {}
|
||||
|
||||
// NetworkNameError is returned when a network with the same name already exists.
|
||||
type NetworkNameError string
|
||||
|
||||
func (nnr NetworkNameError) Error() string {
|
||||
return fmt.Sprintf("network with name %s already exists", string(nnr))
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (nnr NetworkNameError) Forbidden() {}
|
||||
|
||||
// UnknownNetworkError is returned when libnetwork could not find in its database
|
||||
// a network with the same name and id.
|
||||
type UnknownNetworkError struct {
|
||||
name string
|
||||
id string
|
||||
}
|
||||
|
||||
func (une *UnknownNetworkError) Error() string {
|
||||
return fmt.Sprintf("unknown network %s id %s", une.name, une.id)
|
||||
}
|
||||
|
||||
// NotFound denotes the type of this error
|
||||
func (une *UnknownNetworkError) NotFound() {}
|
||||
|
||||
// ActiveEndpointsError is returned when a network is deleted which has active
|
||||
// endpoints in it.
|
||||
type ActiveEndpointsError struct {
|
||||
name string
|
||||
id string
|
||||
}
|
||||
|
||||
func (aee *ActiveEndpointsError) Error() string {
|
||||
return fmt.Sprintf("network %s id %s has active endpoints", aee.name, aee.id)
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (aee *ActiveEndpointsError) Forbidden() {}
|
||||
|
||||
// UnknownEndpointError is returned when libnetwork could not find in its database
|
||||
// an endpoint with the same name and id.
|
||||
type UnknownEndpointError struct {
|
||||
name string
|
||||
id string
|
||||
}
|
||||
|
||||
func (uee *UnknownEndpointError) Error() string {
|
||||
return fmt.Sprintf("unknown endpoint %s id %s", uee.name, uee.id)
|
||||
}
|
||||
|
||||
// NotFound denotes the type of this error
|
||||
func (uee *UnknownEndpointError) NotFound() {}
|
||||
|
||||
// ActiveContainerError is returned when an endpoint is deleted which has active
|
||||
// containers attached to it.
|
||||
type ActiveContainerError struct {
|
||||
name string
|
||||
id string
|
||||
}
|
||||
|
||||
func (ace *ActiveContainerError) Error() string {
|
||||
return fmt.Sprintf("endpoint with name %s id %s has active containers", ace.name, ace.id)
|
||||
}
|
||||
|
||||
// Forbidden denotes the type of this error
|
||||
func (ace *ActiveContainerError) Forbidden() {}
|
||||
|
||||
// InvalidContainerIDError is returned when an invalid container id is passed
|
||||
// in Join/Leave
|
||||
type InvalidContainerIDError string
|
||||
|
||||
func (id InvalidContainerIDError) Error() string {
|
||||
return fmt.Sprintf("invalid container id %s", string(id))
|
||||
}
|
||||
|
||||
// BadRequest denotes the type of this error
|
||||
func (id InvalidContainerIDError) BadRequest() {}
|
||||
|
||||
// ManagerRedirectError is returned when the request should be redirected to Manager
|
||||
type ManagerRedirectError string
|
||||
|
||||
func (mr ManagerRedirectError) Error() string {
|
||||
return "Redirect the request to the manager"
|
||||
}
|
||||
|
||||
// Maskable denotes the type of this error
|
||||
func (mr ManagerRedirectError) Maskable() {}
|
||||
|
||||
// ErrDataStoreNotInitialized is returned if an invalid data scope is passed
|
||||
// for getting data store
|
||||
type ErrDataStoreNotInitialized string
|
||||
|
||||
func (dsni ErrDataStoreNotInitialized) Error() string {
|
||||
return fmt.Sprintf("datastore for scope %q is not initialized", string(dsni))
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue