agent/cgroup/manager.go (132 lines of code) (raw):
//+build linux
package cgroup
import (
"errors"
"fmt"
)
var (
ErrCgroupRemoved = errors.New("Unable to continue. Control group already removed")
)
// The wrapper around the several control groups to more convenient using.
type Manager struct {
pid int
cgroups map[string]Cgroup
isRemoved bool
}
func NewManager(pid int, subpath string, subsystems ...string) (*Manager, error) {
cgroupList, err := GetEnabledSubsystems()
if err != nil {
return nil, err
}
for _, s := range subsystems {
if _, ok := cgroupList[s]; !ok {
return nil, fmt.Errorf("Unknown subsystem: %s", s)
}
}
cgroups := make(map[string]Cgroup)
for _, s := range subsystems {
switch s {
case "cpu":
g, err := NewCpuGroup(subpath, pid)
if err != nil {
return nil, NewCgroupInitError(s, err)
}
cgroups[s] = g
case "memory":
g, err := NewMemoryGroup(subpath, pid)
if err != nil {
return nil, NewCgroupInitError(s, err)
}
cgroups[s] = g
default:
return nil, NewUnsupportedError(s)
}
}
return &Manager{pid: pid, cgroups: cgroups}, nil
}
func LoadManager(pid int) (*Manager, error) {
cgroupList, err := GetProcessCgroups(pid)
if err != nil {
return nil, err
}
if len(cgroupList) == 0 {
return nil, NewCgroupsNotFoundError(pid)
}
cgroups := make(map[string]Cgroup)
for s, _ := range cgroupList {
switch g, err := LookupCgroupByPid(pid, s); {
case err == nil:
cgroups[s] = g
case IsUnsupportedError(err):
continue
default:
return nil, err
}
}
return &Manager{pid: pid, cgroups: cgroups}, nil
}
func (m *Manager) GetPid() int {
return m.pid
}
func (m *Manager) Set(c *Config) error {
if m.isRemoved {
return ErrCgroupRemoved
}
for _, g := range m.cgroups {
if err := g.Set(c); err != nil {
return err
}
}
return nil
}
func (m *Manager) Get(c *Config) error {
if m.isRemoved {
return ErrCgroupRemoved
}
for _, g := range m.cgroups {
if err := g.Get(c); err != nil {
return err
}
}
return nil
}
func (m *Manager) Destroy() error {
m.isRemoved = true
for _, g := range m.cgroups {
if err := DestroyCgroup(g.GetPath()); err != nil {
return err
}
}
return nil
}
type CgroupInitError struct {
Subsystem string
Err error
}
func (e *CgroupInitError) Error() string {
return fmt.Sprintf("Cannot create %s control group: %s", e.Subsystem, e.Err)
}
func NewCgroupInitError(subsystem string, err error) error {
return &CgroupInitError{subsystem, err}
}
func IsCgroupInitError(err error) bool {
if err == nil {
return false
}
_, ok := err.(*CgroupInitError)
return ok
}
type CgroupsNotFoundError struct {
pid int
}
func (e *CgroupsNotFoundError) Error() string {
return fmt.Sprintf("No one control group is found: %d", e.pid)
}
func NewCgroupsNotFoundError(pid int) error {
return &CgroupsNotFoundError{pid}
}
func IsCgroupsNotFoundError(err error) bool {
if err == nil {
return false
}
_, ok := err.(*CgroupsNotFoundError)
return ok
}