+++ /dev/null
-// MsgSyncReq: enable and start services on the remote host (systemd)
-
-// Copyright (C) 2021 Simon Ruderich
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-package sync
-
-import (
- "fmt"
- "strings"
-
- "ruderich.org/simon/safcm"
-)
-
-func (s *Sync) syncServicesSystemd() error {
- s.log.Debugf("services: checking %s (systemd detected)",
- strings.Join(s.req.Services, " "))
- services, err := s.systemdServiceState(s.req.Services)
- if err != nil {
- return err
- }
-
- var start, enable []string
- for _, name := range s.req.Services {
- var change safcm.ServiceChange
-
- x := services[name]
- if x.ActiveState != "active" {
- start = append(start, name)
- change.Started = true
- }
- if x.UnitFileState != "enabled" {
- enable = append(enable, name)
- change.Enabled = true
- }
-
- if change.Started || change.Enabled {
- change.Name = name
- s.resp.ServiceChanges = append(s.resp.ServiceChanges,
- change)
- }
- }
- if len(start) == 0 && len(enable) == 0 {
- return nil
- }
-
- if s.req.DryRun {
- return nil
- }
-
- // Reload service files which were possibly changed during file sync
- // or package installation
- _, _, err = s.cmd.Run("services", "/bin/systemctl", "daemon-reload")
- if err != nil {
- return err
- }
- if len(start) != 0 {
- s.log.Verbosef("services: starting %s",
- strings.Join(start, " "))
- _, _, err := s.cmd.Run("services", append([]string{
- "/bin/systemctl", "start", "--",
- }, start...)...)
- if err != nil {
- return err
- }
- }
- if len(enable) != 0 {
- s.log.Verbosef("services: enabling %s",
- strings.Join(enable, " "))
- _, _, err := s.cmd.Run("services", append([]string{
- "/bin/systemctl", "enable", "--",
- }, enable...)...)
- if err != nil {
- return err
- }
- }
-
- return nil
-}
-
-type SystemdService struct {
- ActiveState string
- UnitFileState string
-}
-
-func (s *Sync) systemdServiceState(services []string) (
- map[string]SystemdService, error) {
-
- out, _, err := s.cmd.Run("services", append([]string{
- "/bin/systemctl",
- "show",
- "--property=ActiveState,UnitFileState,LoadError",
- "--",
- }, services...)...)
- if err != nil {
- return nil, err
- }
-
- i := 0
-
- res := make(map[string]SystemdService)
- for _, block := range strings.Split(string(out), "\n\n") {
- lines := strings.Split(strings.TrimSpace(block), "\n")
- if len(lines) != 3 {
- return nil, fmt.Errorf("invalid systemctl output: %q",
- block)
- }
-
- var service SystemdService
- for _, x := range lines {
- const (
- activePrefix = "ActiveState="
- unitPrefix = "UnitFileState="
- errorPrefix = "LoadError="
- )
-
- if strings.HasPrefix(x, activePrefix) {
- service.ActiveState = strings.TrimPrefix(x,
- activePrefix)
- } else if strings.HasPrefix(x, unitPrefix) {
- service.UnitFileState = strings.TrimPrefix(x,
- unitPrefix)
- } else if strings.HasPrefix(x, errorPrefix) {
- x := strings.TrimPrefix(x, errorPrefix)
- // Older systemd versions (e.g. 237) add empty
- // quotes even if there is no error
- if x != "" && x != ` ""` {
- return nil, fmt.Errorf(
- "systemd unit %q not found",
- services[i])
- }
- } else {
- return nil, fmt.Errorf(
- "invalid systemctl show line %q", x)
- }
- }
- res[services[i]] = service
-
- i++
- }
-
- return res, nil
-}