lxcfs-tools/0007-test-add-tests-for-docker-and-lxcfs.patch
yangjiaqi 6ab02c56ea lxcfs-tools: support lxcfs reliability for docker
Signed-off-by: yangjiaqi <yangjiaqi16@huawei.com>
2024-02-02 21:08:05 +08:00

537 lines
15 KiB
Diff

From 69730a8687a8e56aad46b9b4f309af1c3df6ed06 Mon Sep 17 00:00:00 2001
From: yangjiaqi <yangjiaqi16@huawei.com>
Date: Thu, 25 Jan 2024 15:28:20 +0800
Subject: [PATCH] test: add tests for docker and lxcfs
Signed-off-by: yangjiaqi <yangjiaqi16@huawei.com>
---
Makefile | 5 +-
remountcmd_test.go | 7 +-
tests/lib/commonlib.sh | 224 +++++++++++++++++++++++++++++++++
tests/run_test.sh | 43 +++++++
tests/src/test_docker_lxcfs.sh | 65 ++++++++++
umountcmd_test.go | 61 +++++++--
6 files changed, 394 insertions(+), 11 deletions(-)
create mode 100644 tests/lib/commonlib.sh
create mode 100755 tests/run_test.sh
create mode 100755 tests/src/test_docker_lxcfs.sh
diff --git a/Makefile b/Makefile
index cceab41..a55688b 100644
--- a/Makefile
+++ b/Makefile
@@ -42,11 +42,14 @@ lxcfs-hook: $(SOURCES) | $(DEPS_LINK)
${ENV} go build -buildmode=pie -mod=vendor -tags ${TAGS} -ldflags ${GO_LDFLAGS} -o build/lxcfs-hook ./hooks/lxcfs-hook
@echo "Done!"
-tests:
+tests: funtests
@echo "Checking lxcfs-tools"
${ENV} go test -mod=vendor -tags ${TAGS} -p 1 -v ./... -coverprofile=cover.out
@echo "Done!"
+funtests:
+ bash tests/run_test.sh
+
clean:
rm -rf build
diff --git a/remountcmd_test.go b/remountcmd_test.go
index 106ac5e..aeb83ea 100644
--- a/remountcmd_test.go
+++ b/remountcmd_test.go
@@ -66,12 +66,17 @@ func TestRemountAll(t *testing.T) {
}
defer recoveriSulad()
+ if !tryMoveRunc() {
+ return
+ }
+ defer recoverRunc()
+
tests := []struct {
name, initMountns, initUserns string
wantErr bool
}{
{
- name: "TC1-absent of isulad",
+ name: "TC1-absent of container tools",
initMountns: "1",
initUserns: "5",
wantErr: true,
diff --git a/tests/lib/commonlib.sh b/tests/lib/commonlib.sh
new file mode 100644
index 0000000..2ff4776
--- /dev/null
+++ b/tests/lib/commonlib.sh
@@ -0,0 +1,224 @@
+#!/bin/bash
+###
+ # Copyright (c) Huawei Technologies Co., Ltd. 2021-2024. All rights reserved.
+ # rubik licensed under the Mulan PSL v2.
+ # You can use this software according to the terms and conditions of the Mulan PSL v2.
+ # You may obtain a copy of Mulan PSL v2 at:
+ # http://license.coscl.org.cn/MulanPSL2
+ # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ # PURPOSE.
+ # See the Mulan PSL v2 for more details.
+ # Date: 2024-01-24
+ # Description: This file is common functions file
+###
+
+current_dir="$(dirname "$(realpath "$0")")"
+project_dir="$current_dir/../.."
+build_dir="$project_dir/build"
+exit_flag=0
+tools_bak_name="/usr/local/bin/lxcfs-tools.test.bak"
+
+function echoTxt() {
+ TXT="[$(date "+%Y-%m-%d-%H-%M-%S")]$1"
+ COLOR=$2
+ if [ "${COLOR}" = "red" ]; then
+ echo -e "${color_red}${TXT}${color_reset}"
+ elif [ "${COLOR}" = "green" ]; then
+ echo -e "${color_green}${TXT}${color_reset}"
+ elif [ "${COLOR}" = "yellow" ]; then
+ echo -e "${color_yellow}${TXT}${color_reset}"
+ else
+ echo "${TXT}"
+ fi
+}
+
+function tsm_error() {
+ txt_str=$1
+ echoTxt "$txt_str" red
+}
+
+function tsm_info() {
+ txt_str=$1
+ echoTxt "$txt_str" green
+}
+
+# 检查是否安装了docker和lxcfs rpm包
+function check_packages() {
+ if ! rpm -q docker-engine >/dev/null 2>&1; then
+ echo "docker-engine is not installed, trying to install..."
+ if ! yum install -y docker-engine >/dev/null 2>&1; then
+ echo "Failed to install Docker, skip test cases"
+ exit 0
+ fi
+ fi
+
+ if ! rpm -q lxcfs >/dev/null 2>&1; then
+ echo "LXCFS is not installed, trying to install..."
+ if ! yum install -y lxcfs >/dev/null 2>&1; then
+ echo "Failed to install LXCFS, skip test cases"
+ exit 0
+ fi
+ fi
+}
+
+# 检查服务是否可用
+function check_service() {
+ if ! systemctl is-active $1 >/dev/null 2>&1; then
+ echo "$1 is not running, trying to start..."
+ if ! systemctl start $1 >/dev/null 2>&1; then
+ echo "Failed to start $1, cannot run test cases"
+ exit 0
+ fi
+ fi
+
+ if ! systemctl is-active $1 >/dev/null 2>&1; then
+ echo "$1 is not running, cannot run test cases"
+ exit 0
+ fi
+}
+
+# 检查lxcfs-tools是否可用
+function check_lxcfs_tools() {
+ if [ ! -f "$build_dir"/lxcfs-tools ]; then
+ echo "lxcfs-tools binary not found, compiling..."
+ cd "$project_dir"
+ make || { echo "$project_dir Compilation failed"; exit 0; }
+ fi
+
+ if [ ! "$build_dir"/lxcfs-tools ]; then
+ echo "lxcfs-tools binary still not found, something went wrong"
+ exit 0
+ fi
+
+ # 检查 /usr/local/bin/ 目录下是否存在 lxcfs-tools 二进制
+ if [ -f /usr/local/bin/lxcfs-tools ]; then
+ # 存在,则将其重命名为 lxcfs-tools.bak
+ mv /usr/local/bin/lxcfs-tools "${tools_bak_name}"
+ fi
+
+ # 将 build 目录下的 lxcfs-tools 二进制拷贝到 /usr/local/bin/ 目录
+ cp "$build_dir"/lxcfs-tools /usr/local/bin/
+
+}
+
+function ensure_docker_image_exists() {
+ local image_name="$1"
+
+ # 检查镜像是否存在
+ if ! docker inspect "$image_name" &> /dev/null; then
+ echo "镜像 $image_name 不存在,开始拉取镜像..."
+ docker pull "$image_name"
+
+ # 再次检查镜像是否存在
+ if ! docker inspect "$image_name" &> /dev/null; then
+ echo "拉取镜像失败,退出进程"
+ exit 0
+ fi
+ fi
+}
+
+#####################################################################
+
+# $1:result $2 expect result
+# $1 equal $2
+#############################################################
+
+function fn_check_result() {
+ if [ "$1" = "$2" ]; then
+ tsm_info "PASS:return $1 as expected!($3)"
+ else
+ tsm_error "FAILED:return $1 not as expected $2!($3)"
+ ((exit_flag++))
+ fi
+}
+
+# wait untill the state of container turns to the specified one
+# $1:container ID/container name
+# $2:the expected state
+
+#############################################################
+
+function WaitInspect() {
+ container=$1
+ expect_state=$2
+ result="FAIL"
+ if [ $# -lt 2 ]; then
+ tsm_error "FAILED: take at lease 2 input parameters"
+ ((exit_flag++))
+ return 1
+ fi
+ for ((i = 0; i < 30; i++)); do
+ current_state=$(docker inspect -f '{{.State.Status}}' "$container")
+ if [ "$current_state" == "$expect_state" ]; then
+ result="PASS"
+ break
+ else
+ sleep 1
+ fi
+ done
+ if [ "$result" == "PASS" ]; then
+ tsm_info "PASS:return $current_state as expected!($3)"
+ return 0
+ else
+ tsm_error "FAILED:return $current_state not as expected!($3)"
+ ((exit_flag++))
+ return 1
+ fi
+}
+
+function wait_service_lxcfs_running() {
+ local reTry=${1:-30}
+ local lxcfs_status
+ local i
+ for i in $(seq "${reTry}"); do
+ lxcfs_status=$(systemctl status lxcfs | awk -F "[()]" '/Active/{print $2}')
+ if [[ "${lxcfs_status}" == "running" ]]; then
+ return 0
+ fi
+ sleep 1
+ done
+ return 1
+}
+
+function restart_lxcfs() {
+ local ret i
+ for i in $(seq 10); do
+ systemctl restart lxcfs
+ wait_service_lxcfs_running
+ ret=$?
+ [[ "$ret" -eq 0 ]] && break
+ done
+ return "$ret"
+}
+
+function stop_services() {
+ systemctl stop docker
+ systemctl stop lxcfs
+
+ # 等待服务停止
+ for i in {1..10}; do
+ if [[ $(systemctl is-active docker) == "inactive" && $(systemctl is-active lxcfs) == "inactive" ]]; then
+ echo "Services stopped successfully"
+ return 0
+ fi
+ sleep 1
+ done
+
+ echo "Timeout waiting for services to stop"
+ return 0
+}
+
+function clean_env() {
+ rm -rf /usr/local/bin/lxcfs-tools
+ if [ -f "${tools_bak_name}" ]; then
+ # 存在,则将其重命名为 lxcfs-tools
+ mv "${tools_bak_name}" /usr/local/bin/lxcfs-tools
+ fi
+ docker rm -f `docker ps -aq` > /dev/null
+ stop_services
+}
+
+
+
+
diff --git a/tests/run_test.sh b/tests/run_test.sh
new file mode 100755
index 0000000..6339a70
--- /dev/null
+++ b/tests/run_test.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+###
+ # Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved.
+ # rubik licensed under the Mulan PSL v2.
+ # You can use this software according to the terms and conditions of the Mulan PSL v2.
+ # You may obtain a copy of Mulan PSL v2 at:
+ # http://license.coscl.org.cn/MulanPSL2
+ # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ # PURPOSE.
+ # See the Mulan PSL v2 for more details.
+ # Date: 2024-01-25
+ # Description: This file is used for running testcases
+###
+
+current_dir="$(cd "$(dirname "$0")" && pwd)"
+src_dir="$current_dir/src"
+log_dir="$current_dir/logs"
+fail_cnt=0
+mkdir -p "$log_dir"
+
+for script in "$src_dir"/*.sh; do
+ script_name=$(basename "$script")
+ log_file="${log_dir}/${script_name%.sh}-$(date +%Y-%m-%d-%H-%M-%S).log"
+ echo "Running $script_name..."
+ bash -x "$script" > "$log_file" 2>&1
+ exit_code=$?
+
+ if [ $exit_code -eq 0 ]; then
+ echo "$(date '+%Y-%m-%d %H:%M:%S') $script_name succeeded" | tee -a "$log_file"
+ else
+ cat ${log_file}
+ echo "$(date '+%Y-%m-%d %H:%M:%S') $script_name failed with exit code $exit_code" | tee -a "$log_file"
+ fail_cnt=$((fail_cnt+1))
+ fi
+done
+
+rm -rf "$log_dir"
+
+if [ $fail_cnt -ne 0 ]; then
+ echo "There were $fail_cnt failed test cases."
+ exit 1
+fi
diff --git a/tests/src/test_docker_lxcfs.sh b/tests/src/test_docker_lxcfs.sh
new file mode 100755
index 0000000..bf260d8
--- /dev/null
+++ b/tests/src/test_docker_lxcfs.sh
@@ -0,0 +1,65 @@
+###
+ # Copyright (c) Huawei Technologies Co., Ltd. 2021-2024. All rights reserved.
+ # rubik licensed under the Mulan PSL v2.
+ # You can use this software according to the terms and conditions of the Mulan PSL v2.
+ # You may obtain a copy of Mulan PSL v2 at:
+ # http://license.coscl.org.cn/MulanPSL2
+ # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ # PURPOSE.
+ # See the Mulan PSL v2 for more details.
+ # Author: Jiaqi Yang
+ # Date: 2024-01-24
+ # Description: This file is used for testing docker with lxcfs
+###
+
+current_dir="$(cd "$(dirname "$0")" && pwd)"
+lib_dir="${current_dir}"/../lib
+image_name="rnd-dockerhub.huawei.com/official/ubuntu:latest"
+con_name="test"
+source "${lib_dir}"/commonlib.sh
+
+function pre() {
+ check_packages
+ check_service docker
+ check_service lxcfs
+ check_lxcfs_tools
+ ensure_docker_image_exists "$image_name"
+ docker rm -f "${con_name}" > /dev/null
+}
+
+function test_fun() {
+ cid=`docker run -itd --cpuset-cpus="0-1" -m 256m -v /var/lib/lxc:/var/lib/lxc:slave \
+ -v /var/lib/lxc/lxcfs/proc/cpuinfo:/proc/cpuinfo:rw \
+ -v /var/lib/lxc/lxcfs/proc/meminfo:/proc/meminfo:rw \
+ -v /var/lib/lxc/lxcfs/proc/stat:/proc/stat:rw \
+ -v /var/lib/lxc/lxcfs/sys/devices/system/cpu:/sys/devices/system/cpu:rw \
+ --name ${con_name} ${image_name} /bin/bash`
+
+ WaitInspect $cid running
+
+ docker exec -it ${con_name} bash -c "free -h" | grep Mem | grep 256
+ fn_check_result $? 0 "check meminfo"
+
+ restart_lxcfs
+ fn_check_result $? 0 "restart lxcfs"
+
+ docker exec -it ${con_name} bash -c "free -h" | grep Mem | grep 256
+ fn_check_result $? 0 "check meminfo"
+
+ docker exec -it test bash -c "cat /proc/cpuinfo | grep processor | wc -l | grep 2"
+ fn_check_result $? 0 "check cpuinfo"
+
+ docker exec -it test bash -c "cat /proc/stat | grep cpu | wc -l | grep 3"
+ fn_check_result $? 0 "check stat"
+}
+
+function main() {
+ pre
+ echo "All services are ready, running test cases..."
+ test_fun
+ clean_env
+ exit $exit_flag
+}
+
+main
diff --git a/umountcmd_test.go b/umountcmd_test.go
index bcae021..dd15a3a 100644
--- a/umountcmd_test.go
+++ b/umountcmd_test.go
@@ -23,7 +23,8 @@ import (
)
var (
- oldPath, newPath string
+ oldPath, newPath string
+ oldRuncPath, newRuncPath string
)
func isuladExisted() bool {
@@ -34,8 +35,19 @@ func isuladExisted() bool {
return true
}
-func whereIsIsulad() string {
- cmd := exec.Command("whereis", "isula")
+func runcExisted() bool {
+ cmd := exec.Command("runc", "-v")
+ if err := cmd.Run(); err != nil {
+ return false
+ }
+ return true
+}
+
+func whereIsCmd(cmdStr string) string {
+ if cmdStr != "runc" && cmdStr != "isula" {
+ return ""
+ }
+ cmd := exec.Command("whereis", cmdStr)
out, err := cmd.CombinedOutput()
if err != nil {
return ""
@@ -45,12 +57,12 @@ func whereIsIsulad() string {
return path
}
-func rename(oldPath, newPath string) error {
- if err := os.Rename(oldPath, newPath); err != nil {
+func rename(old, new string) error {
+ if err := os.Rename(old, new); err != nil {
fmt.Println(err)
return err
}
- fmt.Printf("rename isula path from %s to %s\n", oldPath, newPath)
+ fmt.Printf("rename path from %s to %s\n", old, new)
return nil
}
@@ -58,8 +70,8 @@ func tryMoveiSulad() bool {
oldPath = ""
newPath = ""
if isuladExisted() {
- fmt.Println("isuila existed ")
- oldPath = whereIsIsulad()
+ fmt.Println("isuila existed")
+ oldPath = whereIsCmd("isula")
if oldPath == "" {
return false
}
@@ -71,6 +83,23 @@ func tryMoveiSulad() bool {
return true
}
+func tryMoveRunc() bool {
+ oldRuncPath = ""
+ newRuncPath = ""
+ if runcExisted() {
+ fmt.Println("runc existed")
+ oldRuncPath = whereIsCmd("runc")
+ if oldRuncPath == "" {
+ return false
+ }
+ newRuncPath = oldRuncPath + ".bak"
+ if err := rename(oldRuncPath, newRuncPath); err != nil {
+ return false
+ }
+ }
+ return true
+}
+
func recoveriSulad() {
if oldPath == "" || newPath == "" {
return
@@ -80,6 +109,15 @@ func recoveriSulad() {
}
}
+func recoverRunc() {
+ if oldRuncPath == "" || newRuncPath == "" {
+ return
+ }
+ if err := rename(newRuncPath, oldRuncPath); err != nil {
+ return
+ }
+}
+
// TestUmountAll tests umountAll
func TestUmountAll(t *testing.T) {
if !tryMoveiSulad() {
@@ -87,12 +125,17 @@ func TestUmountAll(t *testing.T) {
}
defer recoveriSulad()
+ if !tryMoveRunc() {
+ return
+ }
+ defer recoverRunc()
+
tests := []struct {
name, initMountns, initUserns string
wantErr bool
}{
{
- name: "TC1-absent of isulad",
+ name: "TC1-absent of container tools",
initMountns: "1",
initUserns: "5",
wantErr: true,
--
2.33.0