github.com/ld86/docker@v1.7.1-rc3/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 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.Split(pair, "=") 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 } 62 63 return nil 64 } 65 66 // Returns the network statistics for the network interfaces represented by the NetworkRuntimeInfo. 67 func getNetworkInterfaceStats(interfaceName string) (*libcontainer.NetworkInterface, error) { 68 out := &libcontainer.NetworkInterface{Name: interfaceName} 69 // This can happen if the network runtime information is missing - possible if the 70 // container was created by an old version of libcontainer. 71 if interfaceName == "" { 72 return out, nil 73 } 74 type netStatsPair struct { 75 // Where to write the output. 76 Out *uint64 77 // The network stats file to read. 78 File string 79 } 80 // 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. 81 netStats := []netStatsPair{ 82 {Out: &out.RxBytes, File: "tx_bytes"}, 83 {Out: &out.RxPackets, File: "tx_packets"}, 84 {Out: &out.RxErrors, File: "tx_errors"}, 85 {Out: &out.RxDropped, File: "tx_dropped"}, 86 87 {Out: &out.TxBytes, File: "rx_bytes"}, 88 {Out: &out.TxPackets, File: "rx_packets"}, 89 {Out: &out.TxErrors, File: "rx_errors"}, 90 {Out: &out.TxDropped, File: "rx_dropped"}, 91 } 92 for _, netStat := range netStats { 93 data, err := readSysfsNetworkStats(interfaceName, netStat.File) 94 if err != nil { 95 return nil, err 96 } 97 *(netStat.Out) = data 98 } 99 return out, nil 100 } 101 102 // Reads the specified statistics available under /sys/class/net/<EthInterface>/statistics 103 func readSysfsNetworkStats(ethInterface, statsFile string) (uint64, error) { 104 data, err := ioutil.ReadFile(filepath.Join("/sys/class/net", ethInterface, "statistics", statsFile)) 105 if err != nil { 106 return 0, err 107 } 108 return strconv.ParseUint(strings.TrimSpace(string(data)), 10, 64) 109 } 110 111 func Stats(containerDir string, containerMemoryLimit int64, machineMemory int64) (*ResourceStats, error) { 112 f, err := os.Open(filepath.Join(containerDir, "state.json")) 113 if err != nil { 114 return nil, err 115 } 116 defer f.Close() 117 118 type network struct { 119 Type string 120 HostInterfaceName string 121 } 122 123 state := struct { 124 CgroupPaths map[string]string `json:"cgroup_paths"` 125 Networks []network 126 }{} 127 128 if err := json.NewDecoder(f).Decode(&state); err != nil { 129 return nil, err 130 } 131 now := time.Now() 132 133 mgr := fs.Manager{Paths: state.CgroupPaths} 134 cstats, err := mgr.GetStats() 135 if err != nil { 136 return nil, err 137 } 138 stats := &libcontainer.Stats{CgroupStats: cstats} 139 // if the container does not have any memory limit specified set the 140 // limit to the machines memory 141 memoryLimit := containerMemoryLimit 142 if memoryLimit == 0 { 143 memoryLimit = machineMemory 144 } 145 for _, iface := range state.Networks { 146 switch iface.Type { 147 case "veth": 148 istats, err := getNetworkInterfaceStats(iface.HostInterfaceName) 149 if err != nil { 150 return nil, err 151 } 152 stats.Interfaces = append(stats.Interfaces, istats) 153 } 154 } 155 return &ResourceStats{ 156 Stats: stats, 157 Read: now, 158 MemoryLimit: memoryLimit, 159 }, nil 160 }