github.com/fcwu/docker@v1.4.2-0.20150115145920-2a69ca89f0df/daemon/execdriver/lxc/lxc_template.go (about)

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