github.com/iamlotus/docker@v1.8.1/daemon/execdriver/lxc/lxc_template.go (about)

     1  // +build linux
     2  
     3  package lxc
     4  
     5  import (
     6  	"fmt"
     7  	"os"
     8  	"strings"
     9  	"text/template"
    10  
    11  	"github.com/Sirupsen/logrus"
    12  	"github.com/docker/docker/daemon/execdriver"
    13  	nativeTemplate "github.com/docker/docker/daemon/execdriver/native/template"
    14  	"github.com/docker/docker/pkg/stringutils"
    15  	"github.com/opencontainers/runc/libcontainer/label"
    16  )
    17  
    18  const LxcTemplate = `
    19  lxc.network.type = none
    20  # root filesystem
    21  {{$ROOTFS := .Rootfs}}
    22  lxc.rootfs = {{$ROOTFS}}
    23  
    24  # use a dedicated pts for the container (and limit the number of pseudo terminal
    25  # available)
    26  lxc.pts = 1024
    27  
    28  # disable the main console
    29  lxc.console = none
    30  
    31  # no controlling tty at all
    32  lxc.tty = 1
    33  
    34  {{if .ProcessConfig.Privileged}}
    35  lxc.cgroup.devices.allow = a
    36  {{else}}
    37  # no implicit access to devices
    38  lxc.cgroup.devices.deny = a
    39  #Allow the devices passed to us in the AllowedDevices list.
    40  {{range $allowedDevice := .AllowedDevices}}
    41  lxc.cgroup.devices.allow = {{$allowedDevice.CgroupString}}
    42  {{end}}
    43  {{end}}
    44  
    45  # standard mount point
    46  # Use mnt.putold as per https://bugs.launchpad.net/ubuntu/+source/lxc/+bug/986385
    47  lxc.pivotdir = lxc_putold
    48  
    49  # lxc.autodev is not compatible with lxc --device switch
    50  lxc.autodev = 0
    51  
    52  # NOTICE: These mounts must be applied within the namespace
    53  {{if .ProcessConfig.Privileged}}
    54  # WARNING: mounting procfs and/or sysfs read-write is a known attack vector.
    55  # See e.g. http://blog.zx2c4.com/749 and https://bit.ly/T9CkqJ
    56  # We mount them read-write here, but later, dockerinit will call the Restrict() function to remount them read-only.
    57  # We cannot mount them directly read-only, because that would prevent loading AppArmor profiles.
    58  lxc.mount.entry = proc {{escapeFstabSpaces $ROOTFS}}/proc proc nosuid,nodev,noexec 0 0
    59  lxc.mount.entry = sysfs {{escapeFstabSpaces $ROOTFS}}/sys sysfs nosuid,nodev,noexec 0 0
    60  	{{if .AppArmor}}
    61  lxc.aa_profile = unconfined
    62  	{{end}}
    63  {{else}}
    64  # In non-privileged mode, lxc will automatically mount /proc and /sys in readonly mode
    65  # for security. See: http://man7.org/linux/man-pages/man5/lxc.container.conf.5.html
    66  lxc.mount.auto = proc sys
    67  	{{if .AppArmorProfile}}
    68  lxc.aa_profile = {{.AppArmorProfile}}
    69  	{{end}}
    70  {{end}}
    71  
    72  {{if .ProcessConfig.Tty}}
    73  lxc.mount.entry = {{.ProcessConfig.Console}} {{escapeFstabSpaces $ROOTFS}}/dev/console none bind,rw,create=file 0 0
    74  {{end}}
    75  
    76  lxc.mount.entry = devpts {{escapeFstabSpaces $ROOTFS}}/dev/pts devpts {{formatMountLabel "newinstance,ptmxmode=0666,nosuid,noexec,create=dir" ""}} 0 0
    77  lxc.mount.entry = shm {{escapeFstabSpaces $ROOTFS}}/dev/shm tmpfs {{formatMountLabel "size=65536k,nosuid,nodev,noexec,create=dir" ""}} 0 0
    78  
    79  {{range $value := .Mounts}}
    80  {{$createVal := isDirectory $value.Source}}
    81  {{if $value.Writable}}
    82  lxc.mount.entry = {{$value.Source}} {{escapeFstabSpaces $ROOTFS}}/{{escapeFstabSpaces $value.Destination}} none rbind,rw,create={{$createVal}} 0 0
    83  {{else}}
    84  lxc.mount.entry = {{$value.Source}} {{escapeFstabSpaces $ROOTFS}}/{{escapeFstabSpaces $value.Destination}} none rbind,ro,create={{$createVal}} 0 0
    85  {{end}}
    86  {{end}}
    87  
    88  # limits
    89  {{if .Resources}}
    90  {{if .Resources.Memory}}
    91  lxc.cgroup.memory.limit_in_bytes = {{.Resources.Memory}}
    92  lxc.cgroup.memory.soft_limit_in_bytes = {{.Resources.Memory}}
    93  {{with $memSwap := getMemorySwap .Resources}}
    94  lxc.cgroup.memory.memsw.limit_in_bytes = {{$memSwap}}
    95  {{end}}
    96  {{end}}
    97  {{if .Resources.CpuShares}}
    98  lxc.cgroup.cpu.shares = {{.Resources.CpuShares}}
    99  {{end}}
   100  {{if .Resources.CpuPeriod}}
   101  lxc.cgroup.cpu.cfs_period_us = {{.Resources.CpuPeriod}}
   102  {{end}}
   103  {{if .Resources.CpusetCpus}}
   104  lxc.cgroup.cpuset.cpus = {{.Resources.CpusetCpus}}
   105  {{end}}
   106  {{if .Resources.CpusetMems}}
   107  lxc.cgroup.cpuset.mems = {{.Resources.CpusetMems}}
   108  {{end}}
   109  {{if .Resources.CpuQuota}}
   110  lxc.cgroup.cpu.cfs_quota_us = {{.Resources.CpuQuota}}
   111  {{end}}
   112  {{if .Resources.BlkioWeight}}
   113  lxc.cgroup.blkio.weight = {{.Resources.BlkioWeight}}
   114  {{end}}
   115  {{if .Resources.OomKillDisable}}
   116  lxc.cgroup.memory.oom_control = {{.Resources.OomKillDisable}}
   117  {{end}}
   118  {{if gt .Resources.MemorySwappiness 0}}
   119  lxc.cgroup.memory.swappiness = {{.Resources.MemorySwappiness}}
   120  {{end}}
   121  {{end}}
   122  
   123  {{if .LxcConfig}}
   124  {{range $value := .LxcConfig}}
   125  lxc.{{$value}}
   126  {{end}}
   127  {{end}}
   128  
   129  {{if .Network.Interface}}
   130  {{if .Network.Interface.IPAddress}}
   131  lxc.network.ipv4 = {{.Network.Interface.IPAddress}}/{{.Network.Interface.IPPrefixLen}}
   132  {{end}}
   133  {{if .Network.Interface.Gateway}}
   134  lxc.network.ipv4.gateway = {{.Network.Interface.Gateway}}
   135  {{end}}
   136  {{if .Network.Interface.MacAddress}}
   137  lxc.network.hwaddr = {{.Network.Interface.MacAddress}}
   138  {{end}}
   139  {{end}}
   140  {{if .ProcessConfig.Env}}
   141  lxc.utsname = {{getHostname .ProcessConfig.Env}}
   142  {{end}}
   143  
   144  {{if .ProcessConfig.Privileged}}
   145  # No cap values are needed, as lxc is starting in privileged mode
   146  {{else}}
   147  	{{ with keepCapabilities .CapAdd .CapDrop }}
   148  		{{range .}}
   149  lxc.cap.keep = {{.}}
   150  		{{end}}
   151  	{{else}}
   152  		{{ with dropList .CapDrop }}
   153  		{{range .}}
   154  lxc.cap.drop = {{.}}
   155  		{{end}}
   156  		{{end}}
   157  	{{end}}
   158  {{end}}
   159  `
   160  
   161  var LxcTemplateCompiled *template.Template
   162  
   163  // Escape spaces in strings according to the fstab documentation, which is the
   164  // format for "lxc.mount.entry" lines in lxc.conf. See also "man 5 fstab".
   165  func escapeFstabSpaces(field string) string {
   166  	return strings.Replace(field, " ", "\\040", -1)
   167  }
   168  
   169  func keepCapabilities(adds []string, drops []string) ([]string, error) {
   170  	container := nativeTemplate.New()
   171  	logrus.Debugf("adds %s drops %s\n", adds, drops)
   172  	caps, err := execdriver.TweakCapabilities(container.Capabilities, adds, drops)
   173  	if err != nil {
   174  		return nil, err
   175  	}
   176  	var newCaps []string
   177  	for _, cap := range caps {
   178  		logrus.Debugf("cap %s\n", cap)
   179  		realCap := execdriver.GetCapability(cap)
   180  		numCap := fmt.Sprintf("%d", realCap.Value)
   181  		newCaps = append(newCaps, numCap)
   182  	}
   183  
   184  	return newCaps, nil
   185  }
   186  
   187  func dropList(drops []string) ([]string, error) {
   188  	if stringutils.InSlice(drops, "all") {
   189  		var newCaps []string
   190  		for _, capName := range execdriver.GetAllCapabilities() {
   191  			cap := execdriver.GetCapability(capName)
   192  			logrus.Debugf("drop cap %s\n", cap.Key)
   193  			numCap := fmt.Sprintf("%d", cap.Value)
   194  			newCaps = append(newCaps, numCap)
   195  		}
   196  		return newCaps, nil
   197  	}
   198  	return []string{}, nil
   199  }
   200  
   201  func isDirectory(source string) string {
   202  	f, err := os.Stat(source)
   203  	logrus.Debugf("dir: %s\n", source)
   204  	if err != nil {
   205  		if os.IsNotExist(err) {
   206  			return "dir"
   207  		}
   208  		return ""
   209  	}
   210  	if f.IsDir() {
   211  		return "dir"
   212  	}
   213  	return "file"
   214  }
   215  
   216  func getMemorySwap(v *execdriver.Resources) int64 {
   217  	// By default, MemorySwap is set to twice the size of RAM.
   218  	// If you want to omit MemorySwap, set it to `-1'.
   219  	if v.MemorySwap < 0 {
   220  		return 0
   221  	}
   222  	return v.Memory * 2
   223  }
   224  
   225  func getLabel(c map[string][]string, name string) string {
   226  	label := c["label"]
   227  	for _, l := range label {
   228  		parts := strings.SplitN(l, "=", 2)
   229  		if strings.TrimSpace(parts[0]) == name {
   230  			return strings.TrimSpace(parts[1])
   231  		}
   232  	}
   233  	return ""
   234  }
   235  
   236  func getHostname(env []string) string {
   237  	for _, kv := range env {
   238  		parts := strings.SplitN(kv, "=", 2)
   239  		if parts[0] == "HOSTNAME" && len(parts) == 2 {
   240  			return parts[1]
   241  		}
   242  	}
   243  	return ""
   244  }
   245  
   246  func init() {
   247  	var err error
   248  	funcMap := template.FuncMap{
   249  		"getMemorySwap":     getMemorySwap,
   250  		"escapeFstabSpaces": escapeFstabSpaces,
   251  		"formatMountLabel":  label.FormatMountLabel,
   252  		"isDirectory":       isDirectory,
   253  		"keepCapabilities":  keepCapabilities,
   254  		"dropList":          dropList,
   255  		"getHostname":       getHostname,
   256  	}
   257  	LxcTemplateCompiled, err = template.New("lxc").Funcs(funcMap).Parse(LxcTemplate)
   258  	if err != nil {
   259  		panic(err)
   260  	}
   261  }