github.com/gunjan5/docker@v1.8.2/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 }