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 "$@"