Move lxc template into lxc driver

Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)
This commit is contained in:
Michael Crosby 2014-01-15 17:26:04 -08:00
Родитель 9e9f4b925b
Коммит 70a5cb95b3
6 изменённых файлов: 144 добавлений и 111 удалений

Просмотреть файл

@ -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 {

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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
}

Просмотреть файл

@ -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)

Просмотреть файл

@ -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,
},
}
if err := container.generateLXCConfig(); err != nil {
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)
}
grepFile(t, container.lxcConfigPath(),
process := &execdriver.Process{
ID: "1",
Cgroups: &cgroups.Values{
Memory: int64(mem),
CpuShares: int64(cpu),
},
}
p, err := driver.generateLXCConfig(process)
if err != nil {
t.Fatal(err)
}
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",
},
},
},
}
if err := container.generateLXCConfig(); err != nil {
os.MkdirAll(path.Join(root, "containers", "1"), 0777)
driver, err := NewDriver(root, false)
if err != nil {
t.Fatal(err)
}
grepFile(t, container.lxcConfigPath(), "lxc.utsname = docker")
grepFile(t, container.lxcConfigPath(), "lxc.cgroup.cpuset.cpus = 0,1")
process := &execdriver.Process{
ID: "1",
Privileged: false,
Config: []string{
"lxc.utsname = docker",
"lxc.cgroup.cpuset.cpus = 0,1",
},
}
p, err := driver.generateLXCConfig(process)
if err != nil {
t.Fatal(err)
}
grepFile(t, p, "lxc.utsname = docker")
grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1")
}
func grepFile(t *testing.T, path string, pattern string) {