mirror of
https://github.com/clearlinux/docker.git
synced 2026-10-04 15:58:39 +00:00
Docker integration with libnetwork
- Updated Dockerfile to satisfy libnetwork GOPATH requirements.
- Reworked daemon to allocate network resources using libnetwork.
- Reworked remove link code to also update network resources in libnetwork.
- Adjusted the exec driver command population to reflect libnetwork design.
- Adjusted the exec driver create command steps.
- Updated a few test cases to reflect the change in design.
- Removed the dns setup code from docker as resolv.conf is entirely managed
in libnetwork.
- Integrated with lxc exec driver.
Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
This commit is contained in:
@@ -72,6 +72,7 @@ type Network struct {
|
||||
Interface *NetworkInterface `json:"interface"` // if interface is nil then networking is disabled
|
||||
Mtu int `json:"mtu"`
|
||||
ContainerID string `json:"container_id"` // id of the container to join network.
|
||||
NamespacePath string `json:"namespace_path"`
|
||||
HostNetworking bool `json:"host_networking"`
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -30,6 +31,7 @@ import (
|
||||
"github.com/docker/libcontainer/system"
|
||||
"github.com/docker/libcontainer/user"
|
||||
"github.com/kr/pty"
|
||||
"github.com/vishvananda/netns"
|
||||
)
|
||||
|
||||
const DriverName = "lxc"
|
||||
@@ -80,6 +82,41 @@ func (d *driver) Name() string {
|
||||
return fmt.Sprintf("%s-%s", DriverName, version)
|
||||
}
|
||||
|
||||
func setupNetNs(nsPath string) (*os.Process, error) {
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
origns, err := netns.Get()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer origns.Close()
|
||||
|
||||
f, err := os.OpenFile(nsPath, os.O_RDONLY, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get network namespace %q: %v", nsPath, err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
nsFD := f.Fd()
|
||||
if err := netns.Set(netns.NsHandle(nsFD)); err != nil {
|
||||
return nil, fmt.Errorf("failed to set network namespace %q: %v", nsPath, err)
|
||||
}
|
||||
defer netns.Set(origns)
|
||||
|
||||
cmd := exec.Command("/bin/sh", "-c", "while true; do sleep 1; done")
|
||||
if err := cmd.Start(); err != nil {
|
||||
return nil, fmt.Errorf("failed to start netns process: %v", err)
|
||||
}
|
||||
|
||||
return cmd.Process, nil
|
||||
}
|
||||
|
||||
func killNetNsProc(proc *os.Process) {
|
||||
proc.Kill()
|
||||
proc.Wait()
|
||||
}
|
||||
|
||||
func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (execdriver.ExitStatus, error) {
|
||||
var (
|
||||
term execdriver.Terminal
|
||||
@@ -87,6 +124,10 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
|
||||
dataPath = d.containerDir(c.ID)
|
||||
)
|
||||
|
||||
if c.Network.NamespacePath == "" && c.Network.ContainerID == "" {
|
||||
return execdriver.ExitStatus{ExitCode: -1}, fmt.Errorf("empty namespace path for non-container network")
|
||||
}
|
||||
|
||||
container, err := d.createContainer(c)
|
||||
if err != nil {
|
||||
return execdriver.ExitStatus{ExitCode: -1}, err
|
||||
@@ -136,10 +177,20 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
|
||||
params = append(params, "-F")
|
||||
}
|
||||
|
||||
proc := &os.Process{}
|
||||
if c.Network.ContainerID != "" {
|
||||
params = append(params,
|
||||
"--share-net", c.Network.ContainerID,
|
||||
)
|
||||
} else {
|
||||
proc, err = setupNetNs(c.Network.NamespacePath)
|
||||
if err != nil {
|
||||
return execdriver.ExitStatus{ExitCode: -1}, err
|
||||
}
|
||||
|
||||
pidStr := fmt.Sprintf("%d", proc.Pid)
|
||||
params = append(params,
|
||||
"--share-net", pidStr)
|
||||
}
|
||||
if c.Ipc != nil {
|
||||
if c.Ipc.ContainerID != "" {
|
||||
@@ -157,15 +208,6 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
|
||||
"--",
|
||||
c.InitPath,
|
||||
)
|
||||
if c.Network.Interface != nil {
|
||||
params = append(params,
|
||||
"-g", c.Network.Interface.Gateway,
|
||||
"-i", fmt.Sprintf("%s/%d", c.Network.Interface.IPAddress, c.Network.Interface.IPPrefixLen),
|
||||
)
|
||||
}
|
||||
params = append(params,
|
||||
"-mtu", strconv.Itoa(c.Network.Mtu),
|
||||
)
|
||||
|
||||
if c.ProcessConfig.User != "" {
|
||||
params = append(params, "-u", c.ProcessConfig.User)
|
||||
@@ -214,10 +256,12 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
|
||||
c.ProcessConfig.Args = append([]string{name}, arg...)
|
||||
|
||||
if err := createDeviceNodes(c.Rootfs, c.AutoCreatedDevices); err != nil {
|
||||
killNetNsProc(proc)
|
||||
return execdriver.ExitStatus{ExitCode: -1}, err
|
||||
}
|
||||
|
||||
if err := c.ProcessConfig.Start(); err != nil {
|
||||
killNetNsProc(proc)
|
||||
return execdriver.ExitStatus{ExitCode: -1}, err
|
||||
}
|
||||
|
||||
@@ -245,8 +289,10 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
|
||||
// Poll lxc for RUNNING status
|
||||
pid, err := d.waitForStart(c, waitLock)
|
||||
if err != nil {
|
||||
killNetNsProc(proc)
|
||||
return terminate(err)
|
||||
}
|
||||
killNetNsProc(proc)
|
||||
|
||||
cgroupPaths, err := cgroupPaths(c.ID)
|
||||
if err != nil {
|
||||
|
||||
@@ -15,8 +15,7 @@ import (
|
||||
"github.com/docker/libcontainer/label"
|
||||
)
|
||||
|
||||
const LxcTemplate = `
|
||||
{{if .Network.Interface}}
|
||||
/* {{if .Network.Interface}}
|
||||
# network configuration
|
||||
lxc.network.type = veth
|
||||
lxc.network.link = {{.Network.Interface.Bridge}}
|
||||
@@ -30,8 +29,10 @@ lxc.network.type = none
|
||||
lxc.network.type = empty
|
||||
lxc.network.flags = up
|
||||
lxc.network.mtu = {{.Network.Mtu}}
|
||||
{{end}}
|
||||
{{end}} */
|
||||
|
||||
const LxcTemplate = `
|
||||
lxc.network.type = none
|
||||
# root filesystem
|
||||
{{$ROOTFS := .Rootfs}}
|
||||
lxc.rootfs = {{$ROOTFS}}
|
||||
@@ -145,6 +146,7 @@ lxc.network.ipv4.gateway = {{.Network.Interface.Gateway}}
|
||||
{{if .Network.Interface.MacAddress}}
|
||||
lxc.network.hwaddr = {{.Network.Interface.MacAddress}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{if .ProcessConfig.Env}}
|
||||
lxc.utsname = {{getHostname .ProcessConfig.Env}}
|
||||
{{end}}
|
||||
@@ -164,7 +166,6 @@ lxc.cap.drop = {{.}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
`
|
||||
|
||||
var LxcTemplateCompiled *template.Template
|
||||
|
||||
@@ -264,13 +264,8 @@ func TestCustomLxcConfigMisc(t *testing.T) {
|
||||
"lxc.cgroup.cpuset.cpus = 0,1",
|
||||
},
|
||||
Network: &execdriver.Network{
|
||||
Mtu: 1500,
|
||||
Interface: &execdriver.NetworkInterface{
|
||||
Gateway: "10.10.10.1",
|
||||
IPAddress: "10.10.10.10",
|
||||
IPPrefixLen: 24,
|
||||
Bridge: "docker0",
|
||||
},
|
||||
Mtu: 1500,
|
||||
Interface: nil,
|
||||
},
|
||||
ProcessConfig: processConfig,
|
||||
CapAdd: []string{"net_admin", "syslog"},
|
||||
@@ -282,13 +277,6 @@ func TestCustomLxcConfigMisc(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// network
|
||||
grepFile(t, p, "lxc.network.type = veth")
|
||||
grepFile(t, p, "lxc.network.link = docker0")
|
||||
grepFile(t, p, "lxc.network.name = eth0")
|
||||
grepFile(t, p, "lxc.network.ipv4 = 10.10.10.10/24")
|
||||
grepFile(t, p, "lxc.network.ipv4.gateway = 10.10.10.1")
|
||||
grepFile(t, p, "lxc.network.flags = up")
|
||||
grepFile(t, p, "lxc.aa_profile = lxc-container-default-with-nesting")
|
||||
// hostname
|
||||
grepFile(t, p, "lxc.utsname = testhost")
|
||||
@@ -329,13 +317,8 @@ func TestCustomLxcConfigMiscOverride(t *testing.T) {
|
||||
"lxc.network.ipv4 = 172.0.0.1",
|
||||
},
|
||||
Network: &execdriver.Network{
|
||||
Mtu: 1500,
|
||||
Interface: &execdriver.NetworkInterface{
|
||||
Gateway: "10.10.10.1",
|
||||
IPAddress: "10.10.10.10",
|
||||
IPPrefixLen: 24,
|
||||
Bridge: "docker0",
|
||||
},
|
||||
Mtu: 1500,
|
||||
Interface: nil,
|
||||
},
|
||||
ProcessConfig: processConfig,
|
||||
CapAdd: []string{"NET_ADMIN", "SYSLOG"},
|
||||
@@ -346,13 +329,6 @@ func TestCustomLxcConfigMiscOverride(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// network
|
||||
grepFile(t, p, "lxc.network.type = veth")
|
||||
grepFile(t, p, "lxc.network.link = docker0")
|
||||
grepFile(t, p, "lxc.network.name = eth0")
|
||||
grepFile(t, p, "lxc.network.ipv4 = 172.0.0.1")
|
||||
grepFile(t, p, "lxc.network.ipv4.gateway = 10.10.10.1")
|
||||
grepFile(t, p, "lxc.network.flags = up")
|
||||
|
||||
// hostname
|
||||
grepFile(t, p, "lxc.utsname = testhost")
|
||||
|
||||
@@ -89,40 +89,6 @@ func generateIfaceName() (string, error) {
|
||||
}
|
||||
|
||||
func (d *driver) createNetwork(container *configs.Config, c *execdriver.Command) error {
|
||||
if c.Network.HostNetworking {
|
||||
container.Namespaces.Remove(configs.NEWNET)
|
||||
return nil
|
||||
}
|
||||
|
||||
container.Networks = []*configs.Network{
|
||||
{
|
||||
Type: "loopback",
|
||||
},
|
||||
}
|
||||
|
||||
iName, err := generateIfaceName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if c.Network.Interface != nil {
|
||||
vethNetwork := configs.Network{
|
||||
Name: "eth0",
|
||||
HostInterfaceName: iName,
|
||||
Mtu: c.Network.Mtu,
|
||||
Address: fmt.Sprintf("%s/%d", c.Network.Interface.IPAddress, c.Network.Interface.IPPrefixLen),
|
||||
MacAddress: c.Network.Interface.MacAddress,
|
||||
Gateway: c.Network.Interface.Gateway,
|
||||
Type: "veth",
|
||||
Bridge: c.Network.Interface.Bridge,
|
||||
HairpinMode: c.Network.Interface.HairpinMode,
|
||||
}
|
||||
if c.Network.Interface.GlobalIPv6Address != "" {
|
||||
vethNetwork.IPv6Address = fmt.Sprintf("%s/%d", c.Network.Interface.GlobalIPv6Address, c.Network.Interface.GlobalIPv6PrefixLen)
|
||||
vethNetwork.IPv6Gateway = c.Network.Interface.IPv6Gateway
|
||||
}
|
||||
container.Networks = append(container.Networks, &vethNetwork)
|
||||
}
|
||||
|
||||
if c.Network.ContainerID != "" {
|
||||
d.Lock()
|
||||
active := d.activeContainers[c.Network.ContainerID]
|
||||
@@ -138,8 +104,14 @@ func (d *driver) createNetwork(container *configs.Config, c *execdriver.Command)
|
||||
}
|
||||
|
||||
container.Namespaces.Add(configs.NEWNET, state.NamespacePaths[configs.NEWNET])
|
||||
return nil
|
||||
}
|
||||
|
||||
if c.Network.NamespacePath == "" {
|
||||
return fmt.Errorf("network namespace path is empty")
|
||||
}
|
||||
|
||||
container.Namespaces.Add(configs.NEWNET, c.Network.NamespacePath)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user