github.com/guilhermebr/docker@v1.4.2-0.20150428121140-67da055cebca/daemon/execdriver/native/create.go (about)

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