Browse Source

Move lxc template into lxc driver

Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)
Michael Crosby 11 năm trước cách đây
mục cha
commit
70a5cb95b3

+ 6 - 1
cgroups/cgroups.go

@@ -12,8 +12,13 @@ import (
 	"strings"
 )
 
-// https://www.kernel.org/doc/Documentation/cgroups/cgroups.txt
+type Values struct {
+	Memory     int64 `json:"memory"`
+	MemorySwap int64 `json:"memory_swap"`
+	CpuShares  int64 `json:"cpu_shares"`
+}
 
+// https://www.kernel.org/doc/Documentation/cgroups/cgroups.txt
 func FindCgroupMountpoint(subsystem string) (string, error) {
 	mounts, err := mount.GetMounts()
 	if err != nil {

+ 20 - 19
container.go

@@ -5,6 +5,7 @@ import (
 	"errors"
 	"fmt"
 	"github.com/dotcloud/docker/archive"
+	"github.com/dotcloud/docker/cgroups"
 	"github.com/dotcloud/docker/execdriver"
 	"github.com/dotcloud/docker/graphdriver"
 	"github.com/dotcloud/docker/mount"
@@ -299,15 +300,6 @@ func (container *Container) generateEnvConfig(env []string) error {
 	return nil
 }
 
-func (container *Container) generateLXCConfig() error {
-	fo, err := os.Create(container.lxcConfigPath())
-	if err != nil {
-		return err
-	}
-	defer fo.Close()
-	return LxcTemplateCompiled.Execute(fo, container)
-}
-
 func (container *Container) setupPty() error {
 	ptyMaster, ptySlave, err := pty.Open()
 	if err != nil {
@@ -554,10 +546,6 @@ func (container *Container) Start() (err error) {
 		return err
 	}
 
-	if err := container.generateLXCConfig(); err != nil {
-		return err
-	}
-
 	// Setup environment
 	env := []string{
 		"HOME=/",
@@ -662,17 +650,33 @@ func (container *Container) Start() (err error) {
 		}
 	}
 
-	var en *execdriver.Network
+	var (
+		en           *execdriver.Network
+		driverConfig []string
+	)
+
 	if !container.Config.NetworkDisabled {
 		network := container.NetworkSettings
 		en = &execdriver.Network{
 			Gateway:     network.Gateway,
+			Bridge:      network.Bridge,
 			IPAddress:   network.IPAddress,
 			IPPrefixLen: network.IPPrefixLen,
 			Mtu:         container.runtime.config.Mtu,
 		}
 	}
 
+	if lxcConf := container.hostConfig.LxcConf; lxcConf != nil {
+		for _, pair := range lxcConf {
+			driverConfig = append(driverConfig, fmt.Sprintf("%s = %s", pair.Key, pair.Value))
+		}
+	}
+	cgroupValues := &cgroups.Values{
+		Memory:     container.Config.Memory,
+		MemorySwap: container.Config.MemorySwap,
+		CpuShares:  container.Config.CpuShares,
+	}
+
 	container.process = &execdriver.Process{
 		ID:         container.ID,
 		Privileged: container.hostConfig.Privileged,
@@ -681,10 +685,11 @@ func (container *Container) Start() (err error) {
 		Entrypoint: container.Path,
 		Arguments:  container.Args,
 		WorkingDir: workingDir,
-		ConfigPath: container.lxcConfigPath(),
 		Network:    en,
 		Tty:        container.Config.Tty,
 		User:       container.Config.User,
+		Config:     driverConfig,
+		Cgroups:    cgroupValues,
 	}
 	container.process.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
 
@@ -1381,10 +1386,6 @@ func (container *Container) EnvConfigPath() (string, error) {
 	return p, nil
 }
 
-func (container *Container) lxcConfigPath() string {
-	return path.Join(container.root, "config.lxc")
-}
-
 // This method must be exported to be used from the lxc template
 func (container *Container) RootfsPath() string {
 	return container.rootfs

+ 15 - 11
execdriver/driver.go

@@ -2,6 +2,7 @@ package execdriver
 
 import (
 	"errors"
+	"github.com/dotcloud/docker/cgroups"
 	"os/exec"
 	"syscall"
 )
@@ -71,6 +72,7 @@ type Driver interface {
 type Network struct {
 	Gateway     string `json:"gateway"`
 	IPAddress   string `json:"ip"`
+	Bridge      string `json:"bridge"`
 	IPPrefixLen int    `json:"ip_prefix_len"`
 	Mtu         int    `json:"mtu"`
 }
@@ -79,17 +81,19 @@ type Network struct {
 type Process struct {
 	exec.Cmd
 
-	ID         string   `json:"id"`
-	Privileged bool     `json:"privileged"`
-	User       string   `json:"user"`
-	Rootfs     string   `json:"rootfs"`   // root fs of the container
-	InitPath   string   `json:"initpath"` // dockerinit
-	Entrypoint string   `json:"entrypoint"`
-	Arguments  []string `json:"arguments"`
-	WorkingDir string   `json:"working_dir"`
-	ConfigPath string   `json:"config_path"` // This should be able to be removed when the lxc template is moved into the driver
-	Tty        bool     `json:"tty"`
-	Network    *Network `json:"network"` // if network is nil then networking is disabled
+	ID         string          `json:"id"`
+	Privileged bool            `json:"privileged"`
+	User       string          `json:"user"`
+	Rootfs     string          `json:"rootfs"`   // root fs of the container
+	InitPath   string          `json:"initpath"` // dockerinit
+	Entrypoint string          `json:"entrypoint"`
+	Arguments  []string        `json:"arguments"`
+	WorkingDir string          `json:"working_dir"`
+	ConfigPath string          `json:"config_path"` // This should be able to be removed when the lxc template is moved into the driver
+	Tty        bool            `json:"tty"`
+	Network    *Network        `json:"network"` // if network is nil then networking is disabled
+	Config     []string        `json:"config"`
+	Cgroups    *cgroups.Values `json:"cgroups"`
 }
 
 // Return the pid of the process

+ 25 - 2
execdriver/lxc/driver.go

@@ -72,10 +72,14 @@ func (d *driver) Name() string {
 }
 
 func (d *driver) Run(c *execdriver.Process, startCallback execdriver.StartCallback) (int, error) {
+	configPath, err := d.generateLXCConfig(c)
+	if err != nil {
+		return -1, err
+	}
 	params := []string{
 		"lxc-start",
 		"-n", c.ID,
-		"-f", c.ConfigPath,
+		"-f", configPath,
 		"--",
 		c.InitPath,
 		"-driver",
@@ -259,7 +263,6 @@ func (i *info) IsRunning() bool {
 }
 
 func (d *driver) Info(id string) execdriver.Info {
-
 	return &info{
 		ID:     id,
 		driver: d,
@@ -297,3 +300,23 @@ func rootIsShared() bool {
 	// No idea, probably safe to assume so
 	return true
 }
+
+func (d *driver) generateLXCConfig(p *execdriver.Process) (string, error) {
+	root := path.Join(d.root, "containers", p.ID, "config.lxc")
+	fo, err := os.Create(root)
+	if err != nil {
+		return "", err
+	}
+	defer fo.Close()
+
+	if err := LxcTemplateCompiled.Execute(fo, struct {
+		*execdriver.Process
+		AppArmor bool
+	}{
+		Process:  p,
+		AppArmor: d.apparmor,
+	}); err != nil {
+		return "", err
+	}
+	return root, nil
+}

+ 25 - 33
lxc_template.go → execdriver/lxc/lxc_template.go

@@ -1,24 +1,24 @@
-package docker
+package lxc
 
 import (
-	"github.com/dotcloud/docker/pkg/sysinfo"
+	"github.com/dotcloud/docker/cgroups"
 	"strings"
 	"text/template"
 )
 
 const LxcTemplate = `
-{{if .Config.NetworkDisabled}}
-# network is disabled (-n=false)
-lxc.network.type = empty
-{{else}}
+{{if .Network}}
 # network configuration
 lxc.network.type = veth
-lxc.network.link = {{.NetworkSettings.Bridge}}
+lxc.network.link = {{.Network.Bridge}}
 lxc.network.name = eth0
+{{else}}
+# network is disabled (-n=false)
+lxc.network.type = empty
 {{end}}
 
 # root filesystem
-{{$ROOTFS := .RootfsPath}}
+{{$ROOTFS := .Rootfs}}
 lxc.rootfs = {{$ROOTFS}}
 
 # use a dedicated pts for the container (and limit the number of pseudo terminal
@@ -31,7 +31,7 @@ lxc.console = none
 # no controlling tty at all
 lxc.tty = 1
 
-{{if (getHostConfig .).Privileged}}
+{{if .Privileged}}
 lxc.cgroup.devices.allow = a
 {{else}}
 # no implicit access to devices
@@ -82,8 +82,8 @@ lxc.mount.entry = sysfs {{escapeFstabSpaces $ROOTFS}}/sys sysfs nosuid,nodev,noe
 lxc.mount.entry = devpts {{escapeFstabSpaces $ROOTFS}}/dev/pts devpts newinstance,ptmxmode=0666,nosuid,noexec 0 0
 lxc.mount.entry = shm {{escapeFstabSpaces $ROOTFS}}/dev/shm tmpfs size=65536k,nosuid,nodev,noexec 0 0
 
-{{if (getHostConfig .).Privileged}}
-{{if (getSysInfo .).AppArmor}}
+{{if .Privileged}}
+{{if .AppArmor}}
 lxc.aa_profile = unconfined
 {{else}}
 #lxc.aa_profile = unconfined
@@ -91,20 +91,22 @@ lxc.aa_profile = unconfined
 {{end}}
 
 # limits
-{{if .Config.Memory}}
-lxc.cgroup.memory.limit_in_bytes = {{.Config.Memory}}
-lxc.cgroup.memory.soft_limit_in_bytes = {{.Config.Memory}}
-{{with $memSwap := getMemorySwap .Config}}
+{{if .Cgroups}}
+{{if .Cgroups.Memory}}
+lxc.cgroup.memory.limit_in_bytes = {{.Cgroups.Memory}}
+lxc.cgroup.memory.soft_limit_in_bytes = {{.Cgroups.Memory}}
+{{with $memSwap := getMemorySwap .Cgroups}}
 lxc.cgroup.memory.memsw.limit_in_bytes = {{$memSwap}}
 {{end}}
 {{end}}
-{{if .Config.CpuShares}}
-lxc.cgroup.cpu.shares = {{.Config.CpuShares}}
+{{if .Cgroups.CpuShares}}
+lxc.cgroup.cpu.shares = {{.Cgroups.CpuShares}}
+{{end}}
 {{end}}
 
-{{if (getHostConfig .).LxcConf}}
-{{range $pair := (getHostConfig .).LxcConf}}
-{{$pair.Key}} = {{$pair.Value}}
+{{if .Config}}
+{{range $value := .Config}}
+{{$value}}
 {{end}}
 {{end}}
 `
@@ -117,29 +119,19 @@ func escapeFstabSpaces(field string) string {
 	return strings.Replace(field, " ", "\\040", -1)
 }
 
-func getMemorySwap(config *Config) int64 {
+func getMemorySwap(v *cgroups.Values) int64 {
 	// By default, MemorySwap is set to twice the size of RAM.
 	// If you want to omit MemorySwap, set it to `-1'.
-	if config.MemorySwap < 0 {
+	if v.MemorySwap < 0 {
 		return 0
 	}
-	return config.Memory * 2
-}
-
-func getHostConfig(container *Container) *HostConfig {
-	return container.hostConfig
-}
-
-func getSysInfo(container *Container) *sysinfo.SysInfo {
-	return container.runtime.sysInfo
+	return v.Memory * 2
 }
 
 func init() {
 	var err error
 	funcMap := template.FuncMap{
 		"getMemorySwap":     getMemorySwap,
-		"getHostConfig":     getHostConfig,
-		"getSysInfo":        getSysInfo,
 		"escapeFstabSpaces": escapeFstabSpaces,
 	}
 	LxcTemplateCompiled, err = template.New("lxc").Funcs(funcMap).Parse(LxcTemplate)

+ 49 - 41
lxc_template_unit_test.go → execdriver/lxc/lxc_template_unit_test.go

@@ -1,11 +1,14 @@
-package docker
+package lxc
 
 import (
 	"bufio"
 	"fmt"
+	"github.com/dotcloud/docker/cgroups"
+	"github.com/dotcloud/docker/execdriver"
 	"io/ioutil"
 	"math/rand"
 	"os"
+	"path"
 	"strings"
 	"testing"
 	"time"
@@ -17,32 +20,39 @@ func TestLXCConfig(t *testing.T) {
 		t.Fatal(err)
 	}
 	defer os.RemoveAll(root)
+
+	os.MkdirAll(path.Join(root, "containers", "1"), 0777)
+
 	// Memory is allocated randomly for testing
 	rand.Seed(time.Now().UTC().UnixNano())
-	memMin := 33554432
-	memMax := 536870912
-	mem := memMin + rand.Intn(memMax-memMin)
-	// CPU shares as well
-	cpuMin := 100
-	cpuMax := 10000
-	cpu := cpuMin + rand.Intn(cpuMax-cpuMin)
-	container := &Container{
-		root: root,
-		Config: &Config{
-			Memory:          int64(mem),
-			CpuShares:       int64(cpu),
-			NetworkDisabled: true,
-		},
-		hostConfig: &HostConfig{
-			Privileged: false,
+	var (
+		memMin = 33554432
+		memMax = 536870912
+		mem    = memMin + rand.Intn(memMax-memMin)
+		cpuMin = 100
+		cpuMax = 10000
+		cpu    = cpuMin + rand.Intn(cpuMax-cpuMin)
+	)
+
+	driver, err := NewDriver(root, false)
+	if err != nil {
+		t.Fatal(err)
+	}
+	process := &execdriver.Process{
+		ID: "1",
+		Cgroups: &cgroups.Values{
+			Memory:    int64(mem),
+			CpuShares: int64(cpu),
 		},
 	}
-	if err := container.generateLXCConfig(); err != nil {
+	p, err := driver.generateLXCConfig(process)
+	if err != nil {
 		t.Fatal(err)
 	}
-	grepFile(t, container.lxcConfigPath(),
+	grepFile(t, p,
 		fmt.Sprintf("lxc.cgroup.memory.limit_in_bytes = %d", mem))
-	grepFile(t, container.lxcConfigPath(),
+
+	grepFile(t, p,
 		fmt.Sprintf("lxc.cgroup.memory.memsw.limit_in_bytes = %d", mem*2))
 }
 
@@ -52,31 +62,29 @@ func TestCustomLxcConfig(t *testing.T) {
 		t.Fatal(err)
 	}
 	defer os.RemoveAll(root)
-	container := &Container{
-		root: root,
-		Config: &Config{
-			Hostname:        "foobar",
-			NetworkDisabled: true,
-		},
-		hostConfig: &HostConfig{
-			Privileged: false,
-			LxcConf: []KeyValuePair{
-				{
-					Key:   "lxc.utsname",
-					Value: "docker",
-				},
-				{
-					Key:   "lxc.cgroup.cpuset.cpus",
-					Value: "0,1",
-				},
-			},
+
+	os.MkdirAll(path.Join(root, "containers", "1"), 0777)
+
+	driver, err := NewDriver(root, false)
+	if err != nil {
+		t.Fatal(err)
+	}
+	process := &execdriver.Process{
+		ID:         "1",
+		Privileged: false,
+		Config: []string{
+			"lxc.utsname = docker",
+			"lxc.cgroup.cpuset.cpus = 0,1",
 		},
 	}
-	if err := container.generateLXCConfig(); err != nil {
+
+	p, err := driver.generateLXCConfig(process)
+	if err != nil {
 		t.Fatal(err)
 	}
-	grepFile(t, container.lxcConfigPath(), "lxc.utsname = docker")
-	grepFile(t, container.lxcConfigPath(), "lxc.cgroup.cpuset.cpus = 0,1")
+
+	grepFile(t, p, "lxc.utsname = docker")
+	grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1")
 }
 
 func grepFile(t *testing.T, path string, pattern string) {