github.com/ld86/docker@v1.7.1-rc3/daemon/execdriver/native/create.go (about)

     1  // +build linux,cgo
     2  
     3  package native
     4  
     5  import (
     6  	"errors"
     7  	"fmt"
     8  	"net"
     9  	"strings"
    10  	"syscall"
    11  
    12  	"github.com/docker/docker/daemon/execdriver"
    13  	"github.com/docker/libcontainer/apparmor"
    14  	"github.com/docker/libcontainer/configs"
    15  	"github.com/docker/libcontainer/devices"
    16  	"github.com/docker/libcontainer/utils"
    17  )
    18  
    19  // createContainer populates and configures the container type with the
    20  // data provided by the execdriver.Command
    21  func (d *driver) createContainer(c *execdriver.Command) (*configs.Config, error) {
    22  	container := execdriver.InitContainer(c)
    23  
    24  	if err := d.createIpc(container, c); err != nil {
    25  		return nil, err
    26  	}
    27  
    28  	if err := d.createPid(container, c); err != nil {
    29  		return nil, err
    30  	}
    31  
    32  	if err := d.createUTS(container, c); err != nil {
    33  		return nil, err
    34  	}
    35  
    36  	if err := d.createNetwork(container, c); err != nil {
    37  		return nil, err
    38  	}
    39  
    40  	if c.ProcessConfig.Privileged {
    41  		// clear readonly for /sys
    42  		for i := range container.Mounts {
    43  			if container.Mounts[i].Destination == "/sys" {
    44  				container.Mounts[i].Flags &= ^syscall.MS_RDONLY
    45  			}
    46  		}
    47  		container.ReadonlyPaths = nil
    48  		container.MaskPaths = nil
    49  		if err := d.setPrivileged(container); err != nil {
    50  			return nil, err
    51  		}
    52  	} else {
    53  		if err := d.setCapabilities(container, c); err != nil {
    54  			return nil, err
    55  		}
    56  	}
    57  
    58  	if c.AppArmorProfile != "" {
    59  		container.AppArmorProfile = c.AppArmorProfile
    60  	}
    61  
    62  	if err := execdriver.SetupCgroups(container, c); err != nil {
    63  		return nil, err
    64  	}
    65  
    66  	if err := d.setupMounts(container, c); err != nil {
    67  		return nil, err
    68  	}
    69  
    70  	d.setupLabels(container, c)
    71  	d.setupRlimits(container, c)
    72  	return container, nil
    73  }
    74  
    75  func generateIfaceName() (string, error) {
    76  	for i := 0; i < 10; i++ {
    77  		name, err := utils.GenerateRandomName("veth", 7)
    78  		if err != nil {
    79  			continue
    80  		}
    81  		if _, err := net.InterfaceByName(name); err != nil {
    82  			if strings.Contains(err.Error(), "no such") {
    83  				return name, nil
    84  			}
    85  			return "", err
    86  		}
    87  	}
    88  	return "", errors.New("Failed to find name for new interface")
    89  }
    90  
    91  func (d *driver) createNetwork(container *configs.Config, c *execdriver.Command) error {
    92  	if c.Network == nil {
    93  		return nil
    94  	}
    95  	if c.Network.ContainerID != "" {
    96  		d.Lock()
    97  		active := d.activeContainers[c.Network.ContainerID]
    98  		d.Unlock()
    99  
   100  		if active == nil {
   101  			return fmt.Errorf("%s is not a valid running container to join", c.Network.ContainerID)
   102  		}
   103  
   104  		state, err := active.State()
   105  		if err != nil {
   106  			return err
   107  		}
   108  
   109  		container.Namespaces.Add(configs.NEWNET, state.NamespacePaths[configs.NEWNET])
   110  		return nil
   111  	}
   112  
   113  	if c.Network.NamespacePath == "" {
   114  		return fmt.Errorf("network namespace path is empty")
   115  	}
   116  
   117  	container.Namespaces.Add(configs.NEWNET, c.Network.NamespacePath)
   118  	return nil
   119  }
   120  
   121  func (d *driver) createIpc(container *configs.Config, c *execdriver.Command) error {
   122  	if c.Ipc.HostIpc {
   123  		container.Namespaces.Remove(configs.NEWIPC)
   124  		return nil
   125  	}
   126  
   127  	if c.Ipc.ContainerID != "" {
   128  		d.Lock()
   129  		active := d.activeContainers[c.Ipc.ContainerID]
   130  		d.Unlock()
   131  
   132  		if active == nil {
   133  			return fmt.Errorf("%s is not a valid running container to join", c.Ipc.ContainerID)
   134  		}
   135  
   136  		state, err := active.State()
   137  		if err != nil {
   138  			return err
   139  		}
   140  		container.Namespaces.Add(configs.NEWIPC, state.NamespacePaths[configs.NEWIPC])
   141  	}
   142  
   143  	return nil
   144  }
   145  
   146  func (d *driver) createPid(container *configs.Config, c *execdriver.Command) error {
   147  	if c.Pid.HostPid {
   148  		container.Namespaces.Remove(configs.NEWPID)
   149  		return nil
   150  	}
   151  
   152  	return nil
   153  }
   154  
   155  func (d *driver) createUTS(container *configs.Config, c *execdriver.Command) error {
   156  	if c.UTS.HostUTS {
   157  		container.Namespaces.Remove(configs.NEWUTS)
   158  		container.Hostname = ""
   159  		return nil
   160  	}
   161  
   162  	return nil
   163  }
   164  
   165  func (d *driver) setPrivileged(container *configs.Config) (err error) {
   166  	container.Capabilities = execdriver.GetAllCapabilities()
   167  	container.Cgroups.AllowAllDevices = true
   168  
   169  	hostDevices, err := devices.HostDevices()
   170  	if err != nil {
   171  		return err
   172  	}
   173  	container.Devices = hostDevices
   174  
   175  	if apparmor.IsEnabled() {
   176  		container.AppArmorProfile = "unconfined"
   177  	}
   178  
   179  	return nil
   180  }
   181  
   182  func (d *driver) setCapabilities(container *configs.Config, c *execdriver.Command) (err error) {
   183  	container.Capabilities, err = execdriver.TweakCapabilities(container.Capabilities, c.CapAdd, c.CapDrop)
   184  	return err
   185  }
   186  
   187  func (d *driver) setupRlimits(container *configs.Config, c *execdriver.Command) {
   188  	if c.Resources == nil {
   189  		return
   190  	}
   191  
   192  	for _, rlimit := range c.Resources.Rlimits {
   193  		container.Rlimits = append(container.Rlimits, configs.Rlimit{
   194  			Type: rlimit.Type,
   195  			Hard: rlimit.Hard,
   196  			Soft: rlimit.Soft,
   197  		})
   198  	}
   199  }
   200  
   201  func (d *driver) setupMounts(container *configs.Config, c *execdriver.Command) error {
   202  	userMounts := make(map[string]struct{})
   203  	for _, m := range c.Mounts {
   204  		userMounts[m.Destination] = struct{}{}
   205  	}
   206  
   207  	// Filter out mounts that are overriden by user supplied mounts
   208  	var defaultMounts []*configs.Mount
   209  	_, mountDev := userMounts["/dev"]
   210  	for _, m := range container.Mounts {
   211  		if _, ok := userMounts[m.Destination]; !ok {
   212  			if mountDev && strings.HasPrefix(m.Destination, "/dev/") {
   213  				continue
   214  			}
   215  			defaultMounts = append(defaultMounts, m)
   216  		}
   217  	}
   218  	container.Mounts = defaultMounts
   219  
   220  	for _, m := range c.Mounts {
   221  		flags := syscall.MS_BIND | syscall.MS_REC
   222  		if !m.Writable {
   223  			flags |= syscall.MS_RDONLY
   224  		}
   225  		if m.Slave {
   226  			flags |= syscall.MS_SLAVE
   227  		}
   228  		container.Mounts = append(container.Mounts, &configs.Mount{
   229  			Source:      m.Source,
   230  			Destination: m.Destination,
   231  			Device:      "bind",
   232  			Flags:       flags,
   233  		})
   234  	}
   235  	return nil
   236  }
   237  
   238  func (d *driver) setupLabels(container *configs.Config, c *execdriver.Command) {
   239  	container.ProcessLabel = c.ProcessLabel
   240  	container.MountLabel = c.MountLabel
   241  }