kata-containers/tests/common.bash
David Esparza 55e2f0955b
metrics: stop hypervirsor and shim at init_env stage
This PR kills the hypervisor and the kata shim in the
init_env stage prior to launch any metric test.
Additionally this PR adds info messages in the main blocks
of the blogbench test to help in debugging.

Fixes: #7366

Signed-off-by: David Esparza <david.esparza.borquez@intel.com>
2023-07-18 12:05:29 -06:00

339 lines
10 KiB
Bash

#!/usr/bin/env bash
#
# Copyright (c) 2018-2019 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
# This file contains common functions that
# are being used by our metrics and integration tests
# Kata tests directory used for storing various test-related artifacts.
KATA_TESTS_BASEDIR="${KATA_TESTS_BASEDIR:-/var/log/kata-tests}"
# Directory that can be used for storing test logs.
KATA_TESTS_LOGDIR="${KATA_TESTS_LOGDIR:-${KATA_TESTS_BASEDIR}/logs}"
# Directory that can be used for storing test data.
KATA_TESTS_DATADIR="${KATA_TESTS_DATADIR:-${KATA_TESTS_BASEDIR}/data}"
# Directory that can be used for storing cache kata components
KATA_TESTS_CACHEDIR="${KATA_TESTS_CACHEDIR:-${KATA_TESTS_BASEDIR}/cache}"
KATA_HYPERVISOR="${KATA_HYPERVISOR:-qemu}"
RUNTIME="${RUNTIME:-containerd-shim-kata-v2}"
function die() {
local msg="$*"
echo -e "[$(basename $0):${BASH_LINENO[0]}] ERROR: $msg" >&2
exit 1
}
function warn() {
local msg="$*"
echo -e "[$(basename $0):${BASH_LINENO[0]}] WARNING: $msg"
}
function info() {
local msg="$*"
echo -e "[$(basename $0):${BASH_LINENO[0]}] INFO: $msg"
}
function handle_error() {
local exit_code="${?}"
local line_number="${1:-}"
echo -e "[$(basename $0):$line_number] ERROR: $(eval echo "$BASH_COMMAND")"
exit "${exit_code}"
}
trap 'handle_error $LINENO' ERR
function waitForProcess() {
wait_time="$1"
sleep_time="$2"
cmd="$3"
while [ "$wait_time" -gt 0 ]; do
if eval "$cmd"; then
return 0
else
sleep "$sleep_time"
wait_time=$((wait_time-sleep_time))
fi
done
return 1
}
# Check if the $1 argument is the name of a 'known'
# Kata runtime. Of course, the end user can choose any name they
# want in reality, but this function knows the names of the default
# and recommended Kata docker runtime install names.
function is_a_kata_runtime() {
if [ "$1" = "containerd-shim-kata-v2" ] || [ "$1" = "io.containerd.kata.v2" ]; then
echo "1"
else
echo "0"
fi
}
# Gets versions and paths of all the components
# list in kata-env
function extract_kata_env() {
RUNTIME_CONFIG_PATH=$(kata-runtime kata-env --json | jq -r .Runtime.Config.Path)
RUNTIME_VERSION=$(kata-runtime kata-env --json | jq -r .Runtime.Version | grep Semver | cut -d'"' -f4)
RUNTIME_COMMIT=$(kata-runtime kata-env --json | jq -r .Runtime.Version | grep Commit | cut -d'"' -f4)
RUNTIME_PATH=$(kata-runtime kata-env --json | jq -r .Runtime.Path)
# Shimv2 path is being affected by https://github.com/kata-containers/kata-containers/issues/1151
SHIM_PATH=$(readlink $(command -v containerd-shim-kata-v2))
SHIM_VERSION=${RUNTIME_VERSION}
HYPERVISOR_PATH=$(kata-runtime kata-env --json | jq -r .Hypervisor.Path)
# TODO: there is no kata-runtime of rust version currently
if [ "${KATA_HYPERVISOR}" != "dragonball" ]; then
HYPERVISOR_VERSION=$(sudo -E ${HYPERVISOR_PATH} --version | head -n1)
fi
VIRTIOFSD_PATH=$(kata-runtime kata-env --json | jq -r .Hypervisor.VirtioFSDaemon)
INITRD_PATH=$(kata-runtime kata-env --json | jq -r .Initrd.Path)
}
# Checks that processes are not running
function check_processes() {
extract_kata_env
# Only check the kata-env if we have managed to find the kata executable...
if [ -x "$RUNTIME_PATH" ]; then
local vsock_configured=$($RUNTIME_PATH kata-env | awk '/UseVSock/ {print $3}')
local vsock_supported=$($RUNTIME_PATH kata-env | awk '/SupportVSock/ {print $3}')
else
local vsock_configured="false"
local vsock_supported="false"
fi
general_processes=( ${HYPERVISOR_PATH} ${SHIM_PATH} )
for i in "${general_processes[@]}"; do
if pgrep -f "$i"; then
die "Found unexpected ${i} present"
fi
done
}
# Clean environment, this function will try to remove all
# stopped/running containers.
function clean_env()
{
# If the timeout has not been set, default it to 30s
# Docker has a built in 10s default timeout, so make ours
# longer than that.
KATA_DOCKER_TIMEOUT=${KATA_DOCKER_TIMEOUT:-30}
containers_running=$(sudo timeout ${KATA_DOCKER_TIMEOUT} docker ps -q)
if [ ! -z "$containers_running" ]; then
# First stop all containers that are running
# Use kill, as the containers are generally benign, and most
# of the time our 'stop' request ends up doing a `kill` anyway
sudo timeout ${KATA_DOCKER_TIMEOUT} docker kill $containers_running
# Remove all containers
sudo timeout ${KATA_DOCKER_TIMEOUT} docker rm -f $(docker ps -qa)
fi
}
function clean_env_ctr()
{
local count_running="$(sudo ctr c list -q | wc -l)"
local remaining_attempts=10
declare -a running_tasks=()
local count_tasks=0
local sleep_time=1
local time_out=10
[ "$count_running" -eq "0" ] && return 0
readarray -t running_tasks < <(sudo ctr t list -q)
info "Wait until the containers gets removed"
for task_id in "${running_tasks[@]}"; do
sudo ctr t kill -a -s SIGTERM ${task_id} >/dev/null 2>&1
sleep 0.5
done
# do not stop if the command fails, it will be evaluated by waitForProcess
local cmd="[[ $(sudo ctr tasks list | grep -c "STOPPED") == "$count_running" ]]" || true
local res="ok"
waitForProcess "${time_out}" "${sleep_time}" "$cmd" || res="fail"
[ "$res" == "ok" ] || sudo systemctl restart containerd
while (( remaining_attempts > 0 )); do
[ "${RUNTIME}" == "runc" ] && sudo ctr tasks rm -f $(sudo ctr task list -q)
sudo ctr c rm $(sudo ctr c list -q) >/dev/null 2>&1
count_running="$(sudo ctr c list -q | wc -l)"
[ "$count_running" -eq 0 ] && break
remaining_attempts=$((remaining_attempts-1))
done
count_tasks="$(sudo ctr t list -q | wc -l)"
if (( count_tasks > 0 )); then
die "Can't remove running containers."
fi
kill_kata_components
}
# Kills running shim and hypervisor components
function kill_kata_components() {
local kata_bin_dir="/opt/kata/bin"
local shim_path="${kata_bin_dir}/containerd-shim-kata-v2"
local hypervisor_path="${kata_bin_dir}/qemu-system-x86_64"
local pid_shim_count="$(pgrep -fc ${shim_path} || exit 0)"
[ ${pid_shim_count} -gt "0" ] && sudo kill -SIGKILL "$(pgrep -f ${shim_path})" > /dev/null 2>&1
if [ "${KATA_HYPERVISOR}" = 'clh' ]; then
hypervisor_path="${kata_bin_dir}/cloud-hypervisor"
elif [ "${KATA_HYPERVISOR}" != 'qemu' ]; then
echo "Failed to stop the hypervisor: '${KATA_HYPERVISOR}' as it is not recognized"
return
fi
local pid_hypervisor_count="$(pgrep -fc ${hypervisor_path} || exit 0)"
if [ ${pid_hypervisor_count} -gt "0" ]; then
sudo kill -SIGKILL "$(pgrep -f ${hypervisor_path})" > /dev/null 2>&1
fi
}
# Restarts a systemd service while ensuring the start-limit-burst is set to 0.
# Outputs warnings to stdio if something has gone wrong.
#
# Returns 0 on success, 1 otherwise
function restart_systemd_service_with_no_burst_limit() {
local service=$1
info "restart $service service"
local active=$(systemctl show "$service.service" -p ActiveState | cut -d'=' -f2)
[ "$active" == "active" ] || warn "Service $service is not active"
local start_burst=$(systemctl show "$service".service -p StartLimitBurst | cut -d'=' -f2)
if [ "$start_burst" -ne 0 ]
then
local unit_file=$(systemctl show "$service.service" -p FragmentPath | cut -d'=' -f2)
[ -f "$unit_file" ] || { warn "Can't find $service's unit file: $unit_file"; return 1; }
local start_burst_set=$(sudo grep StartLimitBurst $unit_file | wc -l)
if [ "$start_burst_set" -eq 0 ]
then
sudo sed -i '/\[Service\]/a StartLimitBurst=0' "$unit_file"
else
sudo sed -i 's/StartLimitBurst.*$/StartLimitBurst=0/g' "$unit_file"
fi
sudo systemctl daemon-reload
fi
sudo systemctl restart "$service"
local state=$(systemctl show "$service.service" -p SubState | cut -d'=' -f2)
[ "$state" == "running" ] || { warn "Can't restart the $service service"; return 1; }
start_burst=$(systemctl show "$service.service" -p StartLimitBurst | cut -d'=' -f2)
[ "$start_burst" -eq 0 ] || { warn "Can't set start burst limit for $service service"; return 1; }
return 0
}
function restart_containerd_service() {
restart_systemd_service_with_no_burst_limit containerd || return 1
local retries=5
local counter=0
until [ "$counter" -ge "$retries" ] || sudo ctr --connect-timeout 1s version > /dev/null 2>&1
do
info "Waiting for containerd socket..."
((counter++))
done
[ "$counter" -ge "$retries" ] && { warn "Can't connect to containerd socket"; return 1; }
clean_env_ctr
return 0
}
function create_symbolic_links() {
local KATA_HYPERVISOR="${1}"
local link_configuration_file="/opt/kata/share/defaults/kata-containers/configuration.toml"
local source_configuration_file="/opt/kata/share/defaults/kata-containers/configuration-${KATA_HYPERVISOR}.toml"
if [ "${KATA_HYPERVISOR}" != 'qemu' ] && [ "${KATA_HYPERVISOR}" != 'clh' ]; then
die "Failed to set the configuration.toml: '${KATA_HYPERVISOR}' is not recognized as a valid hypervisor name."
fi
sudo ln -sf "${source_configuration_file}" "${link_configuration_file}"
}
# Configures containerd
function overwrite_containerd_config() {
containerd_config="/etc/containerd/config.toml"
sudo rm -f "${containerd_config}"
sudo tee "${containerd_config}" << EOF
version = 2
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true
[plugins]
[plugins."io.containerd.grpc.v1.cri"]
[plugins."io.containerd.grpc.v1.cri".containerd]
default_runtime_name = "kata"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata]
runtime_type = "io.containerd.kata.v2"
EOF
}
function install_kata() {
local kata_tarball="kata-static.tar.xz"
declare -r katadir="/opt/kata"
declare -r destdir="/"
declare -r local_bin_dir="/usr/local/bin/"
# Removing previous kata installation
sudo rm -rf "${katadir}"
pushd "${kata_tarball_dir}"
sudo tar -xvf "${kata_tarball}" -C "${destdir}"
popd
# create symbolic links to kata components
for b in "${katadir}/bin/*" ; do
sudo ln -sf "${b}" "${local_bin_dir}/$(basename $b)"
done
check_containerd_config_for_kata
restart_containerd_service
install_checkmetrics
}
function check_containerd_config_for_kata() {
# check containerd config
declare -r line1="default_runtime_name = \"kata\""
declare -r line2="runtime_type = \"io.containerd.kata.v2\""
declare -r num_lines_containerd=2
declare -r containerd_path="/etc/containerd/config.toml"
local count_matches=$(grep -ic "$line1\|$line2" "${containerd_path}")
if [ "${count_matches}" = "${num_lines_containerd}" ]; then
info "containerd ok"
else
info "overwriting containerd configuration w/ a valid one"
overwrite_containerd_config
fi
}