2015-04-13 18:40:42 +00:00
|
|
|
package libnetwork
|
2015-02-27 17:34:30 +00:00
|
|
|
|
2015-04-13 18:40:42 +00:00
|
|
|
import (
|
2015-05-08 13:26:35 +00:00
|
|
|
"encoding/json"
|
2015-06-19 06:40:17 +00:00
|
|
|
"net"
|
2015-04-13 18:40:42 +00:00
|
|
|
"sync"
|
2015-02-27 17:34:30 +00:00
|
|
|
|
2015-06-10 20:27:23 +00:00
|
|
|
log "github.com/Sirupsen/logrus"
|
2015-04-18 04:37:54 +00:00
|
|
|
"github.com/docker/docker/pkg/stringid"
|
2015-06-14 16:00:27 +00:00
|
|
|
"github.com/docker/libnetwork/config"
|
2015-05-15 22:23:59 +00:00
|
|
|
"github.com/docker/libnetwork/datastore"
|
2015-04-13 18:40:42 +00:00
|
|
|
"github.com/docker/libnetwork/driverapi"
|
2015-06-19 06:40:17 +00:00
|
|
|
"github.com/docker/libnetwork/etchosts"
|
2015-05-16 23:02:51 +00:00
|
|
|
"github.com/docker/libnetwork/netlabel"
|
|
|
|
"github.com/docker/libnetwork/options"
|
2015-04-20 15:44:06 +00:00
|
|
|
"github.com/docker/libnetwork/types"
|
2015-04-13 18:40:42 +00:00
|
|
|
)
|
2015-02-27 17:34:30 +00:00
|
|
|
|
2015-03-02 18:17:12 +00:00
|
|
|
// A Network represents a logical connectivity zone that containers may
|
2015-04-15 12:42:25 +00:00
|
|
|
// join using the Link method. A Network is managed by a specific driver.
|
2015-03-02 18:17:12 +00:00
|
|
|
type Network interface {
|
|
|
|
// A user chosen name for this network.
|
|
|
|
Name() string
|
|
|
|
|
2015-04-13 18:40:42 +00:00
|
|
|
// A system generated id for this network.
|
|
|
|
ID() string
|
|
|
|
|
2015-03-02 18:17:12 +00:00
|
|
|
// The type of network, which corresponds to its managing driver.
|
|
|
|
Type() string
|
|
|
|
|
2015-04-13 18:40:42 +00:00
|
|
|
// Create a new endpoint to this network symbolically identified by the
|
|
|
|
// specified unique name. The options parameter carry driver specific options.
|
|
|
|
// Labels support will be added in the near future.
|
2015-05-01 00:57:06 +00:00
|
|
|
CreateEndpoint(name string, options ...EndpointOption) (Endpoint, error)
|
2015-03-20 20:54:49 +00:00
|
|
|
|
2015-04-24 19:05:33 +00:00
|
|
|
// Delete the network.
|
|
|
|
Delete() error
|
|
|
|
|
2015-04-20 16:46:11 +00:00
|
|
|
// Endpoints returns the list of Endpoint(s) in this network.
|
2015-04-18 06:13:29 +00:00
|
|
|
Endpoints() []Endpoint
|
|
|
|
|
2015-04-20 16:46:11 +00:00
|
|
|
// WalkEndpoints uses the provided function to walk the Endpoints
|
|
|
|
WalkEndpoints(walker EndpointWalker)
|
|
|
|
|
2015-05-15 23:04:09 +00:00
|
|
|
// EndpointByName returns the Endpoint which has the passed name. If not found, the error ErrNoSuchEndpoint is returned.
|
2015-05-11 23:13:27 +00:00
|
|
|
EndpointByName(name string) (Endpoint, error)
|
2015-04-24 19:05:33 +00:00
|
|
|
|
2015-05-15 23:04:09 +00:00
|
|
|
// EndpointByID returns the Endpoint which has the passed id. If not found, the error ErrNoSuchEndpoint is returned.
|
2015-05-11 23:13:27 +00:00
|
|
|
EndpointByID(id string) (Endpoint, error)
|
2015-03-02 18:17:12 +00:00
|
|
|
}
|
|
|
|
|
2015-04-20 16:46:11 +00:00
|
|
|
// EndpointWalker is a client provided function which will be used to walk the Endpoints.
|
|
|
|
// When the function returns true, the walk will stop.
|
|
|
|
type EndpointWalker func(ep Endpoint) bool
|
2015-02-27 17:34:30 +00:00
|
|
|
|
2015-06-19 06:40:17 +00:00
|
|
|
type svcMap map[string]net.IP
|
|
|
|
|
2015-04-13 18:40:42 +00:00
|
|
|
type network struct {
|
|
|
|
ctrlr *controller
|
|
|
|
name string
|
|
|
|
networkType string
|
2015-07-02 05:00:48 +00:00
|
|
|
id string
|
2015-04-22 23:47:07 +00:00
|
|
|
driver driverapi.Driver
|
2015-05-06 06:41:20 +00:00
|
|
|
enableIPv6 bool
|
2015-06-05 20:31:12 +00:00
|
|
|
endpointCnt uint64
|
2015-04-15 05:25:42 +00:00
|
|
|
endpoints endpointTable
|
2015-05-01 00:57:06 +00:00
|
|
|
generic options.Generic
|
2015-05-08 13:26:35 +00:00
|
|
|
dbIndex uint64
|
2015-06-19 06:40:17 +00:00
|
|
|
svcRecords svcMap
|
2015-06-18 22:13:38 +00:00
|
|
|
dbExists bool
|
2015-09-22 14:09:39 +00:00
|
|
|
persist bool
|
2015-06-17 16:13:31 +00:00
|
|
|
stopWatchCh chan struct{}
|
2015-09-16 11:39:46 +00:00
|
|
|
dataScope datastore.DataScope
|
2015-04-13 18:40:42 +00:00
|
|
|
sync.Mutex
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *network) Name() string {
|
2015-05-28 23:29:21 +00:00
|
|
|
n.Lock()
|
|
|
|
defer n.Unlock()
|
|
|
|
|
2015-04-13 18:40:42 +00:00
|
|
|
return n.name
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *network) ID() string {
|
2015-05-28 23:29:21 +00:00
|
|
|
n.Lock()
|
|
|
|
defer n.Unlock()
|
|
|
|
|
2015-07-02 05:00:48 +00:00
|
|
|
return n.id
|
2015-04-13 18:40:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (n *network) Type() string {
|
2015-05-28 23:29:21 +00:00
|
|
|
n.Lock()
|
|
|
|
defer n.Unlock()
|
|
|
|
|
2015-04-16 05:01:29 +00:00
|
|
|
if n.driver == nil {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
2015-04-22 23:47:07 +00:00
|
|
|
return n.driver.Type()
|
2015-04-13 18:40:42 +00:00
|
|
|
}
|
|
|
|
|
2015-05-08 13:26:35 +00:00
|
|
|
func (n *network) Key() []string {
|
2015-06-05 20:31:12 +00:00
|
|
|
n.Lock()
|
|
|
|
defer n.Unlock()
|
2015-07-02 05:00:48 +00:00
|
|
|
return []string{datastore.NetworkKeyPrefix, n.id}
|
2015-05-08 13:26:35 +00:00
|
|
|
}
|
|
|
|
|
2015-06-01 16:43:24 +00:00
|
|
|
func (n *network) KeyPrefix() []string {
|
|
|
|
return []string{datastore.NetworkKeyPrefix}
|
|
|
|
}
|
|
|
|
|
2015-05-08 13:26:35 +00:00
|
|
|
func (n *network) Value() []byte {
|
2015-06-05 20:31:12 +00:00
|
|
|
n.Lock()
|
|
|
|
defer n.Unlock()
|
2015-05-08 13:26:35 +00:00
|
|
|
b, err := json.Marshal(n)
|
|
|
|
if err != nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return b
|
|
|
|
}
|
|
|
|
|
2015-06-18 22:13:38 +00:00
|
|
|
func (n *network) SetValue(value []byte) error {
|
|
|
|
return json.Unmarshal(value, n)
|
|
|
|
}
|
|
|
|
|
2015-05-08 13:26:35 +00:00
|
|
|
func (n *network) Index() uint64 {
|
2015-06-05 20:31:12 +00:00
|
|
|
n.Lock()
|
|
|
|
defer n.Unlock()
|
2015-05-08 13:26:35 +00:00
|
|
|
return n.dbIndex
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *network) SetIndex(index uint64) {
|
2015-06-05 20:31:12 +00:00
|
|
|
n.Lock()
|
2015-05-08 13:26:35 +00:00
|
|
|
n.dbIndex = index
|
2015-06-18 22:13:38 +00:00
|
|
|
n.dbExists = true
|
2015-06-05 20:31:12 +00:00
|
|
|
n.Unlock()
|
|
|
|
}
|
|
|
|
|
2015-06-18 22:13:38 +00:00
|
|
|
func (n *network) Exists() bool {
|
|
|
|
n.Lock()
|
|
|
|
defer n.Unlock()
|
|
|
|
return n.dbExists
|
|
|
|
}
|
|
|
|
|
2015-09-22 14:09:39 +00:00
|
|
|
func (n *network) Skip() bool {
|
|
|
|
n.Lock()
|
|
|
|
defer n.Unlock()
|
|
|
|
return !n.persist
|
|
|
|
}
|
|
|
|
|
2015-09-16 11:39:46 +00:00
|
|
|
func (n *network) DataScope() datastore.DataScope {
|
|
|
|
n.Lock()
|
|
|
|
defer n.Unlock()
|
|
|
|
return n.dataScope
|
|
|
|
}
|
|
|
|
|
2015-06-05 20:31:12 +00:00
|
|
|
func (n *network) EndpointCnt() uint64 {
|
|
|
|
n.Lock()
|
|
|
|
defer n.Unlock()
|
|
|
|
return n.endpointCnt
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *network) IncEndpointCnt() {
|
|
|
|
n.Lock()
|
|
|
|
n.endpointCnt++
|
|
|
|
n.Unlock()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *network) DecEndpointCnt() {
|
|
|
|
n.Lock()
|
|
|
|
n.endpointCnt--
|
|
|
|
n.Unlock()
|
2015-05-08 13:26:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO : Can be made much more generic with the help of reflection (but has some golang limitations)
|
|
|
|
func (n *network) MarshalJSON() ([]byte, error) {
|
|
|
|
netMap := make(map[string]interface{})
|
|
|
|
netMap["name"] = n.name
|
2015-07-02 05:00:48 +00:00
|
|
|
netMap["id"] = n.id
|
2015-05-08 13:26:35 +00:00
|
|
|
netMap["networkType"] = n.networkType
|
2015-06-05 20:31:12 +00:00
|
|
|
netMap["endpointCnt"] = n.endpointCnt
|
2015-05-08 13:26:35 +00:00
|
|
|
netMap["enableIPv6"] = n.enableIPv6
|
|
|
|
netMap["generic"] = n.generic
|
2015-09-22 14:09:39 +00:00
|
|
|
netMap["persist"] = n.persist
|
2015-05-08 13:26:35 +00:00
|
|
|
return json.Marshal(netMap)
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO : Can be made much more generic with the help of reflection (but has some golang limitations)
|
|
|
|
func (n *network) UnmarshalJSON(b []byte) (err error) {
|
|
|
|
var netMap map[string]interface{}
|
|
|
|
if err := json.Unmarshal(b, &netMap); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
n.name = netMap["name"].(string)
|
2015-07-02 05:00:48 +00:00
|
|
|
n.id = netMap["id"].(string)
|
2015-05-08 13:26:35 +00:00
|
|
|
n.networkType = netMap["networkType"].(string)
|
2015-06-05 20:31:12 +00:00
|
|
|
n.endpointCnt = uint64(netMap["endpointCnt"].(float64))
|
2015-05-08 13:26:35 +00:00
|
|
|
n.enableIPv6 = netMap["enableIPv6"].(bool)
|
2015-05-13 15:41:45 +00:00
|
|
|
if netMap["generic"] != nil {
|
|
|
|
n.generic = netMap["generic"].(map[string]interface{})
|
|
|
|
}
|
2015-09-22 14:09:39 +00:00
|
|
|
if netMap["persist"] != nil {
|
|
|
|
n.persist = netMap["persist"].(bool)
|
|
|
|
}
|
2015-05-08 13:26:35 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-05-01 00:57:06 +00:00
|
|
|
// NetworkOption is a option setter function type used to pass varios options to
|
|
|
|
// NewNetwork method. The various setter functions of type NetworkOption are
|
|
|
|
// provided by libnetwork, they look like NetworkOptionXXXX(...)
|
|
|
|
type NetworkOption func(n *network)
|
|
|
|
|
|
|
|
// NetworkOptionGeneric function returns an option setter for a Generic option defined
|
|
|
|
// in a Dictionary of Key-Value pair
|
|
|
|
func NetworkOptionGeneric(generic map[string]interface{}) NetworkOption {
|
|
|
|
return func(n *network) {
|
|
|
|
n.generic = generic
|
2015-05-06 06:41:20 +00:00
|
|
|
if _, ok := generic[netlabel.EnableIPv6]; ok {
|
|
|
|
n.enableIPv6 = generic[netlabel.EnableIPv6].(bool)
|
|
|
|
}
|
2015-05-01 00:57:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-22 14:09:39 +00:00
|
|
|
// NetworkOptionPersist returns an option setter to set persistence policy for a network
|
|
|
|
func NetworkOptionPersist(persist bool) NetworkOption {
|
|
|
|
return func(n *network) {
|
|
|
|
n.persist = persist
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-01 00:57:06 +00:00
|
|
|
func (n *network) processOptions(options ...NetworkOption) {
|
|
|
|
for _, opt := range options {
|
|
|
|
if opt != nil {
|
|
|
|
opt(n)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-13 18:40:42 +00:00
|
|
|
func (n *network) Delete() error {
|
2015-06-05 20:31:12 +00:00
|
|
|
var err error
|
|
|
|
|
|
|
|
n.Lock()
|
|
|
|
ctrlr := n.ctrlr
|
|
|
|
n.Unlock()
|
|
|
|
|
|
|
|
ctrlr.Lock()
|
|
|
|
_, ok := ctrlr.networks[n.id]
|
|
|
|
ctrlr.Unlock()
|
|
|
|
|
2015-04-13 18:40:42 +00:00
|
|
|
if !ok {
|
2015-07-02 05:00:48 +00:00
|
|
|
return &UnknownNetworkError{name: n.name, id: n.id}
|
2015-04-13 18:40:42 +00:00
|
|
|
}
|
|
|
|
|
2015-06-05 20:31:12 +00:00
|
|
|
numEps := n.EndpointCnt()
|
2015-04-13 18:40:42 +00:00
|
|
|
if numEps != 0 {
|
2015-07-02 05:00:48 +00:00
|
|
|
return &ActiveEndpointsError{name: n.name, id: n.id}
|
2015-04-13 18:40:42 +00:00
|
|
|
}
|
2015-06-01 16:43:24 +00:00
|
|
|
|
2015-06-05 20:31:12 +00:00
|
|
|
// deleteNetworkFromStore performs an atomic delete operation and the network.endpointCnt field will help
|
|
|
|
// prevent any possible race between endpoint join and network delete
|
2015-09-16 11:42:35 +00:00
|
|
|
if err = ctrlr.deleteFromStore(n); err != nil {
|
2015-06-11 12:32:15 +00:00
|
|
|
if err == datastore.ErrKeyModified {
|
2015-06-05 20:31:12 +00:00
|
|
|
return types.InternalErrorf("operation in progress. delete failed for network %s. Please try again.")
|
|
|
|
}
|
2015-06-01 16:43:24 +00:00
|
|
|
return err
|
|
|
|
}
|
2015-04-13 18:40:42 +00:00
|
|
|
|
2015-09-16 11:42:35 +00:00
|
|
|
defer func() {
|
|
|
|
if err != nil {
|
|
|
|
n.dbExists = false
|
|
|
|
if e := ctrlr.updateToStore(n); e != nil {
|
|
|
|
log.Warnf("failed to recreate network in store %s : %v", n.name, e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
2015-06-05 20:31:12 +00:00
|
|
|
if err = n.deleteNetwork(); err != nil {
|
|
|
|
return err
|
2015-06-01 16:43:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *network) deleteNetwork() error {
|
2015-06-05 20:31:12 +00:00
|
|
|
n.Lock()
|
|
|
|
id := n.id
|
|
|
|
d := n.driver
|
2015-06-01 16:43:24 +00:00
|
|
|
n.ctrlr.Lock()
|
2015-06-05 20:31:12 +00:00
|
|
|
delete(n.ctrlr.networks, id)
|
2015-04-13 18:40:42 +00:00
|
|
|
n.ctrlr.Unlock()
|
2015-06-05 20:31:12 +00:00
|
|
|
n.Unlock()
|
|
|
|
|
|
|
|
if err := d.DeleteNetwork(n.id); err != nil {
|
2015-06-10 20:27:23 +00:00
|
|
|
// Forbidden Errors should be honored
|
|
|
|
if _, ok := err.(types.ForbiddenError); ok {
|
2015-04-13 18:40:42 +00:00
|
|
|
n.ctrlr.Lock()
|
|
|
|
n.ctrlr.networks[n.id] = n
|
|
|
|
n.ctrlr.Unlock()
|
2015-06-10 20:27:23 +00:00
|
|
|
return err
|
2015-04-13 18:40:42 +00:00
|
|
|
}
|
2015-06-10 20:27:23 +00:00
|
|
|
log.Warnf("driver error deleting network %s : %v", n.name, err)
|
|
|
|
}
|
2015-06-17 16:13:31 +00:00
|
|
|
n.stopWatch()
|
2015-06-10 20:27:23 +00:00
|
|
|
return nil
|
2015-04-13 18:40:42 +00:00
|
|
|
}
|
|
|
|
|
2015-05-31 18:49:11 +00:00
|
|
|
func (n *network) addEndpoint(ep *endpoint) error {
|
|
|
|
var err error
|
|
|
|
n.Lock()
|
|
|
|
n.endpoints[ep.id] = ep
|
|
|
|
d := n.driver
|
|
|
|
n.Unlock()
|
|
|
|
|
|
|
|
defer func() {
|
|
|
|
if err != nil {
|
|
|
|
n.Lock()
|
|
|
|
delete(n.endpoints, ep.id)
|
|
|
|
n.Unlock()
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
err = d.CreateEndpoint(n.id, ep.id, ep, ep.generic)
|
|
|
|
if err != nil {
|
2015-07-02 05:00:48 +00:00
|
|
|
return types.InternalErrorf("failed to create endpoint %s on network %s: %v", ep.Name(), n.Name(), err)
|
2015-05-31 18:49:11 +00:00
|
|
|
}
|
2015-06-19 06:40:17 +00:00
|
|
|
|
|
|
|
n.updateSvcRecord(ep, true)
|
2015-05-31 18:49:11 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-05-01 00:57:06 +00:00
|
|
|
func (n *network) CreateEndpoint(name string, options ...EndpointOption) (Endpoint, error) {
|
2015-06-05 20:31:12 +00:00
|
|
|
var err error
|
2015-06-14 16:00:27 +00:00
|
|
|
if !config.IsValidName(name) {
|
2015-05-14 21:56:15 +00:00
|
|
|
return nil, ErrInvalidName(name)
|
2015-05-08 02:59:06 +00:00
|
|
|
}
|
2015-06-04 16:41:42 +00:00
|
|
|
|
2015-06-05 20:31:12 +00:00
|
|
|
if _, err = n.EndpointByName(name); err == nil {
|
2015-06-04 16:41:42 +00:00
|
|
|
return nil, types.ForbiddenErrorf("service endpoint with name %s already exists", name)
|
|
|
|
}
|
|
|
|
|
2015-06-18 22:13:38 +00:00
|
|
|
ep := &endpoint{name: name,
|
|
|
|
generic: make(map[string]interface{})}
|
2015-07-02 05:00:48 +00:00
|
|
|
ep.id = stringid.GenerateRandomID()
|
2015-04-13 18:40:42 +00:00
|
|
|
ep.network = n
|
2015-05-01 00:57:06 +00:00
|
|
|
ep.processOptions(options...)
|
2015-04-13 18:40:42 +00:00
|
|
|
|
2015-06-05 20:31:12 +00:00
|
|
|
n.Lock()
|
|
|
|
ctrlr := n.ctrlr
|
|
|
|
n.Unlock()
|
|
|
|
|
|
|
|
n.IncEndpointCnt()
|
2015-09-16 11:42:35 +00:00
|
|
|
if err = ctrlr.updateToStore(n); err != nil {
|
2015-05-31 18:49:11 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
2015-06-05 20:31:12 +00:00
|
|
|
defer func() {
|
|
|
|
if err != nil {
|
|
|
|
n.DecEndpointCnt()
|
2015-09-16 11:42:35 +00:00
|
|
|
if err = ctrlr.updateToStore(n); err != nil {
|
2015-06-05 20:31:12 +00:00
|
|
|
log.Warnf("endpoint count cleanup failed when updating network for %s : %v", name, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
if err = n.addEndpoint(ep); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer func() {
|
|
|
|
if err != nil {
|
|
|
|
if e := ep.Delete(); ep != nil {
|
|
|
|
log.Warnf("cleaning up endpoint failed %s : %v", name, e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
2015-05-31 18:49:11 +00:00
|
|
|
|
2015-09-16 11:42:35 +00:00
|
|
|
if !ep.isLocalScoped() {
|
|
|
|
if err = ctrlr.updateToStore(ep); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2015-04-13 18:40:42 +00:00
|
|
|
}
|
|
|
|
|
2015-04-17 22:42:23 +00:00
|
|
|
return ep, nil
|
2015-04-13 18:40:42 +00:00
|
|
|
}
|
|
|
|
|
2015-04-18 06:13:29 +00:00
|
|
|
func (n *network) Endpoints() []Endpoint {
|
|
|
|
n.Lock()
|
|
|
|
defer n.Unlock()
|
2015-04-20 16:46:11 +00:00
|
|
|
list := make([]Endpoint, 0, len(n.endpoints))
|
2015-04-18 06:13:29 +00:00
|
|
|
for _, e := range n.endpoints {
|
2015-04-20 16:46:11 +00:00
|
|
|
list = append(list, e)
|
2015-04-18 06:13:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return list
|
|
|
|
}
|
|
|
|
|
2015-04-20 16:46:11 +00:00
|
|
|
func (n *network) WalkEndpoints(walker EndpointWalker) {
|
|
|
|
for _, e := range n.Endpoints() {
|
|
|
|
if walker(e) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-11 23:13:27 +00:00
|
|
|
func (n *network) EndpointByName(name string) (Endpoint, error) {
|
|
|
|
if name == "" {
|
2015-05-14 21:56:15 +00:00
|
|
|
return nil, ErrInvalidName(name)
|
2015-05-11 23:13:27 +00:00
|
|
|
}
|
2015-04-24 19:05:33 +00:00
|
|
|
var e Endpoint
|
|
|
|
|
2015-05-11 23:13:27 +00:00
|
|
|
s := func(current Endpoint) bool {
|
|
|
|
if current.Name() == name {
|
|
|
|
e = current
|
|
|
|
return true
|
2015-04-24 19:05:33 +00:00
|
|
|
}
|
2015-05-11 23:13:27 +00:00
|
|
|
return false
|
2015-04-24 19:05:33 +00:00
|
|
|
}
|
|
|
|
|
2015-05-11 23:13:27 +00:00
|
|
|
n.WalkEndpoints(s)
|
|
|
|
|
2015-05-15 23:04:09 +00:00
|
|
|
if e == nil {
|
2015-05-14 21:56:15 +00:00
|
|
|
return nil, ErrNoSuchEndpoint(name)
|
2015-05-15 23:04:09 +00:00
|
|
|
}
|
|
|
|
|
2015-05-11 23:13:27 +00:00
|
|
|
return e, nil
|
2015-04-24 19:05:33 +00:00
|
|
|
}
|
|
|
|
|
2015-05-11 23:13:27 +00:00
|
|
|
func (n *network) EndpointByID(id string) (Endpoint, error) {
|
|
|
|
if id == "" {
|
2015-05-14 21:56:15 +00:00
|
|
|
return nil, ErrInvalidID(id)
|
2015-05-11 23:13:27 +00:00
|
|
|
}
|
2015-04-24 19:05:33 +00:00
|
|
|
n.Lock()
|
|
|
|
defer n.Unlock()
|
2015-07-02 05:00:48 +00:00
|
|
|
if e, ok := n.endpoints[id]; ok {
|
2015-05-11 23:13:27 +00:00
|
|
|
return e, nil
|
2015-04-24 19:05:33 +00:00
|
|
|
}
|
2015-05-14 21:56:15 +00:00
|
|
|
return nil, ErrNoSuchEndpoint(id)
|
2015-04-24 19:05:33 +00:00
|
|
|
}
|
2015-05-13 21:12:57 +00:00
|
|
|
|
2015-09-16 11:39:46 +00:00
|
|
|
func (n *network) isGlobalScoped() bool {
|
|
|
|
return n.DataScope() == datastore.GlobalScope
|
2015-05-13 21:12:57 +00:00
|
|
|
}
|
2015-06-19 06:40:17 +00:00
|
|
|
|
|
|
|
func (n *network) updateSvcRecord(ep *endpoint, isAdd bool) {
|
|
|
|
n.Lock()
|
|
|
|
var recs []etchosts.Record
|
2015-09-09 23:06:35 +00:00
|
|
|
if iface := ep.Iface(); iface != nil {
|
2015-06-19 06:40:17 +00:00
|
|
|
if isAdd {
|
|
|
|
n.svcRecords[ep.Name()] = iface.Address().IP
|
|
|
|
n.svcRecords[ep.Name()+"."+n.name] = iface.Address().IP
|
|
|
|
} else {
|
|
|
|
delete(n.svcRecords, ep.Name())
|
|
|
|
delete(n.svcRecords, ep.Name()+"."+n.name)
|
|
|
|
}
|
|
|
|
|
|
|
|
recs = append(recs, etchosts.Record{
|
|
|
|
Hosts: ep.Name(),
|
|
|
|
IP: iface.Address().IP.String(),
|
|
|
|
})
|
|
|
|
|
|
|
|
recs = append(recs, etchosts.Record{
|
|
|
|
Hosts: ep.Name() + "." + n.name,
|
|
|
|
IP: iface.Address().IP.String(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
n.Unlock()
|
|
|
|
|
2015-06-24 18:42:53 +00:00
|
|
|
// If there are no records to add or delete then simply return here
|
|
|
|
if len(recs) == 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2015-07-02 05:00:48 +00:00
|
|
|
var sbList []*sandbox
|
2015-06-19 06:40:17 +00:00
|
|
|
n.WalkEndpoints(func(e Endpoint) bool {
|
2015-07-02 05:00:48 +00:00
|
|
|
if sb, hasSandbox := e.(*endpoint).getSandbox(); hasSandbox {
|
|
|
|
sbList = append(sbList, sb)
|
2015-06-19 06:40:17 +00:00
|
|
|
}
|
|
|
|
return false
|
|
|
|
})
|
|
|
|
|
2015-07-02 05:00:48 +00:00
|
|
|
for _, sb := range sbList {
|
2015-06-19 06:40:17 +00:00
|
|
|
if isAdd {
|
2015-07-02 05:00:48 +00:00
|
|
|
sb.addHostsEntries(recs)
|
2015-06-19 06:40:17 +00:00
|
|
|
} else {
|
2015-07-02 05:00:48 +00:00
|
|
|
sb.deleteHostsEntries(recs)
|
2015-06-19 06:40:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *network) getSvcRecords() []etchosts.Record {
|
|
|
|
n.Lock()
|
|
|
|
defer n.Unlock()
|
|
|
|
|
|
|
|
var recs []etchosts.Record
|
|
|
|
for h, ip := range n.svcRecords {
|
|
|
|
recs = append(recs, etchosts.Record{
|
|
|
|
Hosts: h,
|
|
|
|
IP: ip.String(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
return recs
|
|
|
|
}
|
2015-07-02 05:00:48 +00:00
|
|
|
|
|
|
|
func (n *network) getController() *controller {
|
|
|
|
n.Lock()
|
|
|
|
defer n.Unlock()
|
|
|
|
return n.ctrlr
|
|
|
|
}
|