bump(github.com/coreos/go-systemd/dbus): 4fbc5060a317b142e6c7bfbedb65596d5f0ab99b
This commit is contained in:
parent
477ae29135
commit
f5f9a0a6a9
@ -18,6 +18,8 @@ limitations under the License.
|
|||||||
package dbus
|
package dbus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@ -73,7 +75,12 @@ func (c *Conn) initConnection() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.sysconn.Auth(nil)
|
// Only use EXTERNAL method, and hardcode the uid (not username)
|
||||||
|
// to avoid a username lookup (which requires a dynamically linked
|
||||||
|
// libc)
|
||||||
|
methods := []dbus.Auth{dbus.AuthExternal(strconv.Itoa(os.Getuid()))}
|
||||||
|
|
||||||
|
err = c.sysconn.Auth(methods)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.sysconn.Close()
|
c.sysconn.Close()
|
||||||
return err
|
return err
|
||||||
|
@ -35,6 +35,7 @@ func (c *Conn) jobComplete(signal *dbus.Signal) {
|
|||||||
out, ok := c.jobListener.jobs[job]
|
out, ok := c.jobListener.jobs[job]
|
||||||
if ok {
|
if ok {
|
||||||
out <- result
|
out <- result
|
||||||
|
delete(c.jobListener.jobs, job)
|
||||||
}
|
}
|
||||||
c.jobListener.Unlock()
|
c.jobListener.Unlock()
|
||||||
}
|
}
|
||||||
@ -137,8 +138,8 @@ func (c *Conn) KillUnit(name string, signal int32) {
|
|||||||
c.sysobj.Call("org.freedesktop.systemd1.Manager.KillUnit", 0, name, "all", signal).Store()
|
c.sysobj.Call("org.freedesktop.systemd1.Manager.KillUnit", 0, name, "all", signal).Store()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUnitProperties takes the unit name and returns all of its dbus object properties.
|
// getProperties takes the unit name and returns all of its dbus object properties, for the given dbus interface
|
||||||
func (c *Conn) GetUnitProperties(unit string) (map[string]interface{}, error) {
|
func (c *Conn) getProperties(unit string, dbusInterface string) (map[string]interface{}, error) {
|
||||||
var err error
|
var err error
|
||||||
var props map[string]dbus.Variant
|
var props map[string]dbus.Variant
|
||||||
|
|
||||||
@ -148,7 +149,7 @@ func (c *Conn) GetUnitProperties(unit string) (map[string]interface{}, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
obj := c.sysconn.Object("org.freedesktop.systemd1", path)
|
obj := c.sysconn.Object("org.freedesktop.systemd1", path)
|
||||||
err = obj.Call("org.freedesktop.DBus.Properties.GetAll", 0, "org.freedesktop.systemd1.Unit").Store(&props)
|
err = obj.Call("org.freedesktop.DBus.Properties.GetAll", 0, dbusInterface).Store(&props)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -161,6 +162,55 @@ func (c *Conn) GetUnitProperties(unit string) (map[string]interface{}, error) {
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetUnitProperties takes the unit name and returns all of its dbus object properties.
|
||||||
|
func (c *Conn) GetUnitProperties(unit string) (map[string]interface{}, error) {
|
||||||
|
return c.getProperties(unit, "org.freedesktop.systemd1.Unit")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) getProperty(unit string, dbusInterface string, propertyName string) (*Property, error) {
|
||||||
|
var err error
|
||||||
|
var prop dbus.Variant
|
||||||
|
|
||||||
|
path := ObjectPath("/org/freedesktop/systemd1/unit/" + unit)
|
||||||
|
if !path.IsValid() {
|
||||||
|
return nil, errors.New("invalid unit name: " + unit)
|
||||||
|
}
|
||||||
|
|
||||||
|
obj := c.sysconn.Object("org.freedesktop.systemd1", path)
|
||||||
|
err = obj.Call("org.freedesktop.DBus.Properties.Get", 0, dbusInterface, propertyName).Store(&prop)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Property{Name: propertyName, Value: prop}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) GetUnitProperty(unit string, propertyName string) (*Property, error) {
|
||||||
|
return c.getProperty(unit, "org.freedesktop.systemd1.Unit", propertyName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUnitTypeProperties returns the extra properties for a unit, specific to the unit type.
|
||||||
|
// Valid values for unitType: Service, Socket, Target, Device, Mount, Automount, Snapshot, Timer, Swap, Path, Slice, Scope
|
||||||
|
// return "dbus.Error: Unknown interface" if the unitType is not the correct type of the unit
|
||||||
|
func (c *Conn) GetUnitTypeProperties(unit string, unitType string) (map[string]interface{}, error) {
|
||||||
|
return c.getProperties(unit, "org.freedesktop.systemd1."+unitType)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetUnitProperties() may be used to modify certain unit properties at runtime.
|
||||||
|
// Not all properties may be changed at runtime, but many resource management
|
||||||
|
// settings (primarily those in systemd.cgroup(5)) may. The changes are applied
|
||||||
|
// instantly, and stored on disk for future boots, unless runtime is true, in which
|
||||||
|
// case the settings only apply until the next reboot. name is the name of the unit
|
||||||
|
// to modify. properties are the settings to set, encoded as an array of property
|
||||||
|
// name and value pairs.
|
||||||
|
func (c *Conn) SetUnitProperties(name string, runtime bool, properties ...Property) error {
|
||||||
|
return c.sysobj.Call("SetUnitProperties", 0, name, runtime, properties).Store()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) GetUnitTypeProperty(unit string, unitType string, propertyName string) (*Property, error) {
|
||||||
|
return c.getProperty(unit, "org.freedesktop.systemd1." + unitType, propertyName)
|
||||||
|
}
|
||||||
|
|
||||||
// ListUnits returns an array with all currently loaded units. Note that
|
// ListUnits returns an array with all currently loaded units. Note that
|
||||||
// units may be known by multiple names at the same time, and hence there might
|
// units may be known by multiple names at the same time, and hence there might
|
||||||
// be more unit names loaded than actual units behind them.
|
// be more unit names loaded than actual units behind them.
|
||||||
@ -253,8 +303,52 @@ type EnableUnitFileChange struct {
|
|||||||
Destination string // Destination of the symlink
|
Destination string // Destination of the symlink
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DisableUnitFiles() may be used to disable one or more units in the system (by
|
||||||
|
// removing symlinks to them from /etc or /run).
|
||||||
|
//
|
||||||
|
// It takes a list of unit files to disable (either just file names or full
|
||||||
|
// absolute paths if the unit files are residing outside the usual unit
|
||||||
|
// search paths), and one boolean: whether the unit was enabled for runtime
|
||||||
|
// only (true, /run), or persistently (false, /etc).
|
||||||
|
//
|
||||||
|
// This call returns an array with the changes made. The changes list
|
||||||
|
// consists of structures with three strings: the type of the change (one of
|
||||||
|
// symlink or unlink), the file name of the symlink and the destination of the
|
||||||
|
// symlink.
|
||||||
|
func (c *Conn) DisableUnitFiles(files []string, runtime bool) ([]DisableUnitFileChange, error) {
|
||||||
|
result := make([][]interface{}, 0)
|
||||||
|
err := c.sysobj.Call("DisableUnitFiles", 0, files, runtime).Store(&result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resultInterface := make([]interface{}, len(result))
|
||||||
|
for i := range result {
|
||||||
|
resultInterface[i] = result[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
changes := make([]DisableUnitFileChange, len(result))
|
||||||
|
changesInterface := make([]interface{}, len(changes))
|
||||||
|
for i := range changes {
|
||||||
|
changesInterface[i] = &changes[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
err = dbus.Store(resultInterface, changesInterface...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return changes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type DisableUnitFileChange struct {
|
||||||
|
Type string // Type of the change (one of symlink or unlink)
|
||||||
|
Filename string // File name of the symlink
|
||||||
|
Destination string // Destination of the symlink
|
||||||
|
}
|
||||||
|
|
||||||
// Reload instructs systemd to scan for and reload unit files. This is
|
// Reload instructs systemd to scan for and reload unit files. This is
|
||||||
// equivalent to a 'systemctl daemon-reload'.
|
// equivalent to a 'systemctl daemon-reload'.
|
||||||
func (c *Conn) Reload() (string, error) {
|
func (c *Conn) Reload() error {
|
||||||
return c.runJob("org.freedesktop.systemd1.Manager.Reload")
|
return c.sysobj.Call("org.freedesktop.systemd1.Manager.Reload", 0).Store()
|
||||||
}
|
}
|
||||||
|
@ -18,9 +18,11 @@ package dbus
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/coreos/coreos-cloudinit/third_party/github.com/guelfey/go.dbus"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -50,13 +52,16 @@ func setupUnit(target string, conn *Conn, t *testing.T) {
|
|||||||
fixture := []string{abs}
|
fixture := []string{abs}
|
||||||
|
|
||||||
install, changes, err := conn.EnableUnitFiles(fixture, true, true)
|
install, changes, err := conn.EnableUnitFiles(fixture, true, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
if install != false {
|
if install != false {
|
||||||
t.Fatal("Install was true")
|
t.Fatal("Install was true")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(changes) < 1 {
|
if len(changes) < 1 {
|
||||||
t.Fatal("Expected one change, got %v", changes)
|
t.Fatalf("Expected one change, got %v", changes)
|
||||||
}
|
}
|
||||||
|
|
||||||
if changes[0].Filename != targetRun {
|
if changes[0].Filename != targetRun {
|
||||||
@ -118,6 +123,37 @@ func TestStartStopUnit(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enables a unit and then immediately tears it down
|
||||||
|
func TestEnableDisableUnit(t *testing.T) {
|
||||||
|
target := "enable-disable.service"
|
||||||
|
conn := setupConn(t)
|
||||||
|
|
||||||
|
setupUnit(target, conn, t)
|
||||||
|
|
||||||
|
abs, err := filepath.Abs("../fixtures/" + target)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
path := filepath.Join("/run/systemd/system/", target)
|
||||||
|
|
||||||
|
// 2. Disable the unit
|
||||||
|
changes, err := conn.DisableUnitFiles([]string{abs}, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(changes) != 1 {
|
||||||
|
t.Fatalf("Changes should include the path, %v", changes)
|
||||||
|
}
|
||||||
|
if changes[0].Filename != path {
|
||||||
|
t.Fatalf("Change should include correct filename, %+v", changes[0])
|
||||||
|
}
|
||||||
|
if changes[0].Destination != "" {
|
||||||
|
t.Fatalf("Change destination should be empty, %+v", changes[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestGetUnitProperties reads the `-.mount` which should exist on all systemd
|
// TestGetUnitProperties reads the `-.mount` which should exist on all systemd
|
||||||
// systems and ensures that one of its properties is valid.
|
// systems and ensures that one of its properties is valid.
|
||||||
func TestGetUnitProperties(t *testing.T) {
|
func TestGetUnitProperties(t *testing.T) {
|
||||||
@ -139,6 +175,20 @@ func TestGetUnitProperties(t *testing.T) {
|
|||||||
if names[0] != "system.slice" {
|
if names[0] != "system.slice" {
|
||||||
t.Fatal("unexpected wants for /")
|
t.Fatal("unexpected wants for /")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prop, err := conn.GetUnitProperty(unit, "Wants")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if prop.Name != "Wants" {
|
||||||
|
t.Fatal("unexpected property name")
|
||||||
|
}
|
||||||
|
|
||||||
|
val := prop.Value.Value().([]string)
|
||||||
|
if !reflect.DeepEqual(val, names) {
|
||||||
|
t.Fatal("unexpected property value")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestGetUnitPropertiesRejectsInvalidName attempts to get the properties for a
|
// TestGetUnitPropertiesRejectsInvalidName attempts to get the properties for a
|
||||||
@ -150,10 +200,37 @@ func TestGetUnitPropertiesRejectsInvalidName(t *testing.T) {
|
|||||||
unit := "//invalid#$^/"
|
unit := "//invalid#$^/"
|
||||||
|
|
||||||
_, err := conn.GetUnitProperties(unit)
|
_, err := conn.GetUnitProperties(unit)
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("Expected an error, got nil")
|
t.Fatal("Expected an error, got nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_, err = conn.GetUnitProperty(unit, "Wants")
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("Expected an error, got nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestSetUnitProperties changes a cgroup setting on the `tmp.mount`
|
||||||
|
// which should exist on all systemd systems and ensures that the
|
||||||
|
// property was set.
|
||||||
|
func TestSetUnitProperties(t *testing.T) {
|
||||||
|
conn := setupConn(t)
|
||||||
|
|
||||||
|
unit := "tmp.mount"
|
||||||
|
|
||||||
|
if err := conn.SetUnitProperties(unit, true, Property{"CPUShares", dbus.MakeVariant(uint64(1023))}); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := conn.GetUnitTypeProperties(unit, "Mount")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
value := info["CPUShares"].(uint64)
|
||||||
|
if value != 1023 {
|
||||||
|
t.Fatal("CPUShares of unit is not 1023, %s", value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that basic transient unit starting and stopping works.
|
// Ensure that basic transient unit starting and stopping works.
|
||||||
@ -211,3 +288,27 @@ func TestStartStopTransientUnit(t *testing.T) {
|
|||||||
t.Fatalf("Test unit found in list, should be stopped")
|
t.Fatalf("Test unit found in list, should be stopped")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestConnJobListener(t *testing.T) {
|
||||||
|
target := "start-stop.service"
|
||||||
|
conn := setupConn(t)
|
||||||
|
|
||||||
|
setupUnit(target, conn, t)
|
||||||
|
|
||||||
|
jobSize := len(conn.jobListener.jobs)
|
||||||
|
|
||||||
|
_, err := conn.StartUnit(target, "replace")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = conn.StopUnit(target, "replace")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
currentJobSize := len(conn.jobListener.jobs)
|
||||||
|
if jobSize != currentJobSize {
|
||||||
|
t.Fatal("JobListener jobs leaked")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -209,3 +209,12 @@ func PropPropagatesReloadTo(units ...string) Property {
|
|||||||
func PropRequiresMountsFor(units ...string) Property {
|
func PropRequiresMountsFor(units ...string) Property {
|
||||||
return propDependency("RequiresMountsFor", units)
|
return propDependency("RequiresMountsFor", units)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PropSlice sets the Slice unit property. See
|
||||||
|
// http://www.freedesktop.org/software/systemd/man/systemd.resource-control.html#Slice=
|
||||||
|
func PropSlice(slice string) Property {
|
||||||
|
return Property{
|
||||||
|
Name: "Slice",
|
||||||
|
Value: dbus.MakeVariant(slice),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user