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  }