diff --git a/cmd/sd-dbus-hooks/start.go b/cmd/sd-dbus-hooks/start.go index 548b6d9..588c1c0 100644 --- a/cmd/sd-dbus-hooks/start.go +++ b/cmd/sd-dbus-hooks/start.go @@ -49,7 +49,8 @@ func (h unitStartHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { func start(conn *dbus.Conn, cfg *Config, u Unit, ch chan<- string) error { // check if unit active - units, err := conn.ListUnitsByPatterns([]string{"active"}, []string{u.Name}) + // units, err := conn.ListUnitsByPatterns([]string{"active"}, []string{u.Name}) + units, err := listUnitsByPatterns(conn, []string{"active"}, []string{u.Name}) if err != nil { return err } @@ -60,7 +61,8 @@ func start(conn *dbus.Conn, cfg *Config, u Unit, ch chan<- string) error { if len(u.BlockedBy) > 0 { // check if unit blocked by other active unit - blockUnits, err := conn.ListUnitsByPatterns([]string{"active"}, u.BlockedBy) + // blockUnits, err := conn.ListUnitsByPatterns([]string{"active"}, u.BlockedBy) + blockUnits, err := listUnitsByPatterns(conn, []string{"active"}, u.BlockedBy) if err != nil { return err } diff --git a/cmd/sd-dbus-hooks/status.go b/cmd/sd-dbus-hooks/status.go index 7fea4b4..ec6f136 100644 --- a/cmd/sd-dbus-hooks/status.go +++ b/cmd/sd-dbus-hooks/status.go @@ -34,7 +34,11 @@ func (h unitStatusHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } else { matchFilter = []string{name} } - units, unitsErr := h.conn.ListUnitsByPatterns([]string{"active", "inactive", "failed"}, matchFilter) + + // ListUnitsByPatterns is not available on systemd-219 (centos7) + //units, unitsErr := h.conn.ListUnitsByPatterns([]string{"active", "inactive", "failed"}, matchFilter) + + units, unitsErr := listUnitsByPatterns(h.conn, []string{"active", "inactive", "failed"}, matchFilter) if unitsErr != nil { log.Printf("[ERROR] %s", unitsErr) http.Error(w, unitsErr.Error(), http.StatusInternalServerError) diff --git a/cmd/sd-dbus-hooks/utils.go b/cmd/sd-dbus-hooks/utils.go new file mode 100644 index 0000000..070e064 --- /dev/null +++ b/cmd/sd-dbus-hooks/utils.go @@ -0,0 +1,74 @@ +package main + +import ( + "errors" + "log" + "path" + + "github.com/coreos/go-systemd/dbus" +) + +func listUnitsByPatterns(conn *dbus.Conn, states []string, patterns []string) ([]dbus.UnitStatus, error) { + var result []dbus.UnitStatus + + units, err := conn.ListUnits() + if err != nil { + return nil, err + } + + for _, unit := range units { + if contains(patterns, unit.Name) && contains(states, unit.ActiveState) { + result = append(result, unit) + continue + } + } + + // systemd can doesn't show all loaded units in some cases (if there's no reason to keep it in memory) + // https://github.com/systemd/systemd/issues/5063 + // + // so, list all units files for matched names and add it to results + unitFiles, err := conn.ListUnitFiles() + if err != nil { + return nil, err + } + +UNIT_FILES_LOOP: + for _, unitFile := range unitFiles { + name := path.Base(unitFile.Path) + // skip unit file if result already exist + for _, v := range result { + if name == v.Name { + log.Printf("[DEBUG] unit %v already in results", v.Name) + continue UNIT_FILES_LOOP + } + } + if contains(patterns, name) { + us := dbus.UnitStatus{ + Name: name, + Description: "", + LoadState: "not in memory", + ActiveState: "not in memory", + SubState: unitFile.Type, + } + result = append(result, us) + continue + } + } + + if len(result) == 0 { + return result, errors.New("units not found") + } + + return result, nil +} + +// return true if string `v` contains in slice `s` +func contains(s []string, v string) bool { + for _, i := range s { + if i == v { + return true + } + } + + return false +} diff --git a/cmd/sd-dbus-hooks/utils_test.go b/cmd/sd-dbus-hooks/utils_test.go new file mode 100644 index 0000000..aa15278 --- /dev/null +++ b/cmd/sd-dbus-hooks/utils_test.go @@ -0,0 +1,14 @@ +package main + +import "testing" + +func TestUtils(t *testing.T) { + items := []string{"one", "two", "three"} + if !contains(items, "one") { + t.Errorf("contains: got false, expected true") + } + + if contains(items, "four") { + t.Errorf("contains: got true, expected false") + } +}