github.com/caos/orbos@v1.5.14-0.20221103111702-e6cd0cea7ad4/internal/operator/nodeagent/dep/systemd.go (about) 1 package dep 2 3 import ( 4 "bytes" 5 "fmt" 6 "os" 7 "os/exec" 8 "strings" 9 10 "github.com/caos/orbos/mntr" 11 ) 12 13 type SystemD struct { 14 monitor mntr.Monitor 15 } 16 17 func NewSystemD(monitor mntr.Monitor) *SystemD { 18 return &SystemD{monitor} 19 } 20 21 func (s *SystemD) Disable(binary string) error { 22 23 errBuf := new(bytes.Buffer) 24 defer errBuf.Reset() 25 26 cmd := exec.Command("systemctl", "stop", binary) 27 cmd.Stderr = errBuf 28 if s.monitor.IsVerbose() { 29 fmt.Println(strings.Join(cmd.Args, " ")) 30 cmd.Stdout = os.Stdout 31 } 32 err := cmd.Run() 33 if err != nil { 34 errString := errBuf.String() 35 if strings.Contains(errString, "not loaded") { 36 err = nil 37 } else { 38 return fmt.Errorf("stopping %s by systemd failed with stderr %s: %w", binary, errString, err) 39 } 40 } 41 42 errBuf.Reset() 43 cmd = exec.Command("systemctl", "disable", binary) 44 cmd.Stderr = errBuf 45 if s.monitor.IsVerbose() { 46 fmt.Println(strings.Join(cmd.Args, " ")) 47 cmd.Stdout = os.Stdout 48 } 49 if err := cmd.Run(); err != nil { 50 errString := errBuf.String() 51 if strings.Contains(errString, "No such file or directory") { 52 err = nil 53 } else { 54 return fmt.Errorf("disabling %s by systemd failed with stderr %s: %w", binary, errString, err) 55 } 56 } 57 58 return nil 59 } 60 61 func (s *SystemD) Start(binary string) error { 62 errBuf := new(bytes.Buffer) 63 defer errBuf.Reset() 64 65 cmd := exec.Command("systemctl", "restart", binary) 66 cmd.Stderr = errBuf 67 68 if err := cmd.Run(); err != nil { 69 return fmt.Errorf("restarting %s from systemd failed with stderr %s: %w", binary, errBuf.String(), err) 70 } 71 return nil 72 } 73 74 func (s *SystemD) Enable(binary string) error { 75 76 errBuf := new(bytes.Buffer) 77 defer errBuf.Reset() 78 79 cmd := exec.Command("systemctl", "enable", binary) 80 cmd.Stderr = errBuf 81 if s.monitor.IsVerbose() { 82 fmt.Println(strings.Join(cmd.Args, " ")) 83 cmd.Stdout = os.Stdout 84 } 85 86 if err := cmd.Run(); err != nil { 87 return fmt.Errorf("enabling systemd unit %s failed with stderr %s: %w", binary, errBuf.String(), err) 88 } 89 90 if !s.Active(binary) { 91 return s.Start(binary) 92 } 93 return nil 94 } 95 96 func (s *SystemD) Active(binary string) bool { 97 cmd := exec.Command("systemctl", "is-active", binary) 98 if s.monitor.IsVerbose() { 99 fmt.Println(strings.Join(cmd.Args, " ")) 100 cmd.Stdout = os.Stdout 101 } 102 return cmd.Run() == nil 103 } 104 105 func (s *SystemD) UnitPath(unit string) (string, error) { 106 107 const showProperty = "FragmentPath" 108 const expectOutputPrefix = showProperty + "=" 109 110 errBuf := new(bytes.Buffer) 111 defer errBuf.Reset() 112 outBuf := new(bytes.Buffer) 113 defer outBuf.Reset() 114 cmd := exec.Command("systemctl", "show", "-p", showProperty, unit) 115 cmd.Stderr = errBuf 116 cmd.Stdout = outBuf 117 err := cmd.Run() 118 errStr := errBuf.String() 119 outStr := outBuf.String() 120 s.monitor.WithFields(map[string]interface{}{ 121 "stdout": outStr, 122 "stderr": errStr, 123 }).Debug("Executed " + strings.Join(cmd.Args, " ")) 124 if err != nil { 125 return "", fmt.Errorf("getting systemd unit path for %s failed with stderr %s: %w", unit, errStr, err) 126 } 127 128 if !strings.HasPrefix(outStr, expectOutputPrefix) { 129 return "", fmt.Errorf("expected prefix %s but got %s", expectOutputPrefix, outStr) 130 } 131 132 return strings.Trim(strings.TrimPrefix(outStr, expectOutputPrefix), "\n"), nil 133 }