113 lines
2.6 KiB
Go
113 lines
2.6 KiB
Go
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
|
|
}
|