github.com/codemac/docker@v1.2.1-0.20150518222241-6a18412d5b9c/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.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  			HairpinMode:       c.Network.Interface.HairpinMode,
   118  		}
   119  		if c.Network.Interface.GlobalIPv6Address != "" {
   120  			vethNetwork.IPv6Address = fmt.Sprintf("%s/%d", c.Network.Interface.GlobalIPv6Address, c.Network.Interface.GlobalIPv6PrefixLen)
   121  			vethNetwork.IPv6Gateway = c.Network.Interface.IPv6Gateway
   122  		}
   123  		container.Networks = append(container.Networks, &vethNetwork)
   124  	}
   125  
   126  	if c.Network.ContainerID != "" {
   127  		d.Lock()
   128  		active := d.activeContainers[c.Network.ContainerID]
   129  		d.Unlock()
   130  
   131  		if active == nil {
   132  			return fmt.Errorf("%s is not a valid running container to join", c.Network.ContainerID)
   133  		}
   134  
   135  		state, err := active.State()
   136  		if err != nil {
   137  			return err
   138  		}
   139  
   140  		container.Namespaces.Add(configs.NEWNET, state.NamespacePaths[configs.NEWNET])
   141  	}
   142  
   143  	return nil
   144  }
   145  
   146  func (d *driver) createIpc(container *configs.Config, c *execdriver.Command) error {
   147  	if c.Ipc.HostIpc {
   148  		container.Namespaces.Remove(configs.NEWIPC)
   149  		return nil
   150  	}
   151  
   152  	if c.Ipc.ContainerID != "" {
   153  		d.Lock()
   154  		active := d.activeContainers[c.Ipc.ContainerID]
   155  		d.Unlock()
   156  
   157  		if active == nil {
   158  			return fmt.Errorf("%s is not a valid running container to join", c.Ipc.ContainerID)
   159  		}
   160  
   161  		state, err := active.State()
   162  		if err != nil {
   163  			return err
   164  		}
   165  		container.Namespaces.Add(configs.NEWIPC, state.NamespacePaths[configs.NEWIPC])
   166  	}
   167  
   168  	return nil
   169  }
   170  
   171  func (d *driver) createPid(container *configs.Config, c *execdriver.Command) error {
   172  	if c.Pid.HostPid {
   173  		container.Namespaces.Remove(configs.NEWPID)
   174  		return nil
   175  	}
   176  
   177  	return nil
   178  }
   179  
   180  func (d *driver) createUTS(container *configs.Config, c *execdriver.Command) error {
   181  	if c.UTS.HostUTS {
   182  		container.Namespaces.Remove(configs.NEWUTS)
   183  		container.Hostname = ""
   184  		return nil
   185  	}
   186  
   187  	return nil
   188  }
   189  
   190  func (d *driver) setPrivileged(container *configs.Config) (err error) {
   191  	container.Capabilities = execdriver.GetAllCapabilities()
   192  	container.Cgroups.AllowAllDevices = true
   193  
   194  	hostDevices, err := devices.HostDevices()
   195  	if err != nil {
   196  		return err
   197  	}
   198  	container.Devices = hostDevices
   199  
   200  	if apparmor.IsEnabled() {
   201  		container.AppArmorProfile = "unconfined"
   202  	}
   203  
   204  	return nil
   205  }
   206  
   207  func (d *driver) setCapabilities(container *configs.Config, c *execdriver.Command) (err error) {
   208  	container.Capabilities, err = execdriver.TweakCapabilities(container.Capabilities, c.CapAdd, c.CapDrop)
   209  	return err
   210  }
   211  
   212  func (d *driver) setupRlimits(container *configs.Config, c *execdriver.Command) {
   213  	if c.Resources == nil {
   214  		return
   215  	}
   216  
   217  	for _, rlimit := range c.Resources.Rlimits {
   218  		container.Rlimits = append(container.Rlimits, configs.Rlimit{
   219  			Type: rlimit.Type,
   220  			Hard: rlimit.Hard,
   221  			Soft: rlimit.Soft,
   222  		})
   223  	}
   224  }
   225  
   226  func (d *driver) setupMounts(container *configs.Config, c *execdriver.Command) error {
   227  	userMounts := make(map[string]struct{})
   228  	for _, m := range c.Mounts {
   229  		userMounts[m.Destination] = struct{}{}
   230  	}
   231  
   232  	// Filter out mounts that are overriden by user supplied mounts
   233  	var defaultMounts []*configs.Mount
   234  	_, mountDev := userMounts["/dev"]
   235  	for _, m := range container.Mounts {
   236  		if _, ok := userMounts[m.Destination]; !ok {
   237  			if mountDev && strings.HasPrefix(m.Destination, "/dev/") {
   238  				continue
   239  			}
   240  			defaultMounts = append(defaultMounts, m)
   241  		}
   242  	}
   243  	container.Mounts = defaultMounts
   244  
   245  	for _, m := range c.Mounts {
   246  		flags := syscall.MS_BIND | syscall.MS_REC
   247  		if !m.Writable {
   248  			flags |= syscall.MS_RDONLY
   249  		}
   250  		if m.Slave {
   251  			flags |= syscall.MS_SLAVE
   252  		}
   253  		container.Mounts = append(container.Mounts, &configs.Mount{
   254  			Source:      m.Source,
   255  			Destination: m.Destination,
   256  			Device:      "bind",
   257  			Flags:       flags,
   258  		})
   259  	}
   260  	return nil
   261  }
   262  
   263  func (d *driver) setupLabels(container *configs.Config, c *execdriver.Command) {
   264  	container.ProcessLabel = c.ProcessLabel
   265  	container.MountLabel = c.MountLabel
   266  }