зеркало из https://github.com/microsoft/docker.git
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:
Родитель
9e9f4b925b
Коммит
70a5cb95b3
|
@ -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 {
|
||||
|
|
39
container.go
39
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
|
||||
|
|
|
@ -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) {
|
Загрузка…
Ссылка в новой задаче