github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/libpod/healthcheck_linux.go (about) 1 package libpod 2 3 import ( 4 "fmt" 5 "os" 6 "os/exec" 7 "strings" 8 9 "github.com/containers/libpod/pkg/rootless" 10 "github.com/containers/libpod/pkg/systemd" 11 "github.com/pkg/errors" 12 "github.com/sirupsen/logrus" 13 ) 14 15 // createTimer systemd timers for healthchecks of a container 16 func (c *Container) createTimer() error { 17 if c.disableHealthCheckSystemd() { 18 return nil 19 } 20 podman, err := os.Executable() 21 if err != nil { 22 return errors.Wrapf(err, "failed to get path for podman for a health check timer") 23 } 24 25 var cmd = []string{} 26 if rootless.IsRootless() { 27 cmd = append(cmd, "--user") 28 } 29 cmd = append(cmd, "--unit", c.ID(), fmt.Sprintf("--on-unit-inactive=%s", c.HealthCheckConfig().Interval.String()), "--timer-property=AccuracySec=1s", podman, "healthcheck", "run", c.ID()) 30 31 conn, err := systemd.ConnectToDBUS() 32 if err != nil { 33 return errors.Wrapf(err, "unable to get systemd connection to add healthchecks") 34 } 35 conn.Close() 36 logrus.Debugf("creating systemd-transient files: %s %s", "systemd-run", cmd) 37 systemdRun := exec.Command("systemd-run", cmd...) 38 _, err = systemdRun.CombinedOutput() 39 if err != nil { 40 return err 41 } 42 return nil 43 } 44 45 // startTimer starts a systemd timer for the healthchecks 46 func (c *Container) startTimer() error { 47 if c.disableHealthCheckSystemd() { 48 return nil 49 } 50 conn, err := systemd.ConnectToDBUS() 51 if err != nil { 52 return errors.Wrapf(err, "unable to get systemd connection to start healthchecks") 53 } 54 defer conn.Close() 55 _, err = conn.StartUnit(fmt.Sprintf("%s.service", c.ID()), "fail", nil) 56 return err 57 } 58 59 // removeTimer removes the systemd timer and unit files 60 // for the container 61 func (c *Container) removeTimer() error { 62 if c.disableHealthCheckSystemd() { 63 return nil 64 } 65 conn, err := systemd.ConnectToDBUS() 66 if err != nil { 67 return errors.Wrapf(err, "unable to get systemd connection to remove healthchecks") 68 } 69 defer conn.Close() 70 timerFile := fmt.Sprintf("%s.timer", c.ID()) 71 _, err = conn.StopUnit(timerFile, "fail", nil) 72 73 // We want to ignore errors where the timer unit has already been removed. The error 74 // return is generic so we have to check against the string in the error 75 if err != nil && strings.HasSuffix(err.Error(), ".timer not loaded.") { 76 return nil 77 } 78 return err 79 }