helpers.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. // Copyright 2014 Google Inc. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package libcontainer
  15. import (
  16. "fmt"
  17. info "github.com/google/cadvisor/info/v1"
  18. "github.com/google/cadvisor/container"
  19. "github.com/opencontainers/runc/libcontainer/cgroups"
  20. "k8s.io/klog"
  21. )
  22. type CgroupSubsystems struct {
  23. // Cgroup subsystem mounts.
  24. // e.g.: "/sys/fs/cgroup/cpu" -> ["cpu", "cpuacct"]
  25. Mounts []cgroups.Mount
  26. // Cgroup subsystem to their mount location.
  27. // e.g.: "cpu" -> "/sys/fs/cgroup/cpu"
  28. MountPoints map[string]string
  29. }
  30. // Get information about the cgroup subsystems those we want
  31. func GetCgroupSubsystems(includedMetrics container.MetricSet) (CgroupSubsystems, error) {
  32. // Get all cgroup mounts.
  33. allCgroups, err := cgroups.GetCgroupMounts(true)
  34. if err != nil {
  35. return CgroupSubsystems{}, err
  36. }
  37. disableCgroups := map[string]struct{}{}
  38. //currently we only support disable blkio subsystem
  39. if !includedMetrics.Has(container.DiskIOMetrics) {
  40. disableCgroups["blkio"] = struct{}{}
  41. disableCgroups["io"] = struct{}{}
  42. }
  43. return getCgroupSubsystemsHelper(allCgroups, disableCgroups)
  44. }
  45. // Get information about all the cgroup subsystems.
  46. func GetAllCgroupSubsystems() (CgroupSubsystems, error) {
  47. // Get all cgroup mounts.
  48. allCgroups, err := cgroups.GetCgroupMounts(true)
  49. if err != nil {
  50. return CgroupSubsystems{}, err
  51. }
  52. emptyDisableCgroups := map[string]struct{}{}
  53. return getCgroupSubsystemsHelper(allCgroups, emptyDisableCgroups)
  54. }
  55. func getCgroupSubsystemsHelper(allCgroups []cgroups.Mount, disableCgroups map[string]struct{}) (CgroupSubsystems, error) {
  56. if len(allCgroups) == 0 {
  57. return CgroupSubsystems{}, fmt.Errorf("failed to find cgroup mounts")
  58. }
  59. // Trim the mounts to only the subsystems we care about.
  60. supportedCgroups := make([]cgroups.Mount, 0, len(allCgroups))
  61. recordedMountpoints := make(map[string]struct{}, len(allCgroups))
  62. mountPoints := make(map[string]string, len(allCgroups))
  63. for _, mount := range allCgroups {
  64. for _, subsystem := range mount.Subsystems {
  65. if _, exists := disableCgroups[subsystem]; exists {
  66. continue
  67. }
  68. if _, ok := supportedSubsystems[subsystem]; !ok {
  69. // Unsupported subsystem
  70. continue
  71. }
  72. if _, ok := mountPoints[subsystem]; ok {
  73. // duplicate mount for this subsystem; use the first one we saw
  74. klog.V(5).Infof("skipping %s, already using mount at %s", mount.Mountpoint, mountPoints[subsystem])
  75. continue
  76. }
  77. if _, ok := recordedMountpoints[mount.Mountpoint]; !ok {
  78. // avoid appending the same mount twice in e.g. `cpu,cpuacct` case
  79. supportedCgroups = append(supportedCgroups, mount)
  80. recordedMountpoints[mount.Mountpoint] = struct{}{}
  81. }
  82. mountPoints[subsystem] = mount.Mountpoint
  83. }
  84. }
  85. return CgroupSubsystems{
  86. Mounts: supportedCgroups,
  87. MountPoints: mountPoints,
  88. }, nil
  89. }
  90. // Cgroup subsystems we support listing (should be the minimal set we need stats from).
  91. var supportedSubsystems map[string]struct{} = map[string]struct{}{
  92. "cpu": {},
  93. "cpuacct": {},
  94. "memory": {},
  95. "pids": {},
  96. "cpuset": {},
  97. "blkio": {},
  98. "io": {},
  99. "devices": {},
  100. }
  101. func DiskStatsCopy0(major, minor uint64) *info.PerDiskStats {
  102. disk := info.PerDiskStats{
  103. Major: major,
  104. Minor: minor,
  105. }
  106. disk.Stats = make(map[string]uint64)
  107. return &disk
  108. }
  109. type DiskKey struct {
  110. Major uint64
  111. Minor uint64
  112. }
  113. func DiskStatsCopy1(disk_stat map[DiskKey]*info.PerDiskStats) []info.PerDiskStats {
  114. i := 0
  115. stat := make([]info.PerDiskStats, len(disk_stat))
  116. for _, disk := range disk_stat {
  117. stat[i] = *disk
  118. i++
  119. }
  120. return stat
  121. }
  122. func DiskStatsCopy(blkio_stats []cgroups.BlkioStatEntry) (stat []info.PerDiskStats) {
  123. if len(blkio_stats) == 0 {
  124. return
  125. }
  126. disk_stat := make(map[DiskKey]*info.PerDiskStats)
  127. for i := range blkio_stats {
  128. major := blkio_stats[i].Major
  129. minor := blkio_stats[i].Minor
  130. disk_key := DiskKey{
  131. Major: major,
  132. Minor: minor,
  133. }
  134. diskp, ok := disk_stat[disk_key]
  135. if !ok {
  136. diskp = DiskStatsCopy0(major, minor)
  137. disk_stat[disk_key] = diskp
  138. }
  139. op := blkio_stats[i].Op
  140. if op == "" {
  141. op = "Count"
  142. }
  143. diskp.Stats[op] = blkio_stats[i].Value
  144. }
  145. return DiskStatsCopy1(disk_stat)
  146. }