2015-04-30 01:25:01 +00:00
|
|
|
package libnetwork
|
|
|
|
|
|
|
|
import (
|
2015-05-03 20:29:43 +00:00
|
|
|
"io/ioutil"
|
2015-04-30 05:58:12 +00:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
2015-05-09 04:50:03 +00:00
|
|
|
"sync"
|
2015-04-30 05:58:12 +00:00
|
|
|
|
2015-05-06 00:33:08 +00:00
|
|
|
"github.com/Sirupsen/logrus"
|
2015-05-03 20:29:43 +00:00
|
|
|
"github.com/docker/libnetwork/driverapi"
|
2015-05-01 17:01:21 -07:00
|
|
|
"github.com/docker/libnetwork/netutils"
|
2015-05-06 22:23:01 +00:00
|
|
|
"github.com/docker/libnetwork/pkg/etchosts"
|
2015-05-06 04:19:57 +00:00
|
|
|
"github.com/docker/libnetwork/pkg/netlabel"
|
2015-05-06 22:23:01 +00:00
|
|
|
"github.com/docker/libnetwork/pkg/resolvconf"
|
2015-04-30 01:25:01 +00:00
|
|
|
"github.com/docker/libnetwork/sandbox"
|
|
|
|
"github.com/docker/libnetwork/types"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Endpoint represents a logical connection between a network and a sandbox.
|
|
|
|
type Endpoint interface {
|
|
|
|
// A system generated id for this endpoint.
|
|
|
|
ID() string
|
|
|
|
|
|
|
|
// Name returns the name of this endpoint.
|
|
|
|
Name() string
|
|
|
|
|
|
|
|
// Network returns the name of the network to which this endpoint is attached.
|
|
|
|
Network() string
|
|
|
|
|
|
|
|
// Join creates a new sandbox for the given container ID and populates the
|
|
|
|
// network resources allocated for the endpoint and joins the sandbox to
|
|
|
|
// the endpoint. It returns the sandbox key to the caller
|
2015-05-01 17:11:13 -07:00
|
|
|
Join(containerID string, options ...EndpointOption) (*ContainerData, error)
|
2015-04-30 01:25:01 +00:00
|
|
|
|
|
|
|
// Leave removes the sandbox associated with container ID and detaches
|
|
|
|
// the network resources populated in the sandbox
|
2015-05-01 17:11:13 -07:00
|
|
|
Leave(containerID string, options ...EndpointOption) error
|
2015-04-30 01:25:01 +00:00
|
|
|
|
|
|
|
// SandboxInfo returns the sandbox information for this endpoint.
|
|
|
|
SandboxInfo() *sandbox.Info
|
|
|
|
|
2015-05-04 11:49:53 -07:00
|
|
|
// Info returns a collection of operational data related to this endpoint retrieved from the driver
|
|
|
|
Info() (map[string]interface{}, error)
|
|
|
|
|
2015-04-30 01:25:01 +00:00
|
|
|
// Delete and detaches this endpoint from the network.
|
|
|
|
Delete() error
|
|
|
|
}
|
|
|
|
|
2015-05-01 17:11:13 -07:00
|
|
|
// EndpointOption is a option setter function type used to pass varios options to Network
|
|
|
|
// and Endpoint interfaces methods. The various setter functions of type EndpointOption are
|
|
|
|
// provided by libnetwork, they look like <Create|Join|Leave>Option[...](...)
|
|
|
|
type EndpointOption func(ep *endpoint)
|
|
|
|
|
2015-04-30 05:58:12 +00:00
|
|
|
// ContainerData is a set of data returned when a container joins an endpoint.
|
|
|
|
type ContainerData struct {
|
|
|
|
SandboxKey string
|
|
|
|
}
|
|
|
|
|
2015-05-05 04:20:45 +00:00
|
|
|
// These are the container configs used to customize container /etc/hosts file.
|
|
|
|
type hostsPathConfig struct {
|
|
|
|
hostName string
|
|
|
|
domainName string
|
|
|
|
hostsPath string
|
|
|
|
extraHosts []extraHost
|
|
|
|
parentUpdates []parentUpdate
|
|
|
|
}
|
|
|
|
|
|
|
|
// These are the container configs used to customize container /etc/resolv.conf file.
|
|
|
|
type resolvConfPathConfig struct {
|
2015-05-04 05:18:49 +00:00
|
|
|
resolvConfPath string
|
|
|
|
dnsList []string
|
|
|
|
dnsSearchList []string
|
2015-05-03 20:29:43 +00:00
|
|
|
}
|
|
|
|
|
2015-05-05 04:20:45 +00:00
|
|
|
type containerConfig struct {
|
|
|
|
hostsPathConfig
|
|
|
|
resolvConfPathConfig
|
|
|
|
generic map[string]interface{}
|
|
|
|
useDefaultSandBox bool
|
|
|
|
}
|
|
|
|
|
2015-05-03 20:29:43 +00:00
|
|
|
type extraHost struct {
|
|
|
|
name string
|
|
|
|
IP string
|
|
|
|
}
|
|
|
|
|
|
|
|
type parentUpdate struct {
|
|
|
|
eid string
|
|
|
|
name string
|
|
|
|
ip string
|
2015-04-30 05:58:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type containerInfo struct {
|
2015-05-01 13:57:03 -07:00
|
|
|
id string
|
|
|
|
config containerConfig
|
|
|
|
data ContainerData
|
2015-04-30 05:58:12 +00:00
|
|
|
}
|
|
|
|
|
2015-04-30 01:25:01 +00:00
|
|
|
type endpoint struct {
|
2015-05-09 04:50:03 +00:00
|
|
|
name string
|
|
|
|
id types.UUID
|
|
|
|
network *network
|
|
|
|
sandboxInfo *sandbox.Info
|
|
|
|
sandBox sandbox.Sandbox
|
|
|
|
joinInfo *driverapi.JoinInfo
|
|
|
|
container *containerInfo
|
|
|
|
exposedPorts []netutils.TransportPort
|
|
|
|
generic map[string]interface{}
|
|
|
|
context map[string]interface{}
|
|
|
|
joinLeaveDone chan struct{}
|
|
|
|
sync.Mutex
|
2015-04-30 01:25:01 +00:00
|
|
|
}
|
|
|
|
|
2015-05-03 20:29:43 +00:00
|
|
|
const defaultPrefix = "/var/lib/docker/network/files"
|
2015-04-30 05:58:12 +00:00
|
|
|
|
2015-04-30 01:25:01 +00:00
|
|
|
func (ep *endpoint) ID() string {
|
2015-05-09 04:50:03 +00:00
|
|
|
ep.Lock()
|
|
|
|
defer ep.Unlock()
|
|
|
|
|
2015-04-30 01:25:01 +00:00
|
|
|
return string(ep.id)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ep *endpoint) Name() string {
|
2015-05-09 04:50:03 +00:00
|
|
|
ep.Lock()
|
|
|
|
defer ep.Unlock()
|
|
|
|
|
2015-04-30 01:25:01 +00:00
|
|
|
return ep.name
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ep *endpoint) Network() string {
|
2015-05-09 04:50:03 +00:00
|
|
|
ep.Lock()
|
|
|
|
defer ep.Unlock()
|
|
|
|
|
2015-04-30 01:25:01 +00:00
|
|
|
return ep.network.name
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ep *endpoint) SandboxInfo() *sandbox.Info {
|
2015-05-09 04:50:03 +00:00
|
|
|
ep.Lock()
|
|
|
|
defer ep.Unlock()
|
|
|
|
|
2015-04-30 01:25:01 +00:00
|
|
|
if ep.sandboxInfo == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return ep.sandboxInfo.GetCopy()
|
|
|
|
}
|
|
|
|
|
2015-05-04 11:49:53 -07:00
|
|
|
func (ep *endpoint) Info() (map[string]interface{}, error) {
|
2015-05-09 04:50:03 +00:00
|
|
|
ep.Lock()
|
|
|
|
network := ep.network
|
|
|
|
epid := ep.id
|
|
|
|
ep.Unlock()
|
|
|
|
|
|
|
|
network.Lock()
|
|
|
|
driver := network.driver
|
|
|
|
nid := network.id
|
|
|
|
network.Unlock()
|
|
|
|
|
|
|
|
return driver.EndpointInfo(nid, epid)
|
2015-05-04 11:49:53 -07:00
|
|
|
}
|
|
|
|
|
2015-04-30 17:57:06 -07:00
|
|
|
func (ep *endpoint) processOptions(options ...EndpointOption) {
|
2015-05-09 04:50:03 +00:00
|
|
|
ep.Lock()
|
|
|
|
defer ep.Unlock()
|
|
|
|
|
2015-04-30 17:57:06 -07:00
|
|
|
for _, opt := range options {
|
|
|
|
if opt != nil {
|
|
|
|
opt(ep)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-30 05:58:12 +00:00
|
|
|
func createBasePath(dir string) error {
|
|
|
|
err := os.MkdirAll(dir, 0644)
|
|
|
|
if err != nil && !os.IsExist(err) {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-05-03 20:29:43 +00:00
|
|
|
func createFile(path string) error {
|
2015-04-30 05:58:12 +00:00
|
|
|
var f *os.File
|
|
|
|
|
|
|
|
dir, _ := filepath.Split(path)
|
|
|
|
err := createBasePath(dir)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
f, err = os.Create(path)
|
|
|
|
if err == nil {
|
|
|
|
f.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2015-05-09 04:50:03 +00:00
|
|
|
// joinLeaveStart waits to ensure there are no joins or leaves in progress and
|
|
|
|
// marks this join/leave in progress without race
|
|
|
|
func (ep *endpoint) joinLeaveStart() {
|
|
|
|
ep.Lock()
|
|
|
|
defer ep.Unlock()
|
|
|
|
|
|
|
|
for ep.joinLeaveDone != nil {
|
|
|
|
joinLeaveDone := ep.joinLeaveDone
|
|
|
|
ep.Unlock()
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-joinLeaveDone:
|
|
|
|
}
|
|
|
|
|
|
|
|
ep.Lock()
|
|
|
|
}
|
|
|
|
|
|
|
|
ep.joinLeaveDone = make(chan struct{})
|
|
|
|
}
|
|
|
|
|
|
|
|
// joinLeaveEnd marks the end of this join/leave operation and
|
|
|
|
// signals the same without race to other join and leave waiters
|
|
|
|
func (ep *endpoint) joinLeaveEnd() {
|
|
|
|
ep.Lock()
|
|
|
|
defer ep.Unlock()
|
|
|
|
|
|
|
|
if ep.joinLeaveDone != nil {
|
|
|
|
close(ep.joinLeaveDone)
|
|
|
|
ep.joinLeaveDone = nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-01 17:11:13 -07:00
|
|
|
func (ep *endpoint) Join(containerID string, options ...EndpointOption) (*ContainerData, error) {
|
2015-04-30 05:58:12 +00:00
|
|
|
var err error
|
|
|
|
|
2015-04-30 01:25:01 +00:00
|
|
|
if containerID == "" {
|
2015-04-30 05:58:12 +00:00
|
|
|
return nil, InvalidContainerIDError(containerID)
|
2015-04-30 01:25:01 +00:00
|
|
|
}
|
|
|
|
|
2015-05-09 04:50:03 +00:00
|
|
|
ep.joinLeaveStart()
|
|
|
|
defer ep.joinLeaveEnd()
|
|
|
|
|
|
|
|
ep.Lock()
|
2015-04-30 05:58:12 +00:00
|
|
|
if ep.container != nil {
|
2015-05-09 04:50:03 +00:00
|
|
|
ep.Unlock()
|
2015-04-30 05:58:12 +00:00
|
|
|
return nil, ErrInvalidJoin
|
|
|
|
}
|
|
|
|
|
2015-05-03 20:29:43 +00:00
|
|
|
ep.container = &containerInfo{
|
2015-05-09 04:50:03 +00:00
|
|
|
id: containerID,
|
2015-05-03 20:29:43 +00:00
|
|
|
config: containerConfig{
|
2015-05-05 04:20:45 +00:00
|
|
|
hostsPathConfig: hostsPathConfig{
|
|
|
|
extraHosts: []extraHost{},
|
|
|
|
parentUpdates: []parentUpdate{},
|
|
|
|
},
|
2015-05-03 20:29:43 +00:00
|
|
|
}}
|
2015-05-09 04:50:03 +00:00
|
|
|
|
|
|
|
container := ep.container
|
|
|
|
network := ep.network
|
|
|
|
epid := ep.id
|
|
|
|
|
|
|
|
ep.Unlock()
|
2015-04-30 05:58:12 +00:00
|
|
|
defer func() {
|
2015-05-09 04:50:03 +00:00
|
|
|
ep.Lock()
|
2015-04-30 05:58:12 +00:00
|
|
|
if err != nil {
|
|
|
|
ep.container = nil
|
|
|
|
}
|
2015-05-09 04:50:03 +00:00
|
|
|
ep.Unlock()
|
2015-04-30 05:58:12 +00:00
|
|
|
}()
|
|
|
|
|
2015-05-09 04:50:03 +00:00
|
|
|
network.Lock()
|
|
|
|
driver := network.driver
|
|
|
|
nid := network.id
|
|
|
|
ctrlr := network.ctrlr
|
|
|
|
network.Unlock()
|
2015-05-03 20:29:43 +00:00
|
|
|
|
2015-05-09 04:50:03 +00:00
|
|
|
ep.processOptions(options...)
|
2015-05-04 05:18:49 +00:00
|
|
|
|
2015-05-03 20:29:43 +00:00
|
|
|
sboxKey := sandbox.GenerateKey(containerID)
|
2015-05-09 04:50:03 +00:00
|
|
|
if container.config.useDefaultSandBox {
|
2015-05-05 04:20:45 +00:00
|
|
|
sboxKey = sandbox.GenerateKey("default")
|
|
|
|
}
|
2015-05-03 20:29:43 +00:00
|
|
|
|
2015-05-09 04:50:03 +00:00
|
|
|
joinInfo, err := driver.Join(nid, epid, sboxKey, container.config.generic)
|
2015-04-30 05:58:12 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2015-05-09 04:50:03 +00:00
|
|
|
|
|
|
|
ep.Lock()
|
2015-05-03 20:29:43 +00:00
|
|
|
ep.joinInfo = joinInfo
|
2015-05-09 04:50:03 +00:00
|
|
|
ep.Unlock()
|
2015-04-30 05:58:12 +00:00
|
|
|
|
|
|
|
err = ep.buildHostsFiles()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2015-04-30 01:25:01 +00:00
|
|
|
}
|
|
|
|
|
2015-05-03 20:29:43 +00:00
|
|
|
err = ep.updateParentHosts()
|
2015-04-30 01:25:01 +00:00
|
|
|
if err != nil {
|
2015-04-30 05:58:12 +00:00
|
|
|
return nil, err
|
2015-04-30 01:25:01 +00:00
|
|
|
}
|
2015-05-03 20:29:43 +00:00
|
|
|
|
2015-05-04 05:18:49 +00:00
|
|
|
err = ep.setupDNS()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2015-05-09 04:50:03 +00:00
|
|
|
sb, err := ctrlr.sandboxAdd(sboxKey, !container.config.useDefaultSandBox)
|
2015-04-30 14:52:46 -07:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2015-05-03 20:29:43 +00:00
|
|
|
defer func() {
|
|
|
|
if err != nil {
|
2015-05-09 04:50:03 +00:00
|
|
|
ctrlr.sandboxRm(sboxKey)
|
2015-05-03 20:29:43 +00:00
|
|
|
}
|
|
|
|
}()
|
2015-04-30 14:52:46 -07:00
|
|
|
|
2015-04-30 01:25:01 +00:00
|
|
|
sinfo := ep.SandboxInfo()
|
|
|
|
if sinfo != nil {
|
|
|
|
for _, i := range sinfo.Interfaces {
|
|
|
|
err = sb.AddInterface(i)
|
|
|
|
if err != nil {
|
2015-04-30 05:58:12 +00:00
|
|
|
return nil, err
|
2015-04-30 01:25:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
err = sb.SetGateway(sinfo.Gateway)
|
|
|
|
if err != nil {
|
2015-04-30 05:58:12 +00:00
|
|
|
return nil, err
|
2015-04-30 01:25:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
err = sb.SetGatewayIPv6(sinfo.GatewayIPv6)
|
|
|
|
if err != nil {
|
2015-04-30 05:58:12 +00:00
|
|
|
return nil, err
|
2015-04-30 01:25:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-09 04:50:03 +00:00
|
|
|
container.data.SandboxKey = sb.Key()
|
|
|
|
cData := container.data
|
2015-04-30 05:58:12 +00:00
|
|
|
|
|
|
|
return &cData, nil
|
2015-04-30 01:25:01 +00:00
|
|
|
}
|
|
|
|
|
2015-05-01 17:11:13 -07:00
|
|
|
func (ep *endpoint) Leave(containerID string, options ...EndpointOption) error {
|
2015-05-09 04:50:03 +00:00
|
|
|
var err error
|
|
|
|
|
|
|
|
ep.joinLeaveStart()
|
|
|
|
defer ep.joinLeaveEnd()
|
2015-04-30 01:25:01 +00:00
|
|
|
|
2015-05-01 17:11:13 -07:00
|
|
|
ep.processOptions(options...)
|
2015-04-30 14:52:46 -07:00
|
|
|
|
2015-05-09 04:50:03 +00:00
|
|
|
ep.Lock()
|
|
|
|
container := ep.container
|
2015-05-01 13:57:03 -07:00
|
|
|
n := ep.network
|
2015-05-09 04:50:03 +00:00
|
|
|
context := ep.context
|
|
|
|
|
|
|
|
if container == nil || container.id == "" ||
|
|
|
|
containerID == "" || container.id != containerID {
|
|
|
|
if container == nil {
|
|
|
|
err = ErrNoContainer
|
|
|
|
} else {
|
|
|
|
err = InvalidContainerIDError(containerID)
|
|
|
|
}
|
|
|
|
|
|
|
|
ep.Unlock()
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
ep.container = nil
|
|
|
|
ep.context = nil
|
|
|
|
ep.Unlock()
|
|
|
|
|
|
|
|
n.Lock()
|
|
|
|
driver := n.driver
|
|
|
|
ctrlr := n.ctrlr
|
|
|
|
n.Unlock()
|
|
|
|
|
|
|
|
err = driver.Leave(n.id, ep.id, context)
|
2015-05-06 00:33:08 +00:00
|
|
|
|
|
|
|
sinfo := ep.SandboxInfo()
|
|
|
|
if sinfo != nil {
|
2015-05-09 04:50:03 +00:00
|
|
|
sb := ctrlr.sandboxGet(container.data.SandboxKey)
|
2015-05-06 00:33:08 +00:00
|
|
|
for _, i := range sinfo.Interfaces {
|
|
|
|
err = sb.RemoveInterface(i)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Debugf("Remove interface failed: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-09 04:50:03 +00:00
|
|
|
ctrlr.sandboxRm(container.data.SandboxKey)
|
|
|
|
|
2015-05-01 15:33:29 -07:00
|
|
|
return err
|
2015-04-30 01:25:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (ep *endpoint) Delete() error {
|
|
|
|
var err error
|
2015-05-09 04:50:03 +00:00
|
|
|
|
|
|
|
ep.Lock()
|
|
|
|
epid := ep.id
|
|
|
|
name := ep.name
|
2015-05-06 13:02:40 -07:00
|
|
|
if ep.container != nil {
|
2015-05-09 04:50:03 +00:00
|
|
|
ep.Unlock()
|
|
|
|
return &ActiveContainerError{name: name, id: string(epid)}
|
2015-05-06 13:02:40 -07:00
|
|
|
}
|
2015-04-30 01:25:01 +00:00
|
|
|
|
|
|
|
n := ep.network
|
2015-05-09 04:50:03 +00:00
|
|
|
ep.Unlock()
|
|
|
|
|
2015-04-30 01:25:01 +00:00
|
|
|
n.Lock()
|
2015-05-09 04:50:03 +00:00
|
|
|
_, ok := n.endpoints[epid]
|
2015-04-30 01:25:01 +00:00
|
|
|
if !ok {
|
|
|
|
n.Unlock()
|
2015-05-09 04:50:03 +00:00
|
|
|
return &UnknownEndpointError{name: name, id: string(epid)}
|
2015-04-30 01:25:01 +00:00
|
|
|
}
|
|
|
|
|
2015-05-09 04:50:03 +00:00
|
|
|
nid := n.id
|
|
|
|
driver := n.driver
|
|
|
|
delete(n.endpoints, epid)
|
2015-04-30 01:25:01 +00:00
|
|
|
n.Unlock()
|
|
|
|
defer func() {
|
|
|
|
if err != nil {
|
|
|
|
n.Lock()
|
2015-05-09 04:50:03 +00:00
|
|
|
n.endpoints[epid] = ep
|
2015-04-30 01:25:01 +00:00
|
|
|
n.Unlock()
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
2015-05-09 04:50:03 +00:00
|
|
|
err = driver.DeleteEndpoint(nid, epid)
|
2015-04-30 01:25:01 +00:00
|
|
|
return err
|
|
|
|
}
|
2015-04-30 05:58:12 +00:00
|
|
|
|
|
|
|
func (ep *endpoint) buildHostsFiles() error {
|
|
|
|
var extraContent []etchosts.Record
|
|
|
|
|
2015-05-09 04:50:03 +00:00
|
|
|
ep.Lock()
|
|
|
|
container := ep.container
|
|
|
|
joinInfo := ep.joinInfo
|
|
|
|
ep.Unlock()
|
|
|
|
|
|
|
|
if container == nil {
|
|
|
|
return ErrNoContainer
|
|
|
|
}
|
|
|
|
|
|
|
|
if container.config.hostsPath == "" {
|
|
|
|
container.config.hostsPath = defaultPrefix + "/" + container.id + "/hosts"
|
|
|
|
}
|
|
|
|
|
|
|
|
dir, _ := filepath.Split(container.config.hostsPath)
|
2015-05-03 20:29:43 +00:00
|
|
|
err := createBasePath(dir)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2015-05-09 04:50:03 +00:00
|
|
|
if joinInfo != nil && joinInfo.HostsPath != "" {
|
|
|
|
content, err := ioutil.ReadFile(joinInfo.HostsPath)
|
2015-05-03 20:29:43 +00:00
|
|
|
if err != nil && !os.IsNotExist(err) {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err == nil {
|
2015-05-09 04:50:03 +00:00
|
|
|
return ioutil.WriteFile(container.config.hostsPath, content, 0644)
|
2015-05-03 20:29:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-09 04:50:03 +00:00
|
|
|
name := container.config.hostName
|
|
|
|
if container.config.domainName != "" {
|
|
|
|
name = name + "." + container.config.domainName
|
2015-04-30 05:58:12 +00:00
|
|
|
}
|
|
|
|
|
2015-05-09 04:50:03 +00:00
|
|
|
for _, extraHost := range container.config.extraHosts {
|
2015-05-03 20:29:43 +00:00
|
|
|
extraContent = append(extraContent,
|
|
|
|
etchosts.Record{Hosts: extraHost.name, IP: extraHost.IP})
|
|
|
|
}
|
|
|
|
|
2015-04-30 05:58:12 +00:00
|
|
|
IP := ""
|
2015-05-09 04:50:03 +00:00
|
|
|
sinfo := ep.SandboxInfo()
|
|
|
|
if sinfo != nil && sinfo.Interfaces[0] != nil &&
|
|
|
|
sinfo.Interfaces[0].Address != nil {
|
|
|
|
IP = sinfo.Interfaces[0].Address.IP.String()
|
2015-04-30 05:58:12 +00:00
|
|
|
}
|
|
|
|
|
2015-05-09 04:50:03 +00:00
|
|
|
return etchosts.Build(container.config.hostsPath, IP, container.config.hostName,
|
|
|
|
container.config.domainName, extraContent)
|
2015-04-30 05:58:12 +00:00
|
|
|
}
|
|
|
|
|
2015-05-03 20:29:43 +00:00
|
|
|
func (ep *endpoint) updateParentHosts() error {
|
2015-05-09 04:50:03 +00:00
|
|
|
ep.Lock()
|
|
|
|
container := ep.container
|
|
|
|
network := ep.network
|
|
|
|
ep.Unlock()
|
|
|
|
|
|
|
|
if container == nil {
|
|
|
|
return ErrNoContainer
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, update := range container.config.parentUpdates {
|
|
|
|
network.Lock()
|
|
|
|
pep, ok := network.endpoints[types.UUID(update.eid)]
|
2015-05-03 20:29:43 +00:00
|
|
|
if !ok {
|
2015-05-09 04:50:03 +00:00
|
|
|
network.Unlock()
|
2015-05-03 20:29:43 +00:00
|
|
|
continue
|
|
|
|
}
|
2015-05-09 04:50:03 +00:00
|
|
|
network.Unlock()
|
2015-05-03 20:29:43 +00:00
|
|
|
|
2015-05-09 04:50:03 +00:00
|
|
|
pep.Lock()
|
|
|
|
pContainer := pep.container
|
|
|
|
pep.Unlock()
|
|
|
|
|
|
|
|
if pContainer != nil {
|
|
|
|
if err := etchosts.Update(pContainer.config.hostsPath, update.ip, update.name); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2015-05-03 20:29:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-05-04 05:18:49 +00:00
|
|
|
func (ep *endpoint) setupDNS() error {
|
2015-05-09 04:50:03 +00:00
|
|
|
ep.Lock()
|
|
|
|
container := ep.container
|
|
|
|
network := ep.network
|
|
|
|
ep.Unlock()
|
|
|
|
|
|
|
|
if container == nil {
|
|
|
|
return ErrNoContainer
|
|
|
|
}
|
|
|
|
|
|
|
|
if container.config.resolvConfPath == "" {
|
|
|
|
container.config.resolvConfPath = defaultPrefix + "/" + container.id + "/resolv.conf"
|
|
|
|
}
|
|
|
|
|
|
|
|
dir, _ := filepath.Split(container.config.resolvConfPath)
|
2015-05-04 05:18:49 +00:00
|
|
|
err := createBasePath(dir)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
resolvConf, err := resolvconf.Get()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2015-05-09 04:50:03 +00:00
|
|
|
if len(container.config.dnsList) > 0 ||
|
|
|
|
len(container.config.dnsSearchList) > 0 {
|
2015-05-04 05:18:49 +00:00
|
|
|
var (
|
|
|
|
dnsList = resolvconf.GetNameservers(resolvConf)
|
|
|
|
dnsSearchList = resolvconf.GetSearchDomains(resolvConf)
|
|
|
|
)
|
|
|
|
|
2015-05-09 04:50:03 +00:00
|
|
|
if len(container.config.dnsList) > 0 {
|
|
|
|
dnsList = container.config.dnsList
|
2015-05-04 05:18:49 +00:00
|
|
|
}
|
|
|
|
|
2015-05-09 04:50:03 +00:00
|
|
|
if len(container.config.dnsSearchList) > 0 {
|
|
|
|
dnsSearchList = container.config.dnsSearchList
|
2015-05-04 05:18:49 +00:00
|
|
|
}
|
|
|
|
|
2015-05-09 04:50:03 +00:00
|
|
|
return resolvconf.Build(container.config.resolvConfPath, dnsList, dnsSearchList)
|
2015-05-04 05:18:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// replace any localhost/127.* but always discard IPv6 entries for now.
|
2015-05-09 04:50:03 +00:00
|
|
|
resolvConf, _ = resolvconf.FilterResolvDNS(resolvConf, network.enableIPv6)
|
2015-05-04 05:18:49 +00:00
|
|
|
return ioutil.WriteFile(ep.container.config.resolvConfPath, resolvConf, 0644)
|
|
|
|
}
|
|
|
|
|
|
|
|
// EndpointOptionGeneric function returns an option setter for a Generic option defined
|
|
|
|
// in a Dictionary of Key-Value pair
|
|
|
|
func EndpointOptionGeneric(generic map[string]interface{}) EndpointOption {
|
|
|
|
return func(ep *endpoint) {
|
|
|
|
for k, v := range generic {
|
|
|
|
ep.generic[k] = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-30 05:58:12 +00:00
|
|
|
// JoinOptionHostname function returns an option setter for hostname option to
|
|
|
|
// be passed to endpoint Join method.
|
2015-05-01 17:11:13 -07:00
|
|
|
func JoinOptionHostname(name string) EndpointOption {
|
2015-04-30 10:35:46 -07:00
|
|
|
return func(ep *endpoint) {
|
2015-05-01 13:57:03 -07:00
|
|
|
ep.container.config.hostName = name
|
2015-04-30 05:58:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// JoinOptionDomainname function returns an option setter for domainname option to
|
|
|
|
// be passed to endpoint Join method.
|
2015-05-01 17:11:13 -07:00
|
|
|
func JoinOptionDomainname(name string) EndpointOption {
|
2015-04-30 10:35:46 -07:00
|
|
|
return func(ep *endpoint) {
|
2015-05-01 13:57:03 -07:00
|
|
|
ep.container.config.domainName = name
|
2015-04-30 05:58:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-03 20:29:43 +00:00
|
|
|
// JoinOptionHostsPath function returns an option setter for hostspath option to
|
|
|
|
// be passed to endpoint Join method.
|
|
|
|
func JoinOptionHostsPath(path string) EndpointOption {
|
|
|
|
return func(ep *endpoint) {
|
|
|
|
ep.container.config.hostsPath = path
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// JoinOptionExtraHost function returns an option setter for extra /etc/hosts options
|
|
|
|
// which is a name and IP as strings.
|
|
|
|
func JoinOptionExtraHost(name string, IP string) EndpointOption {
|
|
|
|
return func(ep *endpoint) {
|
2015-05-05 04:20:45 +00:00
|
|
|
ep.container.config.extraHosts = append(ep.container.config.extraHosts, extraHost{name: name, IP: IP})
|
2015-05-03 20:29:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// JoinOptionParentUpdate function returns an option setter for parent container
|
|
|
|
// which needs to update the IP address for the linked container.
|
|
|
|
func JoinOptionParentUpdate(eid string, name, ip string) EndpointOption {
|
|
|
|
return func(ep *endpoint) {
|
|
|
|
ep.container.config.parentUpdates = append(ep.container.config.parentUpdates, parentUpdate{eid: eid, name: name, ip: ip})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-04 05:18:49 +00:00
|
|
|
// JoinOptionResolvConfPath function returns an option setter for resolvconfpath option to
|
|
|
|
// be passed to endpoint Join method.
|
|
|
|
func JoinOptionResolvConfPath(path string) EndpointOption {
|
|
|
|
return func(ep *endpoint) {
|
|
|
|
ep.container.config.resolvConfPath = path
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// JoinOptionDNS function returns an option setter for dns entry option to
|
|
|
|
// be passed to endpoint Join method.
|
|
|
|
func JoinOptionDNS(dns string) EndpointOption {
|
|
|
|
return func(ep *endpoint) {
|
|
|
|
ep.container.config.dnsList = append(ep.container.config.dnsList, dns)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// JoinOptionDNSSearch function returns an option setter for dns search entry option to
|
|
|
|
// be passed to endpoint Join method.
|
|
|
|
func JoinOptionDNSSearch(search string) EndpointOption {
|
|
|
|
return func(ep *endpoint) {
|
|
|
|
ep.container.config.dnsSearchList = append(ep.container.config.dnsSearchList, search)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-05 04:20:45 +00:00
|
|
|
// JoinOptionUseDefaultSandbox function returns an option setter for using default sandbox to
|
|
|
|
// be passed to endpoint Join method.
|
|
|
|
func JoinOptionUseDefaultSandbox() EndpointOption {
|
|
|
|
return func(ep *endpoint) {
|
|
|
|
ep.container.config.useDefaultSandBox = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-05 13:46:12 -07:00
|
|
|
// CreateOptionExposedPorts function returns an option setter for the container exposed
|
|
|
|
// ports option to be passed to network.CreateEndpoint() method.
|
|
|
|
func CreateOptionExposedPorts(exposedPorts []netutils.TransportPort) EndpointOption {
|
|
|
|
return func(ep *endpoint) {
|
|
|
|
// Defensive copy
|
|
|
|
eps := make([]netutils.TransportPort, len(exposedPorts))
|
|
|
|
copy(eps, exposedPorts)
|
|
|
|
// Store endpoint label and in generic because driver needs it
|
|
|
|
ep.exposedPorts = eps
|
2015-05-06 04:19:57 +00:00
|
|
|
ep.generic[netlabel.ExposedPorts] = eps
|
2015-05-05 13:46:12 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// CreateOptionPortMapping function returns an option setter for the mapping
|
2015-05-01 17:11:13 -07:00
|
|
|
// ports option to be passed to network.CreateEndpoint() method.
|
2015-05-01 17:01:21 -07:00
|
|
|
func CreateOptionPortMapping(portBindings []netutils.PortBinding) EndpointOption {
|
|
|
|
return func(ep *endpoint) {
|
2015-05-04 23:45:07 -07:00
|
|
|
// Store a copy of the bindings as generic data to pass to the driver
|
2015-05-05 13:46:12 -07:00
|
|
|
pbs := make([]netutils.PortBinding, len(portBindings))
|
|
|
|
copy(pbs, portBindings)
|
2015-05-06 04:19:57 +00:00
|
|
|
ep.generic[netlabel.PortMap] = pbs
|
2015-05-01 17:01:21 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-30 14:52:46 -07:00
|
|
|
// JoinOptionGeneric function returns an option setter for Generic configuration
|
|
|
|
// that is not managed by libNetwork but can be used by the Drivers during the call to
|
|
|
|
// endpoint join method. Container Labels are a good example.
|
2015-05-01 17:11:13 -07:00
|
|
|
func JoinOptionGeneric(generic map[string]interface{}) EndpointOption {
|
2015-04-30 14:52:46 -07:00
|
|
|
return func(ep *endpoint) {
|
2015-05-01 17:01:21 -07:00
|
|
|
ep.container.config.generic = generic
|
2015-04-30 14:52:46 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// LeaveOptionGeneric function returns an option setter for Generic configuration
|
|
|
|
// that is not managed by libNetwork but can be used by the Drivers during the call to
|
|
|
|
// endpoint leave method. Container Labels are a good example.
|
2015-05-01 17:11:13 -07:00
|
|
|
func LeaveOptionGeneric(context map[string]interface{}) EndpointOption {
|
2015-04-30 14:52:46 -07:00
|
|
|
return func(ep *endpoint) {
|
|
|
|
ep.context = context
|
|
|
|
}
|
|
|
|
}
|