Add systemd resource budgets with TOML profiles
This commit is contained in:
commit
be8749a384
1 changed files with 2591 additions and 0 deletions
113
internal/budget/bus.go
Normal file
113
internal/budget/bus.go
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
package budget
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/godbus/dbus/v5"
|
||||
)
|
||||
|
||||
const api = "org.freedesktop.systemd1"
|
||||
const noUnit = api + ".NoSuchUnit"
|
||||
const noPID = "org.freedesktop.DBus.Error.UnixProcessIdUnknown"
|
||||
|
||||
type unit struct {
|
||||
Name string
|
||||
Description string
|
||||
Load string
|
||||
Active string
|
||||
Sub string
|
||||
Following string
|
||||
Path dbus.ObjectPath
|
||||
Job uint32
|
||||
JobType string
|
||||
JobPath dbus.ObjectPath
|
||||
}
|
||||
|
||||
type unitState struct {
|
||||
Active string
|
||||
Group string
|
||||
}
|
||||
|
||||
type unitCtl interface {
|
||||
Units() ([]unit, error)
|
||||
Group(string) (string, error)
|
||||
Set(string, []property) error
|
||||
Start(string, []property) error
|
||||
State(string) (unitState, error)
|
||||
Stop(string) error
|
||||
}
|
||||
|
||||
type manager struct {
|
||||
conn *dbus.Conn
|
||||
obj dbus.BusObject
|
||||
}
|
||||
|
||||
type auxiliary struct {
|
||||
Name string
|
||||
Properties []property
|
||||
}
|
||||
|
||||
func connect() (*manager, error) {
|
||||
conn, err := dbus.ConnectSessionBus()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &manager{conn: conn, obj: conn.Object(api, "/org/freedesktop/systemd1")}, nil
|
||||
}
|
||||
|
||||
func busError(err error, name string) bool {
|
||||
var e dbus.Error
|
||||
return errors.As(err, &e) && e.Name == name
|
||||
}
|
||||
|
||||
func (m *manager) Units() ([]unit, error) {
|
||||
var units []unit
|
||||
err := m.obj.Call(api+".Manager.ListUnits", 0).Store(&units)
|
||||
return units, err
|
||||
}
|
||||
|
||||
func (m *manager) object(name string) (dbus.BusObject, error) {
|
||||
var path dbus.ObjectPath
|
||||
if err := m.obj.Call(api+".Manager.GetUnit", 0, name).Store(&path); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m.conn.Object(api, path), nil
|
||||
}
|
||||
|
||||
func (m *manager) Group(name string) (string, error) {
|
||||
obj, err := m.object(name)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
kind := name[strings.LastIndex(name, ".")+1:]
|
||||
kind = strings.ToUpper(kind[:1]) + kind[1:]
|
||||
var group string
|
||||
err = obj.StoreProperty(api+"."+kind+".ControlGroup", &group)
|
||||
return group, err
|
||||
}
|
||||
|
||||
func (m *manager) Set(name string, values []property) error {
|
||||
return m.obj.Call(api+".Manager.SetUnitProperties", 0, name, true, values).Err
|
||||
}
|
||||
|
||||
func (m *manager) Start(name string, values []property) error {
|
||||
return m.obj.Call(api+".Manager.StartTransientUnit", 0, name, "fail", values, []auxiliary{}).Err
|
||||
}
|
||||
|
||||
func (m *manager) State(name string) (unitState, error) {
|
||||
obj, err := m.object(name)
|
||||
if err != nil {
|
||||
return unitState{}, err
|
||||
}
|
||||
var state unitState
|
||||
if err = obj.StoreProperty(api+".Unit.ActiveState", &state.Active); err != nil {
|
||||
return unitState{}, err
|
||||
}
|
||||
err = obj.StoreProperty(api+".Scope.ControlGroup", &state.Group)
|
||||
return state, err
|
||||
}
|
||||
|
||||
func (m *manager) Stop(name string) error {
|
||||
return m.obj.Call(api+".Manager.StopUnit", 0, name, "replace").Err
|
||||
}
|
||||
Loading…
Reference in a new issue