systemd.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. package cgroups
  2. import (
  3. "fmt"
  4. "path/filepath"
  5. "strings"
  6. "sync"
  7. systemdDbus "github.com/coreos/go-systemd/dbus"
  8. "github.com/godbus/dbus"
  9. specs "github.com/opencontainers/runtime-spec/specs-go"
  10. )
  11. const (
  12. SystemdDbus Name = "systemd"
  13. defaultSlice = "system.slice"
  14. )
  15. func Systemd() ([]Subsystem, error) {
  16. root, err := v1MountPoint()
  17. if err != nil {
  18. return nil, err
  19. }
  20. defaultSubsystems, err := defaults(root)
  21. if err != nil {
  22. return nil, err
  23. }
  24. s, err := NewSystemd(root)
  25. if err != nil {
  26. return nil, err
  27. }
  28. // make sure the systemd controller is added first
  29. return append([]Subsystem{s}, defaultSubsystems...), nil
  30. }
  31. func Slice(slice, name string) Path {
  32. if slice == "" {
  33. slice = defaultSlice
  34. }
  35. return func(subsystem Name) (string, error) {
  36. return filepath.Join(slice, unitName(name)), nil
  37. }
  38. }
  39. func NewSystemd(root string) (*SystemdController, error) {
  40. return &SystemdController{
  41. root: root,
  42. }, nil
  43. }
  44. type SystemdController struct {
  45. mu sync.Mutex
  46. root string
  47. }
  48. func (s *SystemdController) Name() Name {
  49. return SystemdDbus
  50. }
  51. func (s *SystemdController) Create(path string, resources *specs.LinuxResources) error {
  52. conn, err := systemdDbus.New()
  53. if err != nil {
  54. return err
  55. }
  56. defer conn.Close()
  57. slice, name := splitName(path)
  58. properties := []systemdDbus.Property{
  59. systemdDbus.PropDescription(fmt.Sprintf("cgroup %s", name)),
  60. systemdDbus.PropWants(slice),
  61. newProperty("DefaultDependencies", false),
  62. newProperty("Delegate", true),
  63. newProperty("MemoryAccounting", true),
  64. newProperty("CPUAccounting", true),
  65. newProperty("BlockIOAccounting", true),
  66. }
  67. ch := make(chan string)
  68. _, err = conn.StartTransientUnit(name, "replace", properties, ch)
  69. if err != nil {
  70. return err
  71. }
  72. <-ch
  73. return nil
  74. }
  75. func (s *SystemdController) Delete(path string) error {
  76. conn, err := systemdDbus.New()
  77. if err != nil {
  78. return err
  79. }
  80. defer conn.Close()
  81. _, name := splitName(path)
  82. ch := make(chan string)
  83. _, err = conn.StopUnit(name, "replace", ch)
  84. if err != nil {
  85. return err
  86. }
  87. <-ch
  88. return nil
  89. }
  90. func newProperty(name string, units interface{}) systemdDbus.Property {
  91. return systemdDbus.Property{
  92. Name: name,
  93. Value: dbus.MakeVariant(units),
  94. }
  95. }
  96. func unitName(name string) string {
  97. return fmt.Sprintf("%s.slice", name)
  98. }
  99. func splitName(path string) (slice string, unit string) {
  100. slice, unit = filepath.Split(path)
  101. return strings.TrimSuffix(slice, "/"), unit
  102. }