github.com/rentongzhang/docker@v1.8.2-rc1/daemon/execdriver/driver_linux.go (about)

     1  package execdriver
     2  
     3  import (
     4  	"encoding/json"
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  	"strconv"
     9  	"strings"
    10  	"time"
    11  
    12  	"github.com/docker/docker/daemon/execdriver/native/template"
    13  	"github.com/opencontainers/runc/libcontainer"
    14  	"github.com/opencontainers/runc/libcontainer/cgroups/fs"
    15  	"github.com/opencontainers/runc/libcontainer/configs"
    16  )
    17  
    18  func InitContainer(c *Command) *configs.Config {
    19  	container := template.New()
    20  
    21  	container.Hostname = getEnv("HOSTNAME", c.ProcessConfig.Env)
    22  	container.Cgroups.Name = c.ID
    23  	container.Cgroups.AllowedDevices = c.AllowedDevices
    24  	container.Devices = c.AutoCreatedDevices
    25  	container.Rootfs = c.Rootfs
    26  	container.Readonlyfs = c.ReadonlyRootfs
    27  	container.Privatefs = true
    28  
    29  	// check to see if we are running in ramdisk to disable pivot root
    30  	container.NoPivotRoot = os.Getenv("DOCKER_RAMDISK") != ""
    31  
    32  	// Default parent cgroup is "docker". Override if required.
    33  	if c.CgroupParent != "" {
    34  		container.Cgroups.Parent = c.CgroupParent
    35  	}
    36  	return container
    37  }
    38  
    39  func getEnv(key string, env []string) string {
    40  	for _, pair := range env {
    41  		parts := strings.SplitN(pair, "=", 2)
    42  		if parts[0] == key {
    43  			return parts[1]
    44  		}
    45  	}
    46  	return ""
    47  }
    48  
    49  func SetupCgroups(container *configs.Config, c *Command) error {
    50  	if c.Resources != nil {
    51  		container.Cgroups.CpuShares = c.Resources.CpuShares
    52  		container.Cgroups.Memory = c.Resources.Memory
    53  		container.Cgroups.MemoryReservation = c.Resources.Memory
    54  		container.Cgroups.MemorySwap = c.Resources.MemorySwap
    55  		container.Cgroups.CpusetCpus = c.Resources.CpusetCpus
    56  		container.Cgroups.CpusetMems = c.Resources.CpusetMems
    57  		container.Cgroups.CpuPeriod = c.Resources.CpuPeriod
    58  		container.Cgroups.CpuQuota = c.Resources.CpuQuota
    59  		container.Cgroups.BlkioWeight = c.Resources.BlkioWeight
    60  		container.Cgroups.OomKillDisable = c.Resources.OomKillDisable
    61  		container.Cgroups.MemorySwappiness = c.Resources.MemorySwappiness
    62  	}
    63  
    64  	return nil
    65  }
    66  
    67  // Returns the network statistics for the network interfaces represented by the NetworkRuntimeInfo.
    68  func getNetworkInterfaceStats(interfaceName string) (*libcontainer.NetworkInterface, error) {
    69  	out := &libcontainer.NetworkInterface{Name: interfaceName}
    70  	// This can happen if the network runtime information is missing - possible if the
    71  	// container was created by an old version of libcontainer.
    72  	if interfaceName == "" {
    73  		return out, nil
    74  	}
    75  	type netStatsPair struct {
    76  		// Where to write the output.
    77  		Out *uint64
    78  		// The network stats file to read.
    79  		File string
    80  	}
    81  	// Ingress for host veth is from the container. Hence tx_bytes stat on the host veth is actually number of bytes received by the container.
    82  	netStats := []netStatsPair{
    83  		{Out: &out.RxBytes, File: "tx_bytes"},
    84  		{Out: &out.RxPackets, File: "tx_packets"},
    85  		{Out: &out.RxErrors, File: "tx_errors"},
    86  		{Out: &out.RxDropped, File: "tx_dropped"},
    87  
    88  		{Out: &out.TxBytes, File: "rx_bytes"},
    89  		{Out: &out.TxPackets, File: "rx_packets"},
    90  		{Out: &out.TxErrors, File: "rx_errors"},
    91  		{Out: &out.TxDropped, File: "rx_dropped"},
    92  	}
    93  	for _, netStat := range netStats {
    94  		data, err := readSysfsNetworkStats(interfaceName, netStat.File)
    95  		if err != nil {
    96  			return nil, err
    97  		}
    98  		*(netStat.Out) = data
    99  	}
   100  	return out, nil
   101  }
   102  
   103  // Reads the specified statistics available under /sys/class/net/<EthInterface>/statistics
   104  func readSysfsNetworkStats(ethInterface, statsFile string) (uint64, error) {
   105  	data, err := ioutil.ReadFile(filepath.Join("/sys/class/net", ethInterface, "statistics", statsFile))
   106  	if err != nil {
   107  		return 0, err
   108  	}
   109  	return strconv.ParseUint(strings.TrimSpace(string(data)), 10, 64)
   110  }
   111  
   112  func Stats(containerDir string, containerMemoryLimit int64, machineMemory int64) (*ResourceStats, error) {
   113  	f, err := os.Open(filepath.Join(containerDir, "state.json"))
   114  	if err != nil {
   115  		return nil, err
   116  	}
   117  	defer f.Close()
   118  
   119  	type network struct {
   120  		Type              string
   121  		HostInterfaceName string
   122  	}
   123  
   124  	state := struct {
   125  		CgroupPaths map[string]string `json:"cgroup_paths"`
   126  		Networks    []network
   127  	}{}
   128  
   129  	if err := json.NewDecoder(f).Decode(&state); err != nil {
   130  		return nil, err
   131  	}
   132  	now := time.Now()
   133  
   134  	mgr := fs.Manager{Paths: state.CgroupPaths}
   135  	cstats, err := mgr.GetStats()
   136  	if err != nil {
   137  		return nil, err
   138  	}
   139  	stats := &libcontainer.Stats{CgroupStats: cstats}
   140  	// if the container does not have any memory limit specified set the
   141  	// limit to the machines memory
   142  	memoryLimit := containerMemoryLimit
   143  	if memoryLimit == 0 {
   144  		memoryLimit = machineMemory
   145  	}
   146  	for _, iface := range state.Networks {
   147  		switch iface.Type {
   148  		case "veth":
   149  			istats, err := getNetworkInterfaceStats(iface.HostInterfaceName)
   150  			if err != nil {
   151  				return nil, err
   152  			}
   153  			stats.Interfaces = append(stats.Interfaces, istats)
   154  		}
   155  	}
   156  	return &ResourceStats{
   157  		Stats:       stats,
   158  		Read:        now,
   159  		MemoryLimit: memoryLimit,
   160  	}, nil
   161  }