manager.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. // Copyright 2019 Yunion
  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 cgroupv1
  15. import (
  16. "io/ioutil"
  17. "os"
  18. "path"
  19. "path/filepath"
  20. "regexp"
  21. "strings"
  22. "yunion.io/x/log"
  23. "yunion.io/x/pkg/errors"
  24. "yunion.io/x/onecloud/pkg/util/cgrouputils/cgroup"
  25. "yunion.io/x/onecloud/pkg/util/fileutils2"
  26. "yunion.io/x/onecloud/pkg/util/procutils"
  27. )
  28. var (
  29. manager *cgroupManager
  30. )
  31. type cgroupManager struct {
  32. cgroupPath string
  33. ioScheduler string
  34. }
  35. func (m *cgroupManager) GetCgroupPath() string {
  36. return m.cgroupPath
  37. }
  38. func (m *cgroupManager) GetSubModulePath(module string) string {
  39. return path.Join(m.cgroupPath, module)
  40. }
  41. func (m *cgroupManager) GetCgroupVersion() string {
  42. return cgroup.CGROUP_V1
  43. }
  44. func (m *cgroupManager) GetIoScheduler() string {
  45. return m.ioScheduler
  46. }
  47. func (m *cgroupManager) CgroupIsMounted() bool {
  48. return procutils.NewCommand("mountpoint", m.cgroupPath).Run() == nil
  49. }
  50. func (m *cgroupManager) ModuleIsMounted(module string) bool {
  51. fullPath := path.Join(m.cgroupPath, module)
  52. if fi, err := os.Lstat(fullPath); err != nil {
  53. log.Errorln(err)
  54. return false
  55. } else if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
  56. // is link
  57. fullPath, err = filepath.EvalSymlinks(fullPath)
  58. if err != nil {
  59. log.Errorln(err)
  60. }
  61. }
  62. return procutils.NewCommand("mountpoint", fullPath).Run() == nil
  63. }
  64. func Init(cgroupPath, ioScheduler string) (*cgroupManager, error) {
  65. if manager != nil {
  66. return manager, nil
  67. }
  68. manager = &cgroupManager{
  69. cgroupPath: cgroupPath,
  70. ioScheduler: ioScheduler,
  71. }
  72. for _, hand := range []cgroup.ICGroupTask{
  73. &CGroupTask{},
  74. &CGroupCPUTask{},
  75. //&CGroupIOTask{},
  76. } {
  77. if !hand.Init() {
  78. return manager, errors.Errorf("Cannot initialize %s control group subsystem", hand.Module())
  79. }
  80. }
  81. return manager, nil
  82. }
  83. func RootTaskPath(module string) string {
  84. return path.Join(manager.cgroupPath, module)
  85. }
  86. func GetTaskParamPath(module, name, pid string) string {
  87. spath := RootTaskPath(module)
  88. if len(pid) > 0 {
  89. spath = path.Join(spath, pid)
  90. }
  91. return path.Join(spath, name)
  92. }
  93. func GetRootParam(module, name, pid string) string {
  94. param, err := fileutils2.FileGetContents(GetTaskParamPath(module, name, pid))
  95. if err != nil {
  96. log.Errorln(err)
  97. return ""
  98. }
  99. return strings.TrimSpace(param)
  100. }
  101. // cpuset, task, tid, cgname
  102. func SetRootParam(module, name, value, pid string) bool {
  103. param := GetRootParam(module, name, pid)
  104. if param != value {
  105. err := ioutil.WriteFile(GetTaskParamPath(module, name, pid), []byte(value), 0644)
  106. if err != nil {
  107. if len(pid) == 0 {
  108. pid = "root"
  109. }
  110. log.Errorf("fail to set %s to %s(%s): %s", name, value, pid, err)
  111. return false
  112. }
  113. }
  114. return true
  115. }
  116. func (m *cgroupManager) CgroupDestroy(pid, name string) bool {
  117. tasks := []cgroup.ICGroupTask{
  118. &CGroupCPUTask{&CGroupTask{}},
  119. &CGroupIOTask{&CGroupTask{}},
  120. &CGroupMemoryTask{&CGroupTask{}},
  121. //&CGroupCPUSetTask{&CGroupTask{}, ""},
  122. &CGroupIOHardlimitTask{CGroupIOTask: &CGroupIOTask{&CGroupTask{}}},
  123. }
  124. for _, hand := range tasks {
  125. hand.InitTask(hand, 0, pid, name)
  126. if !hand.RemoveTask() {
  127. return false
  128. }
  129. }
  130. return true
  131. }
  132. func (m *cgroupManager) CgroupCleanAll(subName string) {
  133. tasks := []cgroup.ICGroupTask{
  134. &CGroupCPUTask{&CGroupTask{}},
  135. &CGroupIOTask{&CGroupTask{}},
  136. &CGroupMemoryTask{&CGroupTask{}},
  137. &CGroupCPUSetTask{CGroupTask: &CGroupTask{}},
  138. &CGroupIOHardlimitTask{CGroupIOTask: &CGroupIOTask{&CGroupTask{}}},
  139. }
  140. for _, hand := range tasks {
  141. hand.SetHand(hand)
  142. cleanupNonexistPids(hand.Module(), subName)
  143. }
  144. }
  145. // cleanup
  146. func cleanupNonexistPids(module string, subName string) {
  147. var root = RootTaskPath(module)
  148. cleanNonexitPidsWithRoot(root)
  149. if subName != "" {
  150. root = path.Join(RootTaskPath(module), subName)
  151. cleanNonexitPidsWithRoot(root)
  152. }
  153. }
  154. func cleanNonexitPidsWithRoot(root string) {
  155. files, err := ioutil.ReadDir(root)
  156. if err != nil {
  157. log.Errorf("GetTaskIds failed: %s", err)
  158. return
  159. }
  160. ids := []string{}
  161. for _, file := range files {
  162. ids = append(ids, file.Name())
  163. }
  164. re1 := regexp.MustCompile(`^\d+$`)
  165. re2 := regexp.MustCompile(`^server_[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}_\d+$`)
  166. for _, pid := range ids {
  167. spid := ""
  168. if re1.MatchString(pid) {
  169. spid = pid
  170. } else if re2.MatchString(pid) {
  171. segs := strings.Split(pid, "_")
  172. spid = segs[len(segs)-1]
  173. }
  174. if fileutils2.IsDir(path.Join(root, pid)) {
  175. if !fileutils2.Exists(path.Join("/proc", spid)) {
  176. log.Infof("Cgroup cleanup %s", path.Join(root, pid))
  177. subFiles, err := ioutil.ReadDir(path.Join(root, pid))
  178. if err != nil {
  179. log.Errorf("sub dir %s GetTaskIds failed: %s", path.Join(root, pid), err)
  180. } else {
  181. for _, fi := range subFiles {
  182. if !fi.IsDir() {
  183. continue
  184. }
  185. if err := os.Remove(path.Join(root, pid, fi.Name())); err != nil {
  186. log.Errorf("CleanupNonexistPids pid=%s tid=%s error: %s", pid, fi.Name(), err)
  187. }
  188. }
  189. }
  190. if err := os.Remove(path.Join(root, pid)); err != nil {
  191. log.Errorf("CleanupNonexistPids pid=%s error: %s", pid, err)
  192. }
  193. }
  194. }
  195. }
  196. }