1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

- Added Join option support

- Added basic /etc/hosts generation support in libnetwork

Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
This commit is contained in:
Jana Radhakrishnan 2015-04-30 05:58:12 +00:00
parent d684600cdf
commit b8f81862d0
3 changed files with 183 additions and 20 deletions

View file

@ -1,6 +1,10 @@
package libnetwork
import (
"os"
"path/filepath"
"github.com/docker/docker/pkg/etchosts"
"github.com/docker/libnetwork/sandbox"
"github.com/docker/libnetwork/types"
)
@ -19,7 +23,7 @@ type Endpoint interface {
// 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
Join(containerID string) (string, error)
Join(containerID string, options ...JoinOption) (*ContainerData, error)
// Leave removes the sandbox associated with container ID and detaches
// the network resources populated in the sandbox
@ -32,15 +36,38 @@ type Endpoint interface {
Delete() error
}
// ContainerData is a set of data returned when a container joins an endpoint.
type ContainerData struct {
SandboxKey string
HostsPath string
}
// JoinOption is a option setter function type used to pass varios options to
// endpoint Join method.
type JoinOption func(ep Endpoint)
type containerConfig struct {
Hostname string
Domainname string
}
type containerInfo struct {
ID string
Config containerConfig
Data ContainerData
}
type endpoint struct {
name string
id types.UUID
network *network
sandboxInfo *sandbox.Info
sandBox sandbox.Sandbox
containerID string
container *containerInfo
}
const prefix = "/var/lib/docker/network/files"
func (ep *endpoint) ID() string {
return string(ep.id)
}
@ -60,19 +87,69 @@ func (ep *endpoint) SandboxInfo() *sandbox.Info {
return ep.sandboxInfo.GetCopy()
}
func (ep *endpoint) Join(containerID string) (string, error) {
if containerID == "" {
return "", InvalidContainerIDError(containerID)
func createBasePath(dir string) error {
err := os.MkdirAll(dir, 0644)
if err != nil && !os.IsExist(err) {
return err
}
if ep.containerID != "" {
return "", ErrInvalidJoin
return nil
}
func createHostsFile(path string) error {
var f *os.File
dir, _ := filepath.Split(path)
err := createBasePath(dir)
if err != nil {
return err
}
f, err = os.Create(path)
if err == nil {
f.Close()
}
return err
}
func (ep *endpoint) Join(containerID string, options ...JoinOption) (*ContainerData, error) {
var err error
if containerID == "" {
return nil, InvalidContainerIDError(containerID)
}
if ep.container != nil {
return nil, ErrInvalidJoin
}
ep.container = &containerInfo{}
defer func() {
if err != nil {
ep.container = nil
}
}()
if options != nil {
ep.processOptions(options...)
}
ep.container.Data.HostsPath = prefix + "/" + containerID + "/hosts"
err = createHostsFile(ep.container.Data.HostsPath)
if err != nil {
return nil, err
}
err = ep.buildHostsFiles()
if err != nil {
return nil, err
}
sboxKey := sandbox.GenerateKey(containerID)
sb, err := ep.network.ctrlr.sandboxAdd(sboxKey)
if err != nil {
return "", err
return nil, err
}
defer func() {
if err != nil {
@ -85,32 +162,36 @@ func (ep *endpoint) Join(containerID string) (string, error) {
for _, i := range sinfo.Interfaces {
err = sb.AddInterface(i)
if err != nil {
return "", err
return nil, err
}
}
err = sb.SetGateway(sinfo.Gateway)
if err != nil {
return "", err
return nil, err
}
err = sb.SetGatewayIPv6(sinfo.GatewayIPv6)
if err != nil {
return "", err
return nil, err
}
}
ep.containerID = containerID
return sb.Key(), nil
ep.container.ID = containerID
ep.container.Data.SandboxKey = sb.Key()
cData := ep.container.Data
return &cData, nil
}
func (ep *endpoint) Leave(containerID string) error {
if ep.containerID == "" || containerID == "" || ep.containerID != containerID {
if ep.container == nil || ep.container.ID == "" ||
containerID == "" || ep.container.ID != containerID {
return InvalidContainerIDError(containerID)
}
ep.network.ctrlr.sandboxRm(sandbox.GenerateKey(containerID))
ep.containerID = ""
ep.container = nil
return nil
}
@ -138,3 +219,45 @@ func (ep *endpoint) Delete() error {
err = n.driver.DeleteEndpoint(n.id, ep.id)
return err
}
func (ep *endpoint) buildHostsFiles() error {
var extraContent []etchosts.Record
name := ep.container.Config.Hostname
if ep.container.Config.Domainname != "" {
name = name + "." + ep.container.Config.Domainname
}
IP := ""
if ep.sandboxInfo != nil && ep.sandboxInfo.Interfaces[0] != nil &&
ep.sandboxInfo.Interfaces[0].Address != nil {
IP = ep.sandboxInfo.Interfaces[0].Address.IP.String()
}
return etchosts.Build(ep.container.Data.HostsPath, IP, ep.container.Config.Hostname,
ep.container.Config.Domainname, extraContent)
}
// JoinOptionHostname function returns an option setter for hostname option to
// be passed to endpoint Join method.
func JoinOptionHostname(name string) JoinOption {
return func(e Endpoint) {
ep := e.(*endpoint)
ep.container.Config.Hostname = name
}
}
// JoinOptionDomainname function returns an option setter for domainname option to
// be passed to endpoint Join method.
func JoinOptionDomainname(name string) JoinOption {
return func(e Endpoint) {
ep := e.(*endpoint)
ep.container.Config.Domainname = name
}
}
func (ep *endpoint) processOptions(options ...JoinOption) {
for _, opt := range options {
opt(ep)
}
}

View file

@ -31,6 +31,38 @@ func createTestNetwork(networkType, networkName string, option options.Generic)
return network, nil
}
func TestNull(t *testing.T) {
network, err := createTestNetwork("null", "testnetwork", options.Generic{})
if err != nil {
t.Fatal(err)
}
ep, err := network.CreateEndpoint("testep", nil)
if err != nil {
t.Fatal(err)
}
_, err = ep.Join(containerID,
libnetwork.JoinOptionHostname("test"),
libnetwork.JoinOptionDomainname("docker.io"))
if err != nil {
t.Fatal(err)
}
err = ep.Leave(containerID)
if err != nil {
t.Fatal(err)
}
if err := ep.Delete(); err != nil {
t.Fatal(err)
}
if err := network.Delete(); err != nil {
t.Fatal(err)
}
}
func TestBridge(t *testing.T) {
defer netutils.SetupTestNetNS(t)()
ip, subnet, err := net.ParseCIDR("192.168.100.1/24")
@ -485,7 +517,9 @@ func TestEndpointJoin(t *testing.T) {
t.Fatal(err)
}
_, err = ep.Join(containerID)
_, err = ep.Join(containerID,
libnetwork.JoinOptionHostname("test"),
libnetwork.JoinOptionDomainname("docker.io"))
if err != nil {
t.Fatal(err)
}
@ -532,7 +566,10 @@ func TestEndpointMultipleJoins(t *testing.T) {
t.Fatal(err)
}
_, err = ep.Join(containerID)
_, err = ep.Join(containerID,
libnetwork.JoinOptionHostname("test"),
libnetwork.JoinOptionDomainname("docker.io"))
if err != nil {
t.Fatal(err)
}
@ -574,7 +611,10 @@ func TestEndpointInvalidLeave(t *testing.T) {
t.Fatalf("Failed for unexpected reason: %v", err)
}
_, err = ep.Join(containerID)
_, err = ep.Join(containerID,
libnetwork.JoinOptionHostname("test"),
libnetwork.JoinOptionDomainname("docker.io"))
if err != nil {
t.Fatal(err)
}

View file

@ -24,7 +24,7 @@ type networkNamespace struct {
sinfo *Info
}
func creatBasePath() {
func createBasePath() {
err := os.MkdirAll(prefix, 0644)
if err != nil && !os.IsExist(err) {
panic("Could not create net namespace path directory")
@ -87,7 +87,7 @@ func createNetworkNamespace(path string) (Sandbox, error) {
func createNamespaceFile(path string) (err error) {
var f *os.File
once.Do(creatBasePath)
once.Do(createBasePath)
if f, err = os.Create(path); err == nil {
f.Close()
}