github.com/canonical/ubuntu-image@v0.0.0-20240430122802-2202fe98b290/tests/lib/external/snapd-testing-tools/tools/tests.systemd (about)

     1  #!/bin/bash -e
     2  
     3  show_help() {
     4      echo "usage: tests.systemd create-and-start-unit <UNIT-NAME> <UNIT-COMMAND-LINE> <UNIT-OVERRIDE>"
     5      echo "       tests.systemd stop-unit [--remove] <UNIT-NAME> ..."
     6      echo "       tests.systemd wait-for-service [-n|--attempts retries] [--wait seconds] [--state STATE] <UNIT-NAME>"
     7  }
     8  
     9  # Create and start a persistent systemd unit that survives reboots. Use as:
    10  #   systemd_create_and_start_unit "name" "my-service --args"
    11  # The third arg supports "overrides" which allow to customize the service
    12  # as needed, e.g.:
    13  #   systemd_create_and_start_unit "name" "start" "[Unit]\nAfter=foo"
    14  create_and_start_unit() {
    15      local name=$1
    16      local start_line=$2
    17      local override=$3
    18  
    19      if [ -z "$name" ]; then
    20          echo "tests.systemd: unit name cannot be empty"
    21          return 1
    22      fi
    23      if [ -z "$start_line" ]; then
    24          echo "tests.systemd: unit command line cannot be empty"
    25          return 1
    26      fi
    27      if [ -f "/etc/systemd/system/$name.service" ]; then
    28          echo "tests.systemd: unit service file already exist, it is going to be overwritten"
    29      fi
    30  
    31      printf '[Unit]\nDescription=Support for test %s\n[Service]\nType=simple\nExecStart=%s\n[Install]\nWantedBy=multi-user.target\n' "$name" "$start_line" > "/etc/systemd/system/$name.service"
    32      if [ -n "$override" ]; then
    33          mkdir -p "/etc/systemd/system/$name.service.d"
    34          # shellcheck disable=SC2059
    35          printf "$override" > "/etc/systemd/system/$name.service.d/override.conf"
    36      fi
    37  
    38      systemctl daemon-reload
    39      systemctl enable "$name"
    40      systemctl start "$name"
    41      wait_for_service "$name"
    42  }
    43  
    44  _stop_unit() {
    45      local unit=$1
    46  
    47      if systemctl is-active "$unit"; then
    48          retries=20
    49          while systemctl status "$unit" | grep -q "Active: activating"; do
    50              if [ $retries -eq 0 ]; then
    51                  echo "tests.systemd: unit $unit could not be stopped"
    52                  systemctl status "$unit"
    53                  exit 1
    54              fi
    55              retries=$(( retries - 1 ))
    56              sleep 1
    57          done
    58  
    59          systemctl stop "$unit"
    60      fi
    61  }
    62  
    63  stop_unit() {
    64      local remove=false
    65      while [ $# -gt 0 ]; do
    66          case "$1" in
    67              --remove)
    68                  remove=true
    69                  shift
    70                  ;;
    71              *)
    72                  break
    73                  ;;
    74          esac
    75      done
    76  
    77      if [ $# -eq 0 ]; then
    78          echo "tests.systemd: at least a unit name is required"
    79          return 1
    80      fi
    81  
    82      for unit in "$@"; do
    83          _stop_unit "$unit"
    84          if [ "$remove" = true ]; then
    85              if systemctl is-enabled "$unit"; then
    86                  systemctl disable "$unit"
    87              fi
    88              rm -f "/etc/systemd/system/$unit.service"
    89              rm -rf "/etc/systemd/system/$unit.service.d"
    90          fi
    91      done
    92  
    93      systemctl daemon-reload
    94  }
    95  
    96  wait_for_service() {
    97      if [ $# -eq 0 ]; then
    98          show_help
    99          exit 0
   100      fi
   101  
   102      local attempts=300
   103      local wait=1
   104      local state="active"
   105      local service_name
   106  
   107      while [ $# -gt 0 ]; do
   108          case "$1" in
   109              --wait)
   110                  wait="$2"
   111                  shift 2
   112                  ;;
   113              -n|--attempts)
   114                  attempts="$2"
   115                  shift 2
   116                  ;;
   117              --state)
   118                  state="$2"
   119                  shift 2
   120                  ;;
   121              *)
   122                  service_name=$1
   123                  break
   124                  ;;
   125          esac
   126      done
   127  
   128      if [ -z "$service_name" ]; then
   129          echo "tests.systemd: unit name cannot be empty"
   130          return 1
   131      fi
   132  
   133      for i in $(seq "$attempts"); do
   134          if systemctl show -p ActiveState "$service_name" | grep -q "ActiveState=$state"; then
   135              return
   136          fi
   137          # show debug output every 1min
   138          if [ "$i" -gt 0 ] && [ $(( i % 60 )) = 0 ]; then
   139              systemctl status "$service_name" || true
   140          fi
   141          sleep "$wait"
   142      done
   143  
   144      echo "tests.systemd: service $service_name did not become $state"
   145      return 1
   146  }
   147  
   148  main() {
   149      if [ $# -eq 0 ]; then
   150          show_help
   151          exit 0
   152      fi
   153  
   154      while [ $# -gt 0 ]; do
   155          case "$1" in
   156              -h|--help)
   157                  show_help
   158                  exit
   159                  ;;
   160              *)
   161                  action=$(echo "$1" | tr '-' '_')
   162                  shift
   163                  break
   164                  ;;
   165          esac
   166      done
   167  
   168      if [ -z "$(declare -f "$action")" ]; then
   169          echo "tests.systemd: no such command: $action" >&2
   170          show_help
   171          exit 1
   172      fi
   173  
   174      "$action" "$@"
   175  }
   176  
   177  main "$@"