github.com/wulonghui/docker@v1.8.0-rc2/daemon/container_unix.go (about)

     1  // +build !windows
     2  
     3  package daemon
     4  
     5  import (
     6  	"fmt"
     7  	"io/ioutil"
     8  	"net"
     9  	"os"
    10  	"path"
    11  	"path/filepath"
    12  	"strconv"
    13  	"strings"
    14  	"syscall"
    15  	"time"
    16  
    17  	"github.com/Sirupsen/logrus"
    18  	"github.com/docker/docker/daemon/execdriver"
    19  	"github.com/docker/docker/daemon/network"
    20  	"github.com/docker/docker/links"
    21  	"github.com/docker/docker/pkg/archive"
    22  	"github.com/docker/docker/pkg/directory"
    23  	"github.com/docker/docker/pkg/ioutils"
    24  	"github.com/docker/docker/pkg/nat"
    25  	"github.com/docker/docker/pkg/stringid"
    26  	"github.com/docker/docker/pkg/system"
    27  	"github.com/docker/docker/pkg/ulimit"
    28  	"github.com/docker/docker/runconfig"
    29  	"github.com/docker/docker/utils"
    30  	"github.com/docker/libnetwork"
    31  	"github.com/docker/libnetwork/netlabel"
    32  	"github.com/docker/libnetwork/options"
    33  	"github.com/docker/libnetwork/types"
    34  	"github.com/opencontainers/runc/libcontainer/configs"
    35  	"github.com/opencontainers/runc/libcontainer/devices"
    36  )
    37  
    38  const DefaultPathEnv = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
    39  
    40  type Container struct {
    41  	CommonContainer
    42  
    43  	// Fields below here are platform specific.
    44  
    45  	AppArmorProfile string
    46  	activeLinks     map[string]*links.Link
    47  }
    48  
    49  func killProcessDirectly(container *Container) error {
    50  	if _, err := container.WaitStop(10 * time.Second); err != nil {
    51  		// Ensure that we don't kill ourselves
    52  		if pid := container.GetPid(); pid != 0 {
    53  			logrus.Infof("Container %s failed to exit within 10 seconds of kill - trying direct SIGKILL", stringid.TruncateID(container.ID))
    54  			if err := syscall.Kill(pid, 9); err != nil {
    55  				if err != syscall.ESRCH {
    56  					return err
    57  				}
    58  				logrus.Debugf("Cannot kill process (pid=%d) with signal 9: no such process.", pid)
    59  			}
    60  		}
    61  	}
    62  	return nil
    63  }
    64  
    65  func (container *Container) setupLinkedContainers() ([]string, error) {
    66  	var (
    67  		env    []string
    68  		daemon = container.daemon
    69  	)
    70  	children, err := daemon.Children(container.Name)
    71  	if err != nil {
    72  		return nil, err
    73  	}
    74  
    75  	if len(children) > 0 {
    76  		container.activeLinks = make(map[string]*links.Link, len(children))
    77  
    78  		// If we encounter an error make sure that we rollback any network
    79  		// config and iptables changes
    80  		rollback := func() {
    81  			for _, link := range container.activeLinks {
    82  				link.Disable()
    83  			}
    84  			container.activeLinks = nil
    85  		}
    86  
    87  		for linkAlias, child := range children {
    88  			if !child.IsRunning() {
    89  				return nil, fmt.Errorf("Cannot link to a non running container: %s AS %s", child.Name, linkAlias)
    90  			}
    91  
    92  			link, err := links.NewLink(
    93  				container.NetworkSettings.IPAddress,
    94  				child.NetworkSettings.IPAddress,
    95  				linkAlias,
    96  				child.Config.Env,
    97  				child.Config.ExposedPorts,
    98  			)
    99  
   100  			if err != nil {
   101  				rollback()
   102  				return nil, err
   103  			}
   104  
   105  			container.activeLinks[link.Alias()] = link
   106  			if err := link.Enable(); err != nil {
   107  				rollback()
   108  				return nil, err
   109  			}
   110  
   111  			for _, envVar := range link.ToEnv() {
   112  				env = append(env, envVar)
   113  			}
   114  		}
   115  	}
   116  	return env, nil
   117  }
   118  
   119  func (container *Container) createDaemonEnvironment(linkedEnv []string) []string {
   120  	// if a domain name was specified, append it to the hostname (see #7851)
   121  	fullHostname := container.Config.Hostname
   122  	if container.Config.Domainname != "" {
   123  		fullHostname = fmt.Sprintf("%s.%s", fullHostname, container.Config.Domainname)
   124  	}
   125  	// Setup environment
   126  	env := []string{
   127  		"PATH=" + DefaultPathEnv,
   128  		"HOSTNAME=" + fullHostname,
   129  		// Note: we don't set HOME here because it'll get autoset intelligently
   130  		// based on the value of USER inside dockerinit, but only if it isn't
   131  		// set already (ie, that can be overridden by setting HOME via -e or ENV
   132  		// in a Dockerfile).
   133  	}
   134  	if container.Config.Tty {
   135  		env = append(env, "TERM=xterm")
   136  	}
   137  	env = append(env, linkedEnv...)
   138  	// because the env on the container can override certain default values
   139  	// we need to replace the 'env' keys where they match and append anything
   140  	// else.
   141  	env = utils.ReplaceOrAppendEnvValues(env, container.Config.Env)
   142  
   143  	return env
   144  }
   145  
   146  func getDevicesFromPath(deviceMapping runconfig.DeviceMapping) (devs []*configs.Device, err error) {
   147  	device, err := devices.DeviceFromPath(deviceMapping.PathOnHost, deviceMapping.CgroupPermissions)
   148  	// if there was no error, return the device
   149  	if err == nil {
   150  		device.Path = deviceMapping.PathInContainer
   151  		return append(devs, device), nil
   152  	}
   153  
   154  	// if the device is not a device node
   155  	// try to see if it's a directory holding many devices
   156  	if err == devices.ErrNotADevice {
   157  
   158  		// check if it is a directory
   159  		if src, e := os.Stat(deviceMapping.PathOnHost); e == nil && src.IsDir() {
   160  
   161  			// mount the internal devices recursively
   162  			filepath.Walk(deviceMapping.PathOnHost, func(dpath string, f os.FileInfo, e error) error {
   163  				childDevice, e := devices.DeviceFromPath(dpath, deviceMapping.CgroupPermissions)
   164  				if e != nil {
   165  					// ignore the device
   166  					return nil
   167  				}
   168  
   169  				// add the device to userSpecified devices
   170  				childDevice.Path = strings.Replace(dpath, deviceMapping.PathOnHost, deviceMapping.PathInContainer, 1)
   171  				devs = append(devs, childDevice)
   172  
   173  				return nil
   174  			})
   175  		}
   176  	}
   177  
   178  	if len(devs) > 0 {
   179  		return devs, nil
   180  	}
   181  
   182  	return devs, fmt.Errorf("error gathering device information while adding custom device %q: %s", deviceMapping.PathOnHost, err)
   183  }
   184  
   185  func populateCommand(c *Container, env []string) error {
   186  	var en *execdriver.Network
   187  	if !c.Config.NetworkDisabled {
   188  		en = &execdriver.Network{
   189  			NamespacePath: c.NetworkSettings.SandboxKey,
   190  		}
   191  
   192  		parts := strings.SplitN(string(c.hostConfig.NetworkMode), ":", 2)
   193  		if parts[0] == "container" {
   194  			nc, err := c.getNetworkedContainer()
   195  			if err != nil {
   196  				return err
   197  			}
   198  			en.ContainerID = nc.ID
   199  		}
   200  	}
   201  
   202  	ipc := &execdriver.Ipc{}
   203  
   204  	if c.hostConfig.IpcMode.IsContainer() {
   205  		ic, err := c.getIpcContainer()
   206  		if err != nil {
   207  			return err
   208  		}
   209  		ipc.ContainerID = ic.ID
   210  	} else {
   211  		ipc.HostIpc = c.hostConfig.IpcMode.IsHost()
   212  	}
   213  
   214  	pid := &execdriver.Pid{}
   215  	pid.HostPid = c.hostConfig.PidMode.IsHost()
   216  
   217  	uts := &execdriver.UTS{
   218  		HostUTS: c.hostConfig.UTSMode.IsHost(),
   219  	}
   220  
   221  	// Build lists of devices allowed and created within the container.
   222  	var userSpecifiedDevices []*configs.Device
   223  	for _, deviceMapping := range c.hostConfig.Devices {
   224  		devs, err := getDevicesFromPath(deviceMapping)
   225  		if err != nil {
   226  			return err
   227  		}
   228  
   229  		userSpecifiedDevices = append(userSpecifiedDevices, devs...)
   230  	}
   231  
   232  	allowedDevices := mergeDevices(configs.DefaultAllowedDevices, userSpecifiedDevices)
   233  
   234  	autoCreatedDevices := mergeDevices(configs.DefaultAutoCreatedDevices, userSpecifiedDevices)
   235  
   236  	// TODO: this can be removed after lxc-conf is fully deprecated
   237  	lxcConfig, err := mergeLxcConfIntoOptions(c.hostConfig)
   238  	if err != nil {
   239  		return err
   240  	}
   241  
   242  	var rlimits []*ulimit.Rlimit
   243  	ulimits := c.hostConfig.Ulimits
   244  
   245  	// Merge ulimits with daemon defaults
   246  	ulIdx := make(map[string]*ulimit.Ulimit)
   247  	for _, ul := range ulimits {
   248  		ulIdx[ul.Name] = ul
   249  	}
   250  	for name, ul := range c.daemon.config.Ulimits {
   251  		if _, exists := ulIdx[name]; !exists {
   252  			ulimits = append(ulimits, ul)
   253  		}
   254  	}
   255  
   256  	for _, limit := range ulimits {
   257  		rl, err := limit.GetRlimit()
   258  		if err != nil {
   259  			return err
   260  		}
   261  		rlimits = append(rlimits, rl)
   262  	}
   263  
   264  	resources := &execdriver.Resources{
   265  		Memory:           c.hostConfig.Memory,
   266  		MemorySwap:       c.hostConfig.MemorySwap,
   267  		CpuShares:        c.hostConfig.CpuShares,
   268  		CpusetCpus:       c.hostConfig.CpusetCpus,
   269  		CpusetMems:       c.hostConfig.CpusetMems,
   270  		CpuPeriod:        c.hostConfig.CpuPeriod,
   271  		CpuQuota:         c.hostConfig.CpuQuota,
   272  		BlkioWeight:      c.hostConfig.BlkioWeight,
   273  		Rlimits:          rlimits,
   274  		OomKillDisable:   c.hostConfig.OomKillDisable,
   275  		MemorySwappiness: -1,
   276  	}
   277  
   278  	if c.hostConfig.MemorySwappiness != nil {
   279  		resources.MemorySwappiness = *c.hostConfig.MemorySwappiness
   280  	}
   281  
   282  	processConfig := execdriver.ProcessConfig{
   283  		Privileged: c.hostConfig.Privileged,
   284  		Entrypoint: c.Path,
   285  		Arguments:  c.Args,
   286  		Tty:        c.Config.Tty,
   287  		User:       c.Config.User,
   288  	}
   289  
   290  	processConfig.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
   291  	processConfig.Env = env
   292  
   293  	c.command = &execdriver.Command{
   294  		ID:                 c.ID,
   295  		Rootfs:             c.RootfsPath(),
   296  		ReadonlyRootfs:     c.hostConfig.ReadonlyRootfs,
   297  		InitPath:           "/.dockerinit",
   298  		WorkingDir:         c.Config.WorkingDir,
   299  		Network:            en,
   300  		Ipc:                ipc,
   301  		Pid:                pid,
   302  		UTS:                uts,
   303  		Resources:          resources,
   304  		AllowedDevices:     allowedDevices,
   305  		AutoCreatedDevices: autoCreatedDevices,
   306  		CapAdd:             c.hostConfig.CapAdd.Slice(),
   307  		CapDrop:            c.hostConfig.CapDrop.Slice(),
   308  		GroupAdd:           c.hostConfig.GroupAdd,
   309  		ProcessConfig:      processConfig,
   310  		ProcessLabel:       c.GetProcessLabel(),
   311  		MountLabel:         c.GetMountLabel(),
   312  		LxcConfig:          lxcConfig,
   313  		AppArmorProfile:    c.AppArmorProfile,
   314  		CgroupParent:       c.hostConfig.CgroupParent,
   315  	}
   316  
   317  	return nil
   318  }
   319  
   320  func mergeDevices(defaultDevices, userDevices []*configs.Device) []*configs.Device {
   321  	if len(userDevices) == 0 {
   322  		return defaultDevices
   323  	}
   324  
   325  	paths := map[string]*configs.Device{}
   326  	for _, d := range userDevices {
   327  		paths[d.Path] = d
   328  	}
   329  
   330  	var devs []*configs.Device
   331  	for _, d := range defaultDevices {
   332  		if _, defined := paths[d.Path]; !defined {
   333  			devs = append(devs, d)
   334  		}
   335  	}
   336  	return append(devs, userDevices...)
   337  }
   338  
   339  // GetSize, return real size, virtual size
   340  func (container *Container) GetSize() (int64, int64) {
   341  	var (
   342  		sizeRw, sizeRootfs int64
   343  		err                error
   344  		driver             = container.daemon.driver
   345  	)
   346  
   347  	if err := container.Mount(); err != nil {
   348  		logrus.Errorf("Failed to compute size of container rootfs %s: %s", container.ID, err)
   349  		return sizeRw, sizeRootfs
   350  	}
   351  	defer container.Unmount()
   352  
   353  	initID := fmt.Sprintf("%s-init", container.ID)
   354  	sizeRw, err = driver.DiffSize(container.ID, initID)
   355  	if err != nil {
   356  		logrus.Errorf("Driver %s couldn't return diff size of container %s: %s", driver, container.ID, err)
   357  		// FIXME: GetSize should return an error. Not changing it now in case
   358  		// there is a side-effect.
   359  		sizeRw = -1
   360  	}
   361  
   362  	if _, err = os.Stat(container.basefs); err == nil {
   363  		if sizeRootfs, err = directory.Size(container.basefs); err != nil {
   364  			sizeRootfs = -1
   365  		}
   366  	}
   367  	return sizeRw, sizeRootfs
   368  }
   369  
   370  // Attempt to set the network mounts given a provided destination and
   371  // the path to use for it; return true if the given destination was a
   372  // network mount file
   373  func (container *Container) trySetNetworkMount(destination string, path string) bool {
   374  	if destination == "/etc/resolv.conf" {
   375  		container.ResolvConfPath = path
   376  		return true
   377  	}
   378  	if destination == "/etc/hostname" {
   379  		container.HostnamePath = path
   380  		return true
   381  	}
   382  	if destination == "/etc/hosts" {
   383  		container.HostsPath = path
   384  		return true
   385  	}
   386  
   387  	return false
   388  }
   389  
   390  func (container *Container) buildHostnameFile() error {
   391  	hostnamePath, err := container.GetRootResourcePath("hostname")
   392  	if err != nil {
   393  		return err
   394  	}
   395  	container.HostnamePath = hostnamePath
   396  
   397  	if container.Config.Domainname != "" {
   398  		return ioutil.WriteFile(container.HostnamePath, []byte(fmt.Sprintf("%s.%s\n", container.Config.Hostname, container.Config.Domainname)), 0644)
   399  	}
   400  	return ioutil.WriteFile(container.HostnamePath, []byte(container.Config.Hostname+"\n"), 0644)
   401  }
   402  
   403  func (container *Container) buildJoinOptions() ([]libnetwork.EndpointOption, error) {
   404  	var (
   405  		joinOptions []libnetwork.EndpointOption
   406  		err         error
   407  		dns         []string
   408  		dnsSearch   []string
   409  	)
   410  
   411  	joinOptions = append(joinOptions, libnetwork.JoinOptionHostname(container.Config.Hostname),
   412  		libnetwork.JoinOptionDomainname(container.Config.Domainname))
   413  
   414  	if container.hostConfig.NetworkMode.IsHost() {
   415  		joinOptions = append(joinOptions, libnetwork.JoinOptionUseDefaultSandbox())
   416  	}
   417  
   418  	container.HostsPath, err = container.GetRootResourcePath("hosts")
   419  	if err != nil {
   420  		return nil, err
   421  	}
   422  	joinOptions = append(joinOptions, libnetwork.JoinOptionHostsPath(container.HostsPath))
   423  
   424  	container.ResolvConfPath, err = container.GetRootResourcePath("resolv.conf")
   425  	if err != nil {
   426  		return nil, err
   427  	}
   428  	joinOptions = append(joinOptions, libnetwork.JoinOptionResolvConfPath(container.ResolvConfPath))
   429  
   430  	if len(container.hostConfig.Dns) > 0 {
   431  		dns = container.hostConfig.Dns
   432  	} else if len(container.daemon.config.Dns) > 0 {
   433  		dns = container.daemon.config.Dns
   434  	}
   435  
   436  	for _, d := range dns {
   437  		joinOptions = append(joinOptions, libnetwork.JoinOptionDNS(d))
   438  	}
   439  
   440  	if len(container.hostConfig.DnsSearch) > 0 {
   441  		dnsSearch = container.hostConfig.DnsSearch
   442  	} else if len(container.daemon.config.DnsSearch) > 0 {
   443  		dnsSearch = container.daemon.config.DnsSearch
   444  	}
   445  
   446  	for _, ds := range dnsSearch {
   447  		joinOptions = append(joinOptions, libnetwork.JoinOptionDNSSearch(ds))
   448  	}
   449  
   450  	if container.NetworkSettings.SecondaryIPAddresses != nil {
   451  		name := container.Config.Hostname
   452  		if container.Config.Domainname != "" {
   453  			name = name + "." + container.Config.Domainname
   454  		}
   455  
   456  		for _, a := range container.NetworkSettings.SecondaryIPAddresses {
   457  			joinOptions = append(joinOptions, libnetwork.JoinOptionExtraHost(name, a.Addr))
   458  		}
   459  	}
   460  
   461  	var childEndpoints, parentEndpoints []string
   462  
   463  	children, err := container.daemon.Children(container.Name)
   464  	if err != nil {
   465  		return nil, err
   466  	}
   467  
   468  	for linkAlias, child := range children {
   469  		_, alias := path.Split(linkAlias)
   470  		// allow access to the linked container via the alias, real name, and container hostname
   471  		aliasList := alias + " " + child.Config.Hostname
   472  		// only add the name if alias isn't equal to the name
   473  		if alias != child.Name[1:] {
   474  			aliasList = aliasList + " " + child.Name[1:]
   475  		}
   476  		joinOptions = append(joinOptions, libnetwork.JoinOptionExtraHost(aliasList, child.NetworkSettings.IPAddress))
   477  		if child.NetworkSettings.EndpointID != "" {
   478  			childEndpoints = append(childEndpoints, child.NetworkSettings.EndpointID)
   479  		}
   480  	}
   481  
   482  	for _, extraHost := range container.hostConfig.ExtraHosts {
   483  		// allow IPv6 addresses in extra hosts; only split on first ":"
   484  		parts := strings.SplitN(extraHost, ":", 2)
   485  		joinOptions = append(joinOptions, libnetwork.JoinOptionExtraHost(parts[0], parts[1]))
   486  	}
   487  
   488  	refs := container.daemon.ContainerGraph().RefPaths(container.ID)
   489  	for _, ref := range refs {
   490  		if ref.ParentID == "0" {
   491  			continue
   492  		}
   493  
   494  		c, err := container.daemon.Get(ref.ParentID)
   495  		if err != nil {
   496  			logrus.Error(err)
   497  		}
   498  
   499  		if c != nil && !container.daemon.config.DisableBridge && container.hostConfig.NetworkMode.IsPrivate() {
   500  			logrus.Debugf("Update /etc/hosts of %s for alias %s with ip %s", c.ID, ref.Name, container.NetworkSettings.IPAddress)
   501  			joinOptions = append(joinOptions, libnetwork.JoinOptionParentUpdate(c.NetworkSettings.EndpointID, ref.Name, container.NetworkSettings.IPAddress))
   502  			if c.NetworkSettings.EndpointID != "" {
   503  				parentEndpoints = append(parentEndpoints, c.NetworkSettings.EndpointID)
   504  			}
   505  		}
   506  	}
   507  
   508  	linkOptions := options.Generic{
   509  		netlabel.GenericData: options.Generic{
   510  			"ParentEndpoints": parentEndpoints,
   511  			"ChildEndpoints":  childEndpoints,
   512  		},
   513  	}
   514  
   515  	joinOptions = append(joinOptions, libnetwork.JoinOptionGeneric(linkOptions))
   516  
   517  	return joinOptions, nil
   518  }
   519  
   520  func (container *Container) buildPortMapInfo(n libnetwork.Network, ep libnetwork.Endpoint, networkSettings *network.Settings) (*network.Settings, error) {
   521  	if ep == nil {
   522  		return nil, fmt.Errorf("invalid endpoint while building port map info")
   523  	}
   524  
   525  	if networkSettings == nil {
   526  		return nil, fmt.Errorf("invalid networksettings while building port map info")
   527  	}
   528  
   529  	driverInfo, err := ep.DriverInfo()
   530  	if err != nil {
   531  		return nil, err
   532  	}
   533  
   534  	if driverInfo == nil {
   535  		// It is not an error for epInfo to be nil
   536  		return networkSettings, nil
   537  	}
   538  
   539  	if mac, ok := driverInfo[netlabel.MacAddress]; ok {
   540  		networkSettings.MacAddress = mac.(net.HardwareAddr).String()
   541  	}
   542  
   543  	networkSettings.Ports = nat.PortMap{}
   544  
   545  	if expData, ok := driverInfo[netlabel.ExposedPorts]; ok {
   546  		if exposedPorts, ok := expData.([]types.TransportPort); ok {
   547  			for _, tp := range exposedPorts {
   548  				natPort, err := nat.NewPort(tp.Proto.String(), strconv.Itoa(int(tp.Port)))
   549  				if err != nil {
   550  					return nil, fmt.Errorf("Error parsing Port value(%s):%v", tp.Port, err)
   551  				}
   552  				networkSettings.Ports[natPort] = nil
   553  			}
   554  		}
   555  	}
   556  
   557  	mapData, ok := driverInfo[netlabel.PortMap]
   558  	if !ok {
   559  		return networkSettings, nil
   560  	}
   561  
   562  	if portMapping, ok := mapData.([]types.PortBinding); ok {
   563  		for _, pp := range portMapping {
   564  			natPort, err := nat.NewPort(pp.Proto.String(), strconv.Itoa(int(pp.Port)))
   565  			if err != nil {
   566  				return nil, err
   567  			}
   568  			natBndg := nat.PortBinding{HostIP: pp.HostIP.String(), HostPort: strconv.Itoa(int(pp.HostPort))}
   569  			networkSettings.Ports[natPort] = append(networkSettings.Ports[natPort], natBndg)
   570  		}
   571  	}
   572  
   573  	return networkSettings, nil
   574  }
   575  
   576  func (container *Container) buildEndpointInfo(n libnetwork.Network, ep libnetwork.Endpoint, networkSettings *network.Settings) (*network.Settings, error) {
   577  	if ep == nil {
   578  		return nil, fmt.Errorf("invalid endpoint while building port map info")
   579  	}
   580  
   581  	if networkSettings == nil {
   582  		return nil, fmt.Errorf("invalid networksettings while building port map info")
   583  	}
   584  
   585  	epInfo := ep.Info()
   586  	if epInfo == nil {
   587  		// It is not an error to get an empty endpoint info
   588  		return networkSettings, nil
   589  	}
   590  
   591  	ifaceList := epInfo.InterfaceList()
   592  	if len(ifaceList) == 0 {
   593  		return networkSettings, nil
   594  	}
   595  
   596  	iface := ifaceList[0]
   597  
   598  	ones, _ := iface.Address().Mask.Size()
   599  	networkSettings.IPAddress = iface.Address().IP.String()
   600  	networkSettings.IPPrefixLen = ones
   601  
   602  	if iface.AddressIPv6().IP.To16() != nil {
   603  		onesv6, _ := iface.AddressIPv6().Mask.Size()
   604  		networkSettings.GlobalIPv6Address = iface.AddressIPv6().IP.String()
   605  		networkSettings.GlobalIPv6PrefixLen = onesv6
   606  	}
   607  
   608  	if len(ifaceList) == 1 {
   609  		return networkSettings, nil
   610  	}
   611  
   612  	networkSettings.SecondaryIPAddresses = make([]network.Address, 0, len(ifaceList)-1)
   613  	networkSettings.SecondaryIPv6Addresses = make([]network.Address, 0, len(ifaceList)-1)
   614  	for _, iface := range ifaceList[1:] {
   615  		ones, _ := iface.Address().Mask.Size()
   616  		addr := network.Address{Addr: iface.Address().IP.String(), PrefixLen: ones}
   617  		networkSettings.SecondaryIPAddresses = append(networkSettings.SecondaryIPAddresses, addr)
   618  
   619  		if iface.AddressIPv6().IP.To16() != nil {
   620  			onesv6, _ := iface.AddressIPv6().Mask.Size()
   621  			addrv6 := network.Address{Addr: iface.AddressIPv6().IP.String(), PrefixLen: onesv6}
   622  			networkSettings.SecondaryIPv6Addresses = append(networkSettings.SecondaryIPv6Addresses, addrv6)
   623  		}
   624  	}
   625  
   626  	return networkSettings, nil
   627  }
   628  
   629  func (container *Container) updateJoinInfo(ep libnetwork.Endpoint) error {
   630  	epInfo := ep.Info()
   631  	if epInfo == nil {
   632  		// It is not an error to get an empty endpoint info
   633  		return nil
   634  	}
   635  
   636  	container.NetworkSettings.Gateway = epInfo.Gateway().String()
   637  	if epInfo.GatewayIPv6().To16() != nil {
   638  		container.NetworkSettings.IPv6Gateway = epInfo.GatewayIPv6().String()
   639  	}
   640  
   641  	container.NetworkSettings.SandboxKey = epInfo.SandboxKey()
   642  
   643  	return nil
   644  }
   645  
   646  func (container *Container) updateNetworkSettings(n libnetwork.Network, ep libnetwork.Endpoint) error {
   647  	networkSettings := &network.Settings{NetworkID: n.ID(), EndpointID: ep.ID()}
   648  
   649  	networkSettings, err := container.buildPortMapInfo(n, ep, networkSettings)
   650  	if err != nil {
   651  		return err
   652  	}
   653  
   654  	networkSettings, err = container.buildEndpointInfo(n, ep, networkSettings)
   655  	if err != nil {
   656  		return err
   657  	}
   658  
   659  	if container.hostConfig.NetworkMode == runconfig.NetworkMode("bridge") {
   660  		networkSettings.Bridge = container.daemon.config.Bridge.Iface
   661  	}
   662  
   663  	container.NetworkSettings = networkSettings
   664  	return nil
   665  }
   666  
   667  func (container *Container) UpdateNetwork() error {
   668  	n, err := container.daemon.netController.NetworkByID(container.NetworkSettings.NetworkID)
   669  	if err != nil {
   670  		return fmt.Errorf("error locating network id %s: %v", container.NetworkSettings.NetworkID, err)
   671  	}
   672  
   673  	ep, err := n.EndpointByID(container.NetworkSettings.EndpointID)
   674  	if err != nil {
   675  		return fmt.Errorf("error locating endpoint id %s: %v", container.NetworkSettings.EndpointID, err)
   676  	}
   677  
   678  	if err := ep.Leave(container.ID); err != nil {
   679  		return fmt.Errorf("endpoint leave failed: %v", err)
   680  
   681  	}
   682  
   683  	joinOptions, err := container.buildJoinOptions()
   684  	if err != nil {
   685  		return fmt.Errorf("Update network failed: %v", err)
   686  	}
   687  
   688  	if err := ep.Join(container.ID, joinOptions...); err != nil {
   689  		return fmt.Errorf("endpoint join failed: %v", err)
   690  	}
   691  
   692  	if err := container.updateJoinInfo(ep); err != nil {
   693  		return fmt.Errorf("Updating join info failed: %v", err)
   694  	}
   695  
   696  	return nil
   697  }
   698  
   699  func (container *Container) buildCreateEndpointOptions() ([]libnetwork.EndpointOption, error) {
   700  	var (
   701  		portSpecs     = make(nat.PortSet)
   702  		bindings      = make(nat.PortMap)
   703  		pbList        []types.PortBinding
   704  		exposeList    []types.TransportPort
   705  		createOptions []libnetwork.EndpointOption
   706  	)
   707  
   708  	if container.Config.ExposedPorts != nil {
   709  		portSpecs = container.Config.ExposedPorts
   710  	}
   711  
   712  	if container.hostConfig.PortBindings != nil {
   713  		for p, b := range container.hostConfig.PortBindings {
   714  			bindings[p] = []nat.PortBinding{}
   715  			for _, bb := range b {
   716  				bindings[p] = append(bindings[p], nat.PortBinding{
   717  					HostIP:   bb.HostIP,
   718  					HostPort: bb.HostPort,
   719  				})
   720  			}
   721  		}
   722  	}
   723  
   724  	container.NetworkSettings.PortMapping = nil
   725  
   726  	ports := make([]nat.Port, len(portSpecs))
   727  	var i int
   728  	for p := range portSpecs {
   729  		ports[i] = p
   730  		i++
   731  	}
   732  	nat.SortPortMap(ports, bindings)
   733  	for _, port := range ports {
   734  		expose := types.TransportPort{}
   735  		expose.Proto = types.ParseProtocol(port.Proto())
   736  		expose.Port = uint16(port.Int())
   737  		exposeList = append(exposeList, expose)
   738  
   739  		pb := types.PortBinding{Port: expose.Port, Proto: expose.Proto}
   740  		binding := bindings[port]
   741  		for i := 0; i < len(binding); i++ {
   742  			pbCopy := pb.GetCopy()
   743  			newP, err := nat.NewPort(nat.SplitProtoPort(binding[i].HostPort))
   744  			if err != nil {
   745  				return nil, fmt.Errorf("Error parsing HostPort value(%s):%v", binding[i].HostPort, err)
   746  			}
   747  			pbCopy.HostPort = uint16(newP.Int())
   748  			pbCopy.HostIP = net.ParseIP(binding[i].HostIP)
   749  			pbList = append(pbList, pbCopy)
   750  		}
   751  
   752  		if container.hostConfig.PublishAllPorts && len(binding) == 0 {
   753  			pbList = append(pbList, pb)
   754  		}
   755  	}
   756  
   757  	createOptions = append(createOptions,
   758  		libnetwork.CreateOptionPortMapping(pbList),
   759  		libnetwork.CreateOptionExposedPorts(exposeList))
   760  
   761  	if container.Config.MacAddress != "" {
   762  		mac, err := net.ParseMAC(container.Config.MacAddress)
   763  		if err != nil {
   764  			return nil, err
   765  		}
   766  
   767  		genericOption := options.Generic{
   768  			netlabel.MacAddress: mac,
   769  		}
   770  
   771  		createOptions = append(createOptions, libnetwork.EndpointOptionGeneric(genericOption))
   772  	}
   773  
   774  	return createOptions, nil
   775  }
   776  
   777  func parseService(controller libnetwork.NetworkController, service string) (string, string, string) {
   778  	dn := controller.Config().Daemon.DefaultNetwork
   779  	dd := controller.Config().Daemon.DefaultDriver
   780  
   781  	snd := strings.Split(service, ".")
   782  	if len(snd) > 2 {
   783  		return strings.Join(snd[:len(snd)-2], "."), snd[len(snd)-2], snd[len(snd)-1]
   784  	}
   785  	if len(snd) > 1 {
   786  		return snd[0], snd[1], dd
   787  	}
   788  	return snd[0], dn, dd
   789  }
   790  
   791  func createNetwork(controller libnetwork.NetworkController, dnet string, driver string) (libnetwork.Network, error) {
   792  	createOptions := []libnetwork.NetworkOption{}
   793  	genericOption := options.Generic{}
   794  
   795  	// Bridge driver is special due to legacy reasons
   796  	if runconfig.NetworkMode(driver).IsBridge() {
   797  		genericOption[netlabel.GenericData] = map[string]interface{}{
   798  			"BridgeName":            dnet,
   799  			"AllowNonDefaultBridge": "true",
   800  		}
   801  		networkOption := libnetwork.NetworkOptionGeneric(genericOption)
   802  		createOptions = append(createOptions, networkOption)
   803  	}
   804  
   805  	return controller.NewNetwork(driver, dnet, createOptions...)
   806  }
   807  
   808  func (container *Container) secondaryNetworkRequired(primaryNetworkType string) bool {
   809  	switch primaryNetworkType {
   810  	case "bridge", "none", "host", "container":
   811  		return false
   812  	}
   813  
   814  	if container.daemon.config.DisableBridge {
   815  		return false
   816  	}
   817  
   818  	if container.Config.ExposedPorts != nil && len(container.Config.ExposedPorts) > 0 {
   819  		return true
   820  	}
   821  	if container.hostConfig.PortBindings != nil && len(container.hostConfig.PortBindings) > 0 {
   822  		return true
   823  	}
   824  	return false
   825  }
   826  
   827  func (container *Container) AllocateNetwork() error {
   828  	mode := container.hostConfig.NetworkMode
   829  	controller := container.daemon.netController
   830  	if container.Config.NetworkDisabled || mode.IsContainer() {
   831  		return nil
   832  	}
   833  
   834  	networkDriver := string(mode)
   835  	service := container.Config.PublishService
   836  	networkName := mode.NetworkName()
   837  	if mode.IsDefault() {
   838  		if service != "" {
   839  			service, networkName, networkDriver = parseService(controller, service)
   840  		} else {
   841  			networkName = controller.Config().Daemon.DefaultNetwork
   842  			networkDriver = controller.Config().Daemon.DefaultDriver
   843  		}
   844  	} else if service != "" {
   845  		return fmt.Errorf("conflicting options: publishing a service and network mode")
   846  	}
   847  
   848  	if runconfig.NetworkMode(networkDriver).IsBridge() && container.daemon.config.DisableBridge {
   849  		container.Config.NetworkDisabled = true
   850  		return nil
   851  	}
   852  
   853  	if service == "" {
   854  		// dot character "." has a special meaning to support SERVICE[.NETWORK] format.
   855  		// For backward compatiblity, replacing "." with "-", instead of failing
   856  		service = strings.Replace(container.Name, ".", "-", -1)
   857  		// Service names dont like "/" in them. removing it instead of failing for backward compatibility
   858  		service = strings.Replace(service, "/", "", -1)
   859  	}
   860  
   861  	if container.secondaryNetworkRequired(networkDriver) {
   862  		// Configure Bridge as secondary network for port binding purposes
   863  		if err := container.configureNetwork("bridge", service, "bridge", false); err != nil {
   864  			return err
   865  		}
   866  	}
   867  
   868  	if err := container.configureNetwork(networkName, service, networkDriver, mode.IsDefault()); err != nil {
   869  		return err
   870  	}
   871  
   872  	return container.WriteHostConfig()
   873  }
   874  
   875  func (container *Container) configureNetwork(networkName, service, networkDriver string, canCreateNetwork bool) error {
   876  	controller := container.daemon.netController
   877  	n, err := controller.NetworkByName(networkName)
   878  	if err != nil {
   879  		if _, ok := err.(libnetwork.ErrNoSuchNetwork); !ok || !canCreateNetwork {
   880  			return err
   881  		}
   882  
   883  		if n, err = createNetwork(controller, networkName, networkDriver); err != nil {
   884  			return err
   885  		}
   886  	}
   887  
   888  	ep, err := n.EndpointByName(service)
   889  	if err != nil {
   890  		if _, ok := err.(libnetwork.ErrNoSuchEndpoint); !ok {
   891  			return err
   892  		}
   893  
   894  		createOptions, err := container.buildCreateEndpointOptions()
   895  		if err != nil {
   896  			return err
   897  		}
   898  
   899  		ep, err = n.CreateEndpoint(service, createOptions...)
   900  		if err != nil {
   901  			return err
   902  		}
   903  	}
   904  
   905  	if err := container.updateNetworkSettings(n, ep); err != nil {
   906  		return err
   907  	}
   908  
   909  	joinOptions, err := container.buildJoinOptions()
   910  	if err != nil {
   911  		return err
   912  	}
   913  
   914  	if err := ep.Join(container.ID, joinOptions...); err != nil {
   915  		return err
   916  	}
   917  
   918  	if err := container.updateJoinInfo(ep); err != nil {
   919  		return fmt.Errorf("Updating join info failed: %v", err)
   920  	}
   921  
   922  	return nil
   923  }
   924  
   925  func (container *Container) initializeNetworking() error {
   926  	var err error
   927  
   928  	// Make sure NetworkMode has an acceptable value before
   929  	// initializing networking.
   930  	if container.hostConfig.NetworkMode == runconfig.NetworkMode("") {
   931  		container.hostConfig.NetworkMode = runconfig.NetworkMode("default")
   932  	}
   933  	if container.hostConfig.NetworkMode.IsContainer() {
   934  		// we need to get the hosts files from the container to join
   935  		nc, err := container.getNetworkedContainer()
   936  		if err != nil {
   937  			return err
   938  		}
   939  		container.HostnamePath = nc.HostnamePath
   940  		container.HostsPath = nc.HostsPath
   941  		container.ResolvConfPath = nc.ResolvConfPath
   942  		container.Config.Hostname = nc.Config.Hostname
   943  		container.Config.Domainname = nc.Config.Domainname
   944  		return nil
   945  	}
   946  
   947  	if container.hostConfig.NetworkMode.IsHost() {
   948  		container.Config.Hostname, err = os.Hostname()
   949  		if err != nil {
   950  			return err
   951  		}
   952  
   953  		parts := strings.SplitN(container.Config.Hostname, ".", 2)
   954  		if len(parts) > 1 {
   955  			container.Config.Hostname = parts[0]
   956  			container.Config.Domainname = parts[1]
   957  		}
   958  
   959  	}
   960  
   961  	if err := container.AllocateNetwork(); err != nil {
   962  		return err
   963  	}
   964  
   965  	return container.buildHostnameFile()
   966  }
   967  
   968  func (container *Container) ExportRw() (archive.Archive, error) {
   969  	if container.daemon == nil {
   970  		return nil, fmt.Errorf("Can't load storage driver for unregistered container %s", container.ID)
   971  	}
   972  	archive, err := container.daemon.Diff(container)
   973  	if err != nil {
   974  		return nil, err
   975  	}
   976  	return ioutils.NewReadCloserWrapper(archive, func() error {
   977  			err := archive.Close()
   978  			return err
   979  		}),
   980  		nil
   981  }
   982  
   983  func (container *Container) getIpcContainer() (*Container, error) {
   984  	containerID := container.hostConfig.IpcMode.Container()
   985  	c, err := container.daemon.Get(containerID)
   986  	if err != nil {
   987  		return nil, err
   988  	}
   989  	if !c.IsRunning() {
   990  		return nil, fmt.Errorf("cannot join IPC of a non running container: %s", containerID)
   991  	}
   992  	return c, nil
   993  }
   994  
   995  func (container *Container) setupWorkingDirectory() error {
   996  	if container.Config.WorkingDir != "" {
   997  		container.Config.WorkingDir = filepath.Clean(container.Config.WorkingDir)
   998  
   999  		pth, err := container.GetResourcePath(container.Config.WorkingDir)
  1000  		if err != nil {
  1001  			return err
  1002  		}
  1003  
  1004  		pthInfo, err := os.Stat(pth)
  1005  		if err != nil {
  1006  			if !os.IsNotExist(err) {
  1007  				return err
  1008  			}
  1009  
  1010  			if err := system.MkdirAll(pth, 0755); err != nil {
  1011  				return err
  1012  			}
  1013  		}
  1014  		if pthInfo != nil && !pthInfo.IsDir() {
  1015  			return fmt.Errorf("Cannot mkdir: %s is not a directory", container.Config.WorkingDir)
  1016  		}
  1017  	}
  1018  	return nil
  1019  }
  1020  
  1021  func (container *Container) getNetworkedContainer() (*Container, error) {
  1022  	parts := strings.SplitN(string(container.hostConfig.NetworkMode), ":", 2)
  1023  	switch parts[0] {
  1024  	case "container":
  1025  		if len(parts) != 2 {
  1026  			return nil, fmt.Errorf("no container specified to join network")
  1027  		}
  1028  		nc, err := container.daemon.Get(parts[1])
  1029  		if err != nil {
  1030  			return nil, err
  1031  		}
  1032  		if container == nc {
  1033  			return nil, fmt.Errorf("cannot join own network")
  1034  		}
  1035  		if !nc.IsRunning() {
  1036  			return nil, fmt.Errorf("cannot join network of a non running container: %s", parts[1])
  1037  		}
  1038  		return nc, nil
  1039  	default:
  1040  		return nil, fmt.Errorf("network mode not set to container")
  1041  	}
  1042  }
  1043  
  1044  func (container *Container) ReleaseNetwork() {
  1045  	if container.hostConfig.NetworkMode.IsContainer() || container.Config.NetworkDisabled {
  1046  		return
  1047  	}
  1048  
  1049  	eid := container.NetworkSettings.EndpointID
  1050  	nid := container.NetworkSettings.NetworkID
  1051  
  1052  	container.NetworkSettings = &network.Settings{}
  1053  
  1054  	if nid == "" || eid == "" {
  1055  		return
  1056  	}
  1057  
  1058  	n, err := container.daemon.netController.NetworkByID(nid)
  1059  	if err != nil {
  1060  		logrus.Errorf("error locating network id %s: %v", nid, err)
  1061  		return
  1062  	}
  1063  
  1064  	ep, err := n.EndpointByID(eid)
  1065  	if err != nil {
  1066  		logrus.Errorf("error locating endpoint id %s: %v", eid, err)
  1067  		return
  1068  	}
  1069  
  1070  	switch {
  1071  	case container.hostConfig.NetworkMode.IsHost():
  1072  		if err := ep.Leave(container.ID); err != nil {
  1073  			logrus.Errorf("Error leaving endpoint id %s for container %s: %v", eid, container.ID, err)
  1074  			return
  1075  		}
  1076  	default:
  1077  		if err := container.daemon.netController.LeaveAll(container.ID); err != nil {
  1078  			logrus.Errorf("Leave all failed for  %s: %v", container.ID, err)
  1079  			return
  1080  		}
  1081  	}
  1082  
  1083  	// In addition to leaving all endpoints, delete implicitly created endpoint
  1084  	if container.Config.PublishService == "" {
  1085  		if err := ep.Delete(); err != nil {
  1086  			logrus.Errorf("deleting endpoint failed: %v", err)
  1087  		}
  1088  	}
  1089  
  1090  }
  1091  
  1092  func disableAllActiveLinks(container *Container) {
  1093  	if container.activeLinks != nil {
  1094  		for _, link := range container.activeLinks {
  1095  			link.Disable()
  1096  		}
  1097  	}
  1098  }
  1099  
  1100  func (container *Container) DisableLink(name string) {
  1101  	if container.activeLinks != nil {
  1102  		if link, exists := container.activeLinks[name]; exists {
  1103  			link.Disable()
  1104  			delete(container.activeLinks, name)
  1105  			if err := container.UpdateNetwork(); err != nil {
  1106  				logrus.Debugf("Could not update network to remove link: %v", err)
  1107  			}
  1108  		} else {
  1109  			logrus.Debugf("Could not find active link for %s", name)
  1110  		}
  1111  	}
  1112  }
  1113  
  1114  func (container *Container) UnmountVolumes(forceSyscall bool) error {
  1115  	var volumeMounts []mountPoint
  1116  
  1117  	for _, mntPoint := range container.MountPoints {
  1118  		dest, err := container.GetResourcePath(mntPoint.Destination)
  1119  		if err != nil {
  1120  			return err
  1121  		}
  1122  
  1123  		volumeMounts = append(volumeMounts, mountPoint{Destination: dest, Volume: mntPoint.Volume})
  1124  	}
  1125  
  1126  	for _, mnt := range container.networkMounts() {
  1127  		dest, err := container.GetResourcePath(mnt.Destination)
  1128  		if err != nil {
  1129  			return err
  1130  		}
  1131  
  1132  		volumeMounts = append(volumeMounts, mountPoint{Destination: dest})
  1133  	}
  1134  
  1135  	for _, volumeMount := range volumeMounts {
  1136  		if forceSyscall {
  1137  			syscall.Unmount(volumeMount.Destination, 0)
  1138  		}
  1139  
  1140  		if volumeMount.Volume != nil {
  1141  			if err := volumeMount.Volume.Unmount(); err != nil {
  1142  				return err
  1143  			}
  1144  		}
  1145  	}
  1146  
  1147  	return nil
  1148  }
  1149  
  1150  func (container *Container) PrepareStorage() error {
  1151  	return nil
  1152  }
  1153  
  1154  func (container *Container) CleanupStorage() error {
  1155  	return nil
  1156  }