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