From 5338b9cae6d674af481faa3aec48befd2a34ff0b Mon Sep 17 00:00:00 2001 From: liuxu Date: Sat, 20 Apr 2024 10:00:53 +0800 Subject: [PATCH] upgrade from upstream --- 0038-add-modify-for-cgroup-v2-ci-test.patch | 608 ++++++++ ...n-ubuntu-container-bug-in-inspect.sh.patch | 2 +- ...0-add-support-for-GetContainerEvents.patch | 2 +- ...ix-cpurt-init-bug-for-systemd-cgroup.patch | 2 +- ...042-fix-message-queue-concurrent-bug.patch | 2 +- ...cify-runtime-as-runc-for-oom-test-CI.patch | 2 +- ...i.patch => 0044-set-oomkilled-in-cri.patch | 2 +- 0045-add-cri-1.29-update-design-doc.patch | 312 ++++ 0046-oom-monitor-in-manual-cases.patch | 120 ++ ...age-restrictions-for-CRI-1.29-update.patch | 27 + 0048-CDI-interface-definition.patch | 1192 ++++++++++++++++ ...een-runtime-and-runtime_cmd-in-isula.patch | 145 ++ ...Use-user-defined-shm-for-CRI-request.patch | 171 +++ ...-in-set_connected_container_shm_path.patch | 26 + 0052-init-enable_pod_events-as-false.patch | 62 + ...-root-path-in-rt_lcr_rm-if-lcr-runti.patch | 33 + ...an-be-removed-if-sandbox-container-r.patch | 58 + ...-shim-timeout-exit-error-log-changes.patch | 175 +++ ...re-created-pipe-was-not-closed-when-.patch | 36 + ...-add-debug-msg-info-in-image_load.sh.patch | 26 + 0058-empty-pointer-check-in-lcr_rt_ops.patch | 214 +++ ...-status-codes-of-cri-in-case-of-erro.patch | 315 +++++ ...i-return-int-instead-of-error-string.patch | 363 +++++ ...modules-operate-registry-annotations.patch | 516 +++++++ ...umount-shmpath-for-sandbox-container.patch | 30 + ...ystemd-cgroup-and-enable-cri-v1-valu.patch | 27 + 0064-cdi-support-module-cache.patch | 862 +++++++++++ ...ge-default-subscribe-timeout-to-5min.patch | 76 + ...odules-version-spec-spec_dirs-device.patch | 1254 +++++++++++++++++ ...pport-modules-container_edits-parser.patch | 1210 ++++++++++++++++ ...perate-when-init-isulad-and-create-c.patch | 371 +++++ 0069-bugfix-fix-cni_operate_ut-ut.patch | 24 + iSulad.spec | 47 +- 33 files changed, 8299 insertions(+), 13 deletions(-) create mode 100644 0038-add-modify-for-cgroup-v2-ci-test.patch rename 0038-fix-run-ubuntu-container-bug-in-inspect.sh.patch => 0039-fix-run-ubuntu-container-bug-in-inspect.sh.patch (94%) rename 0039-add-support-for-GetContainerEvents.patch => 0040-add-support-for-GetContainerEvents.patch (99%) rename 0040-fix-cpurt-init-bug-for-systemd-cgroup.patch => 0041-fix-cpurt-init-bug-for-systemd-cgroup.patch (98%) rename 0041-fix-message-queue-concurrent-bug.patch => 0042-fix-message-queue-concurrent-bug.patch (95%) rename 0042-specify-runtime-as-runc-for-oom-test-CI.patch => 0043-specify-runtime-as-runc-for-oom-test-CI.patch (94%) rename 0043-set-oomkilled-in-cri.patch => 0044-set-oomkilled-in-cri.patch (95%) create mode 100644 0045-add-cri-1.29-update-design-doc.patch create mode 100644 0046-oom-monitor-in-manual-cases.patch create mode 100644 0047-add-usage-restrictions-for-CRI-1.29-update.patch create mode 100644 0048-CDI-interface-definition.patch create mode 100644 0049-distinguish-between-runtime-and-runtime_cmd-in-isula.patch create mode 100644 0050-Use-user-defined-shm-for-CRI-request.patch create mode 100644 0051-Fix-memory-leak-in-set_connected_container_shm_path.patch create mode 100644 0052-init-enable_pod_events-as-false.patch create mode 100644 0053-remove-container-root-path-in-rt_lcr_rm-if-lcr-runti.patch create mode 100644 0054-ensure-sandbox-can-be-removed-if-sandbox-container-r.patch create mode 100644 0055-bugfix-for-shim-timeout-exit-error-log-changes.patch create mode 100644 0056-bugfix-for-the-pre-created-pipe-was-not-closed-when-.patch create mode 100644 0057-add-debug-msg-info-in-image_load.sh.patch create mode 100644 0058-empty-pointer-check-in-lcr_rt_ops.patch create mode 100644 0059-modify-some-grpc-status-codes-of-cri-in-case-of-erro.patch create mode 100644 0060-cdi-return-int-instead-of-error-string.patch create mode 100644 0061-cdi-support-modules-operate-registry-annotations.patch create mode 100644 0062-do-not-umount-shmpath-for-sandbox-container.patch create mode 100644 0063-remove-default-systemd-cgroup-and-enable-cri-v1-valu.patch create mode 100644 0064-cdi-support-module-cache.patch create mode 100644 0065-change-default-subscribe-timeout-to-5min.patch create mode 100644 0066-cdi-support-modules-version-spec-spec_dirs-device.patch create mode 100644 0067-cdi-support-modules-container_edits-parser.patch create mode 100644 0068-cdi-invoke-cdi-operate-when-init-isulad-and-create-c.patch create mode 100644 0069-bugfix-fix-cni_operate_ut-ut.patch diff --git a/0038-add-modify-for-cgroup-v2-ci-test.patch b/0038-add-modify-for-cgroup-v2-ci-test.patch new file mode 100644 index 0000000..843652a --- /dev/null +++ b/0038-add-modify-for-cgroup-v2-ci-test.patch @@ -0,0 +1,608 @@ +From 33b26f27dd897574d73ce8654620a13edbeb947e Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Tue, 2 Apr 2024 02:31:58 +1400 +Subject: [PATCH 38/69] add modify for cgroup v2 ci test + +Signed-off-by: zhongtao +--- + CI/test_cases/manual_cases/cgroupv2.sh | 276 +++++++++++++++---------- + 1 file changed, 165 insertions(+), 111 deletions(-) + +diff --git a/CI/test_cases/manual_cases/cgroupv2.sh b/CI/test_cases/manual_cases/cgroupv2.sh +index f8982f08..8e431688 100755 +--- a/CI/test_cases/manual_cases/cgroupv2.sh ++++ b/CI/test_cases/manual_cases/cgroupv2.sh +@@ -31,59 +31,59 @@ function test_cgroup2_cpu() + + if [[ -f /sys/fs/cgroup/isulad/cpu.weight ]];then + # min value +- isula run -ti --rm --cpu-shares 2 busybox cat /sys/fs/cgroup/cpu.weight | grep ^1$'\r' ++ isula run --runtime $1 -ti --rm --cpu-shares 2 busybox cat /sys/fs/cgroup/cpu.weight | grep ^1$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 cpu.weight min value failed" && ((ret++)) + + # max value +- isula run -ti --rm --cpu-shares 262144 busybox cat /sys/fs/cgroup/cpu.weight | grep ^10000$'\r' ++ isula run --runtime $1 -ti --rm --cpu-shares 262144 busybox cat /sys/fs/cgroup/cpu.weight | grep ^10000$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 cpu.weight max value failed" && ((ret++)) + + # invalid value +- isula run -ti --rm --cpu-shares -1 busybox echo hello ++ isula run --runtime $1 -ti --rm --cpu-shares -1 busybox echo hello + [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 cpu.weight -1 failed" && ((ret++)) + + # default value +- isula run -ti --rm --cpu-shares 0 busybox cat /sys/fs/cgroup/cpu.weight | grep ^100$'\r' ++ isula run --runtime $1 -ti --rm --cpu-shares 0 busybox cat /sys/fs/cgroup/cpu.weight | grep ^100$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 cpu.weight default value failed" && ((ret++)) + fi + + if [[ -f /sys/fs/cgroup/isulad/cpu.max ]];then + # normal value +- isula run -ti --rm --cpu-quota 50000 --cpu-period 12345 busybox cat /sys/fs/cgroup/cpu.max | grep ^"50000 12345"$'\r' ++ isula run --runtime $1 -ti --rm --cpu-quota 50000 --cpu-period 12345 busybox cat /sys/fs/cgroup/cpu.max | grep ^"50000 12345"$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 cpu.max normal value failed" && ((ret++)) + + # invalid min period +- isula run -ti --rm --cpu-quota 50000 --cpu-period 999 busybox echo hello ++ isula run --runtime $1 -ti --rm --cpu-quota 50000 --cpu-period 999 busybox echo hello + [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 cpu.max invalid min period failed" && ((ret++)) + + # invalid max period +- isula run -ti --rm --cpu-quota 50000 --cpu-period 1000001 busybox echo hello ++ isula run --runtime $1 -ti --rm --cpu-quota 50000 --cpu-period 1000001 busybox echo hello + [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 cpu.max invalid max period failed" && ((ret++)) + + # invalid quota +- isula run -ti --rm --cpu-quota 999 --cpu-period 1000000 busybox echo hello ++ isula run --runtime $1 -ti --rm --cpu-quota 999 --cpu-period 1000000 busybox echo hello + [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 cpu.max invalid quota failed" && ((ret++)) + + # default 0 quota +- isula run -ti --rm --cpu-quota 0 --cpu-period 1000000 busybox cat /sys/fs/cgroup/cpu.max | grep ^"max 1000000"$'\r' ++ isula run --runtime $1 -ti --rm --cpu-quota 0 --cpu-period 1000000 busybox cat /sys/fs/cgroup/cpu.max | grep ^"max 1000000"$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 cpu.max default 0 quota failed" && ((ret++)) + + # default -1 quota +- isula run -ti --rm --cpu-quota -1 --cpu-period 1000000 busybox cat /sys/fs/cgroup/cpu.max | grep ^"max 1000000"$'\r' ++ isula run --runtime $1 -ti --rm --cpu-quota -1 --cpu-period 1000000 busybox cat /sys/fs/cgroup/cpu.max | grep ^"max 1000000"$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 cpu.max default -1 quota failed" && ((ret++)) + + # cpus 1 +- isula run -ti --rm --cpus 1 busybox cat /sys/fs/cgroup/cpu.max | grep ^"100000 100000"$'\r' ++ isula run --runtime $1 -ti --rm --cpus 1 busybox cat /sys/fs/cgroup/cpu.max | grep ^"100000 100000"$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 cpu.max cpus 1 failed" && ((ret++)) + + # cpus 0 +- isula run -ti --rm --cpus 0 busybox cat /sys/fs/cgroup/cpu.max | grep ^"max 100000"$'\r' ++ isula run --runtime $1 -ti --rm --cpus 0 busybox cat /sys/fs/cgroup/cpu.max | grep ^"max 100000"$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 cpu.max cpus 0 failed" && ((ret++)) + fi + + if [[ -f /sys/fs/cgroup/isulad/cpuset.cpus.effective ]];then + # normal value +- isula run -tid -n cpuset --cpuset-cpus 0 --cpuset-mems 0 busybox sh ++ isula run --runtime $1 -tid -n cpuset --cpuset-cpus 0 --cpuset-mems 0 busybox sh + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 cpuset run container failed" && ((ret++)) + + isula exec -ti cpuset cat /sys/fs/cgroup/cpuset.cpus | grep ^0$'\r' +@@ -96,19 +96,19 @@ function test_cgroup2_cpu() + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 cpuset remove container failed" && ((ret++)) + + # invalid cpus -1 value +- isula run -tid -n cpuset --cpuset-cpus -1 busybox sh ++ isula run --runtime $1 -tid -n cpuset --cpuset-cpus -1 busybox sh + [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 cpuset cpus invalid -1 failed" && ((ret++)) + + # invalid cpus 100000 value +- isula run -tid -n cpuset --cpuset-cpus 100000 busybox sh ++ isula run --runtime $1 -tid -n cpuset --cpuset-cpus 100000 busybox sh + [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 cpuset cpus invalid 100000 failed" && ((ret++)) + + # invalid mems -1 value +- isula run -tid -n cpuset --cpuset-mems -1 busybox sh ++ isula run --runtime $1 -tid -n cpuset --cpuset-mems -1 busybox sh + [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 cpuset mems invalid -1 failed" && ((ret++)) + + # invalid mems 100000 value +- isula run -tid -n cpuset --cpuset-mems 100000 busybox sh ++ isula run --runtime $1 -tid -n cpuset --cpuset-mems 100000 busybox sh + [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 cpuset mems invalid 100000 failed" && ((ret++)) + fi + +@@ -121,33 +121,38 @@ function test_cgroup2_io() + + if [[ -f "/sys/fs/cgroup/isulad/io.bfq.weight" ]];then + # min value +- isula run -ti --rm --blkio-weight 10 busybox cat "/sys/fs/cgroup/io.bfq.weight" | grep 1$'\r' +- [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 io.bfq.weight min value failed" && ((ret++)) ++ if [ $1 == "lcr" ]; then ++ isula run --runtime $1 -ti --rm --blkio-weight 10 busybox cat "/sys/fs/cgroup/io.bfq.weight" | grep 1$'\r' ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 io.bfq.weight min value failed" && ((ret++)) ++ else ++ isula run --runtime $1 -ti --rm --blkio-weight 10 busybox cat "/sys/fs/cgroup/io.bfq.weight" | grep 10$'\r' ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 io.bfq.weight min value failed" && ((ret++)) ++ fi + + # max value +- isula run -ti --rm --blkio-weight 1000 busybox cat "/sys/fs/cgroup/io.bfq.weight" | grep 1000$'\r' ++ isula run --runtime $1 -ti --rm --blkio-weight 1000 busybox cat "/sys/fs/cgroup/io.bfq.weight" | grep 1000$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 io.bfq.weight max value failed" && ((ret++)) + + # default value +- isula run -ti --rm --blkio-weight 0 busybox cat "/sys/fs/cgroup/io.bfq.weight" | grep 100$'\r' ++ isula run --runtime $1 -ti --rm --blkio-weight 0 busybox cat "/sys/fs/cgroup/io.bfq.weight" | grep 100$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 io.bfq.weight default value failed" && ((ret++)) + + # invalid value +- isula run -ti --rm --blkio-weight -1 busybox echo hello ++ isula run --runtime $1 -ti --rm --blkio-weight -1 busybox echo hello + [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 io.bfq.weight -1 failed" && ((ret++)) + fi + + if [[ -f "/sys/fs/cgroup/isulad/io.bfq.weight_device" ]];then + # min value +- isula run -ti --rm --blkio-weight-device /dev/null:10 busybox cat "/sys/fs/cgroup/io.bfq.weight_device" | grep ^"1:3 10"$'\r' ++ isula run --runtime $1 -ti --rm --blkio-weight-device /dev/null:10 busybox cat "/sys/fs/cgroup/io.bfq.weight_device" | grep ^"1:3 10"$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 io.bfq.weight_device max value failed" && ((ret++)) + + # max value +- isula run -ti --rm --blkio-weight-device /dev/null:1000 busybox cat "/sys/fs/cgroup/io.bfq.weight_device" | grep ^"1:3 10000"$'\r' ++ isula run --runtime $1 -ti --rm --blkio-weight-device /dev/null:1000 busybox cat "/sys/fs/cgroup/io.bfq.weight_device" | grep ^"1:3 10000"$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 io.bfq.weight_device max value failed" && ((ret++)) + + # disable weight device +- isula run -tid -n weight_device --rm --blkio-weight-device /dev/null:0 busybox sh ++ isula run --runtime $1 -tid -n weight_device --rm --blkio-weight-device /dev/null:0 busybox sh + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 io.bfq.weight_device failed" && ((ret++)) + + isula exec -ti weight_device cat "/sys/fs/cgroup/io.bfq.weight_device" | grep "1:3" +@@ -159,33 +164,43 @@ function test_cgroup2_io() + + if [[ -f "/sys/fs/cgroup/isulad/io.weight" ]];then + # min value +- isula run -ti --rm --blkio-weight 10 busybox cat "/sys/fs/cgroup/io.weight" | grep ^"default 1"$'\r' +- [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 io.weight min value failed" && ((ret++)) ++ if [ $1 == "lcr" ]; then ++ isula run --runtime $1 -ti --rm --blkio-weight 10 busybox cat "/sys/fs/cgroup/io.weight" | grep ^"default 1"$'\r' ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 io.weight min value failed" && ((ret++)) ++ else ++ isula run --runtime $1 -ti --rm --blkio-weight 10 busybox cat "/sys/fs/cgroup/io.bfq.weight" | grep ^"default 10"$'\r' ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 io.weight min value failed" && ((ret++)) ++ fi + + # max value +- isula run -ti --rm --blkio-weight 1000 busybox cat "/sys/fs/cgroup/io.weight" | grep ^"default 10000"$'\r' +- [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 io.weight max value failed" && ((ret++)) ++ if [ $1 == "lcr" ]; then ++ isula run --runtime $1 -ti --rm --blkio-weight 1000 busybox cat "/sys/fs/cgroup/io.weight" | grep ^"default 10000"$'\r' ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 io.weight max value failed" && ((ret++)) ++ else ++ isula run --runtime $1 -ti --rm --blkio-weight 1000 busybox cat "/sys/fs/cgroup/io.bfq.weight" | grep ^"default 1000"$'\r' ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 io.weight max value failed" && ((ret++)) ++ fi + + # default value +- isula run -ti --rm --blkio-weight 0 busybox cat "/sys/fs/cgroup/io.weight" | grep ^"default 100"$'\r' ++ isula run --runtime $1 -ti --rm --blkio-weight 0 busybox cat "/sys/fs/cgroup/io.weight" | grep ^"default 100"$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 io.weight default value failed" && ((ret++)) + + # invalid value +- isula run -ti --rm --blkio-weight -1 busybox echo hello ++ isula run --runtime $1 -ti --rm --blkio-weight -1 busybox echo hello + [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 io.weight -1 failed" && ((ret++)) + fi + + if [[ -f "/sys/fs/cgroup/isulad/io.weight_device" ]];then + # min value +- isula run -ti --rm --blkio-weight-device /dev/null:10 busybox cat "/sys/fs/cgroup/io.weight_device" | grep ^"1:3 10"$'\r' ++ isula run --runtime $1 -ti --rm --blkio-weight-device /dev/null:10 busybox cat "/sys/fs/cgroup/io.weight_device" | grep ^"1:3 10"$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 io.weight max value failed" && ((ret++)) + + # max value +- isula run -ti --rm --blkio-weight-device /dev/null:1000 busybox cat "/sys/fs/cgroup/io.weight_device" | grep ^"1:3 10000"$'\r' ++ isula run --runtime $1 -ti --rm --blkio-weight-device /dev/null:1000 busybox cat "/sys/fs/cgroup/io.weight_device" | grep ^"1:3 10000"$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 io.weight max value failed" && ((ret++)) + + # disable weight device +- isula run -tid -n weight_device --rm --blkio-weight-device /dev/null:0 busybox sh ++ isula run --runtime $1 -tid -n weight_device --rm --blkio-weight-device /dev/null:0 busybox sh + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 io.weight failed" && ((ret++)) + + isula exec -ti weight_device cat "/sys/fs/cgroup/io.weight_device" | grep ^"1:3"$'\r' +@@ -197,16 +212,22 @@ function test_cgroup2_io() + + if [[ -f /sys/fs/cgroup/isulad/io.max ]];then + # normal value +- isula run -ti --rm --device-read-bps /dev/null:1g --device-read-iops /dev/null:1000 --device-write-bps /dev/null:2g --device-write-iops /dev/null:2000 busybox cat /sys/fs/cgroup/io.max | grep ^"1:3 rbps=1073741824 wbps=2147483648 riops=1000 wiops=2000"$'\r' ++ isula run --runtime $1 -ti --rm --device-read-bps /dev/null:1g --device-read-iops /dev/null:1000 --device-write-bps /dev/null:2g --device-write-iops /dev/null:2000 busybox cat /sys/fs/cgroup/io.max | grep ^"1:3 rbps=1073741824 wbps=2147483648 riops=1000 wiops=2000"$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 io.max failed" && ((ret++)) + + # invalid +- isula run -ti --rm --device-read-bps /dev/null:-1 busybox echo hello ++ isula run --runtime $1 -ti --rm --device-read-bps /dev/null:-1 busybox echo hello + [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 io.max -1 failed" && ((ret++)) + +- # 0 is no limit +- isula run -ti --rm --device-read-bps /dev/null:0 --device-read-iops /dev/null:0 --device-write-bps /dev/null:0 --device-write-iops /dev/null:0 busybox echo hello +- [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 io.max 0 failed" && ((ret++)) ++ if [ $1 == "lcr" ]; then ++ # 0 is no limit ++ isula run --runtime $1 -ti --rm --device-read-bps /dev/null:0 --device-read-iops /dev/null:0 --device-write-bps /dev/null:0 --device-write-iops /dev/null:0 busybox echo hello ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 io.max 0 failed" && ((ret++)) ++ else ++ # 0 is limit ++ isula run --runtime $1 -ti --rm --device-read-bps /dev/null:0 --device-read-iops /dev/null:0 --device-write-bps /dev/null:0 --device-write-iops /dev/null:0 busybox echo hello ++ [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 io.max 0 success" && ((ret++)) ++ fi + fi + + return ${ret} +@@ -218,51 +239,51 @@ function test_cgroup2_memory() + + if [[ -f /sys/fs/cgroup/isulad/memory.max ]];then + # normal value +- isula run -ti --rm -m 10m busybox cat /sys/fs/cgroup/memory.max | grep ^10485760$'\r' ++ isula run --runtime $1 -ti --rm -m 10m busybox cat /sys/fs/cgroup/memory.max | grep ^10485760$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 memory.max run container failed" && ((ret++)) + + # 0 is max +- isula run -ti --rm -m 0 busybox cat /sys/fs/cgroup/memory.max | grep ^max$'\r' ++ isula run --runtime $1 -ti --rm -m 0 busybox cat /sys/fs/cgroup/memory.max | grep ^max$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 memory.max 0 failed" && ((ret++)) + + # invalid +- isula run -ti --rm -m -1 busybox echo hello ++ isula run --runtime $1 -ti --rm -m -1 busybox echo hello + [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 memory.max -1 failed" && ((ret++)) + fi + + if [[ -f /sys/fs/cgroup/isulad/memory.low ]];then + # normal value +- isula run -ti --rm --memory-reservation 10m busybox cat /sys/fs/cgroup/memory.low | grep ^10485760$'\r' ++ isula run --runtime $1 -ti --rm --memory-reservation 10m busybox cat /sys/fs/cgroup/memory.low | grep ^10485760$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 memory.low normal value failed" && ((ret++)) + + # -1 is invalid +- isula run -ti --rm --memory-reservation -1 busybox echo hello ++ isula run --runtime $1 -ti --rm --memory-reservation -1 busybox echo hello + [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 memory.low invalid failed" && ((ret++)) + + # 0 +- isula run -ti --rm --memory-reservation 0 busybox cat /sys/fs/cgroup/memory.low | grep ^0$'\r' ++ isula run --runtime $1 -ti --rm --memory-reservation 0 busybox cat /sys/fs/cgroup/memory.low | grep ^0$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 memory.low 0 failed" && ((ret++)) + fi + + if [[ -f /sys/fs/cgroup/isulad/memory.swap.max ]];then + # normal value +- isula run -ti --rm --memory 10m --memory-swap 20m busybox cat /sys/fs/cgroup/memory.swap.max | grep ^10485760$'\r' ++ isula run --runtime $1 -ti --rm --memory 10m --memory-swap 20m busybox cat /sys/fs/cgroup/memory.swap.max | grep ^10485760$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 memory.swap.max normal value failed" && ((ret++)) + + # invalid +- isula run -ti --rm --memory 10m --memory-swap 5m busybox echo hello ++ isula run --runtime $1 -ti --rm --memory 10m --memory-swap 5m busybox echo hello + [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 memory.swap.max invalid failed" && ((ret++)) + + # 0 is the same as memory +- isula run -ti --rm --memory 10m --memory-swap 0 busybox cat /sys/fs/cgroup/memory.swap.max | grep ^10485760$'\r' ++ isula run --runtime $1 -ti --rm --memory 10m --memory-swap 0 busybox cat /sys/fs/cgroup/memory.swap.max | grep ^10485760$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 memory.swap.max 0 failed" && ((ret++)) + + # -1 is max +- isula run -ti --rm --memory 10m --memory-swap -1 busybox cat /sys/fs/cgroup/memory.swap.max | grep ^max$'\r' ++ isula run --runtime $1 -ti --rm --memory 10m --memory-swap -1 busybox cat /sys/fs/cgroup/memory.swap.max | grep ^max$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 memory.swap.max -1 failed" && ((ret++)) + + # disable swap +- isula run -ti --rm --memory 10m --memory-swap 10m busybox cat /sys/fs/cgroup/memory.swap.max | grep ^0$'\r' ++ isula run --runtime $1 -ti --rm --memory 100m --memory-swap 100m busybox cat /sys/fs/cgroup/memory.swap.max | grep ^0$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 memory.swap.max disable swap failed" && ((ret++)) + fi + +@@ -275,15 +296,15 @@ function test_cgroup2_pids() + + if [[ -f /sys/fs/cgroup/isulad/pids.max ]];then + # normal value +- isula run -ti --rm --pids-limit 123456 busybox cat /sys/fs/cgroup/pids.max | grep ^123456$'\r' ++ isula run --runtime $1 -ti --rm --pids-limit 123456 busybox cat /sys/fs/cgroup/pids.max | grep ^123456$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 pids.max run container failed" && ((ret++)) + + # -1 is max +- isula run -ti --rm --pids-limit -1 busybox cat /sys/fs/cgroup/pids.max | grep ^max$'\r' ++ isula run --runtime $1 -ti --rm --pids-limit -1 busybox cat /sys/fs/cgroup/pids.max | grep ^max$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 pids.max run container failed" && ((ret++)) + + # 0 is max +- isula run -ti --rm --pids-limit 0 busybox cat /sys/fs/cgroup/pids.max | grep ^max$'\r' ++ isula run --runtime $1 -ti --rm --pids-limit 0 busybox cat /sys/fs/cgroup/pids.max | grep ^max$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 pids.max run container failed" && ((ret++)) + fi + +@@ -295,7 +316,7 @@ function test_cgroup2_hugetlb() + local ret=0 + + if [[ -f /sys/fs/cgroup/isulad/hugetlb.2MB.max ]];then +- isula run -ti --rm --hugetlb-limit 2M:32M busybox cat /sys/fs/cgroup/hugetlb.2MB.max | grep ^33554432$'\r' ++ isula run --runtime $1 -ti --rm --hugetlb-limit 2M:32M busybox cat /sys/fs/cgroup/hugetlb.2MB.max | grep ^33554432$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 hugetlb.2M.max run container failed" && ((ret++)) + fi + +@@ -307,7 +328,7 @@ function test_cgroup2_freeze() + local ret=0 + + if [[ -f /sys/fs/cgroup/isulad/cgroup.freeze ]];then +- isula run -tid -n freeze busybox sh ++ isula run --runtime $1 -tid -n freeze busybox sh + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 freeze run container failed" && ((ret++)) + + isula pause freeze +@@ -335,15 +356,15 @@ function test_cgroup2_files() + + if [[ -f /sys/fs/cgroup/isulad/files.limit ]];then + # normal value +- isula run -ti --rm --files-limit 123 busybox cat /sys/fs/cgroup/files.limit | grep ^123$'\r' ++ isula run --runtime $1 -ti --rm --files-limit 123 busybox cat /sys/fs/cgroup/files.limit | grep ^123$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 files.limit run container failed" && ((ret++)) + + # -1 is max +- isula run -ti --rm --files-limit -1 busybox cat /sys/fs/cgroup/files.limit | grep ^max$'\r' ++ isula run --runtime $1 -ti --rm --files-limit -1 busybox cat /sys/fs/cgroup/files.limit | grep ^max$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 files.limit run container failed" && ((ret++)) + + # 0 is max +- isula run -ti --rm --files-limit 0 busybox cat /sys/fs/cgroup/files.limit | grep ^max$'\r' ++ isula run --runtime $1 -ti --rm --files-limit 0 busybox cat /sys/fs/cgroup/files.limit | grep ^max$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 files.limit run container failed" && ((ret++)) + fi + +@@ -405,8 +426,13 @@ function test_cgroup2_cpu_update() + isula update --cpu-quota 0 --cpu-period 1000000 $cgroup2_update + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 update cpu.max 0 quota failed" && ((ret++)) + +- isula exec -ti $cgroup2_update cat /sys/fs/cgroup/cpu.max | grep ^"max 1000000"$'\r' +- [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 update cpu.max 0 quota value not right" && ((ret++)) ++ if [ $1 == "lcr" ]; then ++ isula exec -ti $cgroup2_update cat /sys/fs/cgroup/cpu.max | grep ^"max 1000000"$'\r' ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 update cpu.max 0 quota value not right" && ((ret++)) ++ else ++ isula exec -ti $cgroup2_update cat /sys/fs/cgroup/cpu.max | grep ^"50000 1000000"$'\r' ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 update cpu.max 0 quota value not right" && ((ret++)) ++ fi + + # default -1 quota + isula update --cpu-quota -1 --cpu-period 1000000 $cgroup2_update +@@ -416,7 +442,7 @@ function test_cgroup2_cpu_update() + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 update cpu.max -1 quota value not right" && ((ret++)) + + # cpus 1 +- isula run -tid -n cpu_update busybox sh ++ isula run --runtime $1 -tid -n cpu_update busybox sh + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 run cpu_update failed" && ((ret++)) + + isula update --cpus 1 cpu_update +@@ -476,8 +502,13 @@ function test_cgroup2_io_update() + isula update --blkio-weight 10 $cgroup2_update + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 update io.bfq.weight min value failed" && ((ret++)) + +- isula exec -ti $cgroup2_update cat "/sys/fs/cgroup/io.bfq.weight" | grep 1$'\r' +- [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 update io.bfq.weight min value not right" && ((ret++)) ++ if [ $1 == "lcr" ]; then ++ isula exec -ti $cgroup2_update cat "/sys/fs/cgroup/io.bfq.weight" | grep 1$'\r' ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 update io.bfq.weight min value not right" && ((ret++)) ++ else ++ isula exec -ti $cgroup2_update cat "/sys/fs/cgroup/io.bfq.weight" | grep 10$'\r' ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 update io.bfq.weight min value not right" && ((ret++)) ++ fi + + # max value + isula update --blkio-weight 1000 $cgroup2_update +@@ -503,22 +534,38 @@ function test_cgroup2_io_update() + isula update --blkio-weight 10 $cgroup2_update + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 update io.weight min value failed" && ((ret++)) + +- isula exec -ti $cgroup2_update cat "/sys/fs/cgroup/io.weight" | grep ^"default 1"$'\r' +- [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 update io.weight min value not right" && ((ret++)) ++ if [ $1 == "lcr" ]; then ++ isula exec -ti $cgroup2_update cat "/sys/fs/cgroup/io.weight" | grep ^"default 1"$'\r' ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 update io.weight min value not right" && ((ret++)) ++ else ++ isula exec -ti $cgroup2_update cat "/sys/fs/cgroup/io.bfq.weight" | grep ^"default 10"$'\r' ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 update io.weight min value not right" && ((ret++)) ++ fi + + # max value + isula update --blkio-weight 1000 $cgroup2_update + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 update io.weight max value failed" && ((ret++)) + +- isula exec -ti $cgroup2_update cat "/sys/fs/cgroup/io.weight" | grep ^"default 10000"$'\r' +- [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 update io.weight max value not right" && ((ret++)) ++ if [ $1 == "lcr" ]; then ++ isula exec -ti $cgroup2_update cat "/sys/fs/cgroup/io.weight" | grep ^"default 10000"$'\r' ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 update io.weight max value not right" && ((ret++)) ++ else ++ isula exec -ti $cgroup2_update cat "/sys/fs/cgroup/io.bfq.weight" | grep ^"default 1000"$'\r' ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 update io.weight max value not right" && ((ret++)) ++ fi + + # 0 means value not change + isula update --blkio-weight 0 $cgroup2_update + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 update io.weight 0 failed" && ((ret++)) + +- isula exec -ti $cgroup2_update cat "/sys/fs/cgroup/io.weight" | grep ^"default 10000"$'\r' +- [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 update io.weight 0 not right" && ((ret++)) ++ ++ if [ $1 == "lcr" ]; then ++ isula exec -ti $cgroup2_update cat "/sys/fs/cgroup/io.weight" | grep ^"default 10000"$'\r' ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 update io.weight max value not right" && ((ret++)) ++ else ++ isula exec -ti $cgroup2_update cat "/sys/fs/cgroup/io.bfq.weight" | grep ^"default 1000"$'\r' ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 update io.weight max value not right" && ((ret++)) ++ fi + + # invalid value + isula update --blkio-weight -1 $cgroup2_update echo hello +@@ -591,12 +638,13 @@ function test_cgroup2_memory_update() + isula exec -ti $cgroup2_update cat /sys/fs/cgroup/memory.swap.max | grep ^10485760$'\r' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 update memory.swap.max 0 value not right" && ((ret++)) + +- # -1 is max +- isula update --memory 10m --memory-swap -1 $cgroup2_update +- [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 update memory.swap.max -1 failed" && ((ret++)) +- +- isula exec -ti $cgroup2_update cat /sys/fs/cgroup/memory.swap.max | grep ^max$'\r' +- [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 update memory.swap.max -1 value not right" && ((ret++)) ++ if [ $1 == "lcr" ]; then ++ # -1 is max ++ isula update --memory 10m --memory-swap -1 $cgroup2_update ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 update memory.swap.max -1 failed" && ((ret++)) ++ isula exec -ti $cgroup2_update cat /sys/fs/cgroup/memory.swap.max | grep ^max$'\r' ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 update memory.swap.max -1 value not right" && ((ret++)) ++ fi + + # disable swap + isula update --memory 10m --memory-swap 10m $cgroup2_update +@@ -613,16 +661,16 @@ function test_cgroup2_unsupported() + { + local ret=0 + +- isula run -ti --rm --cpu-rt-period 1000000 --cpu-rt-runtime 1000000 busybox echo hello ++ isula run --runtime $1 -ti --rm --cpu-rt-period 1000000 --cpu-rt-runtime 1000000 busybox echo hello + [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 --cpu-rt-period and --cpu-rt-runtime should failed" && ((ret++)) + +- isula run -ti --rm --kernel-memory 100m busybox echo hello ++ isula run --runtime $1 -ti --rm --kernel-memory 100m busybox echo hello + [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 --kernel-memory should failed" && ((ret++)) + +- isula run -ti --rm --memory-swappiness 50 busybox echo hello ++ isula run --runtime $1 -ti --rm --memory-swappiness 50 busybox echo hello + [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 --memory-swappiness should failed" && ((ret++)) + +- isula run -ti --rm --oom-kill-disable busybox echo hello ++ isula run --runtime $1 -ti --rm --oom-kill-disable busybox echo hello + [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 --oom-kill-disable should failed" && ((ret++)) + + isula update --cpu-rt-period 1000000 --cpu-rt-runtime 1000000 $cgroup2_update +@@ -641,7 +689,7 @@ function test_cgroup2_parent() + rmdir /sys/fs/cgroup/isulad + rmdir /sys/fs/cgroup/abc + +- id=`isula run -tid --cgroup-parent /abc -m 10m busybox sh` ++ id=`isula run --runtime $1 -tid --cgroup-parent /abc -m 10m busybox sh` + cat /sys/fs/cgroup/abc/$id/memory.max | grep ^10485760$ + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 --cgroup-parent cannot work" && ((ret++)) + +@@ -657,39 +705,39 @@ function test_cgroup2_device() + mknod_num=$(echo $dev_num | sed 's/:/ /g') + + # read only +- isula run -ti --rm --device=$dev_name:/dev/sdx:r busybox sh -c 'echo q | fdisk /dev/sdx | grep "read only"' ++ isula run --runtime $1 -ti --rm --device=$dev_name:/dev/sdx:r busybox sh -c 'echo q | fdisk /dev/sdx | grep "read only"' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 --device r failed" && ((ret++)) + +- isula run -ti --rm --device=$dev_name:/dev/sdx:rm busybox sh -c 'echo q | fdisk /dev/sdx | grep "read only"' ++ isula run --runtime $1 -ti --rm --device=$dev_name:/dev/sdx:rm busybox sh -c 'echo q | fdisk /dev/sdx | grep "read only"' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 --device rm failed" && ((ret++)) + +- isula run -ti --rm --device-cgroup-rule="b $dev_num r" busybox sh -c "mknod /dev/sdx b $mknod_num && echo q | fdisk /dev/sdx | grep 'read only'" ++ isula run --runtime $1 -ti --rm --device-cgroup-rule="b $dev_num r" busybox sh -c "mknod /dev/sdx b $mknod_num && echo q | fdisk /dev/sdx | grep 'read only'" + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 --device r failed" && ((ret++)) + +- isula run -ti --rm --device-cgroup-rule="b $dev_num rm" busybox sh -c "mknod /dev/sdx b $mknod_num && echo q | fdisk /dev/sdx | grep 'read only'" ++ isula run --runtime $1 -ti --rm --device-cgroup-rule="b $dev_num rm" busybox sh -c "mknod /dev/sdx b $mknod_num && echo q | fdisk /dev/sdx | grep 'read only'" + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 --device rm failed" && ((ret++)) + + # can't read +- isula run -ti --rm --device=$dev_name:/dev/sdx:w busybox sh -c 'echo q | fdisk /dev/sdx 2>&1 | grep "t open"' ++ isula run --runtime $1 -ti --rm --device=$dev_name:/dev/sdx:w busybox sh -c 'echo q | fdisk /dev/sdx 2>&1 | grep "t open"' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 --device w failed" && ((ret++)) + +- isula run -ti --rm --device=$dev_name:/dev/sdx:wm busybox sh -c 'echo q | fdisk /dev/sdx 2>&1 | grep "t open"' ++ isula run --runtime $1 -ti --rm --device=$dev_name:/dev/sdx:wm busybox sh -c 'echo q | fdisk /dev/sdx 2>&1 | grep "t open"' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 --device wm failed" && ((ret++)) + +- isula run -ti --rm --device-cgroup-rule="b $dev_num w" busybox sh -c "mknod /dev/sdx b $mknod_num && echo q | fdisk /dev/sdx 2>&1 | grep 't open'" ++ isula run --runtime $1 -ti --rm --device-cgroup-rule="b $dev_num w" busybox sh -c "mknod /dev/sdx b $mknod_num && echo q | fdisk /dev/sdx 2>&1 | grep 't open'" + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 --device w failed" && ((ret++)) + +- isula run -ti --rm --device-cgroup-rule="b $dev_num wm" busybox sh -c "mknod /dev/sdx b $mknod_num && echo q | fdisk /dev/sdx 2>&1 | grep 't open'" ++ isula run --runtime $1 -ti --rm --device-cgroup-rule="b $dev_num wm" busybox sh -c "mknod /dev/sdx b $mknod_num && echo q | fdisk /dev/sdx 2>&1 | grep 't open'" + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 --device wm failed" && ((ret++)) + + # can't read write +- isula run -ti --rm --device=$dev_name:/dev/sdx:m busybox sh -c 'echo q | fdisk /dev/sdx 2>&1 | grep "t open"' ++ isula run --runtime $1 -ti --rm --device=$dev_name:/dev/sdx:m busybox sh -c 'echo q | fdisk /dev/sdx 2>&1 | grep "t open"' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 --device m" && ((ret++)) + +- isula run -ti --rm --device-cgroup-rule="b $dev_num m" busybox sh -c "mknod /dev/sdx b $mknod_num && echo q | fdisk /dev/sdx 2>&1 | grep 't open'" ++ isula run --runtime $1 -ti --rm --device-cgroup-rule="b $dev_num m" busybox sh -c "mknod /dev/sdx b $mknod_num && echo q | fdisk /dev/sdx 2>&1 | grep 't open'" + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 --device wm failed" && ((ret++)) + +- isula run -ti --rm --device-cgroup-rule="b *:* m" busybox sh -c "mknod /dev/sdx b $mknod_num && echo q | fdisk /dev/sdx 2>&1 | grep 't open'" ++ isula run --runtime $1 -ti --rm --device-cgroup-rule="b *:* m" busybox sh -c "mknod /dev/sdx b $mknod_num && echo q | fdisk /dev/sdx 2>&1 | grep 't open'" + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 --device wm failed" && ((ret++)) + + return ${ret} +@@ -723,7 +771,7 @@ function prepare_test_cgroupv2() + + isula rm -f `isula ps -a -q` + +- isula run -tid -n $cgroup2_update busybox sh ++ isula run --runtime $1 -tid -n $cgroup2_update busybox sh + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - cgroup2 run container failed" && ((ret++)) + + return ${ret} +@@ -740,25 +788,31 @@ declare -i ans=0 + msg_info "${test} starting..." + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - start isulad failed" && ((ret++)) + +-prepare_test_cgroupv2 || ((ans++)) +-if [ "$cgroupv2" == "1" ];then +- test_cgroup2_cpu || ((ans++)) +- test_cgroup2_io || ((ans++)) +- test_cgroup2_memory || ((ans++)) +- test_cgroup2_pids || ((ans++)) +- test_cgroup2_hugetlb || ((ans++)) +- test_cgroup2_freeze || ((ans++)) +- test_cgroup2_files || ((ans++)) +- test_cgroup2_cpu_update || ((ans++)) +- test_cgroup2_io_update || ((ans++)) +- test_cgroup2_memory_update || ((ans++)) +- test_cgroup2_unsupported || ((ans++)) +- test_cgroup2_parent || ((ans++)) +- test_cgroup2_device || ((ans++)) +-else +- msg_info "${test} not cgroup v2 enviorment, ignore test..." +-fi +-post_test_cgroupv2 ++for element in ${RUNTIME_LIST[@]}; ++do ++ prepare_test_cgroupv2 $element || ((ans++)) ++ if [ "$cgroupv2" == "1" ];then ++ local test="cgroup v2 test => (${element})" ++ msg_info "${test} starting..." ++ test_cgroup2_cpu $element || ((ans++)) ++ test_cgroup2_io $element || ((ans++)) ++ test_cgroup2_memory $element || ((ans++)) ++ test_cgroup2_pids $element || ((ans++)) ++ test_cgroup2_hugetlb $element || ((ans++)) ++ test_cgroup2_freeze $element || ((ans++)) ++ test_cgroup2_files $element || ((ans++)) ++ test_cgroup2_cpu_update $element || ((ans++)) ++ test_cgroup2_io_update $element || ((ans++)) ++ test_cgroup2_memory_update $element || ((ans++)) ++ test_cgroup2_unsupported $element || ((ans++)) ++ test_cgroup2_parent $element || ((ans++)) ++ test_cgroup2_device $element || ((ans++)) ++ msg_info "${test} finished with return ${ans}..." ++ else ++ msg_info "${test} not cgroup v2 enviorment, ignore test..." ++ fi ++ post_test_cgroupv2 $element ++done + + msg_info "${test} finished with return ${ans}..." + +-- +2.34.1 + diff --git a/0038-fix-run-ubuntu-container-bug-in-inspect.sh.patch b/0039-fix-run-ubuntu-container-bug-in-inspect.sh.patch similarity index 94% rename from 0038-fix-run-ubuntu-container-bug-in-inspect.sh.patch rename to 0039-fix-run-ubuntu-container-bug-in-inspect.sh.patch index f16356c..5501261 100644 --- a/0038-fix-run-ubuntu-container-bug-in-inspect.sh.patch +++ b/0039-fix-run-ubuntu-container-bug-in-inspect.sh.patch @@ -1,7 +1,7 @@ From 8e1fe0302bf1a871f66a296e456811e878b1fa3b Mon Sep 17 00:00:00 2001 From: jikai Date: Tue, 2 Apr 2024 10:06:18 +0800 -Subject: [PATCH 38/43] fix run ubuntu container bug in inspect.sh +Subject: [PATCH 39/69] fix run ubuntu container bug in inspect.sh Signed-off-by: jikai --- diff --git a/0039-add-support-for-GetContainerEvents.patch b/0040-add-support-for-GetContainerEvents.patch similarity index 99% rename from 0039-add-support-for-GetContainerEvents.patch rename to 0040-add-support-for-GetContainerEvents.patch index 6e7d03f..397a792 100644 --- a/0039-add-support-for-GetContainerEvents.patch +++ b/0040-add-support-for-GetContainerEvents.patch @@ -1,7 +1,7 @@ From 745497bdc5c5192709ecc7b3edc91a5170f5b30e Mon Sep 17 00:00:00 2001 From: jikai Date: Fri, 29 Mar 2024 09:33:38 +0000 -Subject: [PATCH 39/43] add support for GetContainerEvents +Subject: [PATCH 40/69] add support for GetContainerEvents Signed-off-by: jikai --- diff --git a/0040-fix-cpurt-init-bug-for-systemd-cgroup.patch b/0041-fix-cpurt-init-bug-for-systemd-cgroup.patch similarity index 98% rename from 0040-fix-cpurt-init-bug-for-systemd-cgroup.patch rename to 0041-fix-cpurt-init-bug-for-systemd-cgroup.patch index ce92d43..1f5e9eb 100644 --- a/0040-fix-cpurt-init-bug-for-systemd-cgroup.patch +++ b/0041-fix-cpurt-init-bug-for-systemd-cgroup.patch @@ -1,7 +1,7 @@ From fe11b34a3c2843ea2198b310160b182d63aeb63b Mon Sep 17 00:00:00 2001 From: jikai Date: Tue, 2 Apr 2024 11:22:09 +0800 -Subject: [PATCH 40/43] fix cpurt init bug for systemd-cgroup +Subject: [PATCH 41/69] fix cpurt init bug for systemd-cgroup Signed-off-by: jikai --- diff --git a/0041-fix-message-queue-concurrent-bug.patch b/0042-fix-message-queue-concurrent-bug.patch similarity index 95% rename from 0041-fix-message-queue-concurrent-bug.patch rename to 0042-fix-message-queue-concurrent-bug.patch index 12c9876..063742a 100644 --- a/0041-fix-message-queue-concurrent-bug.patch +++ b/0042-fix-message-queue-concurrent-bug.patch @@ -1,7 +1,7 @@ From f90a145d9d29682295aebf2bcd30865ee5f6491f Mon Sep 17 00:00:00 2001 From: jikai Date: Tue, 2 Apr 2024 07:53:54 +0000 -Subject: [PATCH 41/43] fix message queue concurrent bug +Subject: [PATCH 42/69] fix message queue concurrent bug Signed-off-by: jikai --- diff --git a/0042-specify-runtime-as-runc-for-oom-test-CI.patch b/0043-specify-runtime-as-runc-for-oom-test-CI.patch similarity index 94% rename from 0042-specify-runtime-as-runc-for-oom-test-CI.patch rename to 0043-specify-runtime-as-runc-for-oom-test-CI.patch index 9db5fe1..3f807c8 100644 --- a/0042-specify-runtime-as-runc-for-oom-test-CI.patch +++ b/0043-specify-runtime-as-runc-for-oom-test-CI.patch @@ -1,7 +1,7 @@ From 7af700c4021ef9961aaac37ffa5767bd4f3dd184 Mon Sep 17 00:00:00 2001 From: jikai Date: Tue, 2 Apr 2024 08:00:37 +0000 -Subject: [PATCH 42/43] specify runtime as runc for oom test CI +Subject: [PATCH 43/69] specify runtime as runc for oom test CI Signed-off-by: jikai --- diff --git a/0043-set-oomkilled-in-cri.patch b/0044-set-oomkilled-in-cri.patch similarity index 95% rename from 0043-set-oomkilled-in-cri.patch rename to 0044-set-oomkilled-in-cri.patch index 486579e..a9d21ea 100644 --- a/0043-set-oomkilled-in-cri.patch +++ b/0044-set-oomkilled-in-cri.patch @@ -1,7 +1,7 @@ From 5393ce7d02bb73ce4760edefa959dfb4846f1958 Mon Sep 17 00:00:00 2001 From: jikai Date: Tue, 2 Apr 2024 11:19:06 +0000 -Subject: [PATCH 43/43] set oomkilled in cri +Subject: [PATCH 44/69] set oomkilled in cri Signed-off-by: jikai --- diff --git a/0045-add-cri-1.29-update-design-doc.patch b/0045-add-cri-1.29-update-design-doc.patch new file mode 100644 index 0000000..7098ecf --- /dev/null +++ b/0045-add-cri-1.29-update-design-doc.patch @@ -0,0 +1,312 @@ +From a1f8641f7b440362a615e72246c92654008f61e9 Mon Sep 17 00:00:00 2001 +From: jikai +Date: Thu, 22 Feb 2024 11:09:50 +0800 +Subject: [PATCH 45/69] add cri 1.29 update design doc + +Signed-off-by: jikai +--- + README.md | 2 +- + docs/design/README_zh.md | 3 +- + .../detailed/CRI/CRI_1.29_update_design.md | 237 ++++++++++++++++++ + .../cri_api_1.29_GetContainerEvents.svg | 8 + + docs/images/cri_api_1.29_overview.svg | 5 + + 5 files changed, 253 insertions(+), 2 deletions(-) + create mode 100644 docs/design/detailed/CRI/CRI_1.29_update_design.md + create mode 100644 docs/images/cri_api_1.29_GetContainerEvents.svg + create mode 100644 docs/images/cri_api_1.29_overview.svg + +diff --git a/README.md b/README.md +index 970b6e72..694ddbc2 100644 +--- a/README.md ++++ b/README.md +@@ -240,4 +240,4 @@ iSulad Version | Kubernetes Version | CRI Version + --- | --- | --- + v2.0.0+ | v1.13-v1.18 | v1alpha2 + v2.0.8+ | v1.19-v1.22 | v1alpha2 +-v2.1.4+ | v1.23-v1.26 | v1, v1alpha2 ++v2.1.4+ | v1.23-v1.29 | v1, v1alpha2 +diff --git a/docs/design/README_zh.md b/docs/design/README_zh.md +index b7ec3ddb..3382bfbe 100644 +--- a/docs/design/README_zh.md ++++ b/docs/design/README_zh.md +@@ -69,4 +69,5 @@ + + - 查看 Sandbox 模块的设计文档: [sandbox_design_zh](./detailed/Sandbox/sandbox_design_zh.md) 。 + - 查看 Controller 模块的设计文档: [controller_design_zh](./detailed/Sandbox/controller_design_zh.md) 。 +-- 查看 CRI V1 模块的设计文档: [podsandbox_cri_interface_design](./detailed/Sandbox/podsandbox_cri_interface_design.md) 。 +\ No newline at end of file ++- 查看 CRI V1 模块的设计文档: [podsandbox_cri_interface_design](./detailed/Sandbox/podsandbox_cri_interface_design.md) 。 ++- 查看 CRI 1.29 更新模块的设计文档: [cri_1.29_update_design](./detailed/CRI/CRI_1.29_update_design.md) 。 +diff --git a/docs/design/detailed/CRI/CRI_1.29_update_design.md b/docs/design/detailed/CRI/CRI_1.29_update_design.md +new file mode 100644 +index 00000000..0a0c860b +--- /dev/null ++++ b/docs/design/detailed/CRI/CRI_1.29_update_design.md +@@ -0,0 +1,237 @@ ++| Author | 吉凯 | ++| ------ | ----------------------| ++| Date | 2024-02-20 | ++| Email | jikai11@huawei.com | ++ ++### 方案目标 ++ ++当前iSulad CRI接口版本采用的1.25版本, 预期升级至1.29版本,iSulad CRI接口需要对升级后的新增CRI字段进行补充。 ++ ++该需求需要iSulad对K8S新版本CRI接口1.29提供支持,在K8S 1.25及之前,K8S存在CRI V1alpha2 和 CRI V1两种版本的CRI接口, ++但从1.26开始,K8S开始仅提供对于新版本CRI V1的支持,对1.25及之前的CRI接口,此次升级中,iSulad引用CRI V1, ++对于1.25及之前的CRI接口,V1alpha2和V1功能保持一致,1.26及之后新增的特性仅在CRI V1中提供支持。 ++ ++CRI V1使能: ++ ++1、编译iSulad时开启ENABLE_CRI_API_V1编译选项 ++ ++```bash ++cmake ../ -D ENABLE_CRI_API_V1=ON ++``` ++ ++2、daemon.json中enable-cri-v1设置为true ++ ++```json ++{ ++ "group": "isula", ++ "default-runtime": "runc", ++ "graph": "/var/lib/isulad", ++ "state": "/var/run/isulad", ++ "log-level": "ERROR", ++ "pidfile": "/var/run/isulad.pid", ++ ... ++ "enable-cri-v1": true, ++} ++``` ++ ++### 总体设计 ++ ++#### 变更文档 ++ ++ ++ ++#### 总体设计图 ++ ++![](../../../images/cri_api_1.29_overview.svg) ++ ++#### 此次更新包含以下变更 ++ ++##### [kubelet: get cgroup driver config from CRI](https://github.com/kubernetes/kubernetes/pull/118770) ++ ++`RuntimeConfig` 获取cgroup驱动配置 cgroupfs 或 systemd-cgroup ++ ++##### [Add Support for Evented PLEG](https://github.com/kubernetes/kubernetes/pull/111384) ++ ++`GetContainerEents`,提供对pod生命周期相关事件流 ++ ++`PodSandboxStatus`有相应调整 ++ ++##### [Add swap to stats to Summary API and Prometheus endpoints (/stats/summary and /metrics/resource)](https://github.com/kubernetes/kubernetes/pull/118865) ++ ++`ContainerStats`新增虚拟内存使用情况信息: `SwapUsage` ++ ++##### 变更排查 ++ ++1、[Propose comment to standardize the reason field](https://github.com/kubernetes/kubernetes/pull/112977) ++ ++Must be set to "OOMKilled" for containers terminated by cgroup-based Out-of-Memory killer. ++ ++container status中reason字段在cgroup out-of-memory时应该设置为OOMKilled ++ ++2、[Improve the API description of `PodSecurityContext.SupplementalGroups` to clarify its unfamiliar behavior](https://github.com/kubernetes/kubernetes/pull/113047) ++ ++描述修改,优化`PodSecurityContext.SupplementalGroups`的注释,明确容器镜像定义的主UID不在该列表下的行为 ++ ++- Clarified the expected behavior of `SupplementalGroups` field of `PodSecurityContext` ++ ++```txt ++ // List of groups applied to the first process run in the sandbox, in ++ // addition to the sandbox's primary GID, and group memberships defined ++ // in the container image for the sandbox's primary UID of the container process. ++ // If the list is empty, no additional groups are added to any container. ++ // Note that group memberships defined in the container image for the sandbox's primary UID ++ // of the container process are still effective, even if they are not included in this list. ++``` ++ ++3、[cri-api: document expectation of 16 MB limit](https://github.com/kubernetes/kubernetes/pull/110435) ++ ++```txt ++ // Captured command stdout output. ++ // The runtime should cap the output of this response to 16MB. ++ // If the stdout of the command produces more than 16MB, the remaining output ++ // should be discarded, and the command should proceed with no error. ++ // See CVE-2022-1708 and CVE-2022-31030 for more information. ++``` ++ ++##### 其它不涉及 ++ ++1、windows相关 ++ ++[CRI: Add Windows Podsandbox Stats](https://github.com/kubernetes/kubernetes/pull/110754) ++ ++[Windows hostnetwork alpha](https://github.com/kubernetes/kubernetes/pull/112961) ++ ++[Expose commit memory used in WindowsMemoryUsage struct](https://github.com/kubernetes/kubernetes/pull/119238) ++ ++2、iSulad 底层暂不支持 ++ ++[Add mappings for volumes](https://github.com/kubernetes/kubernetes/pull/116377) ++ ++[CRI: Add CDI device info for containers](https://github.com/kubernetes/kubernetes/pull/115891/) ++ ++3、K8S KEP 初期,其它容器引擎未支持,iSulad暂不支持 ++ ++[kubelet: add support for broadcasting metrics from CRI](https://github.com/kubernetes/kubernetes/pull/113609) ++ ++4、其它 ++ ++[Add user specified image to CRI ContainerConfig](https://github.com/kubernetes/kubernetes/pull/118652) ++ ++[Add runtime handler field to ImageSpec struct](https://github.com/kubernetes/kubernetes/pull/121121) ++ ++[cri-api: fix comment lines about PROPAGATION_PRIVATE](https://github.com/kubernetes/kubernetes/pull/115704) ++ ++[Kubelet disk api cri update](https://github.com/kubernetes/kubernetes/pull/120914) ++ ++### 详细设计 ++ ++#### Add swap stats to ContainerStats ++ ++`ContainerStats`新增虚拟内存使用情况信息: `SwapUsage` ++ ++```mermaid ++sequenceDiagram ++ participant kubelet ++ participant isulad ++ participant runc ++ participant cgroup ++ ++ kubelet->>isulad:CRI request(ContainerStats)isulad->>isulad:container stats request ++ isulad->>runc:container create request(w/wo --sytemd-cgroup) ++ runc->>cgroup:read cgroup file ++ runc->>isulad:container stats info ++ isulad ->> kubelet:response ++``` ++ ++#### define reason to ContainerStatus ++ ++container status中reason字段在cgroup out-of-memory时应该设置为OOMKilled ++ ++```mermaid ++sequenceDiagram ++ participant kubelet ++ participant isulad ++ participant runc ++ participant cgroup ++ ++ kubelet->>isulad:CRI request ++ alt CreateContainer&StartContainer ++ isulad->>runc:container create request(w memory limit set) ++ runc ->> cgroup:create cgroup path ++ isulad->>cgroup:monitor cgroup oom event ++ cgroup->>isulad:oom triggered ++ else ContainerStatus ++ isulad->>isulad:get container status ++ end ++ isulad ->> kubelet:response ++``` ++ ++#### kubelet: get cgroup driver config from CRI ++ ++KEP: ++ ++##### RuntimeConfig CRI API修改 ++ ++新增rpc,获取cgroup驱动配置: cgroupfs 或者 systemd-cgroup ++ ++##### iSulad RuntimeConfig 设计 ++ ++仅提供对runc的支持 ++ ++配置文件daemon.json: systemd-cgroup: true表示使用systemd-cgroup否则使用cgroupfs ++ ++在iSulad配置cgroup driver为systemd-cgroup时,底层runc采用对应的systemd-cgroup ++ ++```mermaid ++sequenceDiagram ++ participant kubelet ++ participant isulad ++ participant runc ++ participant cgroup ++ ++ kubelet->>isulad:CRI request ++ alt RuntimeConfig ++ isulad->>isulad:get cgroup driver from conf ++ else RunPodSandbox/CreateContainer ++ isulad->>isulad:get cgroup driver from conf ++ isulad->>runc:container create request(w/wo --sytemd-cgroup) ++ runc ->> cgroup:create cgroup path ++ end ++ isulad ->> kubelet:response ++``` ++ ++#### Add Support for Evented PLEG ++ ++##### GetContainerEvents CRI API修改 ++ ++`GetContainerEvents` rpc接口此前尚未支持,此次提供对该接口的支持 ++ ++##### iSulad GetContainerEvents设计 ++ ++CRIContainerEvents 模块 ++ ++增加接口mailbox_publish ++ ++事件包括沙箱和容器以下几种类型生命周期事件 ++ ++```proto ++enum ContainerEventType { ++ // Container created ++ CONTAINER_CREATED_EVENT = 0; ++ ++ // Container started ++ CONTAINER_STARTED_EVENT = 1; ++ ++ // Container stopped ++ CONTAINER_STOPPED_EVENT = 2; ++ ++ // Container deleted ++ CONTAINER_DELETED_EVENT = 3; ++} ++``` ++ ++![](../../../images/cri_api_1.29_GetContainerEvents.svg) ++ ++### 使用限制 ++ ++以上特性仅保证容器运行时设置为runc时支持。 +diff --git a/docs/images/cri_api_1.29_GetContainerEvents.svg b/docs/images/cri_api_1.29_GetContainerEvents.svg +new file mode 100644 +index 00000000..be855b5b +--- /dev/null ++++ b/docs/images/cri_api_1.29_GetContainerEvents.svg +@@ -0,0 +1,8 @@ ++ ++ ++ ++ ++ ++ ++ ++ KubletCRI requestGetContainerEventsiSuladCRI ModuleSandboxModuleContainer Runtime ModuleGetContainerEventsMailbox ModulePublishSubscribe +\ No newline at end of file +diff --git a/docs/images/cri_api_1.29_overview.svg b/docs/images/cri_api_1.29_overview.svg +new file mode 100644 +index 00000000..94911913 +--- /dev/null ++++ b/docs/images/cri_api_1.29_overview.svg +@@ -0,0 +1,5 @@ ++ ++ ++ ++ ++ ListPodSandboxStatsPodSandboxStatsPodSandboxStatsContainerStatsSwapUsageListContainerStatsContainerStatsLinuxPodSandboxStatsGetContainerEventsContainerEventResponse无变更新增修改接口内部数据RuntimeConfigLinuxRuntimeConfigurationCgroupDriverPodSandboxStatusPodSandboxStatusResponseContainerStatusContainerStatusContainerStatusResponse +\ No newline at end of file +-- +2.34.1 + diff --git a/0046-oom-monitor-in-manual-cases.patch b/0046-oom-monitor-in-manual-cases.patch new file mode 100644 index 0000000..37d7d40 --- /dev/null +++ b/0046-oom-monitor-in-manual-cases.patch @@ -0,0 +1,120 @@ +From aa77c85ea6879698663d4ef9e01bb63a0db1e57d Mon Sep 17 00:00:00 2001 +From: jikai +Date: Wed, 3 Apr 2024 09:34:39 +0000 +Subject: [PATCH 46/69] oom monitor in manual cases + +Signed-off-by: jikai +--- + CI/test_cases/container_cases/inspect.sh | 15 ------ + CI/test_cases/manual_cases/oom_monitor.sh | 59 +++++++++++++++++++++++ + 2 files changed, 59 insertions(+), 15 deletions(-) + create mode 100755 CI/test_cases/manual_cases/oom_monitor.sh + +diff --git a/CI/test_cases/container_cases/inspect.sh b/CI/test_cases/container_cases/inspect.sh +index 5d976281..cde9ea1f 100755 +--- a/CI/test_cases/container_cases/inspect.sh ++++ b/CI/test_cases/container_cases/inspect.sh +@@ -27,7 +27,6 @@ function test_inspect_spec() + { + local ret=0 + local image="busybox" +- local ubuntu_image="ubuntu" + local test="container inspect test => (${FUNCNAME[@]})" + + msg_info "${test} starting..." +@@ -38,12 +37,6 @@ function test_inspect_spec() + isula images | grep busybox + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - missing list image: ${image}" && ((ret++)) + +- isula pull ${ubuntu_image} +- [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to pull image: ${ubuntu_image}" && return ${FAILURE} +- +- isula images | grep ubuntu +- [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - missing list image: ${ubuntu_image}" && ((ret++)) +- + containername=test_inspect + + isula create --name $containername --ipc host --pid host --uts host --restart=on-failure:10 --hook-spec ${test_data_path}/test-hookspec.json --cpu-shares 100 --memory 5MB --memory-reservation 4MB --cpu-period 1000000 --cpu-quota 200000 --cpuset-cpus 1 --cpuset-mems 0 --kernel-memory 50M --pids-limit=10000 --volume /home:/root --env a=1 $image /bin/sh ls +@@ -146,14 +139,6 @@ function test_inspect_spec() + + isula rm -f $containername + +- # use more than 10m memory limit, otherwise it might fail to run +- isula run -it -m 10m --runtime runc --name $containername $ubuntu_image perl -e 'for ($i = 0; $i < 100000000; $i++) { $a .= " " x 1024 }' +- +- isula inspect -f "{{json .State.OOMKilled}} {{.Name}}" $containername 2>&1 | sed -n '1p' | grep "true" +- [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to check container with image: ${ubuntu_image}" && ((ret++)) +- +- isula rm -f $containername +- + msg_info "${test} finished with return ${ret}..." + return ${ret} + } +diff --git a/CI/test_cases/manual_cases/oom_monitor.sh b/CI/test_cases/manual_cases/oom_monitor.sh +new file mode 100755 +index 00000000..a1c2503d +--- /dev/null ++++ b/CI/test_cases/manual_cases/oom_monitor.sh +@@ -0,0 +1,59 @@ ++#!/bin/bash ++# ++# attributes: isulad oom monitor ++# concurrent: NA ++# spend time: 6 ++ ++####################################################################### ++##- Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++# - iSulad 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. ++##- @Description:CI ++##- @Author: jikai ++##- @Create: 2024-04-03 ++####################################################################### ++ ++declare -r curr_path=$(dirname $(readlink -f "$0")) ++source ../helpers.sh ++test_data_path=$(realpath $curr_path/test_data) ++ ++function test_oom_monitor() ++{ ++ local ret=0 ++ local ubuntu_image="ubuntu" ++ local test="container oom monitor test => (${FUNCNAME[@]})" ++ containername="oommonitor" ++ ++ msg_info "${test} starting..." ++ ++ isula pull ${ubuntu_image} ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to pull image: ${ubuntu_image}" && return ${FAILURE} ++ ++ isula images | grep ubuntu ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - missing list image: ${ubuntu_image}" && ((ret++)) ++ ++ # use more than 10m memory limit, otherwise it might fail to run ++ # iSulad monitor cgroup file for oom event, however oom triggers cgroup files delete ++ # if cgroup files were deleted before oom event was handled for iSulad we might failed to detect oom event ++ isula run -it -m 10m --runtime runc --name $containername $ubuntu_image perl -e 'for ($i = 0; $i < 100000000; $i++) { $a .= " " x 1024 }' ++ ++ isula inspect -f "{{json .State.OOMKilled}} {{.Name}}" $containername 2>&1 | sed -n '1p' | grep "true" ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to check container with image: ${ubuntu_image}" && ((ret++)) ++ ++ isula rm -f $containername ++ ++ msg_info "${test} finished with return ${ret}..." ++ return ${ret} ++} ++ ++declare -i ans=0 ++ ++test_oom_monitor || ((ans++)) ++ ++show_result ${ans} "${curr_path}/${0}" +-- +2.34.1 + diff --git a/0047-add-usage-restrictions-for-CRI-1.29-update.patch b/0047-add-usage-restrictions-for-CRI-1.29-update.patch new file mode 100644 index 0000000..e6990b7 --- /dev/null +++ b/0047-add-usage-restrictions-for-CRI-1.29-update.patch @@ -0,0 +1,27 @@ +From 9f066a405a95299c182ef7356b6518a9457af298 Mon Sep 17 00:00:00 2001 +From: jikai +Date: Mon, 8 Apr 2024 02:52:11 +0000 +Subject: [PATCH 47/69] add usage restrictions for CRI 1.29 update + +Signed-off-by: jikai +--- + docs/design/detailed/CRI/CRI_1.29_update_design.md | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/docs/design/detailed/CRI/CRI_1.29_update_design.md b/docs/design/detailed/CRI/CRI_1.29_update_design.md +index 0a0c860b..0c66db48 100644 +--- a/docs/design/detailed/CRI/CRI_1.29_update_design.md ++++ b/docs/design/detailed/CRI/CRI_1.29_update_design.md +@@ -234,4 +234,8 @@ enum ContainerEventType { + + ### 使用限制 + +-以上特性仅保证容器运行时设置为runc时支持。 ++1. 以上新增特性,iSulad仅提供容器运行时设置为runc时的支持。 ++2. 由于cgroup oom会同时触发容器cgroup路径删除,若iSulad对oom事件处理发生在 ++cgroup路径删除之后,iSulad则无法成功捕捉容器oom事件, ++可能导致ContainerStatus中reason字段设置不正确。 ++3. iSulad不支持交叉使用不同的cgroup驱动管理容器,启动容器后iSulad的cgroup驱动配置不应该发生变化。 +-- +2.34.1 + diff --git a/0048-CDI-interface-definition.patch b/0048-CDI-interface-definition.patch new file mode 100644 index 0000000..e84db63 --- /dev/null +++ b/0048-CDI-interface-definition.patch @@ -0,0 +1,1192 @@ +From 040e39827049cd557987f505d1bd6c6e4f18b4b3 Mon Sep 17 00:00:00 2001 +From: liuxu +Date: Mon, 11 Mar 2024 17:48:11 +0800 +Subject: [PATCH 48/69] CDI:interface definition + +--- + cmake/options.cmake | 11 +++ + src/daemon/modules/CMakeLists.txt | 11 +++ + src/daemon/modules/api/cdi_operate_api.h | 39 ++++++++++ + src/daemon/modules/device/CMakeLists.txt | 23 ++++++ + src/daemon/modules/device/cdi/CMakeLists.txt | 13 ++++ + .../device/cdi/behavior/CMakeLists.txt | 13 ++++ + .../device/cdi/behavior/cdi_container_edits.c | 49 ++++++++++++ + .../device/cdi/behavior/cdi_container_edits.h | 39 ++++++++++ + .../modules/device/cdi/behavior/cdi_device.c | 40 ++++++++++ + .../modules/device/cdi/behavior/cdi_device.h | 46 ++++++++++++ + .../modules/device/cdi/behavior/cdi_spec.c | 60 +++++++++++++++ + .../modules/device/cdi/behavior/cdi_spec.h | 56 ++++++++++++++ + .../device/cdi/behavior/cdi_spec_dirs.c | 29 +++++++ + .../device/cdi/behavior/cdi_spec_dirs.h | 47 ++++++++++++ + .../modules/device/cdi/behavior/cdi_version.c | 40 ++++++++++ + .../modules/device/cdi/behavior/cdi_version.h | 34 +++++++++ + .../device/cdi/behavior/parser/CMakeLists.txt | 3 + + .../device/cdi/behavior/parser/cdi_parser.c | 55 ++++++++++++++ + .../device/cdi/behavior/parser/cdi_parser.h | 38 ++++++++++ + .../modules/device/cdi/cdi_annotations.c | 31 ++++++++ + .../modules/device/cdi/cdi_annotations.h | 32 ++++++++ + src/daemon/modules/device/cdi/cdi_cache.c | 69 +++++++++++++++++ + src/daemon/modules/device/cdi/cdi_cache.h | 75 +++++++++++++++++++ + src/daemon/modules/device/cdi/cdi_registry.c | 25 +++++++ + src/daemon/modules/device/cdi/cdi_registry.h | 36 +++++++++ + src/daemon/modules/device/cdi_operate.c | 35 +++++++++ + 26 files changed, 949 insertions(+) + create mode 100644 src/daemon/modules/api/cdi_operate_api.h + create mode 100644 src/daemon/modules/device/CMakeLists.txt + create mode 100644 src/daemon/modules/device/cdi/CMakeLists.txt + create mode 100644 src/daemon/modules/device/cdi/behavior/CMakeLists.txt + create mode 100644 src/daemon/modules/device/cdi/behavior/cdi_container_edits.c + create mode 100644 src/daemon/modules/device/cdi/behavior/cdi_container_edits.h + create mode 100644 src/daemon/modules/device/cdi/behavior/cdi_device.c + create mode 100644 src/daemon/modules/device/cdi/behavior/cdi_device.h + create mode 100644 src/daemon/modules/device/cdi/behavior/cdi_spec.c + create mode 100644 src/daemon/modules/device/cdi/behavior/cdi_spec.h + create mode 100644 src/daemon/modules/device/cdi/behavior/cdi_spec_dirs.c + create mode 100644 src/daemon/modules/device/cdi/behavior/cdi_spec_dirs.h + create mode 100644 src/daemon/modules/device/cdi/behavior/cdi_version.c + create mode 100644 src/daemon/modules/device/cdi/behavior/cdi_version.h + create mode 100644 src/daemon/modules/device/cdi/behavior/parser/CMakeLists.txt + create mode 100644 src/daemon/modules/device/cdi/behavior/parser/cdi_parser.c + create mode 100644 src/daemon/modules/device/cdi/behavior/parser/cdi_parser.h + create mode 100644 src/daemon/modules/device/cdi/cdi_annotations.c + create mode 100644 src/daemon/modules/device/cdi/cdi_annotations.h + create mode 100644 src/daemon/modules/device/cdi/cdi_cache.c + create mode 100644 src/daemon/modules/device/cdi/cdi_cache.h + create mode 100644 src/daemon/modules/device/cdi/cdi_registry.c + create mode 100644 src/daemon/modules/device/cdi/cdi_registry.h + create mode 100644 src/daemon/modules/device/cdi_operate.c + +diff --git a/cmake/options.cmake b/cmake/options.cmake +index b7a7c65d..c1eac472 100644 +--- a/cmake/options.cmake ++++ b/cmake/options.cmake +@@ -40,6 +40,17 @@ if (ENABLE_CRI_API_V1 STREQUAL "ON") + message("${Green}-- Enable CRI API V1${ColourReset}") + endif() + ++option(ENABLE_CDI "Enable CDI" OFF) ++if (ENABLE_CDI STREQUAL "ON") ++ if (ENABLE_CRI_API_V1) ++ add_definitions(-DENABLE_CDI) ++ set(ENABLE_CDI 1) ++ message("${Green}-- Enable CDI${ColourReset}") ++ else() ++ message("${Yellow}-- Can not enable CDI, CDI need enable CRI API V1 first ${ColourReset}") ++ endif() ++endif() ++ + option(ENABLE_SANDBOXER "Enable sandbox API" ON) + if (ENABLE_SANDBOXER STREQUAL "ON") + add_definitions(-DENABLE_SANDBOXER) +diff --git a/src/daemon/modules/CMakeLists.txt b/src/daemon/modules/CMakeLists.txt +index a70c094f..ff2ea226 100644 +--- a/src/daemon/modules/CMakeLists.txt ++++ b/src/daemon/modules/CMakeLists.txt +@@ -49,6 +49,16 @@ if (ENABLE_PLUGIN) + ) + endif() + ++if (ENABLE_CDI) ++ add_subdirectory(device) ++ list(APPEND local_modules_srcs ++ ${DEVICE_SRCS} ++ ) ++ list(APPEND local_modules_incs ++ ${DEVICE_INCS} ++ ) ++endif() ++ + set(MODULES_SRCS + ${local_modules_srcs} + PARENT_SCOPE +@@ -70,3 +80,4 @@ if(ENABLE_NETWORK) + ) + endif() + ++ +diff --git a/src/daemon/modules/api/cdi_operate_api.h b/src/daemon/modules/api/cdi_operate_api.h +new file mode 100644 +index 00000000..4f4c339e +--- /dev/null ++++ b/src/daemon/modules/api/cdi_operate_api.h +@@ -0,0 +1,39 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. ++ * iSulad 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: liuxu ++ * Create: 2024-03-06 ++ * Description: provide cdi device manager function definition ++ ******************************************************************************/ ++#ifndef CDI_OPERATE_API_H ++#define CDI_OPERATE_API_H ++ ++#include ++#include ++ ++#include "utils_array.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++int cdi_operate_registry_init(char **specs_dirs, size_t specs_dirs_len); ++ ++char *cdi_operate_refresh(void); ++ ++string_array *cdi_operate_inject_devices(oci_runtime_spec *spec, string_array *devices, char **error); ++ ++char *cdi_operate_parse_annotations(json_map_string_string *annotations, string_array **keys, string_array **devices); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/src/daemon/modules/device/CMakeLists.txt b/src/daemon/modules/device/CMakeLists.txt +new file mode 100644 +index 00000000..e3468c0b +--- /dev/null ++++ b/src/daemon/modules/device/CMakeLists.txt +@@ -0,0 +1,23 @@ ++# get current directory sources files ++aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} device_top_srcs) ++ ++add_subdirectory(cdi) ++ ++set(local_device_srcs ++ ${device_top_srcs} ++ ${CDI_SRCS} ++ ) ++ ++set(local_device_incs ++ ${CMAKE_CURRENT_SOURCE_DIR} ++ ${CDI_INCS} ++ ) ++ ++set(DEVICE_SRCS ++ ${local_device_srcs} ++ PARENT_SCOPE ++ ) ++set(DEVICE_INCS ++ ${local_device_incs} ++ PARENT_SCOPE ++ ) +\ No newline at end of file +diff --git a/src/daemon/modules/device/cdi/CMakeLists.txt b/src/daemon/modules/device/cdi/CMakeLists.txt +new file mode 100644 +index 00000000..12d9b222 +--- /dev/null ++++ b/src/daemon/modules/device/cdi/CMakeLists.txt +@@ -0,0 +1,13 @@ ++aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} cdi_top_srcs) ++add_subdirectory(behavior) ++ ++set(CDI_SRCS ++ ${cdi_top_srcs} ++ ${BEHAVIOR_SRCS} ++ PARENT_SCOPE ++ ) ++set(CDI_INCS ++ ${CMAKE_CURRENT_SOURCE_DIR} ++ ${BEHAVIOR_INCS} ++ PARENT_SCOPE ++ ) +diff --git a/src/daemon/modules/device/cdi/behavior/CMakeLists.txt b/src/daemon/modules/device/cdi/behavior/CMakeLists.txt +new file mode 100644 +index 00000000..39881a7b +--- /dev/null ++++ b/src/daemon/modules/device/cdi/behavior/CMakeLists.txt +@@ -0,0 +1,13 @@ ++aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} behavior_top_srcs) ++add_subdirectory(parser) ++ ++set(BEHAVIOR_SRCS ++ ${behavior_top_srcs} ++ ${PARSER_SRCS} ++ PARENT_SCOPE ++ ) ++set(BEHAVIOR_INCS ++ ${CMAKE_CURRENT_SOURCE_DIR} ++ ${CMAKE_CURRENT_SOURCE_DIR}/parser/ ++ PARENT_SCOPE ++ ) +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_container_edits.c b/src/daemon/modules/device/cdi/behavior/cdi_container_edits.c +new file mode 100644 +index 00000000..ce7b16db +--- /dev/null ++++ b/src/daemon/modules/device/cdi/behavior/cdi_container_edits.c +@@ -0,0 +1,49 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. ++ * iSulad 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: liuxu ++ * Create: 2024-03-06 ++ * Description: provide cdi container edits function ++ ******************************************************************************/ ++#include "cdi_container_edits.h" ++ ++// PRESTART_HOOK is the name of the OCI "prestart" hook. ++#define PRESTART_HOOK "prestart" ++// CREATE_RUNTIME_HOOK is the name of the OCI "createRuntime" hook. ++#define CREATE_RUNTIME_HOOK "createRuntime" ++// CREATE_CONTAINER_HOOK is the name of the OCI "createContainer" hook. ++#define CREATE_CONTAINER_HOOK "createContainer" ++// START_CONTAINER_HOOK is the name of the OCI "startContainer" hook. ++#define START_CONTAINER_HOOK "startContainer" ++// POSTSTART_HOOK is the name of the OCI "poststart" hook. ++#define POSTSTART_HOOK "poststart" ++// POSTSTOP_HOOK is the name of the OCI "poststop" hook. ++#define POSTSTOP_HOOK "poststop" ++ ++char *cdi_container_edits_apply(cdi_container_edits *e, oci_runtime_spec *spec) ++{ ++ return NULL; ++} ++ ++char *cdi_container_edits_validate(cdi_container_edits *e) ++{ ++ return NULL; ++} ++ ++cdi_container_edits *cdi_container_edits_append(cdi_container_edits *e, cdi_container_edits *o) ++{ ++ return NULL; ++} ++ ++bool cdi_container_edits_is_empty(cdi_container_edits *e) ++{ ++ return true; ++} ++ +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_container_edits.h b/src/daemon/modules/device/cdi/behavior/cdi_container_edits.h +new file mode 100644 +index 00000000..7b16d2bc +--- /dev/null ++++ b/src/daemon/modules/device/cdi/behavior/cdi_container_edits.h +@@ -0,0 +1,39 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. ++ * iSulad 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: liuxu ++ * Create: 2024-03-06 ++ * Description: provide cdi container edits function definition ++ ******************************************************************************/ ++#ifndef CDI_CONTAINER_EDITS_H ++#define CDI_CONTAINER_EDITS_H ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "utils_array.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++char *cdi_container_edits_apply(cdi_container_edits *e, oci_runtime_spec *spec); ++char *cdi_container_edits_validate(cdi_container_edits *e); ++cdi_container_edits *cdi_container_edits_append(cdi_container_edits *e, cdi_container_edits *o); ++bool cdi_container_edits_is_empty(cdi_container_edits *e); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +\ No newline at end of file +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_device.c b/src/daemon/modules/device/cdi/behavior/cdi_device.c +new file mode 100644 +index 00000000..9904e9ee +--- /dev/null ++++ b/src/daemon/modules/device/cdi/behavior/cdi_device.c +@@ -0,0 +1,40 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. ++ * iSulad 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: liuxu ++ * Create: 2024-03-06 ++ * Description: provide cdi device function ++ ******************************************************************************/ ++#include "cdi_device.h" ++ ++void free_cdi_cache_device(struct cdi_cache_device *d) ++{ ++ (void)d; ++} ++ ++struct cdi_cache_device *cdi_device_new_device(struct cdi_cache_spec *spec, cdi_device *d, char **error) ++{ ++ return NULL; ++} ++ ++struct cdi_cache_spec *cdi_device_get_spec(struct cdi_cache_device *d) ++{ ++ return NULL; ++} ++ ++char *cdi_device_get_qualified_name(struct cdi_cache_device *d) ++{ ++ return NULL; ++} ++ ++cdi_container_edits *cdi_device_edits(struct cdi_cache_device *d) ++{ ++ return NULL; ++} +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_device.h b/src/daemon/modules/device/cdi/behavior/cdi_device.h +new file mode 100644 +index 00000000..3f460152 +--- /dev/null ++++ b/src/daemon/modules/device/cdi/behavior/cdi_device.h +@@ -0,0 +1,46 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. ++ * iSulad 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: liuxu ++ * Create: 2024-03-06 ++ * Description: provide cdi device function definition ++ ******************************************************************************/ ++#ifndef CDI_DEVICE_H ++#define CDI_DEVICE_H ++ ++#include ++#include ++#include ++ ++#include "cdi_container_edits.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++struct cdi_cache_spec; ++ ++struct cdi_cache_device { ++ cdi_device *raw_device; ++ struct cdi_cache_spec *cache_spec; ++}; ++ ++void free_cdi_cache_device(struct cdi_cache_device *d); ++ ++struct cdi_cache_device *cdi_device_new_device(struct cdi_cache_spec *spec, cdi_device *d, char **error); ++struct cdi_cache_spec *cdi_device_get_spec(struct cdi_cache_device *d); ++char *cdi_device_get_qualified_name(struct cdi_cache_device *d); ++cdi_container_edits *cdi_device_edits(struct cdi_cache_device *d); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +\ No newline at end of file +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_spec.c b/src/daemon/modules/device/cdi/behavior/cdi_spec.c +new file mode 100644 +index 00000000..38fc9e38 +--- /dev/null ++++ b/src/daemon/modules/device/cdi/behavior/cdi_spec.c +@@ -0,0 +1,60 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. ++ * iSulad 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: liuxu ++ * Create: 2024-03-06 ++ * Description: provide cdi spec function ++ ******************************************************************************/ ++#include "cdi_spec.h" ++ ++void free_cdi_cache_spec(struct cdi_cache_spec *s) ++{ ++ (void)s; ++} ++ ++struct cdi_cache_spec *cdi_spec_read_spec(const char *path, int priority, char **error) ++{ ++ return NULL; ++} ++ ++struct cdi_cache_spec *cdi_spec_new_spec(cdi_spec *raw, const char *path, int priority, char **error) ++{ ++ return NULL; ++} ++ ++const char *cdi_spec_get_vendor(struct cdi_cache_spec *s) ++{ ++ return NULL; ++} ++ ++const char *cdi_spec_get_class(struct cdi_cache_spec *s) ++{ ++ return NULL; ++} ++ ++struct cdi_cache_device *cdi_spec_get_cache_device(struct cdi_cache_spec *s, const char *name) ++{ ++ return NULL; ++} ++ ++const char *cdi_spec_get_path(struct cdi_cache_spec *s) ++{ ++ return NULL; ++} ++ ++int cdi_spec_get_priority(struct cdi_cache_spec *s) ++{ ++ return 0; ++} ++ ++cdi_container_edits *cdi_spec_edits(struct cdi_cache_spec *s) ++{ ++ return NULL; ++} +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_spec.h b/src/daemon/modules/device/cdi/behavior/cdi_spec.h +new file mode 100644 +index 00000000..bd4fc9d1 +--- /dev/null ++++ b/src/daemon/modules/device/cdi/behavior/cdi_spec.h +@@ -0,0 +1,56 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. ++ * iSulad 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: liuxu ++ * Create: 2024-03-06 ++ * Description: provide cdi spec function definition ++ ******************************************************************************/ ++#ifndef CDI_SPEC_H ++#define CDI_SPEC_H ++ ++#include ++#include ++ ++#include "map.h" ++#include "cdi_container_edits.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++struct cdi_cache_device; ++ ++struct cdi_cache_spec { ++ cdi_spec *raw_spec; ++ char *vendor; ++ char *class; ++ char *path; ++ int priority; ++ map_t *devices; // MAP_STR_PTR devices[cdi_device.name] = cdi_cache_device* ++}; ++ ++#define CDI_DEFAULT_SPEC_EXT ".json" ++ ++void free_cdi_cache_spec(struct cdi_cache_spec *s); ++ ++struct cdi_cache_spec *cdi_spec_read_spec(const char *path, int priority, char **error); ++struct cdi_cache_spec *cdi_spec_new_spec(cdi_spec *raw, const char *path, int priority, char **error); ++const char *cdi_spec_get_vendor(struct cdi_cache_spec *s); ++const char *cdi_spec_get_class(struct cdi_cache_spec *s); ++struct cdi_cache_device *cdi_spec_get_cache_device(struct cdi_cache_spec *s, const char *name); ++const char *cdi_spec_get_path(struct cdi_cache_spec *s); ++int cdi_spec_get_priority(struct cdi_cache_spec *s); ++cdi_container_edits *cdi_spec_edits(struct cdi_cache_spec *s); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +\ No newline at end of file +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_spec_dirs.c b/src/daemon/modules/device/cdi/behavior/cdi_spec_dirs.c +new file mode 100644 +index 00000000..5df4c937 +--- /dev/null ++++ b/src/daemon/modules/device/cdi/behavior/cdi_spec_dirs.c +@@ -0,0 +1,29 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. ++ * iSulad 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: liuxu ++ * Create: 2024-03-06 ++ * Description: provide cdi spec dirs function ++ ******************************************************************************/ ++#include "cdi_spec_dirs.h" ++ ++#define DEFAULT_SPEC_DIRS_LEN 2 ++static char *default_spec_dirs_items[DEFAULT_SPEC_DIRS_LEN] = {CDI_DEFAULT_STATIC_DIR, CDI_DEFAULT_DYNAMIC_DIR}; ++ ++string_array g_default_spec_dirs = { ++ .items = default_spec_dirs_items, ++ .len = DEFAULT_SPEC_DIRS_LEN, ++ .cap = DEFAULT_SPEC_DIRS_LEN, ++}; ++ ++char *cdi_scan_spec_dirs(string_array *dirs, struct cdi_scan_fn_maps *scan_fn_maps, cdi_scan_spec_func scan_fn) ++{ ++ return NULL; ++} +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_spec_dirs.h b/src/daemon/modules/device/cdi/behavior/cdi_spec_dirs.h +new file mode 100644 +index 00000000..bd00e318 +--- /dev/null ++++ b/src/daemon/modules/device/cdi/behavior/cdi_spec_dirs.h +@@ -0,0 +1,47 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. ++ * iSulad 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: liuxu ++ * Create: 2024-03-06 ++ * Description: provide cdi spec dirs function definition ++ ******************************************************************************/ ++#ifndef CDI_SPEC_DIRS_H ++#define CDI_SPEC_DIRS_H ++ ++#include "cdi_cache.h" ++#include "utils_array.h" ++#include "map.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define CDI_DEFAULT_STATIC_DIR "/etc/cdi" ++#define CDI_DEFAULT_DYNAMIC_DIR "/var/run/cdi" ++ ++extern string_array g_default_spec_dirs; ++ ++struct cdi_scan_fn_maps { ++ map_t *specs; ++ map_t *devices; ++ map_t *conflicts; ++ map_t *spec_errors; ++ string_array *result; ++}; ++typedef char *(*cdi_scan_spec_func)(struct cdi_scan_fn_maps *scan_fn_maps, const char *path, int priority, ++ struct cdi_cache_spec *spec, char **error); ++ ++char *cdi_scan_spec_dirs(string_array *dirs, struct cdi_scan_fn_maps *scan_fn_maps, cdi_scan_spec_func scan_fn); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +\ No newline at end of file +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_version.c b/src/daemon/modules/device/cdi/behavior/cdi_version.c +new file mode 100644 +index 00000000..3e87c111 +--- /dev/null ++++ b/src/daemon/modules/device/cdi/behavior/cdi_version.c +@@ -0,0 +1,40 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. ++ * iSulad 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: liuxu ++ * Create: 2024-03-06 ++ * Description: provide cdi version function ++ ******************************************************************************/ ++#include "cdi_version.h" ++ ++#define CDI_V_CURRENT_VERSION "v"##CDI_CURRENT_VERSION ++ ++#define CDI_V010 "v0.1.0" ++#define CDI_V020 "v0.2.0" ++#define CDI_V030 "v0.3.0" ++#define CDI_V040 "v0.4.0" ++#define CDI_V050 "v0.5.0" ++#define CDI_V060 "v0.6.0" ++#define CDI_V_EARLIEST CDI_V030 ++ ++const char *cdi_minimum_required_version(cdi_spec *spec) ++{ ++ return NULL; ++} ++ ++bool cdi_is_greater_than_version(const char *v, const char *o) ++{ ++ return true; ++} ++ ++bool cdi_is_valid_version(const char *spec_version) ++{ ++ return true; ++} +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_version.h b/src/daemon/modules/device/cdi/behavior/cdi_version.h +new file mode 100644 +index 00000000..99b7e692 +--- /dev/null ++++ b/src/daemon/modules/device/cdi/behavior/cdi_version.h +@@ -0,0 +1,34 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. ++ * iSulad 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: liuxu ++ * Create: 2024-03-06 ++ * Description: provide cdi version function definition ++ ******************************************************************************/ ++#ifndef CDI_VERSION_H ++#define CDI_VERSION_H ++ ++#include ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define CDI_CURRENT_VERSION "0.6.0" ++ ++const char *cdi_minimum_required_version(cdi_spec *spec); ++bool cdi_is_greater_than_version(const char *v, const char *o); ++bool cdi_is_valid_version(const char *spec_version); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +\ No newline at end of file +diff --git a/src/daemon/modules/device/cdi/behavior/parser/CMakeLists.txt b/src/daemon/modules/device/cdi/behavior/parser/CMakeLists.txt +new file mode 100644 +index 00000000..9bf5f3f2 +--- /dev/null ++++ b/src/daemon/modules/device/cdi/behavior/parser/CMakeLists.txt +@@ -0,0 +1,3 @@ ++# get current directory sources files ++aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} local_cdi_parser_srcs) ++set(PARSER_SRCS ${local_cdi_parser_srcs} PARENT_SCOPE) +diff --git a/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.c b/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.c +new file mode 100644 +index 00000000..45048f9a +--- /dev/null ++++ b/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.c +@@ -0,0 +1,55 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. ++ * iSulad 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: liuxu ++ * Create: 2024-03-06 ++ * Description: provide cdi parser linux function ++ ******************************************************************************/ ++#include "cdi_parser.h" ++ ++char *cdi_parser_qualified_name(const char *vendor, const char *class, const char *name) ++{ ++ return NULL; ++} ++ ++bool cdi_parser_is_qualified_name(const char *device) ++{ ++ return true; ++} ++ ++char *cdi_parser_parse_qualified_name(const char *device, char **vendor, char **class, char **name) ++{ ++ return NULL; ++} ++ ++int cdi_parser_parse_device(const char *device, char **vendor, char **class, char **name) ++{ ++ return 0; ++} ++ ++int cdi_parser_parse_qualifier(const char *kind, char **vendor, char **class) ++{ ++ return 0; ++} ++ ++char *cdi_parser_validate_vendor_name(const char *vendor) ++{ ++ return NULL; ++} ++ ++char *cdi_parser_validate_class_name(const char *class) ++{ ++ return NULL; ++} ++ ++char *cdi_parser_validate_device_name(const char *name) ++{ ++ return NULL; ++} +diff --git a/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.h b/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.h +new file mode 100644 +index 00000000..d9c057ea +--- /dev/null ++++ b/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.h +@@ -0,0 +1,38 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. ++ * iSulad 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: liuxu ++ * Create: 2024-03-06 ++ * Description: provide cdi parser function definition ++ ******************************************************************************/ ++#ifndef CDI_PARSER_H ++#define CDI_PARSER_H ++ ++#include ++#include ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++char *cdi_parser_qualified_name(const char *vendor, const char *class, const char *name); ++bool cdi_parser_is_qualified_name(const char *device); ++char *cdi_parser_parse_qualified_name(const char *device, char **vendor, char **class, char **name); ++int cdi_parser_parse_device(const char *device, char **vendor, char **class, char **name); ++int cdi_parser_parse_qualifier(const char *kind, char **vendor, char **class); ++char *cdi_parser_validate_vendor_name(const char *vendor); ++char *cdi_parser_validate_class_name(const char *class); ++char *cdi_parser_validate_device_name(const char *name); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +\ No newline at end of file +diff --git a/src/daemon/modules/device/cdi/cdi_annotations.c b/src/daemon/modules/device/cdi/cdi_annotations.c +new file mode 100644 +index 00000000..3cb9be84 +--- /dev/null ++++ b/src/daemon/modules/device/cdi/cdi_annotations.c +@@ -0,0 +1,31 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. ++ * iSulad 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: liuxu ++ * Create: 2024-03-06 ++ * Description: provide cdi annotations function ++ ******************************************************************************/ ++#include "cdi_annotations.h" ++ ++#include ++#include ++#include ++#include ++ ++#include "error.h" ++#include "utils.h" ++#include "cdi_parser.h" ++ ++#define CDI_ANNOTATIONS_PREFIX "cdi.k8s.io/" ++ ++char *cdi_parse_annotations(json_map_string_string *annotations, string_array **keys, string_array **devices) ++{ ++ return NULL; ++} +diff --git a/src/daemon/modules/device/cdi/cdi_annotations.h b/src/daemon/modules/device/cdi/cdi_annotations.h +new file mode 100644 +index 00000000..52355099 +--- /dev/null ++++ b/src/daemon/modules/device/cdi/cdi_annotations.h +@@ -0,0 +1,32 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. ++ * iSulad 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: liuxu ++ * Create: 2024-03-06 ++ * Description: provide cdi annotations function definition ++ ******************************************************************************/ ++#ifndef CDI_ANNOTATIONS_H ++#define CDI_ANNOTATIONS_H ++ ++#include ++ ++#include "utils_array.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++char *cdi_parse_annotations(json_map_string_string *annotations, string_array **keys, string_array **devices); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +\ No newline at end of file +diff --git a/src/daemon/modules/device/cdi/cdi_cache.c b/src/daemon/modules/device/cdi/cdi_cache.c +new file mode 100644 +index 00000000..9c54acbf +--- /dev/null ++++ b/src/daemon/modules/device/cdi/cdi_cache.c +@@ -0,0 +1,69 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. ++ * iSulad 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: liuxu ++ * Create: 2024-03-06 ++ * Description: provide cdi cache function ++ ******************************************************************************/ ++#include "cdi_cache.h" ++ ++void free_cdi_cache(struct cdi_cache *c) ++{ ++ (void)c; ++} ++ ++struct cdi_cache *cdi_new_cache(string_array *spec_dirs, char **error) ++{ ++ return NULL; ++} ++ ++static string_array *cdi_inject_devices(struct cdi_cache *c, oci_runtime_spec *oci_spec, string_array *devices, char **error) ++{ ++ return NULL; ++} ++ ++static char *cdi_configure(struct cdi_cache *c, string_array *spec_dirs) ++{ ++ return NULL; ++} ++ ++static char *cdi_refresh(struct cdi_cache *c) ++{ ++ return NULL; ++} ++ ++static map_t *cdi_get_errors(struct cdi_cache *c) ++{ ++ return NULL; ++} ++ ++static string_array *cdi_get_spec_directories(struct cdi_cache *c) ++{ ++ return NULL; ++} ++ ++static map_t *cdi_get_spec_dir_errors(struct cdi_cache *c) ++{ ++ return NULL; ++} ++ ++static struct cdi_cache_ops g_cdi_cache_ops = { ++ .inject_devices = cdi_inject_devices, ++ .configure = cdi_configure, ++ .refresh = cdi_refresh, ++ .get_errors = cdi_get_errors, ++ .get_spec_directories = cdi_get_spec_directories, ++ .get_spec_dir_errors = cdi_get_spec_dir_errors ++}; ++ ++struct cdi_cache_ops *cdi_get_cache_ops(void) ++{ ++ return &g_cdi_cache_ops; ++} +\ No newline at end of file +diff --git a/src/daemon/modules/device/cdi/cdi_cache.h b/src/daemon/modules/device/cdi/cdi_cache.h +new file mode 100644 +index 00000000..92fb64af +--- /dev/null ++++ b/src/daemon/modules/device/cdi/cdi_cache.h +@@ -0,0 +1,75 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. ++ * iSulad 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: liuxu ++ * Create: 2024-03-06 ++ * Description: provide cdi cache function definition ++ ******************************************************************************/ ++#ifndef CDI_CACHE_H ++#define CDI_CACHE_H ++ ++#include ++#include ++#include ++ ++#include "utils_array.h" ++#include "map.h" ++#include "cdi_device.h" ++#include "cdi_spec.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++struct cdi_cache; ++ ++struct cdi_cache_ops { ++ // injecting CDI devices into an OCI Spec. ++ // Resolver ++ string_array *(*inject_devices)(struct cdi_cache *c, oci_runtime_spec *spec, string_array *devices, char **error); ++ ++ // refreshing the cache of CDI Specs and devices. ++ // Refresher ++ char *(*configure)(struct cdi_cache *c, string_array *spec_dirs); ++ char *(*refresh)(struct cdi_cache *c); ++ map_t *(*get_errors)(struct cdi_cache *c); ++ string_array *(*get_spec_directories)(struct cdi_cache *c); ++ map_t *(*get_spec_dir_errors)(struct cdi_cache *c); ++}; ++ ++struct cdi_watch { ++ int watcher_fd; // inotify fd ++ map_t *tracked; // MAP_STR_BOOL tracked[spec_dirs[i]] = bool ++ map_t *wd_dirs; // MAP_INT_STR wd_dirs[wd] = spec_dirs[i] ++}; ++ ++// Cache stores CDI Specs loaded from Spec directories. ++struct cdi_cache { ++ pthread_mutex_t mutex; ++ string_array *spec_dirs; // cdi-spec-dirs will scan for CDI Spec files ++ map_t *specs; // MAP_STR_PTR specs[vendor] = cdi_cache_spec** ++ map_t *devices; // MAP_STR_PTR devices[cdi_device.name] = cdi_cache_device* ++ map_t *errors; // MAP_STR_PTR errors[cdi_cache_spec.path] = string_array *errors ++ map_t *dir_errors; // MAP_STR_STR dir_errors[spec_dirs[i]] = error ++ ++ bool auto_refresh; ++ struct cdi_watch *watch; ++}; ++ ++void free_cdi_cache(struct cdi_cache *c); ++ ++struct cdi_cache *cdi_new_cache(string_array *spec_dirs, char **error); ++struct cdi_cache_ops *cdi_get_cache_ops(void); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +\ No newline at end of file +diff --git a/src/daemon/modules/device/cdi/cdi_registry.c b/src/daemon/modules/device/cdi/cdi_registry.c +new file mode 100644 +index 00000000..68767a5f +--- /dev/null ++++ b/src/daemon/modules/device/cdi/cdi_registry.c +@@ -0,0 +1,25 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. ++ * iSulad 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: liuxu ++ * Create: 2024-03-06 ++ * Description: provide cdi registry function ++ ******************************************************************************/ ++#include "cdi_registry.h" ++ ++int cdi_registry_init(string_array *spec_dirs) ++{ ++ return 0; ++} ++ ++struct cdi_registry *cdi_get_registry(void) ++{ ++ return NULL; ++} +diff --git a/src/daemon/modules/device/cdi/cdi_registry.h b/src/daemon/modules/device/cdi/cdi_registry.h +new file mode 100644 +index 00000000..c27d37e3 +--- /dev/null ++++ b/src/daemon/modules/device/cdi/cdi_registry.h +@@ -0,0 +1,36 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. ++ * iSulad 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: liuxu ++ * Create: 2024-03-06 ++ * Description: provide cdi registry function definition ++ ******************************************************************************/ ++#ifndef CDI_REGISTRY_H ++#define CDI_REGISTRY_H ++ ++#include "cdi_cache.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++struct cdi_registry { ++ struct cdi_cache *cdi_cache; ++ struct cdi_cache_ops *ops; ++}; ++ ++int cdi_registry_init(string_array *spec_dirs); ++struct cdi_registry *cdi_get_registry(void); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +\ No newline at end of file +diff --git a/src/daemon/modules/device/cdi_operate.c b/src/daemon/modules/device/cdi_operate.c +new file mode 100644 +index 00000000..c7aa77d8 +--- /dev/null ++++ b/src/daemon/modules/device/cdi_operate.c +@@ -0,0 +1,35 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. ++ * iSulad 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: liuxu ++ * Create: 2024-03-06 ++ * Description: provide cdi device manager function ++ ******************************************************************************/ ++#include "cdi_operate_api.h" ++ ++int cdi_operate_registry_init(char **specs_dirs, size_t specs_dirs_len) ++{ ++ return 0; ++} ++ ++char *cdi_operate_refresh(void) ++{ ++ return NULL; ++} ++ ++string_array *cdi_operate_inject_devices(oci_runtime_spec *spec, string_array *devices, char **error) ++{ ++ return NULL; ++} ++ ++char *cdi_operate_parse_annotations(json_map_string_string *annotations, string_array **keys, string_array **devices) ++{ ++ return NULL; ++} +\ No newline at end of file +-- +2.34.1 + diff --git a/0049-distinguish-between-runtime-and-runtime_cmd-in-isula.patch b/0049-distinguish-between-runtime-and-runtime_cmd-in-isula.patch new file mode 100644 index 0000000..4366d7a --- /dev/null +++ b/0049-distinguish-between-runtime-and-runtime_cmd-in-isula.patch @@ -0,0 +1,145 @@ +From 491baece02522128720b3bd992a76dc5148aa7b2 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Mon, 8 Apr 2024 11:37:13 +0800 +Subject: [PATCH 49/69] distinguish between runtime and runtime_cmd in + isulad-shim + +Signed-off-by: zhongtao +--- + src/cmd/isulad-shim/process.c | 20 +++++++++---------- + src/cmd/isulad-shim/process.h | 4 ++-- + .../modules/runtime/isula/isula_rt_ops.c | 2 ++ + 3 files changed, 14 insertions(+), 12 deletions(-) + +diff --git a/src/cmd/isulad-shim/process.c b/src/cmd/isulad-shim/process.c +index 8a4ca175..6b5f8f7f 100644 +--- a/src/cmd/isulad-shim/process.c ++++ b/src/cmd/isulad-shim/process.c +@@ -1131,7 +1131,7 @@ static int init_root_path(process_t *p) + return SHIM_ERR; + } + +- if (buffer->nappend(buffer, PATH_MAX, "%s/%s", state_path, p->runtime) < 0) { ++ if (buffer->nappend(buffer, PATH_MAX, "%s/%s", state_path, p->state->runtime) < 0) { + ERROR("Failed to append state_path\n"); + isula_buffer_free(buffer); + return SHIM_ERR; +@@ -1146,7 +1146,7 @@ static int init_root_path(process_t *p) + return SHIM_OK; + } + +-process_t *new_process(char *id, char *bundle, char *runtime) ++process_t *new_process(char *id, char *bundle, char *runtime_cmd) + { + shim_client_process_state *p_state; + process_t *p = NULL; +@@ -1174,7 +1174,7 @@ process_t *new_process(char *id, char *bundle, char *runtime) + + p->id = id; + p->bundle = bundle; +- p->runtime = runtime; ++ p->runtime_cmd = runtime_cmd; + p->state = p_state; + p->console_sock_path = NULL; + p->exit_fd = -1; +@@ -1247,7 +1247,7 @@ static void set_common_params(process_t *p, const char *params[], int *index, co + { + int j; + +- params[(*index)++] = p->runtime; ++ params[(*index)++] = p->runtime_cmd; + for (j = 0; j < p->state->runtime_args_len; j++) { + params[(*index)++] = p->state->runtime_args[j]; + } +@@ -1261,7 +1261,7 @@ static void set_common_params(process_t *p, const char *params[], int *index, co + + // In addition to kata, other commonly used oci runtimes (runc, crun, youki, gvisor) + // need to set the --root option +- if (strcasecmp(p->runtime, "kata-runtime") != 0) { ++ if (strcasecmp(p->state->runtime, "kata-runtime") != 0) { + params[(*index)++] = "--root"; + params[(*index)++] = p->root_path; + } +@@ -1347,7 +1347,7 @@ static void process_kill_all(process_t *p) + params[i++] = p->id; + params[i++] = "SIGKILL"; + +- (void)cmd_combined_output(p->runtime, params, output, &output_len); ++ (void)cmd_combined_output(p->runtime_cmd, params, output, &output_len); + + return; + } +@@ -1375,7 +1375,7 @@ static void process_delete(process_t *p) + params[i++] = "--force"; + params[i++] = p->id; + +- (void)cmd_combined_output(p->runtime, params, output, &output_len); ++ (void)cmd_combined_output(p->runtime_cmd, params, output, &output_len); + + return; + } +@@ -1444,8 +1444,8 @@ static void exec_runtime_process(process_t *p, int exec_fd) + + const char *params[MAX_RUNTIME_ARGS] = { 0 }; + get_runtime_cmd(p, log_path, pid_path, process_desc, params); +- execvp(p->runtime, (char * const *)params); +- (void)dprintf(exec_fd, "run process: %s error: %s", p->runtime, strerror(errno)); ++ execvp(p->runtime_cmd, (char * const *)params); ++ (void)dprintf(exec_fd, "run process: %s error: %s", p->runtime_cmd, strerror(errno)); + _exit(EXIT_FAILURE); + } + +@@ -1586,7 +1586,7 @@ static int waitpid_with_timeout(int ctr_pid, int *status, const uint64_t timeou + static int wait_container_process_with_timeout(process_t *p, const uint64_t timeout, int *status) + { + // currently, kata runtime does not support setting timeout during exec +- if (strcasecmp(p->runtime, "kata-runtime") != 0 && timeout > 0) { ++ if (strcasecmp(p->state->runtime, "kata-runtime") != 0 && timeout > 0) { + return waitpid_with_timeout(p->ctr_pid, status, timeout); + } + +diff --git a/src/cmd/isulad-shim/process.h b/src/cmd/isulad-shim/process.h +index 32ba7366..05fd87b0 100644 +--- a/src/cmd/isulad-shim/process.h ++++ b/src/cmd/isulad-shim/process.h +@@ -44,7 +44,7 @@ typedef struct { + typedef struct process { + char *id; + char *bundle; +- char *runtime; ++ char *runtime_cmd; + char *console_sock_path; // pty socket path + char *workdir; + char *root_path; +@@ -70,7 +70,7 @@ typedef struct { + int status; + } process_exit_t; + +-process_t* new_process(char *id, char *bundle, char *runtime); ++process_t* new_process(char *id, char *bundle, char *runtime_cmd); + + int prepare_attach_socket(process_t *p); + +diff --git a/src/daemon/modules/runtime/isula/isula_rt_ops.c b/src/daemon/modules/runtime/isula/isula_rt_ops.c +index b9aba3e3..bc3c36c8 100644 +--- a/src/daemon/modules/runtime/isula/isula_rt_ops.c ++++ b/src/daemon/modules/runtime/isula/isula_rt_ops.c +@@ -1154,6 +1154,7 @@ int rt_isula_create(const char *id, const char *runtime, const rt_create_params_ + p.isulad_stdin = (char *)params->stdin; + p.isulad_stdout = (char *)params->stdout; + p.isulad_stderr = (char *)params->stderr; ++ p.runtime = (char *)runtime; + p.runtime_args = (char **)runtime_args; + p.runtime_args_len = runtime_args_len; + p.attach_socket = attach_socket; +@@ -1409,6 +1410,7 @@ static int preparation_exec(const char *id, const char *runtime, const char *wor + p.isulad_stdout = (char *)params->console_fifos[1]; + p.isulad_stderr = (char *)params->console_fifos[2]; + p.resize_fifo = resize_fifo_dir; ++ p.runtime = (char *)runtime; + p.runtime_args = (char **)runtime_args; + p.runtime_args_len = runtime_args_len; + copy_process(&p, process); +-- +2.34.1 + diff --git a/0050-Use-user-defined-shm-for-CRI-request.patch b/0050-Use-user-defined-shm-for-CRI-request.patch new file mode 100644 index 0000000..2d61c9d --- /dev/null +++ b/0050-Use-user-defined-shm-for-CRI-request.patch @@ -0,0 +1,171 @@ +From 162123bdec0f45f7b2001b2b0b83705cc6b9b1b1 Mon Sep 17 00:00:00 2001 +From: xuxuepeng +Date: Mon, 8 Apr 2024 20:53:57 +0800 +Subject: [PATCH 50/69] Use user defined shm for CRI request + +Signed-off-by: xuxuepeng +--- + src/daemon/modules/spec/specs_mount.c | 128 +++++++++++++++++--------- + 1 file changed, 85 insertions(+), 43 deletions(-) + +diff --git a/src/daemon/modules/spec/specs_mount.c b/src/daemon/modules/spec/specs_mount.c +index 20bf5378..6903ae40 100644 +--- a/src/daemon/modules/spec/specs_mount.c ++++ b/src/daemon/modules/spec/specs_mount.c +@@ -2799,33 +2799,31 @@ out_free: + return ret; + } + +-#define SHM_MOUNT_POINT "/dev/shm" +-static int set_shm_path(host_config *host_spec, container_config_v2_common_config *v2_spec) ++static inline int set_sharable_ipc_mode(host_config *host_spec, container_config_v2_common_config *v2_spec) + { +- int ret = 0; +- container_t *cont = NULL; +- char *tmp_cid = NULL; +- char *right_path = NULL; +- +- // ignore shm of system container +- if (host_spec->system_container) { ++ free(v2_spec->shm_path); ++#ifdef ENABLE_CRI_API_V1 ++ // In the case of sandbox API is used, the shm path has already been created in CRI, ++ // so we need to use the sandbox's shm path ++ if (is_sandbox_container(v2_spec->sandbox_info)) { ++ v2_spec->shm_path = util_strdup_s(v2_spec->sandbox_info->shm_path); + return 0; + } +- // setup shareable dirs +- if (is_shareable_ipc(host_spec->ipc_mode)) { +- // has mount for /dev/shm +- if (has_mount_shm(host_spec, v2_spec)) { +- return 0; +- } ++#endif ++ v2_spec->shm_path = get_prepare_share_shm_path(host_spec->runtime, v2_spec->id); ++ if (v2_spec->shm_path == NULL) { ++ ERROR("Failed to get prepare share shm path"); ++ return -1; ++ } + +- v2_spec->shm_path = get_prepare_share_shm_path(host_spec->runtime, v2_spec->id); +- if (v2_spec->shm_path == NULL) { +- ERROR("Failed to get prepare share shm path"); +- return -1; +- } ++ return 0; ++} + +- return 0; +- } ++static inline int set_connected_container_shm_path(host_config *host_spec, container_config_v2_common_config *v2_spec) ++{ ++ container_t *cont = NULL; ++ char *tmp_cid = NULL; ++ char *right_path = NULL; + + #ifdef ENABLE_CRI_API_V1 + // Sandbox API is used and the connected container is actually a sandbox +@@ -2833,34 +2831,78 @@ static int set_shm_path(host_config *host_spec, container_config_v2_common_confi + if (namespace_is_sandbox(host_spec->ipc_mode, v2_spec->sandbox_info)) { + free(v2_spec->shm_path); + v2_spec->shm_path = util_strdup_s(v2_spec->sandbox_info->shm_path); +- goto out; ++ return 0; + } + #endif + +- if (namespace_is_container(host_spec->ipc_mode)) { +- tmp_cid = namespace_get_connected_container(host_spec->ipc_mode); +- cont = containers_store_get(tmp_cid); +- if (cont == NULL) { +- ERROR("Invalid share path: %s", host_spec->ipc_mode); +- ret = -1; +- goto out; +- } +- right_path = util_strdup_s(cont->common_config->shm_path); +- container_unref(cont); +- } else if (namespace_is_host(host_spec->ipc_mode)) { +- if (!util_file_exists(SHM_MOUNT_POINT)) { +- ERROR("/dev/shm is not mounted, but must be for --ipc=host"); +- ret = -1; +- goto out; +- } +- right_path = util_strdup_s(SHM_MOUNT_POINT); ++ tmp_cid = namespace_get_connected_container(host_spec->ipc_mode); ++ cont = containers_store_get(tmp_cid); ++ if (cont == NULL) { ++ ERROR("Invalid share path: %s", host_spec->ipc_mode); ++ return -1; + } ++ right_path = util_strdup_s(cont->common_config->shm_path); ++ container_unref(cont); + + free(v2_spec->shm_path); + v2_spec->shm_path = right_path; +-out: +- free(tmp_cid); +- return ret; ++ ++ return 0; ++} ++ ++#define SHM_MOUNT_POINT "/dev/shm" ++static inline int set_host_ipc_shm_path(container_config_v2_common_config *v2_spec) ++{ ++ if (!util_file_exists(SHM_MOUNT_POINT)) { ++ ERROR("/dev/shm is not mounted, but must be for --ipc=host"); ++ return -1; ++ } ++ free(v2_spec->shm_path); ++ v2_spec->shm_path = util_strdup_s(SHM_MOUNT_POINT); ++ return 0; ++} ++ ++/** ++ * There are 4 cases for setting shm path: ++ * 1. The user defined /dev/shm in mounts, which takes the first priority ++ * 2. If sharable is set in ipc mode (or by default ipc_mode is null), the container provides shm path, ++ * in the case of sandbox API is used, the sandbox module has already provided shm path ++ * 3. Use the connected container's shm path if ipc_mode is set to container:, ++ * if connected containerd is a sandbox, use the sandbox's shm path ++ * 4. Use /dev/shm if ipc_mode is set to host ++ */ ++static int set_shm_path(host_config *host_spec, container_config_v2_common_config *v2_spec) ++{ ++ // ignore shm of system container ++ if (host_spec->system_container) { ++ return 0; ++ } ++ ++ // case 1: Defined in mounts already ++ if (has_mount_shm(host_spec, v2_spec)) { ++ return 0; ++ } ++ ++ // case 2: Container has its own IPC namespace ++ if (is_shareable_ipc(host_spec->ipc_mode)) { ++ return set_sharable_ipc_mode(host_spec, v2_spec); ++ } ++ ++ // case 3: Connected container ++ if (namespace_is_container(host_spec->ipc_mode)) { ++ return set_connected_container_shm_path(host_spec, v2_spec); ++ } ++ ++ // case 4: Host IPC namespace ++ if (namespace_is_host(host_spec->ipc_mode)) { ++ return set_host_ipc_shm_path(v2_spec); ++ } ++ ++ // Otherwise, the case is unknown, nothing is set ++ free(v2_spec->shm_path); ++ v2_spec->shm_path = NULL; ++ ++ return 0; + } + + int destination_compare(const void *p1, const void *p2) +-- +2.34.1 + diff --git a/0051-Fix-memory-leak-in-set_connected_container_shm_path.patch b/0051-Fix-memory-leak-in-set_connected_container_shm_path.patch new file mode 100644 index 0000000..c31e092 --- /dev/null +++ b/0051-Fix-memory-leak-in-set_connected_container_shm_path.patch @@ -0,0 +1,26 @@ +From 1052a7b67a35b3504045729e1408d4ace8bf50ca Mon Sep 17 00:00:00 2001 +From: xuxuepeng +Date: Tue, 9 Apr 2024 06:35:03 +0800 +Subject: [PATCH 51/69] Fix memory leak in set_connected_container_shm_path + +Signed-off-by: xuxuepeng +--- + src/daemon/modules/spec/specs_mount.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/daemon/modules/spec/specs_mount.c b/src/daemon/modules/spec/specs_mount.c +index 6903ae40..50ee9a85 100644 +--- a/src/daemon/modules/spec/specs_mount.c ++++ b/src/daemon/modules/spec/specs_mount.c +@@ -2822,7 +2822,7 @@ static inline int set_sharable_ipc_mode(host_config *host_spec, container_config + static inline int set_connected_container_shm_path(host_config *host_spec, container_config_v2_common_config *v2_spec) + { + container_t *cont = NULL; +- char *tmp_cid = NULL; ++ __isula_auto_free char *tmp_cid = NULL; + char *right_path = NULL; + + #ifdef ENABLE_CRI_API_V1 +-- +2.34.1 + diff --git a/0052-init-enable_pod_events-as-false.patch b/0052-init-enable_pod_events-as-false.patch new file mode 100644 index 0000000..08cfa2f --- /dev/null +++ b/0052-init-enable_pod_events-as-false.patch @@ -0,0 +1,62 @@ +From cfbb9f5ea40b3b654d7b6f9ad861877e97ed24be Mon Sep 17 00:00:00 2001 +From: jikai +Date: Thu, 11 Apr 2024 02:04:47 +0000 +Subject: [PATCH 52/69] init enable_pod_events as false + +Signed-off-by: jikai +--- + src/daemon/entry/connect/grpc/cri/cri_service.cc | 3 +-- + src/daemon/entry/connect/grpc/cri/cri_service.h | 1 - + .../connect/grpc/cri/v1/cri_v1_runtime_runtime_service.cc | 2 +- + 3 files changed, 2 insertions(+), 4 deletions(-) + +diff --git a/src/daemon/entry/connect/grpc/cri/cri_service.cc b/src/daemon/entry/connect/grpc/cri/cri_service.cc +index d10a60b5..80bcfef0 100644 +--- a/src/daemon/entry/connect/grpc/cri/cri_service.cc ++++ b/src/daemon/entry/connect/grpc/cri/cri_service.cc +@@ -89,9 +89,8 @@ int CRIService::Init(const isulad_daemon_configs *config) + + #ifdef ENABLE_CRI_API_V1 + m_enableCRIV1 = config->enable_cri_v1; +- m_enablePodEvents = config->enable_pod_events; + if (m_enableCRIV1) { +- m_runtimeV1RuntimeService.Init(m_podSandboxImage, m_pluginManager, m_enablePodEvents, err); ++ m_runtimeV1RuntimeService.Init(m_podSandboxImage, m_pluginManager, config->enable_pod_events, err); + if (err.NotEmpty()) { + ERROR("Init CRI v1 runtime service failed: %s", err.GetCMessage()); + return -1; +diff --git a/src/daemon/entry/connect/grpc/cri/cri_service.h b/src/daemon/entry/connect/grpc/cri/cri_service.h +index 041c7c63..77b2eb72 100644 +--- a/src/daemon/entry/connect/grpc/cri/cri_service.h ++++ b/src/daemon/entry/connect/grpc/cri/cri_service.h +@@ -56,7 +56,6 @@ private: + std::string m_podSandboxImage; + std::shared_ptr m_pluginManager; + bool m_enableCRIV1; +- bool m_enablePodEvents; + }; + + } +diff --git a/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_runtime_service.cc b/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_runtime_service.cc +index bc5ab591..e2591ce0 100644 +--- a/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_runtime_service.cc ++++ b/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_runtime_service.cc +@@ -62,6 +62,7 @@ void RuntimeV1RuntimeServiceImpl::Init(std::string &podSandboxImage, + return; + } + ++ m_enablePodEvents = false; + if (enablePodEvents) { + if (mailbox_register_topic_handler(MAILBOX_TOPIC_CRI_CONTAINER, cri_container_topic_handler, + this, cri_container_topic_release, true) != 0) { +@@ -72,7 +73,6 @@ void RuntimeV1RuntimeServiceImpl::Init(std::string &podSandboxImage, + m_enablePodEvents = enablePodEvents; + } + +- + m_rService = std::unique_ptr(new CRIRuntimeServiceImpl(podSandboxImage, cb, networkPlugin, m_enablePodEvents)); + } + +-- +2.34.1 + diff --git a/0053-remove-container-root-path-in-rt_lcr_rm-if-lcr-runti.patch b/0053-remove-container-root-path-in-rt_lcr_rm-if-lcr-runti.patch new file mode 100644 index 0000000..1d9b3a3 --- /dev/null +++ b/0053-remove-container-root-path-in-rt_lcr_rm-if-lcr-runti.patch @@ -0,0 +1,33 @@ +From 0cb96d50302f9f3ad1c17e0bb650ac37db4d5206 Mon Sep 17 00:00:00 2001 +From: jikai +Date: Wed, 10 Apr 2024 08:41:46 +0000 +Subject: [PATCH 53/69] remove container root path in rt_lcr_rm if lcr runtime + missing + +Signed-off-by: jikai +--- + src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.c b/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.c +index 6b862958..978da079 100644 +--- a/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.c ++++ b/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.c +@@ -238,7 +238,13 @@ int rt_lcr_rm(const char *name, const char *runtime, const rt_rm_params_t *param + + engine_ops = engines_get_handler(runtime); + if (engine_ops == NULL || engine_ops->engine_delete_op == NULL) { +- ERROR("Failed to get engine delete operations"); ++ // if engine_ops is NULL, container root path may have been corrupted, try to remove by daemon ++ // If user runs container with lcr but remove lcr runtime after, there might be resources remaining ++ ERROR("Failed to get engine delete operations, container %s root path may have been corrupted, try to remove by daemon", name); ++ if (remove_container_rootpath(name, params->rootpath) == 0) { ++ ret = 0; ++ goto out; ++ } + ret = -1; + goto out; + } +-- +2.34.1 + diff --git a/0054-ensure-sandbox-can-be-removed-if-sandbox-container-r.patch b/0054-ensure-sandbox-can-be-removed-if-sandbox-container-r.patch new file mode 100644 index 0000000..4fefbe1 --- /dev/null +++ b/0054-ensure-sandbox-can-be-removed-if-sandbox-container-r.patch @@ -0,0 +1,58 @@ +From 21afb41e02886df0b5251889cc443f28b7da274f Mon Sep 17 00:00:00 2001 +From: jikai +Date: Thu, 11 Apr 2024 01:21:34 +0000 +Subject: [PATCH 54/69] ensure sandbox can be removed if sandbox container + removed + +Signed-off-by: jikai +--- + .../sandbox/controller/shim/shim_controller.cc | 16 ++++++++++++---- + src/daemon/sandbox/sandbox.cc | 3 ++- + 2 files changed, 14 insertions(+), 5 deletions(-) + +diff --git a/src/daemon/sandbox/controller/shim/shim_controller.cc b/src/daemon/sandbox/controller/shim/shim_controller.cc +index 593fade9..4da637c7 100644 +--- a/src/daemon/sandbox/controller/shim/shim_controller.cc ++++ b/src/daemon/sandbox/controller/shim/shim_controller.cc +@@ -517,12 +517,20 @@ bool ShimController::Shutdown(const std::string &sandboxId, Errors &error) + container_delete_response *response {nullptr}; + int ret = m_cb->container.remove(request, &response); + auto responseWrapper = makeUniquePtrCStructWrapper(response, free_container_delete_response); ++ if (ret == 0) { ++ return true; ++ } + +- if (ret != 0) { +- std::string msg = (response != nullptr && response->errmsg != nullptr) ? response->errmsg : "internal"; +- ERROR("Failed to remove sandbox %s: %s", sandboxId.c_str(), msg.c_str()); +- error.SetError(msg); ++ std::string errMsg = "internal"; ++ if (response != nullptr && response->errmsg != nullptr) { ++ if (strstr(response->errmsg, "No such container") != nullptr) { ++ ERROR("Container for sandbox %s not found", sandboxId.c_str()); ++ return true; ++ } ++ errMsg = response->errmsg; + } ++ ERROR("Failed to remove sandbox %s: %s", sandboxId.c_str(), errMsg.c_str()); ++ error.SetError(errMsg); + return error.Empty(); + } + +diff --git a/src/daemon/sandbox/sandbox.cc b/src/daemon/sandbox/sandbox.cc +index c70116c1..bae5b8db 100644 +--- a/src/daemon/sandbox/sandbox.cc ++++ b/src/daemon/sandbox/sandbox.cc +@@ -757,7 +757,8 @@ auto Sandbox::Remove(Errors &error) -> bool + + WriteGuard lock(m_mutex); + +- if (!DoStop(DEFAULT_STOP_TIMEOUT, error)) { ++ // Only stop the sandbox when it is running ++ if (IsReady() && !DoStop(DEFAULT_STOP_TIMEOUT, error)) { + ERROR("Failed to stop Sandbox before removing, id='%s'", m_id.c_str()); + return false; + } +-- +2.34.1 + diff --git a/0055-bugfix-for-shim-timeout-exit-error-log-changes.patch b/0055-bugfix-for-shim-timeout-exit-error-log-changes.patch new file mode 100644 index 0000000..7009560 --- /dev/null +++ b/0055-bugfix-for-shim-timeout-exit-error-log-changes.patch @@ -0,0 +1,175 @@ +From 35ffb77f568124e6e7c8fd7b3d021878b92c13f7 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Tue, 9 Apr 2024 20:04:33 +0800 +Subject: [PATCH 55/69] bugfix for shim timeout exit error log changes + +Signed-off-by: zhongtao +--- + .../modules/runtime/isula/isula_rt_ops.c | 55 ++++++++++++------- + 1 file changed, 34 insertions(+), 21 deletions(-) + +diff --git a/src/daemon/modules/runtime/isula/isula_rt_ops.c b/src/daemon/modules/runtime/isula/isula_rt_ops.c +index bc3c36c8..1875cf5b 100644 +--- a/src/daemon/modules/runtime/isula/isula_rt_ops.c ++++ b/src/daemon/modules/runtime/isula/isula_rt_ops.c +@@ -861,6 +861,8 @@ static int shim_create(shim_create_args *args) + pid_t pid = 0; + int shim_stderr_pipe[2] = { -1, -1 }; + int shim_stdout_pipe[2] = { -1, -1 }; ++ // used to accept exec error msg ++ int exec_err_pipe[2] = {-1, -1}; + int num = 0; + int ret = 0; + char exec_buff[BUFSIZ + 1] = { 0 }; +@@ -904,6 +906,11 @@ static int shim_create(shim_create_args *args) + return -1; + } + ++ if (pipe2(exec_err_pipe, O_CLOEXEC) != 0) { ++ ERROR("Failed to create pipe for exec err"); ++ return -1; ++ } ++ + pid = fork(); + if (pid < 0) { + SYSERROR("Failed fork for shim parent"); +@@ -911,30 +918,32 @@ static int shim_create(shim_create_args *args) + close(shim_stderr_pipe[1]); + close(shim_stdout_pipe[0]); + close(shim_stdout_pipe[1]); ++ close(exec_err_pipe[0]); ++ close(exec_err_pipe[1]); + return -1; + } + + if (pid == (pid_t)0) { + if (chdir(args->workdir) < 0) { +- (void)dprintf(shim_stderr_pipe[1], "%s: failed chdir to %s", args->id, args->workdir); ++ (void)dprintf(exec_err_pipe[1], "%s: failed chdir to %s", args->id, args->workdir); + exit(EXIT_FAILURE); + } + + //prevent the child process from having the same standard streams as the parent process + if (isula_null_stdfds() != 0) { +- (void)dprintf(shim_stderr_pipe[1], "failed to set std console to /dev/null"); ++ (void)dprintf(exec_err_pipe[1], "failed to set std console to /dev/null"); + exit(EXIT_FAILURE); + } + + if (args->fg) { + // child process, dup2 shim_stdout_pipe[1] to STDOUT, get container process exit_code in STDOUT + if (dup2(shim_stdout_pipe[1], STDOUT_FILENO) < 0) { +- (void)dprintf(shim_stderr_pipe[1], "Dup stdout fd error: %s", strerror(errno)); ++ (void)dprintf(exec_err_pipe[1], "Dup stdout fd error: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + // child process, dup2 shim_stderr_pipe[1] to STDERR, get isulad-shim errmsg in STDERR + if (dup2(shim_stderr_pipe[1], STDERR_FILENO) < 0) { +- (void)dprintf(shim_stderr_pipe[1], "Dup stderr fd error: %s", strerror(errno)); ++ (void)dprintf(exec_err_pipe[1], "Dup stderr fd error: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + goto realexec; +@@ -942,18 +951,18 @@ static int shim_create(shim_create_args *args) + + // clear NOTIFY_SOCKET from the env to adapt runc create + if (unsetenv("NOTIFY_SOCKET") != 0) { +- (void)dprintf(shim_stderr_pipe[1], "%s: unset env NOTIFY_SOCKET failed %s", args->id, strerror(errno)); ++ (void)dprintf(exec_err_pipe[1], "%s: unset env NOTIFY_SOCKET failed %s", args->id, strerror(errno)); + exit(EXIT_FAILURE); + } + + pid = fork(); + if (pid < 0) { +- (void)dprintf(shim_stderr_pipe[1], "%s: fork shim-process failed %s", args->id, strerror(errno)); ++ (void)dprintf(exec_err_pipe[1], "%s: fork shim-process failed %s", args->id, strerror(errno)); + _exit(EXIT_FAILURE); + } + if (pid != 0) { + if (file_write_int(fpid, pid) != 0) { +- (void)dprintf(shim_stderr_pipe[1], "%s: write %s with %d failed", args->id, fpid, pid); ++ (void)dprintf(exec_err_pipe[1], "%s: write %s with %d failed", args->id, fpid, pid); + } + _exit(EXIT_SUCCESS); + } +@@ -962,35 +971,38 @@ realexec: + /* real shim process. */ + close(shim_stderr_pipe[0]); + close(shim_stdout_pipe[0]); ++ close(exec_err_pipe[0]); + + if (setsid() < 0) { +- (void)dprintf(shim_stderr_pipe[1], "%s: failed setsid for process %d", args->id, getpid()); ++ (void)dprintf(exec_err_pipe[1], "%s: failed setsid for process %d", args->id, getpid()); + exit(EXIT_FAILURE); + } + + if (util_check_inherited(true, shim_stderr_pipe[1]) != 0) { +- (void)dprintf(shim_stderr_pipe[1], "close inherited fds failed"); ++ (void)dprintf(exec_err_pipe[1], "close inherited fds failed"); + exit(EXIT_FAILURE); + } + + if (setenv(SHIIM_LOG_PATH_ENV, engine_log_path, 1) != 0) { +- (void)dprintf(shim_stderr_pipe[1], "%s: failed to set SHIIM_LOG_PATH_ENV for process %d", args->id, getpid()); ++ (void)dprintf(exec_err_pipe[1], "%s: failed to set SHIIM_LOG_PATH_ENV for process %d", args->id, getpid()); + exit(EXIT_FAILURE); + } + + if (setenv(SHIIM_LOG_LEVEL_ENV, log_level, 1) != 0) { +- (void)dprintf(shim_stderr_pipe[1], "%s: failed to set SHIIM_LOG_LEVEL_ENV env for process %d", args->id, getpid()); ++ (void)dprintf(exec_err_pipe[1], "%s: failed to set SHIIM_LOG_LEVEL_ENV env for process %d", args->id, getpid()); + exit(EXIT_FAILURE); + } + + execvp(SHIM_BINARY, (char * const *)params); +- (void)dprintf(shim_stderr_pipe[1], "run process: %s failed: %s", SHIM_BINARY, strerror(errno)); ++ (void)dprintf(exec_err_pipe[1], "run process: %s failed: %s", SHIM_BINARY, strerror(errno)); + exit(EXIT_FAILURE); + } + + close(shim_stderr_pipe[1]); + close(shim_stdout_pipe[1]); +- num = util_read_nointr(shim_stderr_pipe[0], exec_buff, sizeof(exec_buff) - 1); ++ close(exec_err_pipe[1]); ++ num = util_read_nointr(exec_err_pipe[0], exec_buff, sizeof(exec_buff) - 1); ++ close(exec_err_pipe[0]); + + status = util_wait_for_pid_status(pid); + if (status < 0) { +@@ -1035,8 +1047,10 @@ realexec: + out: + close(shim_stdout_pipe[0]); + if (ret != 0) { +- show_runtime_errlog(args->workdir); + show_shim_errlog(shim_stderr_pipe[0]); ++ // Since users are more concerned about runtime error information, ++ // the runtime log will overwrite the shim log if it exists. ++ show_runtime_errlog(args->workdir); + if (args->timeout != NULL) { + kill(pid, SIGKILL); /* can kill other process? */ + } +@@ -1491,14 +1505,13 @@ int rt_isula_exec(const char *id, const char *runtime, const rt_exec_params_t *p + args.exit_code = exit_code; + args.timeout = timeout; + ret = shim_create(&args); +- if (args.shim_exit_code == SHIM_EXIT_TIMEOUT) { +- ret = -1; +- isulad_set_error_message("Exec container error;exec timeout"); +- ERROR("isulad-shim %d exit for execing timeout", pid); +- goto errlog_out; +- } + if (ret != 0) { +- ERROR("%s: failed create shim process for exec %s", id, exec_id); ++ if (args.shim_exit_code == SHIM_EXIT_TIMEOUT) { ++ isulad_set_error_message("Exec container error;exec timeout"); ++ ERROR("isulad-shim %d exit for execing timeout", pid); ++ } else { ++ ERROR("%s: failed create shim process for exec %s", id, exec_id); ++ } + goto errlog_out; + } + +-- +2.34.1 + diff --git a/0056-bugfix-for-the-pre-created-pipe-was-not-closed-when-.patch b/0056-bugfix-for-the-pre-created-pipe-was-not-closed-when-.patch new file mode 100644 index 0000000..607f721 --- /dev/null +++ b/0056-bugfix-for-the-pre-created-pipe-was-not-closed-when-.patch @@ -0,0 +1,36 @@ +From e8ba4368f4be369f99d7da6fc04dcbe173985cd0 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Fri, 12 Apr 2024 14:42:05 +0800 +Subject: [PATCH 56/69] bugfix for the pre-created pipe was not closed when the + pipe creation failed + +Signed-off-by: zhongtao +--- + src/daemon/modules/runtime/isula/isula_rt_ops.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/daemon/modules/runtime/isula/isula_rt_ops.c b/src/daemon/modules/runtime/isula/isula_rt_ops.c +index 1875cf5b..47a14b1d 100644 +--- a/src/daemon/modules/runtime/isula/isula_rt_ops.c ++++ b/src/daemon/modules/runtime/isula/isula_rt_ops.c +@@ -903,11 +903,17 @@ static int shim_create(shim_create_args *args) + + if (pipe2(shim_stdout_pipe, O_CLOEXEC) != 0) { + ERROR("Failed to create pipe for shim stdout"); ++ close(shim_stderr_pipe[0]); ++ close(shim_stderr_pipe[1]); + return -1; + } + + if (pipe2(exec_err_pipe, O_CLOEXEC) != 0) { + ERROR("Failed to create pipe for exec err"); ++ close(shim_stderr_pipe[0]); ++ close(shim_stderr_pipe[1]); ++ close(shim_stdout_pipe[0]); ++ close(shim_stdout_pipe[1]); + return -1; + } + +-- +2.34.1 + diff --git a/0057-add-debug-msg-info-in-image_load.sh.patch b/0057-add-debug-msg-info-in-image_load.sh.patch new file mode 100644 index 0000000..81f61c8 --- /dev/null +++ b/0057-add-debug-msg-info-in-image_load.sh.patch @@ -0,0 +1,26 @@ +From c3f7cf2a54188e5fc890a8d23b95254ac69cfa52 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Fri, 12 Apr 2024 15:23:07 +0800 +Subject: [PATCH 57/69] add debug msg info in image_load.sh + +Signed-off-by: zhongtao +--- + CI/test_cases/image_cases/image_load.sh | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/CI/test_cases/image_cases/image_load.sh b/CI/test_cases/image_cases/image_load.sh +index a2cada5f..d50b3203 100755 +--- a/CI/test_cases/image_cases/image_load.sh ++++ b/CI/test_cases/image_cases/image_load.sh +@@ -103,6 +103,8 @@ function test_concurrent_load() + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - fail to do isulad load $i" && ((ret++)) + done + ++ tail -n 50 /var/lib/isulad/isulad.log ++ + ubuntu_id=`isula inspect -f '{{.image.id}}' ubuntu` + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - fail to inspect image: ubuntu" && ((ret++)) + +-- +2.34.1 + diff --git a/0058-empty-pointer-check-in-lcr_rt_ops.patch b/0058-empty-pointer-check-in-lcr_rt_ops.patch new file mode 100644 index 0000000..1cbe4b2 --- /dev/null +++ b/0058-empty-pointer-check-in-lcr_rt_ops.patch @@ -0,0 +1,214 @@ +From ea1bc00c894a3717ea375f5ff40c3eb05447ae17 Mon Sep 17 00:00:00 2001 +From: jikai +Date: Sat, 13 Apr 2024 14:07:33 +0000 +Subject: [PATCH 58/69] empty pointer check in lcr_rt_ops + +Signed-off-by: jikai +--- + .../modules/runtime/engines/lcr/lcr_rt_ops.c | 84 ++++++++++++++++++- + 1 file changed, 81 insertions(+), 3 deletions(-) + +diff --git a/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.c b/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.c +index 978da079..a89d0375 100644 +--- a/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.c ++++ b/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.c +@@ -53,6 +53,11 @@ int rt_lcr_create(const char *name, const char *runtime, const rt_create_params_ + char *runtime_root = NULL; + struct engine_operation *engine_ops = NULL; + ++ if (name == NULL || runtime == NULL || params == NULL) { ++ ERROR("Nullptr arguments not allowed"); ++ return -1; ++ } ++ + if (conf_get_systemd_cgroup()) { + ERROR("Systemd cgroup not supported for lcr runtime"); + isulad_set_error_message("Systemd cgroup not supported for lcr runtime"); +@@ -129,6 +134,11 @@ int rt_lcr_start(const char *name, const char *runtime, const rt_start_params_t + struct engine_operation *engine_ops = NULL; + engine_start_request_t request = { 0 }; + ++ if (name == NULL || runtime == NULL || params == NULL || pid_info == NULL) { ++ ERROR("Nullptr arguments not allowed"); ++ return -1; ++ } ++ + engine_ops = engines_get_handler(runtime); + if (engine_ops == NULL || engine_ops->engine_start_op == NULL) { + ERROR("Failed to get engine start operations"); +@@ -183,6 +193,11 @@ int rt_lcr_clean_resource(const char *name, const char *runtime, const rt_clean_ + int ret = 0; + struct engine_operation *engine_ops = NULL; + ++ if (name == NULL || runtime == NULL || params == NULL) { ++ ERROR("Nullptr arguments not allowed"); ++ return -1; ++ } ++ + engine_ops = engines_get_handler(runtime); + if (engine_ops == NULL || engine_ops->engine_clean_op == NULL) { + ERROR("Failed to get engine clean operations"); +@@ -236,6 +251,15 @@ int rt_lcr_rm(const char *name, const char *runtime, const rt_rm_params_t *param + int ret = 0; + struct engine_operation *engine_ops = NULL; + ++ if (name == NULL || runtime == NULL || params == NULL) { ++ ERROR("Nullptr arguments not allowed"); ++ return -1; ++ } ++ if (params->rootpath == NULL) { ++ ERROR("Missing root path"); ++ return -1; ++ } ++ + engine_ops = engines_get_handler(runtime); + if (engine_ops == NULL || engine_ops->engine_delete_op == NULL) { + // if engine_ops is NULL, container root path may have been corrupted, try to remove by daemon +@@ -284,6 +308,11 @@ int rt_lcr_status(const char *name, const char *runtime, const rt_status_params_ + int nret = 0; + struct engine_operation *engine_ops = NULL; + ++ if (name == NULL || runtime == NULL || params == NULL || status == NULL) { ++ ERROR("Nullptr arguments not allowed"); ++ return -1; ++ } ++ + engine_ops = engines_get_handler(runtime); + if (engine_ops == NULL || engine_ops->engine_get_container_status_op == NULL) { + ERROR("Failed to get engine status operations"); +@@ -322,6 +351,11 @@ int rt_lcr_resources_stats(const char *name, const char *runtime, const rt_stats + int nret = 0; + struct engine_operation *engine_ops = NULL; + ++ if (name == NULL || runtime == NULL || params == NULL || rs_stats == NULL) { ++ ERROR("Nullptr arguments not allowed"); ++ return -1; ++ } ++ + engine_ops = engines_get_handler(runtime); + if (engine_ops == NULL || engine_ops->engine_get_container_resources_stats_op == NULL) { + ERROR("Failed to get engine stats operations"); +@@ -451,6 +485,11 @@ int rt_lcr_exec(const char *id, const char *runtime, const rt_exec_params_t *par + char *user = NULL; + char *add_gids = NULL; + ++ if (id == NULL || runtime == NULL || params == NULL || exit_code == NULL) { ++ ERROR("Nullptr arguments not allowed"); ++ return -1; ++ } ++ + engine_ops = engines_get_handler(runtime); + if (engine_ops == NULL || engine_ops->engine_exec_op == NULL) { + DEBUG("Failed to get engine exec operations"); +@@ -519,6 +558,11 @@ int rt_lcr_pause(const char *name, const char *runtime, const rt_pause_params_t + int ret = 0; + struct engine_operation *engine_ops = NULL; + ++ if (name == NULL || runtime == NULL || params == NULL) { ++ ERROR("Nullptr arguments not allowed"); ++ return -1; ++ } ++ + engine_ops = engines_get_handler(runtime); + if (engine_ops == NULL || engine_ops->engine_pause_op == NULL) { + DEBUG("Failed to get engine pause operations"); +@@ -549,6 +593,11 @@ int rt_lcr_resume(const char *name, const char *runtime, const rt_resume_params_ + int ret = 0; + struct engine_operation *engine_ops = NULL; + ++ if (name == NULL || runtime == NULL || params == NULL) { ++ ERROR("Nullptr arguments not allowed"); ++ return -1; ++ } ++ + engine_ops = engines_get_handler(runtime); + if (engine_ops == NULL || engine_ops->engine_resume_op == NULL) { + DEBUG("Failed to get engine resume operations"); +@@ -579,6 +628,11 @@ int rt_lcr_attach(const char *name, const char *runtime, const rt_attach_params_ + int ret = 0; + struct engine_operation *engine_ops = NULL; + ++ if (name == NULL || runtime == NULL || params == NULL) { ++ ERROR("Null argument"); ++ return -1; ++ } ++ + engine_ops = engines_get_handler(runtime); + if (engine_ops == NULL || engine_ops->engine_console_op == NULL) { + DEBUG("Failed to get engine attach operations"); +@@ -641,6 +695,11 @@ int rt_lcr_update(const char *id, const char *runtime, const rt_update_params_t + struct engine_operation *engine_ops = NULL; + struct engine_cgroup_resources cr = { 0 }; + ++ if (id == NULL || runtime == NULL || params == NULL) { ++ ERROR("Nullptr arguments not allowed"); ++ return -1; ++ } ++ + engine_ops = engines_get_handler(runtime); + if (engine_ops == NULL || engine_ops->engine_update_op == NULL) { + DEBUG("Failed to get engine update operations"); +@@ -673,10 +732,9 @@ int rt_lcr_listpids(const char *name, const char *runtime, const rt_listpids_par + int ret = 0; + struct engine_operation *engine_ops = NULL; + +- if (out == NULL) { ++ if (name == NULL || runtime == NULL || params == NULL || out == NULL) { + ERROR("Invalid arguments"); +- ret = -1; +- goto out; ++ return -1; + } + + engine_ops = engines_get_handler(runtime); +@@ -709,6 +767,11 @@ int rt_lcr_resize(const char *id, const char *runtime, const rt_resize_params_t + int ret = 0; + struct engine_operation *engine_ops = NULL; + ++ if (id == NULL || runtime == NULL || params == NULL) { ++ ERROR("Invalid arguments"); ++ return -1; ++ } ++ + engine_ops = engines_get_handler(runtime); + if (engine_ops == NULL || engine_ops->engine_resize_op == NULL) { + DEBUG("Failed to get engine resume operations"); +@@ -740,6 +803,11 @@ int rt_lcr_exec_resize(const char *id, const char *runtime, const rt_exec_resize + int ret = 0; + struct engine_operation *engine_ops = NULL; + ++ if (id == NULL || runtime == NULL || params == NULL) { ++ ERROR("Nullptr arguments not allowed"); ++ return -1; ++ } ++ + engine_ops = engines_get_handler(runtime); + if (engine_ops == NULL || engine_ops->engine_resize_op == NULL) { + DEBUG("Failed to get engine resume operations"); +@@ -767,6 +835,11 @@ out: + + int rt_lcr_kill(const char *id, const char *runtime, const rt_kill_params_t *params) + { ++ if (id == NULL || runtime == NULL || params == NULL || params->pid < 0) { ++ ERROR("Invalid arguments not allowed"); ++ return -1; ++ } ++ + if (util_process_alive(params->pid, params->start_time) == false) { + if (params->signal == params->stop_signal || params->signal == SIGKILL) { + WARN("Process %d is not alive", params->pid); +@@ -798,6 +871,11 @@ int rt_lcr_rebuild_config(const char *name, const char *runtime, const rt_rebuil + oci_runtime_spec *oci_spec = NULL; + __isula_auto_free parser_error err = NULL; + ++ if (name == NULL || runtime == NULL || params == NULL) { ++ ERROR("Invalid arguments not allowed"); ++ return -1; ++ } ++ + engine_ops = engines_get_handler(runtime); + if (engine_ops == NULL || engine_ops->engine_create_op == NULL) { + ERROR("Failed to get engine rebuild config operations"); +-- +2.34.1 + diff --git a/0059-modify-some-grpc-status-codes-of-cri-in-case-of-erro.patch b/0059-modify-some-grpc-status-codes-of-cri-in-case-of-erro.patch new file mode 100644 index 0000000..1153418 --- /dev/null +++ b/0059-modify-some-grpc-status-codes-of-cri-in-case-of-erro.patch @@ -0,0 +1,315 @@ +From 628f4ceb329e16991ed33d3a460bcf8f5542ba99 Mon Sep 17 00:00:00 2001 +From: jikai +Date: Mon, 8 Apr 2024 09:30:04 +0000 +Subject: [PATCH 59/69] modify some grpc status codes of cri in case of error + +Signed-off-by: jikai +--- + .../cri/v1/cri_v1_runtime_runtime_service.cc | 41 +++++++++++++------ + .../cri/v1/cri_v1_runtime_runtime_service.h | 3 ++ + .../v1alpha/cri_runtime_runtime_service.cc | 41 +++++++++++++------ + .../cri/v1alpha/cri_runtime_runtime_service.h | 2 + + 4 files changed, 63 insertions(+), 24 deletions(-) + +diff --git a/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_runtime_service.cc b/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_runtime_service.cc +index e2591ce0..fb5aad3c 100644 +--- a/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_runtime_service.cc ++++ b/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_runtime_service.cc +@@ -50,6 +50,23 @@ static void cri_container_topic_release(void *arg) + delete resp; + } + ++grpc::Status RuntimeV1RuntimeServiceImpl::ToGRPCStatus(Errors &error) ++{ ++ if (error.Empty()) { ++ return grpc::Status::OK; ++ } ++ if (error.GetMessage().find("Failed to find") != std::string::npos) { ++ return grpc::Status(grpc::StatusCode::NOT_FOUND, error.GetMessage()); ++ } ++ ++ // Attach exceeded timeout for lxc and Exec container error;exec timeout for runc ++ if (error.GetMessage().find("Attach exceeded timeout") != std::string::npos ++ || error.GetMessage().find("Exec container error;exec timeout") != std::string::npos) { ++ return grpc::Status(grpc::StatusCode::DEADLINE_EXCEEDED, error.GetMessage()); ++ } ++ return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage()); ++} ++ + void RuntimeV1RuntimeServiceImpl::Init(std::string &podSandboxImage, + std::shared_ptr networkPlugin, + bool enablePodEvents, Errors &err) +@@ -167,7 +184,7 @@ grpc::Status RuntimeV1RuntimeServiceImpl::CreateContainer(grpc::ServerContext *c + m_rService->CreateContainer(request->pod_sandbox_id(), request->config(), request->sandbox_config(), error); + if (!error.Empty() || responseID.empty()) { + ERROR("Object: CRI, Type: Failed to create container"); +- return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage()); ++ return ToGRPCStatus(error); + } + reply->set_container_id(responseID); + +@@ -192,7 +209,7 @@ grpc::Status RuntimeV1RuntimeServiceImpl::StartContainer(grpc::ServerContext *co + m_rService->StartContainer(request->container_id(), error); + if (!error.Empty()) { + ERROR("Object: CRI, Type: Failed to start container %s", request->container_id().c_str()); +- return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage()); ++ return ToGRPCStatus(error); + } + + EVENT("Event: {Object: CRI, Type: Started Container: %s}", request->container_id().c_str()); +@@ -216,7 +233,7 @@ grpc::Status RuntimeV1RuntimeServiceImpl::StopContainer(grpc::ServerContext *con + m_rService->StopContainer(request->container_id(), (int64_t)request->timeout(), error); + if (!error.Empty()) { + ERROR("Object: CRI, Type: Failed to stop container %s", request->container_id().c_str()); +- return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage()); ++ return ToGRPCStatus(error); + } + + EVENT("Event: {Object: CRI, Type: Stopped Container: %s}", request->container_id().c_str()); +@@ -240,7 +257,7 @@ grpc::Status RuntimeV1RuntimeServiceImpl::RemoveContainer(grpc::ServerContext *c + m_rService->RemoveContainer(request->container_id(), error); + if (!error.Empty()) { + ERROR("Object: CRI, Type: Failed to remove container %s", request->container_id().c_str()); +- return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage()); ++ return ToGRPCStatus(error); + } + + EVENT("Event: {Object: CRI, Type: Removed Container: %s}", request->container_id().c_str()); +@@ -359,7 +376,7 @@ grpc::Status RuntimeV1RuntimeServiceImpl::ContainerStatus(grpc::ServerContext *c + m_rService->ContainerStatus(request->container_id(), error); + if (!error.Empty() || !contStatus) { + ERROR("Object: CRI, Type: Failed to get container status %s", request->container_id().c_str()); +- return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage()); ++ return ToGRPCStatus(error); + } + *(reply->mutable_status()) = *contStatus; + +@@ -384,7 +401,7 @@ grpc::Status RuntimeV1RuntimeServiceImpl::ExecSync(grpc::ServerContext *context, + m_rService->ExecSync(request->container_id(), request->cmd(), request->timeout(), reply, error); + if (!error.Empty()) { + ERROR("Object: CRI, Type: Failed to sync exec container: %s", request->container_id().c_str()); +- return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage()); ++ return ToGRPCStatus(error); + } + + WARN("Event: {Object: CRI, Type: sync execed Container: %s}", request->container_id().c_str()); +@@ -437,7 +454,7 @@ grpc::Status RuntimeV1RuntimeServiceImpl::StopPodSandbox(grpc::ServerContext *co + if (!error.Empty()) { + ERROR("Object: CRI, Type: Failed to stop pod:%s due to %s", request->pod_sandbox_id().c_str(), + error.GetMessage().c_str()); +- return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage()); ++ return ToGRPCStatus(error); + } + + EVENT("Event: {Object: CRI, Type: Stopped Pod: %s}", request->pod_sandbox_id().c_str()); +@@ -462,7 +479,7 @@ grpc::Status RuntimeV1RuntimeServiceImpl::RemovePodSandbox(grpc::ServerContext * + if (!error.Empty()) { + ERROR("Object: CRI, Type: Failed to remove pod:%s due to %s", request->pod_sandbox_id().c_str(), + error.GetMessage().c_str()); +- return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage()); ++ return ToGRPCStatus(error); + } + + EVENT("Event: {Object: CRI, Type: Removed Pod: %s}", request->pod_sandbox_id().c_str()); +@@ -487,7 +504,7 @@ grpc::Status RuntimeV1RuntimeServiceImpl::PodSandboxStatus(grpc::ServerContext * + if (!error.Empty()) { + ERROR("Object: CRI, Type: Failed to status pod:%s due to %s", request->pod_sandbox_id().c_str(), + error.GetMessage().c_str()); +- return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage()); ++ return ToGRPCStatus(error); + } + + INFO("Event: {Object: CRI, Type: Statused Pod: %s}", request->pod_sandbox_id().c_str()); +@@ -608,7 +625,7 @@ RuntimeV1RuntimeServiceImpl::UpdateContainerResources(grpc::ServerContext *conte + if (error.NotEmpty()) { + ERROR("Object: CRI, Type: Failed to update container:%s due to %s", request->container_id().c_str(), + error.GetMessage().c_str()); +- return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage()); ++ return ToGRPCStatus(error); + } + + WARN("Event: {Object: CRI, Type: Updated container resources: %s}", request->container_id().c_str()); +@@ -633,7 +650,7 @@ grpc::Status RuntimeV1RuntimeServiceImpl::Exec(grpc::ServerContext *context, + if (!error.Empty()) { + ERROR("Object: CRI, Type: Failed to exec container:%s due to %s", request->container_id().c_str(), + error.GetMessage().c_str()); +- return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage()); ++ return ToGRPCStatus(error); + } + + EVENT("Event: {Object: CRI, Type: execed Container: %s}", request->container_id().c_str()); +@@ -658,7 +675,7 @@ grpc::Status RuntimeV1RuntimeServiceImpl::Attach(grpc::ServerContext *context, + if (!error.Empty()) { + ERROR("Object: CRI, Type: Failed to attach container:%s due to %s", request->container_id().c_str(), + error.GetMessage().c_str()); +- return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage()); ++ return ToGRPCStatus(error); + } + + EVENT("Event: {Object: CRI, Type: attched Container: %s}", request->container_id().c_str()); +diff --git a/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_runtime_service.h b/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_runtime_service.h +index 842d1811..1cf375a4 100644 +--- a/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_runtime_service.h ++++ b/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_runtime_service.h +@@ -114,6 +114,9 @@ public: + grpc::ServerWriter *writer) override; + + private: ++ ++ grpc::Status ToGRPCStatus(Errors &error); ++ + std::unique_ptr m_rService; + bool m_enablePodEvents; + }; +diff --git a/src/daemon/entry/connect/grpc/cri/v1alpha/cri_runtime_runtime_service.cc b/src/daemon/entry/connect/grpc/cri/v1alpha/cri_runtime_runtime_service.cc +index 5e85702c..1c83f4ca 100644 +--- a/src/daemon/entry/connect/grpc/cri/v1alpha/cri_runtime_runtime_service.cc ++++ b/src/daemon/entry/connect/grpc/cri/v1alpha/cri_runtime_runtime_service.cc +@@ -23,6 +23,23 @@ + + using namespace CRI; + ++grpc::Status RuntimeRuntimeServiceImpl::ToGRPCStatus(Errors &error) ++{ ++ if (error.Empty()) { ++ return grpc::Status::OK; ++ } ++ if (error.GetMessage().find("Failed to find") != std::string::npos) { ++ return grpc::Status(grpc::StatusCode::NOT_FOUND, error.GetMessage()); ++ } ++ ++ // Attach exceeded timeout for lxc and Exec container error;exec timeout for runc ++ if (error.GetMessage().find("Attach exceeded timeout") != std::string::npos ++ || error.GetMessage().find("Exec container error;exec timeout") != std::string::npos) { ++ return grpc::Status(grpc::StatusCode::DEADLINE_EXCEEDED, error.GetMessage()); ++ } ++ return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage()); ++} ++ + void RuntimeRuntimeServiceImpl::Init(std::string &podSandboxImage, + std::shared_ptr networkPlugin, Errors &err) + { +@@ -80,7 +97,7 @@ grpc::Status RuntimeRuntimeServiceImpl::CreateContainer(grpc::ServerContext *con + m_rService->CreateContainer(request->pod_sandbox_id(), request->config(), request->sandbox_config(), error); + if (!error.Empty() || responseID.empty()) { + ERROR("Object: CRI, Type: Failed to create container"); +- return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage()); ++ return ToGRPCStatus(error); + } + reply->set_container_id(responseID); + +@@ -105,7 +122,7 @@ grpc::Status RuntimeRuntimeServiceImpl::StartContainer(grpc::ServerContext *cont + m_rService->StartContainer(request->container_id(), error); + if (!error.Empty()) { + ERROR("Object: CRI, Type: Failed to start container %s", request->container_id().c_str()); +- return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage()); ++ return ToGRPCStatus(error); + } + + EVENT("Event: {Object: CRI, Type: Started Container: %s}", request->container_id().c_str()); +@@ -129,7 +146,7 @@ grpc::Status RuntimeRuntimeServiceImpl::StopContainer(grpc::ServerContext *conte + m_rService->StopContainer(request->container_id(), (int64_t)request->timeout(), error); + if (!error.Empty()) { + ERROR("Object: CRI, Type: Failed to stop container %s", request->container_id().c_str()); +- return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage()); ++ return ToGRPCStatus(error); + } + + EVENT("Event: {Object: CRI, Type: Stopped Container: %s}", request->container_id().c_str()); +@@ -153,7 +170,7 @@ grpc::Status RuntimeRuntimeServiceImpl::RemoveContainer(grpc::ServerContext *con + m_rService->RemoveContainer(request->container_id(), error); + if (!error.Empty()) { + ERROR("Object: CRI, Type: Failed to remove container %s", request->container_id().c_str()); +- return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage()); ++ return ToGRPCStatus(error); + } + + EVENT("Event: {Object: CRI, Type: Removed Container: %s}", request->container_id().c_str()); +@@ -272,7 +289,7 @@ grpc::Status RuntimeRuntimeServiceImpl::ContainerStatus(grpc::ServerContext *con + m_rService->ContainerStatus(request->container_id(), error); + if (!error.Empty() || !contStatus) { + ERROR("Object: CRI, Type: Failed to get container status %s", request->container_id().c_str()); +- return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage()); ++ return ToGRPCStatus(error); + } + *(reply->mutable_status()) = *contStatus; + +@@ -297,7 +314,7 @@ grpc::Status RuntimeRuntimeServiceImpl::ExecSync(grpc::ServerContext *context, + m_rService->ExecSync(request->container_id(), request->cmd(), request->timeout(), reply, error); + if (!error.Empty()) { + ERROR("Object: CRI, Type: Failed to sync exec container: %s", request->container_id().c_str()); +- return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage()); ++ return ToGRPCStatus(error); + } + + WARN("Event: {Object: CRI, Type: sync execed Container: %s}", request->container_id().c_str()); +@@ -351,7 +368,7 @@ grpc::Status RuntimeRuntimeServiceImpl::StopPodSandbox(grpc::ServerContext *cont + if (!error.Empty()) { + ERROR("Object: CRI, Type: Failed to stop pod:%s due to %s", request->pod_sandbox_id().c_str(), + error.GetMessage().c_str()); +- return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage()); ++ return ToGRPCStatus(error); + } + + EVENT("Event: {Object: CRI, Type: Stopped Pod: %s}", request->pod_sandbox_id().c_str()); +@@ -376,7 +393,7 @@ grpc::Status RuntimeRuntimeServiceImpl::RemovePodSandbox(grpc::ServerContext *co + if (!error.Empty()) { + ERROR("Object: CRI, Type: Failed to remove pod:%s due to %s", request->pod_sandbox_id().c_str(), + error.GetMessage().c_str()); +- return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage()); ++ return ToGRPCStatus(error); + } + + EVENT("Event: {Object: CRI, Type: Removed Pod: %s}", request->pod_sandbox_id().c_str()); +@@ -402,7 +419,7 @@ grpc::Status RuntimeRuntimeServiceImpl::PodSandboxStatus(grpc::ServerContext *co + if (!error.Empty() || !podStatus) { + ERROR("Object: CRI, Type: Failed to status pod:%s due to %s", request->pod_sandbox_id().c_str(), + error.GetMessage().c_str()); +- return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage()); ++ return ToGRPCStatus(error); + } + *(reply->mutable_status()) = *podStatus; + +@@ -523,7 +540,7 @@ RuntimeRuntimeServiceImpl::UpdateContainerResources(grpc::ServerContext *context + if (error.NotEmpty()) { + ERROR("Object: CRI, Type: Failed to update container:%s due to %s", request->container_id().c_str(), + error.GetMessage().c_str()); +- return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage()); ++ return ToGRPCStatus(error); + } + + WARN("Event: {Object: CRI, Type: Updated container resources: %s}", request->container_id().c_str()); +@@ -548,7 +565,7 @@ grpc::Status RuntimeRuntimeServiceImpl::Exec(grpc::ServerContext *context, + if (!error.Empty()) { + ERROR("Object: CRI, Type: Failed to exec container:%s due to %s", request->container_id().c_str(), + error.GetMessage().c_str()); +- return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage()); ++ return ToGRPCStatus(error); + } + + EVENT("Event: {Object: CRI, Type: execed Container: %s}", request->container_id().c_str()); +@@ -573,7 +590,7 @@ grpc::Status RuntimeRuntimeServiceImpl::Attach(grpc::ServerContext *context, + if (!error.Empty()) { + ERROR("Object: CRI, Type: Failed to attach container:%s due to %s", request->container_id().c_str(), + error.GetMessage().c_str()); +- return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage()); ++ return ToGRPCStatus(error); + } + + EVENT("Event: {Object: CRI, Type: attched Container: %s}", request->container_id().c_str()); +diff --git a/src/daemon/entry/connect/grpc/cri/v1alpha/cri_runtime_runtime_service.h b/src/daemon/entry/connect/grpc/cri/v1alpha/cri_runtime_runtime_service.h +index e0f75897..210e67cc 100644 +--- a/src/daemon/entry/connect/grpc/cri/v1alpha/cri_runtime_runtime_service.h ++++ b/src/daemon/entry/connect/grpc/cri/v1alpha/cri_runtime_runtime_service.h +@@ -103,6 +103,8 @@ public: + runtime::v1alpha2::StatusResponse *reply) override; + + private: ++ grpc::Status ToGRPCStatus(Errors &err); ++ + std::unique_ptr m_rService; + }; + +-- +2.34.1 + diff --git a/0060-cdi-return-int-instead-of-error-string.patch b/0060-cdi-return-int-instead-of-error-string.patch new file mode 100644 index 0000000..e2ebc9b --- /dev/null +++ b/0060-cdi-return-int-instead-of-error-string.patch @@ -0,0 +1,363 @@ +From e7b94411b174c8445d9bdc84ec6c94b5d4343470 Mon Sep 17 00:00:00 2001 +From: liuxu +Date: Mon, 15 Apr 2024 15:38:57 +0800 +Subject: [PATCH 60/69] cdi:return int instead of error string + +--- + src/daemon/modules/api/cdi_operate_api.h | 7 ++++--- + .../device/cdi/behavior/cdi_container_edits.c | 12 ++++++------ + .../device/cdi/behavior/cdi_container_edits.h | 6 +++--- + .../modules/device/cdi/behavior/cdi_device.c | 2 +- + .../modules/device/cdi/behavior/cdi_device.h | 2 +- + .../modules/device/cdi/behavior/cdi_spec.c | 2 +- + .../modules/device/cdi/behavior/cdi_spec.h | 2 +- + .../modules/device/cdi/behavior/cdi_spec_dirs.c | 4 ++-- + .../modules/device/cdi/behavior/cdi_spec_dirs.h | 6 +++--- + .../device/cdi/behavior/parser/cdi_parser.c | 16 ++++++++-------- + .../device/cdi/behavior/parser/cdi_parser.h | 8 ++++---- + src/daemon/modules/device/cdi/cdi_annotations.c | 5 +++-- + src/daemon/modules/device/cdi/cdi_annotations.h | 3 ++- + src/daemon/modules/device/cdi/cdi_cache.c | 14 +++++++------- + src/daemon/modules/device/cdi/cdi_cache.h | 8 ++++---- + src/daemon/modules/device/cdi_operate.c | 13 +++++++------ + 16 files changed, 57 insertions(+), 53 deletions(-) + +diff --git a/src/daemon/modules/api/cdi_operate_api.h b/src/daemon/modules/api/cdi_operate_api.h +index 4f4c339e..49820ed7 100644 +--- a/src/daemon/modules/api/cdi_operate_api.h ++++ b/src/daemon/modules/api/cdi_operate_api.h +@@ -26,11 +26,12 @@ extern "C" { + + int cdi_operate_registry_init(char **specs_dirs, size_t specs_dirs_len); + +-char *cdi_operate_refresh(void); ++int cdi_operate_refresh(void); + +-string_array *cdi_operate_inject_devices(oci_runtime_spec *spec, string_array *devices, char **error); ++int cdi_operate_inject_devices(oci_runtime_spec *spec, string_array *devices); + +-char *cdi_operate_parse_annotations(json_map_string_string *annotations, string_array **keys, string_array **devices); ++int cdi_operate_parse_annotations(json_map_string_string *annotations, string_array **keys, ++ string_array **devices, char **error); + + #ifdef __cplusplus + } +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_container_edits.c b/src/daemon/modules/device/cdi/behavior/cdi_container_edits.c +index ce7b16db..590118b1 100644 +--- a/src/daemon/modules/device/cdi/behavior/cdi_container_edits.c ++++ b/src/daemon/modules/device/cdi/behavior/cdi_container_edits.c +@@ -27,19 +27,19 @@ + // POSTSTOP_HOOK is the name of the OCI "poststop" hook. + #define POSTSTOP_HOOK "poststop" + +-char *cdi_container_edits_apply(cdi_container_edits *e, oci_runtime_spec *spec) ++int cdi_container_edits_apply(cdi_container_edits *e, oci_runtime_spec *spec) + { +- return NULL; ++ return 0; + } + +-char *cdi_container_edits_validate(cdi_container_edits *e) ++int cdi_container_edits_validate(cdi_container_edits *e, char **error) + { +- return NULL; ++ return 0; + } + +-cdi_container_edits *cdi_container_edits_append(cdi_container_edits *e, cdi_container_edits *o) ++int cdi_container_edits_append(cdi_container_edits *e, cdi_container_edits *o) + { +- return NULL; ++ return 0; + } + + bool cdi_container_edits_is_empty(cdi_container_edits *e) +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_container_edits.h b/src/daemon/modules/device/cdi/behavior/cdi_container_edits.h +index 7b16d2bc..ea921e37 100644 +--- a/src/daemon/modules/device/cdi/behavior/cdi_container_edits.h ++++ b/src/daemon/modules/device/cdi/behavior/cdi_container_edits.h +@@ -27,9 +27,9 @@ + extern "C" { + #endif + +-char *cdi_container_edits_apply(cdi_container_edits *e, oci_runtime_spec *spec); +-char *cdi_container_edits_validate(cdi_container_edits *e); +-cdi_container_edits *cdi_container_edits_append(cdi_container_edits *e, cdi_container_edits *o); ++int cdi_container_edits_apply(cdi_container_edits *e, oci_runtime_spec *spec); ++int cdi_container_edits_validate(cdi_container_edits *e, char **error); ++int cdi_container_edits_append(cdi_container_edits *e, cdi_container_edits *o); + bool cdi_container_edits_is_empty(cdi_container_edits *e); + + #ifdef __cplusplus +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_device.c b/src/daemon/modules/device/cdi/behavior/cdi_device.c +index 9904e9ee..0fef8f42 100644 +--- a/src/daemon/modules/device/cdi/behavior/cdi_device.c ++++ b/src/daemon/modules/device/cdi/behavior/cdi_device.c +@@ -34,7 +34,7 @@ char *cdi_device_get_qualified_name(struct cdi_cache_device *d) + return NULL; + } + +-cdi_container_edits *cdi_device_edits(struct cdi_cache_device *d) ++cdi_container_edits *cdi_device_get_edits(struct cdi_cache_device *d) + { + return NULL; + } +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_device.h b/src/daemon/modules/device/cdi/behavior/cdi_device.h +index 3f460152..5d63a576 100644 +--- a/src/daemon/modules/device/cdi/behavior/cdi_device.h ++++ b/src/daemon/modules/device/cdi/behavior/cdi_device.h +@@ -37,7 +37,7 @@ void free_cdi_cache_device(struct cdi_cache_device *d); + struct cdi_cache_device *cdi_device_new_device(struct cdi_cache_spec *spec, cdi_device *d, char **error); + struct cdi_cache_spec *cdi_device_get_spec(struct cdi_cache_device *d); + char *cdi_device_get_qualified_name(struct cdi_cache_device *d); +-cdi_container_edits *cdi_device_edits(struct cdi_cache_device *d); ++cdi_container_edits *cdi_device_get_edits(struct cdi_cache_device *d); + + #ifdef __cplusplus + } +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_spec.c b/src/daemon/modules/device/cdi/behavior/cdi_spec.c +index 38fc9e38..f79b5a44 100644 +--- a/src/daemon/modules/device/cdi/behavior/cdi_spec.c ++++ b/src/daemon/modules/device/cdi/behavior/cdi_spec.c +@@ -54,7 +54,7 @@ int cdi_spec_get_priority(struct cdi_cache_spec *s) + return 0; + } + +-cdi_container_edits *cdi_spec_edits(struct cdi_cache_spec *s) ++cdi_container_edits *cdi_spec_get_edits(struct cdi_cache_spec *s) + { + return NULL; + } +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_spec.h b/src/daemon/modules/device/cdi/behavior/cdi_spec.h +index bd4fc9d1..87248041 100644 +--- a/src/daemon/modules/device/cdi/behavior/cdi_spec.h ++++ b/src/daemon/modules/device/cdi/behavior/cdi_spec.h +@@ -47,7 +47,7 @@ const char *cdi_spec_get_class(struct cdi_cache_spec *s); + struct cdi_cache_device *cdi_spec_get_cache_device(struct cdi_cache_spec *s, const char *name); + const char *cdi_spec_get_path(struct cdi_cache_spec *s); + int cdi_spec_get_priority(struct cdi_cache_spec *s); +-cdi_container_edits *cdi_spec_edits(struct cdi_cache_spec *s); ++cdi_container_edits *cdi_spec_get_edits(struct cdi_cache_spec *s); + + #ifdef __cplusplus + } +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_spec_dirs.c b/src/daemon/modules/device/cdi/behavior/cdi_spec_dirs.c +index 5df4c937..e340abc0 100644 +--- a/src/daemon/modules/device/cdi/behavior/cdi_spec_dirs.c ++++ b/src/daemon/modules/device/cdi/behavior/cdi_spec_dirs.c +@@ -23,7 +23,7 @@ string_array g_default_spec_dirs = { + .cap = DEFAULT_SPEC_DIRS_LEN, + }; + +-char *cdi_scan_spec_dirs(string_array *dirs, struct cdi_scan_fn_maps *scan_fn_maps, cdi_scan_spec_func scan_fn) ++int cdi_scan_spec_dirs(string_array *dirs, struct cdi_scan_fn_maps *scan_fn_maps, cdi_scan_spec_func scan_fn) + { +- return NULL; ++ return 0; + } +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_spec_dirs.h b/src/daemon/modules/device/cdi/behavior/cdi_spec_dirs.h +index bd00e318..73d8c0f5 100644 +--- a/src/daemon/modules/device/cdi/behavior/cdi_spec_dirs.h ++++ b/src/daemon/modules/device/cdi/behavior/cdi_spec_dirs.h +@@ -35,10 +35,10 @@ struct cdi_scan_fn_maps { + map_t *spec_errors; + string_array *result; + }; +-typedef char *(*cdi_scan_spec_func)(struct cdi_scan_fn_maps *scan_fn_maps, const char *path, int priority, +- struct cdi_cache_spec *spec, char **error); ++typedef void(*cdi_scan_spec_func)(struct cdi_scan_fn_maps *scan_fn_maps, const char *path, int priority, ++ struct cdi_cache_spec *spec, char *error); + +-char *cdi_scan_spec_dirs(string_array *dirs, struct cdi_scan_fn_maps *scan_fn_maps, cdi_scan_spec_func scan_fn); ++int cdi_scan_spec_dirs(string_array *dirs, struct cdi_scan_fn_maps *scan_fn_maps, cdi_scan_spec_func scan_fn); + + #ifdef __cplusplus + } +diff --git a/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.c b/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.c +index 45048f9a..14293c72 100644 +--- a/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.c ++++ b/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.c +@@ -24,9 +24,9 @@ bool cdi_parser_is_qualified_name(const char *device) + return true; + } + +-char *cdi_parser_parse_qualified_name(const char *device, char **vendor, char **class, char **name) ++int cdi_parser_parse_qualified_name(const char *device, char **vendor, char **class, char **name) + { +- return NULL; ++ return 0; + } + + int cdi_parser_parse_device(const char *device, char **vendor, char **class, char **name) +@@ -39,17 +39,17 @@ int cdi_parser_parse_qualifier(const char *kind, char **vendor, char **class) + return 0; + } + +-char *cdi_parser_validate_vendor_name(const char *vendor) ++int cdi_parser_validate_vendor_name(const char *vendor, char **error) + { +- return NULL; ++ return 0; + } + +-char *cdi_parser_validate_class_name(const char *class) ++int cdi_parser_validate_class_name(const char *class, char **error) + { +- return NULL; ++ return 0; + } + +-char *cdi_parser_validate_device_name(const char *name) ++int cdi_parser_validate_device_name(const char *name, char **error) + { +- return NULL; ++ return 0; + } +diff --git a/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.h b/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.h +index d9c057ea..467641a1 100644 +--- a/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.h ++++ b/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.h +@@ -24,12 +24,12 @@ extern "C" { + + char *cdi_parser_qualified_name(const char *vendor, const char *class, const char *name); + bool cdi_parser_is_qualified_name(const char *device); +-char *cdi_parser_parse_qualified_name(const char *device, char **vendor, char **class, char **name); ++int cdi_parser_parse_qualified_name(const char *device, char **vendor, char **class, char **name); + int cdi_parser_parse_device(const char *device, char **vendor, char **class, char **name); + int cdi_parser_parse_qualifier(const char *kind, char **vendor, char **class); +-char *cdi_parser_validate_vendor_name(const char *vendor); +-char *cdi_parser_validate_class_name(const char *class); +-char *cdi_parser_validate_device_name(const char *name); ++int cdi_parser_validate_vendor_name(const char *vendor, char **error); ++int cdi_parser_validate_class_name(const char *class, char **error); ++int cdi_parser_validate_device_name(const char *name, char **error); + + #ifdef __cplusplus + } +diff --git a/src/daemon/modules/device/cdi/cdi_annotations.c b/src/daemon/modules/device/cdi/cdi_annotations.c +index 3cb9be84..cfe6e099 100644 +--- a/src/daemon/modules/device/cdi/cdi_annotations.c ++++ b/src/daemon/modules/device/cdi/cdi_annotations.c +@@ -25,7 +25,8 @@ + + #define CDI_ANNOTATIONS_PREFIX "cdi.k8s.io/" + +-char *cdi_parse_annotations(json_map_string_string *annotations, string_array **keys, string_array **devices) ++int cdi_parse_annotations(json_map_string_string *annotations, string_array **keys, ++ string_array **devices, char **error) + { +- return NULL; ++ return 0; + } +diff --git a/src/daemon/modules/device/cdi/cdi_annotations.h b/src/daemon/modules/device/cdi/cdi_annotations.h +index 52355099..49930963 100644 +--- a/src/daemon/modules/device/cdi/cdi_annotations.h ++++ b/src/daemon/modules/device/cdi/cdi_annotations.h +@@ -23,7 +23,8 @@ + extern "C" { + #endif + +-char *cdi_parse_annotations(json_map_string_string *annotations, string_array **keys, string_array **devices); ++int cdi_parse_annotations(json_map_string_string *annotations, string_array **keys, ++ string_array **devices, char **error); + + #ifdef __cplusplus + } +diff --git a/src/daemon/modules/device/cdi/cdi_cache.c b/src/daemon/modules/device/cdi/cdi_cache.c +index 9c54acbf..cfc23a1c 100644 +--- a/src/daemon/modules/device/cdi/cdi_cache.c ++++ b/src/daemon/modules/device/cdi/cdi_cache.c +@@ -19,24 +19,24 @@ void free_cdi_cache(struct cdi_cache *c) + (void)c; + } + +-struct cdi_cache *cdi_new_cache(string_array *spec_dirs, char **error) ++struct cdi_cache *cdi_new_cache(string_array *spec_dirs) + { + return NULL; + } + +-static string_array *cdi_inject_devices(struct cdi_cache *c, oci_runtime_spec *oci_spec, string_array *devices, char **error) ++static int cdi_inject_devices(struct cdi_cache *c, oci_runtime_spec *oci_spec, string_array *devices) + { +- return NULL; ++ return 0; + } + +-static char *cdi_configure(struct cdi_cache *c, string_array *spec_dirs) ++static int cdi_configure(struct cdi_cache *c, string_array *spec_dirs) + { +- return NULL; ++ return 0; + } + +-static char *cdi_refresh(struct cdi_cache *c) ++static int cdi_refresh(struct cdi_cache *c) + { +- return NULL; ++ return 0; + } + + static map_t *cdi_get_errors(struct cdi_cache *c) +diff --git a/src/daemon/modules/device/cdi/cdi_cache.h b/src/daemon/modules/device/cdi/cdi_cache.h +index 92fb64af..34c27471 100644 +--- a/src/daemon/modules/device/cdi/cdi_cache.h ++++ b/src/daemon/modules/device/cdi/cdi_cache.h +@@ -33,12 +33,12 @@ struct cdi_cache; + struct cdi_cache_ops { + // injecting CDI devices into an OCI Spec. + // Resolver +- string_array *(*inject_devices)(struct cdi_cache *c, oci_runtime_spec *spec, string_array *devices, char **error); ++ int (*inject_devices)(struct cdi_cache *c, oci_runtime_spec *spec, string_array *devices); + + // refreshing the cache of CDI Specs and devices. + // Refresher +- char *(*configure)(struct cdi_cache *c, string_array *spec_dirs); +- char *(*refresh)(struct cdi_cache *c); ++ int (*configure)(struct cdi_cache *c, string_array *spec_dirs); ++ int (*refresh)(struct cdi_cache *c); + map_t *(*get_errors)(struct cdi_cache *c); + string_array *(*get_spec_directories)(struct cdi_cache *c); + map_t *(*get_spec_dir_errors)(struct cdi_cache *c); +@@ -65,7 +65,7 @@ struct cdi_cache { + + void free_cdi_cache(struct cdi_cache *c); + +-struct cdi_cache *cdi_new_cache(string_array *spec_dirs, char **error); ++struct cdi_cache *cdi_new_cache(string_array *spec_dirs); + struct cdi_cache_ops *cdi_get_cache_ops(void); + + #ifdef __cplusplus +diff --git a/src/daemon/modules/device/cdi_operate.c b/src/daemon/modules/device/cdi_operate.c +index c7aa77d8..c5187ab1 100644 +--- a/src/daemon/modules/device/cdi_operate.c ++++ b/src/daemon/modules/device/cdi_operate.c +@@ -19,17 +19,18 @@ int cdi_operate_registry_init(char **specs_dirs, size_t specs_dirs_len) + return 0; + } + +-char *cdi_operate_refresh(void) ++int cdi_operate_refresh(void) + { +- return NULL; ++ return 0; + } + +-string_array *cdi_operate_inject_devices(oci_runtime_spec *spec, string_array *devices, char **error) ++int cdi_operate_inject_devices(oci_runtime_spec *spec, string_array *devices) + { +- return NULL; ++ return 0; + } + +-char *cdi_operate_parse_annotations(json_map_string_string *annotations, string_array **keys, string_array **devices) ++int cdi_operate_parse_annotations(json_map_string_string *annotations, string_array **keys, ++ string_array **devices, char **error) + { +- return NULL; ++ return 0; + } +\ No newline at end of file +-- +2.34.1 + diff --git a/0061-cdi-support-modules-operate-registry-annotations.patch b/0061-cdi-support-modules-operate-registry-annotations.patch new file mode 100644 index 0000000..aa26ca2 --- /dev/null +++ b/0061-cdi-support-modules-operate-registry-annotations.patch @@ -0,0 +1,516 @@ +From 4527dc8b6f7ab438742a8f7403b24420f646236d Mon Sep 17 00:00:00 2001 +From: liuxu +Date: Mon, 8 Apr 2024 11:57:16 +0800 +Subject: [PATCH 61/69] cdi:support modules operate/registry/annotations + +--- + .../modules/device/cdi/cdi_annotations.c | 72 +++++++ + src/daemon/modules/device/cdi/cdi_registry.c | 14 +- + src/daemon/modules/device/cdi_operate.c | 53 +++++- + src/utils/cutils/utils.c | 11 ++ + src/utils/cutils/utils.h | 2 + + src/utils/cutils/utils_array.c | 175 +++++++++++++++++- + src/utils/cutils/utils_array.h | 31 ++++ + 7 files changed, 350 insertions(+), 8 deletions(-) + +diff --git a/src/daemon/modules/device/cdi/cdi_annotations.c b/src/daemon/modules/device/cdi/cdi_annotations.c +index cfe6e099..020816d7 100644 +--- a/src/daemon/modules/device/cdi/cdi_annotations.c ++++ b/src/daemon/modules/device/cdi/cdi_annotations.c +@@ -21,12 +21,84 @@ + + #include "error.h" + #include "utils.h" ++#include "utils_array.h" + #include "cdi_parser.h" + + #define CDI_ANNOTATIONS_PREFIX "cdi.k8s.io/" + ++static int parse_devices(string_array *devices, const char *value, char **error) ++{ ++ __isula_auto_array_t char **parts = NULL; ++ char **pos; ++ ++ parts = util_string_split(value, ','); ++ if (parts == NULL) { ++ ERROR("Invalid CDI device value %s", value); ++ format_errorf(error, "Invalid CDI device value %s", value); ++ return -1; ++ } ++ for (pos = parts; pos != NULL && *pos != NULL; pos++) { ++ if (!cdi_parser_is_qualified_name(*pos)) { ++ ERROR("Invalid CDI device name %s", *pos); ++ format_errorf(error, "Invalid CDI device name %s", *pos); ++ return -1; ++ } ++ if (util_append_string_array(devices, *pos) != 0) { ++ ERROR("Out of memory"); ++ *error = util_strdup_s("Out of memory"); ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ + int cdi_parse_annotations(json_map_string_string *annotations, string_array **keys, + string_array **devices, char **error) + { ++ char *key = NULL; ++ char *value = NULL; ++ size_t i; ++ __isula_auto_string_array_t string_array *keys_array = NULL; ++ __isula_auto_string_array_t string_array *devices_array = NULL; ++ ++ if (annotations == NULL || keys == NULL || devices == NULL || error == NULL) { ++ ERROR("Invalid argument"); ++ return -1; ++ } ++ ++ keys_array = util_common_calloc_s(sizeof(*keys_array)); ++ if (keys_array == NULL) { ++ ERROR("Out of memory"); ++ *error = util_strdup_s("Out of memory"); ++ return -1; ++ } ++ devices_array = util_common_calloc_s(sizeof(*devices_array)); ++ if (devices_array == NULL) { ++ ERROR("Out of memory"); ++ *error = util_strdup_s("Out of memory"); ++ return -1; ++ } ++ ++ for (i = 0; i < annotations->len; i++) { ++ key = annotations->keys[i]; ++ value = annotations->values[i]; ++ if (!util_has_prefix(key, CDI_ANNOTATIONS_PREFIX)) { ++ continue; ++ } ++ if (parse_devices(devices_array, value, error) != 0) { ++ return -1; ++ } ++ if (util_append_string_array(keys_array, key) != 0) { ++ ERROR("Out of memory"); ++ *error = util_strdup_s("Out of memory"); ++ return -1; ++ } ++ } ++ ++ *keys = keys_array; ++ keys_array = NULL; ++ *devices = devices_array; ++ devices_array = NULL; + return 0; + } +diff --git a/src/daemon/modules/device/cdi/cdi_registry.c b/src/daemon/modules/device/cdi/cdi_registry.c +index 68767a5f..be381132 100644 +--- a/src/daemon/modules/device/cdi/cdi_registry.c ++++ b/src/daemon/modules/device/cdi/cdi_registry.c +@@ -14,12 +14,24 @@ + ******************************************************************************/ + #include "cdi_registry.h" + ++#include ++#include ++ ++static struct cdi_registry g_cdi_reg = { 0 }; ++ + int cdi_registry_init(string_array *spec_dirs) + { ++ // isulad will use default dirs when spec_dirs == NULL ++ g_cdi_reg.cdi_cache = cdi_new_cache(spec_dirs); ++ if (g_cdi_reg.cdi_cache == NULL) { ++ ERROR("Failed to init registry"); ++ return -1; ++ } ++ g_cdi_reg.ops = cdi_get_cache_ops(); + return 0; + } + + struct cdi_registry *cdi_get_registry(void) + { +- return NULL; ++ return &g_cdi_reg; + } +diff --git a/src/daemon/modules/device/cdi_operate.c b/src/daemon/modules/device/cdi_operate.c +index c5187ab1..f99bb7e4 100644 +--- a/src/daemon/modules/device/cdi_operate.c ++++ b/src/daemon/modules/device/cdi_operate.c +@@ -14,23 +14,66 @@ + ******************************************************************************/ + #include "cdi_operate_api.h" + ++#include ++ ++#include "utils.h" ++#include "error.h" ++#include "cdi_registry.h" ++#include "cdi_annotations.h" ++#include "cdi_spec_dirs.h" ++ + int cdi_operate_registry_init(char **specs_dirs, size_t specs_dirs_len) + { +- return 0; ++ string_array spec_dirs_array = { ++ .items = specs_dirs, ++ .len = specs_dirs_len, ++ .cap = specs_dirs_len, ++ }; ++ ++ return cdi_registry_init(&spec_dirs_array); + } + + int cdi_operate_refresh(void) + { +- return 0; ++ struct cdi_registry *registry = cdi_get_registry(); ++ if (registry == NULL || registry->ops == NULL || registry->ops->refresh == NULL) { ++ ERROR("Failed to get registry"); ++ return -1; ++ } ++ ++ return registry->ops->refresh(registry->cdi_cache); + } + + int cdi_operate_inject_devices(oci_runtime_spec *spec, string_array *devices) + { +- return 0; ++ struct cdi_registry *registry = NULL; ++ ++ if (spec == NULL || devices == NULL) { ++ ERROR("Invalid params"); ++ return -1; ++ } ++ ++ registry = cdi_get_registry(); ++ if (registry == NULL || registry->ops == NULL || registry->ops->inject_devices == NULL) { ++ ERROR("Failed to get registry"); ++ return -1; ++ } ++ ++ return registry->ops->inject_devices(registry->cdi_cache, spec, devices); + } + + int cdi_operate_parse_annotations(json_map_string_string *annotations, string_array **keys, + string_array **devices, char **error) + { +- return 0; +-} +\ No newline at end of file ++ if (error == NULL) { ++ ERROR("Invalid argument"); ++ return -1; ++ } ++ if (annotations == NULL || keys == NULL || devices == NULL) { ++ ERROR("Invalid params"); ++ *error = util_strdup_s("Invalid params"); ++ return -1; ++ } ++ ++ return cdi_parse_annotations(annotations, keys, devices, error); ++} +diff --git a/src/utils/cutils/utils.c b/src/utils/cutils/utils.c +index 8da2cc60..9a33f935 100644 +--- a/src/utils/cutils/utils.c ++++ b/src/utils/cutils/utils.c +@@ -59,6 +59,17 @@ int malloc_trim(size_t pad) + } + #endif + ++void util_swap_ptr(void **p1, void **p2) ++{ ++ void *tmp; ++ if (p1 == NULL || p2 == NULL) { ++ return; ++ } ++ tmp = *p1; ++ *p1 = *p2; ++ *p2 = tmp; ++} ++ + int util_mem_realloc(void **newptr, size_t newsize, void *oldptr, size_t oldsize) + { + void *tmp = NULL; +diff --git a/src/utils/cutils/utils.h b/src/utils/cutils/utils.h +index 3acf0698..3671272a 100644 +--- a/src/utils/cutils/utils.h ++++ b/src/utils/cutils/utils.h +@@ -320,6 +320,8 @@ struct signame { + } \ + } while (0) + ++void util_swap_ptr(void **p1, void **p2); ++ + int util_mem_realloc(void **newptr, size_t newsize, void *oldptr, size_t oldsize); + + int util_check_inherited(bool closeall, int fd_to_ignore); +diff --git a/src/utils/cutils/utils_array.c b/src/utils/cutils/utils_array.c +index 25f19b8b..72294005 100644 +--- a/src/utils/cutils/utils_array.c ++++ b/src/utils/cutils/utils_array.c +@@ -86,6 +86,27 @@ void util_free_sensitive_array(char **array) + free(array); + } + ++char **util_copy_array_by_len(char **array, size_t len) ++{ ++ char **new_array = NULL; ++ size_t i; ++ ++ if (array == NULL || len == 0) { ++ return NULL; ++ } ++ ++ new_array = util_smart_calloc_s(sizeof(char *), len); ++ if (new_array == NULL) { ++ ERROR("Out of memory"); ++ return NULL; ++ } ++ ++ for (i = 0; i < len; i++) { ++ new_array[i] = util_strdup_s(array[i]); ++ } ++ return new_array; ++} ++ + int util_array_append(char ***array, const char *element) + { + size_t len; +@@ -166,7 +187,7 @@ bool util_array_contain(const char **array, const char *element) + return false; + } + +-static size_t get_string_array_scale_size(size_t old_size) ++static size_t get_array_scale_size(size_t old_size) + { + #define DOUBLE_THRESHOLD 1024 + const size_t max_threshold = MAX_MEMORY_SIZE / sizeof(char *); +@@ -188,7 +209,7 @@ static size_t get_string_array_scale_size(size_t old_size) + + static bool do_expand_array(string_array *array) + { +- size_t new_size = get_string_array_scale_size(array->cap); ++ size_t new_size = get_array_scale_size(array->cap); + char **new_items = NULL; + + // array capability sure less than MAX_MEMORY_SIZE +@@ -237,6 +258,29 @@ out: + return 0; + } + ++string_array *util_copy_string_array(string_array *sarr) ++{ ++ string_array *ptr = NULL; ++ size_t i; ++ ++ if (sarr == NULL) { ++ ERROR("Invalid string array"); ++ return NULL; ++ } ++ ++ ptr = util_string_array_new(sarr->cap); ++ if (ptr == NULL) { ++ ERROR("Out of memory"); ++ return NULL; ++ } ++ for (i = 0; i < sarr->len; i++) { ++ ptr->items[i] = util_strdup_s(sarr->items[i]); ++ ptr->len += 1; ++ } ++ ++ return ptr; ++} ++ + bool util_string_array_contain(const string_array *sarr, const char *elem) + { + size_t i; +@@ -339,3 +383,130 @@ int util_common_array_append_pointer(void ***array, void *element) + + return 0; + } ++ ++void *util_clone_ptr(void *item) ++{ ++ return item; ++} ++ ++common_array *util_common_array_new(size_t len, free_common_array_item_cb free_item_cb, ++ clone_common_array_item_cb clone_item_cb) ++{ ++ common_array *ptr = NULL; ++ ++ if (len == 0 || free_item_cb == NULL || clone_item_cb == NULL) { ++ return NULL; ++ } ++ ++ ptr = (common_array *)util_common_calloc_s(sizeof(common_array)); ++ if (ptr == NULL) { ++ ERROR("Out of memory"); ++ return NULL; ++ } ++ ++ ptr->items = (void **)util_smart_calloc_s(sizeof(void *), len); ++ if (ptr->items == NULL) { ++ ERROR("Out of memory"); ++ free(ptr); ++ return NULL; ++ } ++ ++ ptr->len = 0; ++ ptr->cap = len; ++ ptr->free_item_cb = free_item_cb; ++ ptr->clone_item_cb = clone_item_cb; ++ ++ return ptr; ++} ++ ++void util_free_common_array(common_array *ptr) ++{ ++ size_t i; ++ ++ if (ptr == NULL || ptr->free_item_cb == NULL) { ++ return; ++ } ++ ++ for (i = 0; i < ptr->len; i++) { ++ ptr->free_item_cb(ptr->items[i]); ++ ptr->items[i] = NULL; ++ } ++ free(ptr->items); ++ ptr->items = NULL; ++ ptr->len = 0; ++ ptr->cap = 0; ++ ptr->free_item_cb = NULL; ++ ptr->clone_item_cb = NULL; ++ ++ free(ptr); ++} ++ ++static bool do_expand_common_array(common_array *array) ++{ ++ size_t new_size = get_array_scale_size(array->cap); ++ void **new_items = NULL; ++ ++ // array capability sure less than MAX_MEMORY_SIZE ++ // so we need to check Overflow: ++ if (new_size == array->cap) { ++ ERROR("Too large common array, overflow memory"); ++ return false; ++ } ++ ++ // new_size * sizeof(*new_items) and list->len * sizeof(*list->items) ++ if (util_mem_realloc((void **)&new_items, new_size * sizeof(void *), (void *)array->items, ++ array->len * sizeof(void *)) != 0) { ++ ERROR("Out of memory"); ++ return false; ++ } ++ array->items = new_items; ++ array->cap = new_size; ++ ++ return true; ++} ++ ++int util_append_common_array(common_array *arr, void *val) ++{ ++ if (arr == NULL || arr->clone_item_cb == NULL) { ++ ERROR("Invalid common array"); ++ return -1; ++ } ++ ++ if (val == NULL) { ++ DEBUG("Empty new item, just ignore it"); ++ return 0; ++ } ++ ++ if (arr->len < arr->cap) { ++ goto out; ++ } ++ ++ // expand common array ++ if (!do_expand_common_array(arr)) { ++ return -1; ++ } ++ ++out: ++ arr->items[arr->len] = arr->clone_item_cb(val); ++ arr->len += 1; ++ return 0; ++} ++ ++int util_merge_common_array(common_array *dest_arr, common_array *src_arr) ++{ ++ size_t i; ++ ++ if (dest_arr == NULL || dest_arr->clone_item_cb == NULL || ++ src_arr == NULL || src_arr->clone_item_cb == NULL) { ++ ERROR("Invalid common array"); ++ return -1; ++ } ++ ++ for (i = 0; i < src_arr->len; i++) { ++ if (util_append_common_array(dest_arr, src_arr->items[i]) != 0) { ++ ERROR("Failed to append element"); ++ return -1; ++ } ++ } ++ return 0; ++} +diff --git a/src/utils/cutils/utils_array.h b/src/utils/cutils/utils_array.h +index 1c084595..0c4fd217 100644 +--- a/src/utils/cutils/utils_array.h ++++ b/src/utils/cutils/utils_array.h +@@ -30,6 +30,8 @@ void util_free_array_by_len(char **array, size_t len); + + void util_free_array(char **array); + ++char **util_copy_array_by_len(char **array, size_t len); ++ + int util_grow_array(char ***orig_array, size_t *orig_capacity, size_t size, + size_t increment); + +@@ -52,6 +54,8 @@ void util_free_string_array(string_array *ptr); + + int util_append_string_array(string_array *sarr, const char *val); + ++string_array *util_copy_string_array(string_array *sarr); ++ + bool util_string_array_contain(const string_array *sarr, const char *elem); + + void util_free_sensitive_array(char **array); +@@ -63,6 +67,33 @@ define_auto_cleanup_callback(util_free_array, char *); + // define auto free macro for char * + #define __isula_auto_array_t auto_cleanup_tag(util_free_array) + ++define_auto_cleanup_callback(util_free_string_array, string_array); ++#define __isula_auto_string_array_t auto_cleanup_tag(util_free_string_array) ++ ++typedef void (*free_common_array_item_cb)(void *item); ++typedef void *(*clone_common_array_item_cb)(void *item); ++typedef struct common_array_t { ++ void **items; ++ size_t len; ++ size_t cap; ++ free_common_array_item_cb free_item_cb; ++ clone_common_array_item_cb clone_item_cb; ++} common_array; ++ ++void *util_clone_ptr(void *item); ++ ++common_array *util_common_array_new(size_t len, free_common_array_item_cb free_item_cb, ++ clone_common_array_item_cb clone_item_cb); ++ ++void util_free_common_array(common_array *ptr); ++ ++int util_append_common_array(common_array *arr, void *val); ++ ++int util_merge_common_array(common_array *dest_arr, common_array *src_arr); ++ ++define_auto_cleanup_callback(util_free_common_array, common_array); ++#define __isula_auto_common_array_t auto_cleanup_tag(util_free_common_array) ++ + #ifdef __cplusplus + } + #endif +-- +2.34.1 + diff --git a/0062-do-not-umount-shmpath-for-sandbox-container.patch b/0062-do-not-umount-shmpath-for-sandbox-container.patch new file mode 100644 index 0000000..8b719a3 --- /dev/null +++ b/0062-do-not-umount-shmpath-for-sandbox-container.patch @@ -0,0 +1,30 @@ +From 8e35525073b52b5d161984015de641bd21570380 Mon Sep 17 00:00:00 2001 +From: jikai +Date: Tue, 16 Apr 2024 10:32:50 +0000 +Subject: [PATCH 62/69] do not umount shmpath for sandbox container + +Signed-off-by: jikai +--- + src/daemon/modules/service/service_container.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/daemon/modules/service/service_container.c b/src/daemon/modules/service/service_container.c +index eb7ce4f4..a2322309 100644 +--- a/src/daemon/modules/service/service_container.c ++++ b/src/daemon/modules/service/service_container.c +@@ -1718,6 +1718,12 @@ void umount_share_shm(container_t *cont) + return; + } + if (cont->hostconfig->ipc_mode == NULL || namespace_is_shareable(cont->hostconfig->ipc_mode)) { ++#ifdef ENABLE_CRI_API_V1 ++ // For sandbox in cri v1, the shm path is created and umounted in CRI ++ if (is_sandbox_container(cont->common_config->sandbox_info)) { ++ return; ++ } ++#endif + if (cont->common_config == NULL || cont->common_config->shm_path == NULL) { + return; + } +-- +2.34.1 + diff --git a/0063-remove-default-systemd-cgroup-and-enable-cri-v1-valu.patch b/0063-remove-default-systemd-cgroup-and-enable-cri-v1-valu.patch new file mode 100644 index 0000000..b6a0e6b --- /dev/null +++ b/0063-remove-default-systemd-cgroup-and-enable-cri-v1-valu.patch @@ -0,0 +1,27 @@ +From c092597565e5f24b29ecd83b4b371a19a9c2db0d Mon Sep 17 00:00:00 2001 +From: jikai +Date: Wed, 17 Apr 2024 01:52:45 +0000 +Subject: [PATCH 63/69] remove default systemd-cgroup and enable-cri-v1 value + in daemon.json + +Signed-off-by: jikai +--- + src/contrib/config/daemon.json | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/src/contrib/config/daemon.json b/src/contrib/config/daemon.json +index 69362c26..711dda94 100644 +--- a/src/contrib/config/daemon.json ++++ b/src/contrib/config/daemon.json +@@ -35,7 +35,5 @@ + "insecure-skip-verify-enforce": false, + "cri-runtimes": { + "kata": "io.containerd.kata.v2" +- }, +- "enable-cri-v1": false, +- "systemd-cgroup": false ++ } + } +-- +2.34.1 + diff --git a/0064-cdi-support-module-cache.patch b/0064-cdi-support-module-cache.patch new file mode 100644 index 0000000..4ed9fb5 --- /dev/null +++ b/0064-cdi-support-module-cache.patch @@ -0,0 +1,862 @@ +From f87f0fddaec4b3aea72f3b9c91f2dc91b89683ce Mon Sep 17 00:00:00 2001 +From: liuxu +Date: Tue, 16 Apr 2024 11:44:22 +0800 +Subject: [PATCH 64/69] cdi:support module cache + +--- + .../device/cdi/behavior/cdi_spec_dirs.h | 3 +- + src/daemon/modules/device/cdi/cdi_cache.c | 760 +++++++++++++++++- + src/daemon/modules/device/cdi/cdi_cache.h | 9 +- + 3 files changed, 747 insertions(+), 25 deletions(-) + +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_spec_dirs.h b/src/daemon/modules/device/cdi/behavior/cdi_spec_dirs.h +index 73d8c0f5..eedcabad 100644 +--- a/src/daemon/modules/device/cdi/behavior/cdi_spec_dirs.h ++++ b/src/daemon/modules/device/cdi/behavior/cdi_spec_dirs.h +@@ -32,8 +32,7 @@ struct cdi_scan_fn_maps { + map_t *specs; + map_t *devices; + map_t *conflicts; +- map_t *spec_errors; +- string_array *result; ++ bool *refresh_error_flag; + }; + typedef void(*cdi_scan_spec_func)(struct cdi_scan_fn_maps *scan_fn_maps, const char *path, int priority, + struct cdi_cache_spec *spec, char *error); +diff --git a/src/daemon/modules/device/cdi/cdi_cache.c b/src/daemon/modules/device/cdi/cdi_cache.c +index cfc23a1c..37767855 100644 +--- a/src/daemon/modules/device/cdi/cdi_cache.c ++++ b/src/daemon/modules/device/cdi/cdi_cache.c +@@ -14,56 +14,784 @@ + ******************************************************************************/ + #include "cdi_cache.h" + ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "utils.h" ++#include "utils_file.h" ++#include "path.h" ++#include "error.h" ++#include "cdi_device.h" ++#include "cdi_spec.h" ++#include "cdi_spec_dirs.h" ++#include "cdi_container_edits.h" ++ ++// cache ++static int cdi_set_spec_dirs(struct cdi_cache *c, string_array *spec_dirs); ++static int configure(struct cdi_cache *c, string_array *spec_dirs); ++static int refresh(struct cdi_cache *c); ++static bool refresh_if_required(struct cdi_cache *c, bool force, int *ret); ++ ++// watch ++static void free_cdi_watch(struct cdi_watch *watch); ++static void watch_setup(struct cdi_watch *watch, string_array *dirs); ++static void watch_start(struct cdi_cache *c); ++static void watch_stop(struct cdi_watch *w); ++static void *watch_thread_func(void *arg); ++static bool watch_update(struct cdi_watch *w, const char *removed, int wd); ++ ++static int cdi_set_spec_dirs(struct cdi_cache *c, string_array *spec_dirs) ++{ ++ __isula_auto_string_array_t string_array *new_spec_dirs = NULL; ++ char clean_path[PATH_MAX] = { 0 }; ++ size_t i; ++ ++ if (c == NULL || spec_dirs == NULL) { ++ ERROR("Invalid argument"); ++ return -1; ++ } ++ if (spec_dirs->len == 0) { ++ return 0; ++ } ++ ++ new_spec_dirs = util_string_array_new(spec_dirs->len); ++ if (new_spec_dirs == NULL) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ for (i = 0; i < spec_dirs->len; i++) { ++ if (util_clean_path(spec_dirs->items[i], clean_path, sizeof(clean_path)) == NULL) { ++ ERROR("Failed to get clean path %s", spec_dirs->items[i]); ++ return -1; ++ } ++ if (util_append_string_array(new_spec_dirs, clean_path) != 0) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ } ++ util_free_string_array(c->spec_dirs); ++ c->spec_dirs = new_spec_dirs; ++ new_spec_dirs = NULL; ++ ++ return 0; ++} ++ + void free_cdi_cache(struct cdi_cache *c) + { +- (void)c; ++ if (c == NULL) { ++ return; ++ } ++ ++ util_free_string_array(c->spec_dirs); ++ c->spec_dirs = NULL; ++ map_free(c->specs); ++ c->specs = NULL; ++ map_free(c->devices); ++ c->devices = NULL; ++ free_cdi_watch(c->watch); ++ c->watch = NULL; ++ ++ free(c); + } + + struct cdi_cache *cdi_new_cache(string_array *spec_dirs) + { ++ struct cdi_cache *c = NULL; ++ int ret = 0; ++ ++ c = util_common_calloc_s(sizeof(*c)); ++ if (c == NULL) { ++ ERROR("Out of memory"); ++ return NULL; ++ } ++ c->refresh_error_flag = false; ++ c->auto_refresh = true; ++ c->watch = util_common_calloc_s(sizeof(struct cdi_watch)); ++ if (c->watch == NULL) { ++ ERROR("Out of memory"); ++ goto free_out; ++ } ++ c->watch->watcher_fd = -1; ++ ++ if (cdi_set_spec_dirs(c, &g_default_spec_dirs) != 0) { ++ ERROR("Failed to set spec dirs by default"); ++ goto free_out; ++ } ++ ++ (void)pthread_mutex_lock(&c->mutex); ++ ret = configure(c, spec_dirs); ++ (void)pthread_mutex_unlock(&c->mutex); ++ if (ret != 0) { ++ ERROR("Failed to configure"); ++ goto free_out; ++ } ++ ++ return c; ++ ++free_out: ++ free_cdi_cache(c); + return NULL; + } + +-static int cdi_inject_devices(struct cdi_cache *c, oci_runtime_spec *oci_spec, string_array *devices) ++static int cdi_configure(struct cdi_cache *c, string_array *spec_dirs) + { +- return 0; ++ int ret = 0; ++ ++ if (c == NULL) { ++ ERROR("Invalid arguments"); ++ return -1; ++ } ++ ++ (void)pthread_mutex_lock(&c->mutex); ++ ret = configure(c, spec_dirs); ++ (void)pthread_mutex_unlock(&c->mutex); ++ ++ return ret; + } + +-static int cdi_configure(struct cdi_cache *c, string_array *spec_dirs) ++static int configure(struct cdi_cache *c, string_array *spec_dirs) + { ++ int ret = 0; ++ ++ if (spec_dirs != NULL) { ++ ret = cdi_set_spec_dirs(c, spec_dirs); ++ if (ret != 0) { ++ ERROR("Failed to apply cache spec dirs"); ++ return -1; ++ } ++ } ++ ++ watch_stop(c->watch); ++ if (c->auto_refresh) { ++ watch_setup(c->watch, c->spec_dirs); ++ watch_start(c); ++ } ++ (void)refresh(c); + return 0; + } + + static int cdi_refresh(struct cdi_cache *c) + { +- return 0; ++ bool refreshed; ++ int ret = 0; ++ ++ if (c == NULL) { ++ ERROR("Invalid arguments"); ++ return -1; ++ } ++ ++ (void)pthread_mutex_lock(&c->mutex); ++ refreshed = refresh_if_required(c, !c->auto_refresh, &ret); ++ if (refreshed) { ++ goto unlock_out; ++ } ++ ++ ret = c->refresh_error_flag ? -1 : 0; ++unlock_out: ++ (void)pthread_mutex_unlock(&c->mutex); ++ return ret; + } + +-static map_t *cdi_get_errors(struct cdi_cache *c) ++static void map_cdi_cache_specs_kvfree(void *key, void *value) + { +- return NULL; ++ free(key); ++ util_free_common_array((common_array *)value); + } + +-static string_array *cdi_get_spec_directories(struct cdi_cache *c) ++static void map_cdi_cache_device_kvfree(void *key, void *value) + { +- return NULL; ++ free(key); ++ free_cdi_cache_device((struct cdi_cache_device *)value); + } + +-static map_t *cdi_get_spec_dir_errors(struct cdi_cache *c) ++static void set_refresh_error_flag(bool *refresh_error_flag, const char *error, const char *path) + { +- return NULL; ++ *refresh_error_flag = true; ++ ERROR("Cdi refresh error: %s, spec %s", error, path); ++} ++ ++static bool resolve_conflict(struct cdi_scan_fn_maps *scan_fn_maps, const char *name, ++ struct cdi_cache_device *dev, struct cdi_cache_device *old) ++{ ++ map_t *conflicts = scan_fn_maps->conflicts; ++ bool *refresh_error_flag = scan_fn_maps->refresh_error_flag; ++ struct cdi_cache_spec *dev_spec = NULL; ++ struct cdi_cache_spec *old_spec = NULL; ++ int dev_prio; ++ int old_prio; ++ bool val = true; ++ const char *dev_path = NULL; ++ const char *old_path = NULL; ++ ++ dev_spec = cdi_device_get_spec(dev); ++ old_spec = cdi_device_get_spec(old); ++ dev_prio = cdi_spec_get_priority(dev_spec); ++ old_prio = cdi_spec_get_priority(old_spec); ++ if (dev_prio > old_prio) { ++ return false; ++ } else if (dev_prio == old_prio) { ++ dev_path = cdi_spec_get_path(dev_spec); ++ old_path = cdi_spec_get_path(old_spec); ++ *refresh_error_flag = true; ++ ERROR("Conflicting device %s (specs %s, %s)", name, dev_path, old_path); ++ if (!map_replace(conflicts, (void *)name, (void *)&val)) { ++ ERROR("Failed to insert bool to conflicts by name %s", name); ++ return true; ++ } ++ } else { ++ // do nothing ++ } ++ ++ return true; ++} ++ ++static void refresh_scan_spec_func(struct cdi_scan_fn_maps *scan_fn_maps, const char *path, ++ int priority, struct cdi_cache_spec *spec, char *error) ++{ ++ map_t *specs = scan_fn_maps->specs; ++ map_t *devices = scan_fn_maps->devices; ++ bool *refresh_error_flag = scan_fn_maps->refresh_error_flag; ++ char clean_path[PATH_MAX] = { 0 }; ++ __isula_auto_free char *tmp_error = NULL; ++ const char *vendor = NULL; ++ __isula_auto_common_array_t common_array *spec_array = NULL; ++ map_itor *itor = NULL; ++ __isula_auto_free char *qualified = NULL; ++ struct cdi_cache_device *dev = NULL; ++ struct cdi_cache_device *other = NULL; ++ ++ if (util_clean_path(path, clean_path, sizeof(clean_path)) == NULL) { ++ ERROR("Failed to get clean path %s", path); ++ format_errorf(&tmp_error, "Failed to get clean path %s", path); ++ return; ++ } ++ if (error != NULL) { ++ ERROR("Failed to load CDI Spec %s", error); ++ format_errorf(&tmp_error, "Failed to load CDI Spec %s", error); ++ goto error_out; ++ } ++ ++ vendor = cdi_spec_get_vendor(spec); ++ spec_array = map_search(specs, (void *)vendor); ++ if (spec_array == NULL) { ++ spec_array = util_common_array_new(1, (free_common_array_item_cb)free_cdi_cache_spec, util_clone_ptr); ++ if (spec_array == NULL) { ++ ERROR("Out of memory"); ++ tmp_error = util_strdup_s("Out of memory"); ++ goto error_out; ++ } ++ if (!map_insert(specs, (void *)vendor, spec_array)) { ++ ERROR("Failed to insert spec array to specs"); ++ tmp_error = util_strdup_s("Failed to insert spec array to specs"); ++ goto error_out; ++ } ++ } ++ if (util_append_common_array(spec_array, spec) != 0) { ++ ERROR("Failed to append spec"); ++ tmp_error = util_strdup_s("Failed to append spec"); ++ goto error_out; ++ } ++ spec_array = NULL; ++ ++ itor = map_itor_new(spec->devices); ++ if (itor == NULL) { ++ ERROR("Out of memory, create new map itor failed"); ++ tmp_error = util_strdup_s("Out of memory, create new map itor failed"); ++ goto error_out; ++ } ++ for (; map_itor_valid(itor); map_itor_next(itor)) { ++ dev = map_itor_value(itor); ++ qualified = cdi_device_get_qualified_name(dev); ++ other = map_search(devices, (void *)qualified); ++ if (other != NULL) { ++ if (resolve_conflict(scan_fn_maps, qualified, dev, other)) { ++ continue; ++ } ++ } ++ if (!map_replace(devices, (void *)qualified, dev)) { ++ ERROR("Failed to insert device to devices by name %s", qualified); ++ format_errorf(&tmp_error, "Failed to insert device to devices by name %s", qualified); ++ goto error_out; ++ } ++ free(qualified); ++ qualified = NULL; ++ } ++ goto out; ++ ++error_out: ++ set_refresh_error_flag(refresh_error_flag, tmp_error, path); ++out: ++ map_itor_free(itor); ++ return; ++} ++ ++static int refresh(struct cdi_cache *c) ++{ ++ int ret = 0; ++ __isula_auto_free char *error = NULL; ++ map_t *specs = NULL; ++ map_t *devices = NULL; ++ map_t *conflicts = NULL; ++ struct cdi_scan_fn_maps scan_fn_maps = { 0 }; ++ map_itor *itor = NULL; ++ char *conflict = NULL; ++ ++ c->refresh_error_flag = false; ++ specs = map_new(MAP_STR_PTR, MAP_DEFAULT_CMP_FUNC, map_cdi_cache_specs_kvfree); ++ if (specs == NULL) { ++ ERROR("Out of memory"); ++ ret = -1; ++ goto free_out; ++ } ++ devices = map_new(MAP_STR_PTR, MAP_DEFAULT_CMP_FUNC, map_cdi_cache_device_kvfree); ++ if (devices == NULL) { ++ ERROR("Out of memory"); ++ ret = -1; ++ goto free_out; ++ } ++ conflicts = map_new(MAP_STR_BOOL, MAP_DEFAULT_CMP_FUNC, MAP_DEFAULT_FREE_FUNC); ++ if (conflicts == NULL) { ++ ERROR("Out of memory"); ++ ret = -1; ++ goto free_out; ++ } ++ ++ scan_fn_maps.specs = specs; ++ scan_fn_maps.devices = devices; ++ scan_fn_maps.conflicts = conflicts; ++ scan_fn_maps.refresh_error_flag = &c->refresh_error_flag; ++ // ignore error when scan spec dirs ++ (void)cdi_scan_spec_dirs(c->spec_dirs, &scan_fn_maps, refresh_scan_spec_func); ++ ++ itor = map_itor_new(conflicts); ++ if (itor == NULL) { ++ ERROR("Out of memory, create new map itor failed"); ++ ret = -1; ++ goto free_out; ++ } ++ for (; map_itor_valid(itor); map_itor_next(itor)) { ++ conflict = map_itor_key(itor); ++ if ((map_search(devices, conflict) != NULL) && ++ !map_remove(devices, conflict)) { ++ ERROR("Failed to remove conflict device from devices"); ++ ret = -1; ++ goto free_out; ++ } ++ } ++ ++ util_swap_ptr((void **)&c->specs, (void **)&specs); ++ util_swap_ptr((void **)&c->devices, (void **)&devices); ++ ++ ret = c->refresh_error_flag ? -1 : 0; ++ ++free_out: ++ map_itor_free(itor); ++ map_free(specs); ++ map_free(devices); ++ map_free(conflicts); ++ return ret; ++} ++ ++static bool refresh_if_required(struct cdi_cache *c, bool force, int *ret) ++{ ++ if (force || (c->auto_refresh && watch_update(c->watch, NULL, -1))) { ++ *ret = refresh(c); ++ return true; ++ } ++ return false; ++} ++ ++static void map_spec_ptr_kvfree(void *key, void *value) ++{ ++ // do not need free spec* ++ (void)key; ++ free(value); ++} ++ ++static int cdi_inject_devices(struct cdi_cache *c, oci_runtime_spec *oci_spec, string_array *devices) ++{ ++ int ret = 0; ++ __isula_auto_string_array_t string_array *unresolved = NULL; ++ cdi_container_edits *edits = NULL; ++ map_t *specs = NULL; ++ size_t i; ++ const char *device = NULL; ++ struct cdi_cache_device *d = NULL; ++ int tmp_val = 0; ++ __isula_auto_free char *unresolved_str = NULL; ++ ++ if (c == NULL || devices == NULL) { ++ ERROR("Can't inject devices"); ++ return -1; ++ } ++ if (oci_spec == NULL) { ++ ERROR("Can't inject devices, nil OCI Spec"); ++ return -1; ++ } ++ ++ unresolved = util_common_calloc_s(sizeof(*unresolved)); ++ if (unresolved == NULL) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ specs = map_new(MAP_PTR_INT, MAP_DEFAULT_CMP_FUNC, map_spec_ptr_kvfree); ++ if (specs == NULL) { ++ ERROR("Out of memory"); ++ ret = -1; ++ goto out; ++ } ++ edits = util_common_calloc_s(sizeof(*edits)); ++ if (edits == NULL) { ++ ERROR("Out of memory"); ++ ret = -1; ++ goto out; ++ } ++ ++ (void)pthread_mutex_lock(&c->mutex); ++ ++ (void)refresh_if_required(c, false, &ret); ++ ++ for(i = 0; i < devices->len; i++) { ++ device = devices->items[i]; ++ d = map_search(c->devices, (void *)device); ++ if (d == NULL) { ++ if (util_append_string_array(unresolved, device) != 0) { ++ ERROR("Out of memory"); ++ ret = -1; ++ goto out; ++ } ++ continue; ++ } ++ if (map_search(specs, (void *)cdi_device_get_spec(d)) == NULL) { ++ if (!map_insert(specs, (void *)cdi_device_get_spec(d), (void *)&tmp_val)) { ++ ERROR("Failed to insert spec ptr to specs when find device %s", device); ++ ret = -1; ++ goto out; ++ } ++ if (cdi_container_edits_append(edits, cdi_spec_get_edits(cdi_device_get_spec(d))) != 0) { ++ ERROR("Failed to append edits when find device %s", device); ++ ret = -1; ++ goto out; ++ } ++ } ++ if (cdi_container_edits_append(edits, cdi_device_get_edits(d)) != 0) { ++ ERROR("Failed to append edits when find device %s", device); ++ ret = -1; ++ goto out; ++ } ++ } ++ ++ if (unresolved->len != 0) { ++ unresolved_str = util_string_join(", ", (const char **)unresolved->items, unresolved->len); ++ ERROR("Unresolvable CDI devices %s", unresolved_str); ++ ret = -1; ++ goto out; ++ } ++ ++ ret = cdi_container_edits_apply(edits, oci_spec); ++ if (ret != 0) { ++ ERROR("Failed to apply edits when inject devices"); ++ ret = -1; ++ } ++ ++out: ++ (void)pthread_mutex_unlock(&c->mutex); ++ map_free(specs); ++ free_cdi_container_edits(edits); ++ return ret; + } + + static struct cdi_cache_ops g_cdi_cache_ops = { + .inject_devices = cdi_inject_devices, + .configure = cdi_configure, +- .refresh = cdi_refresh, +- .get_errors = cdi_get_errors, +- .get_spec_directories = cdi_get_spec_directories, +- .get_spec_dir_errors = cdi_get_spec_dir_errors ++ .refresh = cdi_refresh + }; + + struct cdi_cache_ops *cdi_get_cache_ops(void) + { + return &g_cdi_cache_ops; +-} +\ No newline at end of file ++} ++ ++static void free_cdi_watch(struct cdi_watch *w) ++{ ++ if (w == NULL) { ++ return; ++ } ++ ++ watch_stop(w); ++ free(w); ++} ++ ++static int init_tracked(struct cdi_watch *w, string_array *dirs) ++{ ++ size_t i; ++ bool tmp_value = false; ++ ++ w->tracked = map_new(MAP_STR_BOOL, MAP_DEFAULT_CMP_FUNC, MAP_DEFAULT_FREE_FUNC); ++ if (w->tracked == NULL) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ for(i = 0; i < dirs->len; i++) { ++ if (!map_replace(w->tracked, (void *)dirs->items[i], (void *)&tmp_value)) { ++ ERROR("Failed to insert tracked by dir %s", dirs->items[i]); ++ goto error_out; ++ } ++ } ++ w->wd_dirs = map_new(MAP_INT_STR, MAP_DEFAULT_CMP_FUNC, MAP_DEFAULT_FREE_FUNC); ++ if (w->wd_dirs == NULL) { ++ ERROR("Out of memory"); ++ goto error_out; ++ } ++ ++ return 0; ++ ++error_out: ++ map_free(w->tracked); ++ w->tracked = NULL; ++ return -1; ++} ++ ++static void watch_setup(struct cdi_watch *w, string_array *dirs) ++{ ++ __isula_auto_free char *error = NULL; ++ ++ if (w == NULL || dirs == NULL || dirs->len == 0) { ++ ERROR("Invalid param"); ++ return; ++ } ++ ++ if (init_tracked(w, dirs) != 0) { ++ ERROR("Failed to initialize tracked"); ++ return; ++ } ++ ++ w->watcher_fd = inotify_init(); ++ if (w->watcher_fd < 0) { ++ ERROR("Failed to initialize inotify fd"); ++ map_free(w->tracked); ++ w->tracked = NULL; ++ map_free(w->wd_dirs); ++ w->wd_dirs = NULL; ++ return; ++ } ++ ++ (void)watch_update(w, NULL, -1); ++} ++ ++static void watch_start(struct cdi_cache *c) ++{ ++ pthread_t thread = 0; ++ int ret = 0; ++ ++ ret = pthread_create(&thread, NULL, watch_thread_func, c); ++ if (ret != 0) { ++ ERROR("Cdi watch thread create failed"); ++ return; ++ } ++} ++ ++static void watch_stop(struct cdi_watch *w) ++{ ++ if (w == NULL) { ++ return; ++ } ++ ++ if (w->watcher_fd >= 0) { ++ close(w->watcher_fd); ++ w->watcher_fd = -1; ++ } ++ map_free(w->tracked); ++ w->tracked = NULL; ++ map_free(w->wd_dirs); ++ w->wd_dirs = NULL; ++} ++ ++// wait_events wait until inotify ++static int wait_events(int watcher_fd) ++{ ++ fd_set rfds; ++ FD_ZERO(&rfds); ++ FD_SET(watcher_fd, &rfds); ++ return select(FD_SETSIZE, &rfds, NULL, NULL, NULL); ++} ++ ++#define CDI_WATCH_EVENTS (IN_MOVED_TO | IN_MOVED_FROM | IN_DELETE | IN_MODIFY | IN_MOVE_SELF | IN_DELETE_SELF) ++ ++static int process_cdi_events(int watcher_fd, struct cdi_cache *c) ++{ ++ ssize_t events_length = 0; ++ ssize_t events_index = 0; ++ struct inotify_event *cdi_event = NULL; ++ char buffer[MAXLINE] __attribute__((aligned(__alignof__(struct inotify_event)))) = { 0 }; ++ int update_cnt = 0; ++ __isula_auto_free char *event_dir = NULL; ++ ++ events_length = util_read_nointr(watcher_fd, buffer, sizeof(buffer)); ++ if (events_length <= 0) { ++ ERROR("Failed to wait events"); ++ return -1; ++ } ++ ++ (void)pthread_mutex_lock(&c->mutex); ++ ++ while (events_index < events_length) { ++ cdi_event = (struct inotify_event *)(&buffer[events_index]); ++ ssize_t event_size = (ssize_t)(cdi_event->len) + (ssize_t)offsetof(struct inotify_event, name); ++ if (event_size == 0 || event_size > (events_length - events_index)) { ++ break; ++ } ++ events_index += event_size; ++ ++ /* ++ * file: ++ * Rename: mask == IN_MOVED_TO | IN_MOVED_FROM ++ * Remove: mask == IN_MOVED_FROM || mask == IN_DELETE ++ * Write: mask == IN_MODIFY ++ * dir: ++ * Remove: mask == IN_MOVE_SELF || mask == IN_DELETE_SELF ++ */ ++ if ((cdi_event->mask & CDI_WATCH_EVENTS) == 0) { ++ continue; ++ } ++ DEBUG("Cdi spec file %s is changed", cdi_event->name); ++ if (cdi_event->mask == IN_MODIFY) { ++ if (!util_has_suffix(cdi_event->name, ".json")) { ++ WARN("Invalid spec %s ext", cdi_event->name); ++ continue; ++ } ++ } ++ event_dir = util_strdup_s(map_search(c->watch->wd_dirs, &(cdi_event->wd))); ++ if (!(cdi_event->mask == IN_DELETE_SELF || cdi_event->mask == IN_MOVE_SELF)) { ++ free(event_dir); ++ event_dir = NULL; ++ } ++ watch_update(c->watch, event_dir, cdi_event->wd); ++ update_cnt++; ++ } ++ if (update_cnt > 0) { ++ (void)refresh(c); ++ } ++ ++ (void)pthread_mutex_unlock(&c->mutex); ++ return 0; ++} ++ ++// Watch Spec directory changes, triggering a refresh if necessary. ++static void *watch_thread_func(void *arg) ++{ ++ struct cdi_cache *c = (struct cdi_cache *)arg; ++ int errcode = 0; ++ int watcher_fd = -1; ++ ++ errcode = pthread_detach(pthread_self()); ++ if (errcode != 0) { ++ errno = errcode; ++ SYSERROR("Detach thread failed"); ++ return NULL; ++ } ++ ++ prctl(PR_SET_NAME, "cdi-watcher"); ++ ++ watcher_fd = c->watch->watcher_fd; ++ if (watcher_fd < 0) { ++ ERROR("Invalid inotify fd"); ++ return NULL; ++ } ++ ++ for (;;) { ++ if (wait_events(watcher_fd) < 0) { ++ ERROR("Failed to wait events"); ++ break; ++ } ++ if (process_cdi_events(watcher_fd, c) != 0) { ++ break; ++ } ++ } ++ return NULL; ++} ++ ++static void update_remove_watch_dir(struct cdi_watch *w, const char *dir, int wd) ++{ ++ bool tmp_value = false; ++ if (wd >= 0) { ++ (void)inotify_rm_watch(w->watcher_fd, wd); ++ if ((map_search(w->wd_dirs, &wd) != NULL) && ++ !map_remove(w->wd_dirs, &wd)) { ++ ERROR("Failed to remove watch fd of %s", dir); ++ } ++ } ++ if (!map_replace(w->tracked, (void *)dir, (void *)&tmp_value)) { ++ ERROR("Failed to insert tracked by dir %s", dir); ++ } ++} ++ ++static void update_add_watch_dir(struct cdi_watch *w, const char *dir, bool *update) ++{ ++ int wd = -1; ++ bool tmp_value = true; ++ __isula_auto_free char *error = NULL; ++ ++ wd = inotify_add_watch(w->watcher_fd, dir, CDI_WATCH_EVENTS); ++ if (wd < 0) { ++ if (errno == ENOENT) { ++ SYSINFO("Watch device dir %s", dir); ++ } else { ++ SYSERROR("Failed to watch device dir %s", dir); ++ } ++ return; ++ } else { ++ DEBUG("Watching %s for device disovery", dir); ++ tmp_value = true; ++ if (!map_replace(w->tracked, (void *)dir, (void *)&tmp_value)) { ++ ERROR("Failed to insert tracked by dir %s", dir); ++ goto error_out; ++ } ++ if (!map_replace(w->wd_dirs, (void *)&wd, (void *)dir)) { ++ ERROR("Failed to insert dir %s by wd", dir); ++ goto error_out; ++ } ++ *update = true; ++ } ++ return; ++ ++error_out: ++ update_remove_watch_dir(w, dir, wd); ++} ++ ++static bool watch_update(struct cdi_watch *w, const char *removed, int wd) ++{ ++ const char *dir = NULL; ++ bool *ok = NULL; ++ bool update = false; ++ map_itor *itor = NULL; ++ __isula_auto_free char *error = NULL; ++ ++ itor = map_itor_new(w->tracked); ++ if (itor == NULL) { ++ ERROR("Out of memory, create new map itor failed"); ++ return false; ++ } ++ for (; map_itor_valid(itor); map_itor_next(itor)) { ++ dir = map_itor_key(itor); ++ ok = map_itor_value(itor); ++ if (ok == NULL || *ok) { ++ continue; ++ } ++ update_add_watch_dir(w, dir, &update); ++ } ++ ++ if (removed != NULL) { ++ update_remove_watch_dir(w, removed, wd); ++ WARN("Directory removed: %s", removed); ++ update = true; ++ } ++ ++ map_itor_free(itor); ++ return update; ++} +diff --git a/src/daemon/modules/device/cdi/cdi_cache.h b/src/daemon/modules/device/cdi/cdi_cache.h +index 34c27471..da315de2 100644 +--- a/src/daemon/modules/device/cdi/cdi_cache.h ++++ b/src/daemon/modules/device/cdi/cdi_cache.h +@@ -39,9 +39,6 @@ struct cdi_cache_ops { + // Refresher + int (*configure)(struct cdi_cache *c, string_array *spec_dirs); + int (*refresh)(struct cdi_cache *c); +- map_t *(*get_errors)(struct cdi_cache *c); +- string_array *(*get_spec_directories)(struct cdi_cache *c); +- map_t *(*get_spec_dir_errors)(struct cdi_cache *c); + }; + + struct cdi_watch { +@@ -54,11 +51,9 @@ struct cdi_watch { + struct cdi_cache { + pthread_mutex_t mutex; + string_array *spec_dirs; // cdi-spec-dirs will scan for CDI Spec files +- map_t *specs; // MAP_STR_PTR specs[vendor] = cdi_cache_spec** ++ map_t *specs; // MAP_STR_PTR specs[vendor] = common_array of cdi_cache_spec* + map_t *devices; // MAP_STR_PTR devices[cdi_device.name] = cdi_cache_device* +- map_t *errors; // MAP_STR_PTR errors[cdi_cache_spec.path] = string_array *errors +- map_t *dir_errors; // MAP_STR_STR dir_errors[spec_dirs[i]] = error +- ++ bool refresh_error_flag; + bool auto_refresh; + struct cdi_watch *watch; + }; +-- +2.34.1 + diff --git a/0065-change-default-subscribe-timeout-to-5min.patch b/0065-change-default-subscribe-timeout-to-5min.patch new file mode 100644 index 0000000..7e4d067 --- /dev/null +++ b/0065-change-default-subscribe-timeout-to-5min.patch @@ -0,0 +1,76 @@ +From 5c89c23f5e0de06a17a9263114430674221a1ee0 Mon Sep 17 00:00:00 2001 +From: jikai +Date: Wed, 17 Apr 2024 06:59:08 +0000 +Subject: [PATCH 65/69] change default subscribe timeout to 5min + +Signed-off-by: jikai +--- + src/daemon/mailbox/message_queue.c | 4 ++-- + src/utils/cutils/blocking_queue.c | 13 +++++++------ + src/utils/cutils/blocking_queue.h | 2 +- + 3 files changed, 10 insertions(+), 9 deletions(-) + +diff --git a/src/daemon/mailbox/message_queue.c b/src/daemon/mailbox/message_queue.c +index 7e53301e..699ea0bc 100644 +--- a/src/daemon/mailbox/message_queue.c ++++ b/src/daemon/mailbox/message_queue.c +@@ -20,8 +20,8 @@ + + #include "utils.h" + +-// default set subscriber timeout to 1000ms, maybe could be configured later +-const int64_t subscribe_timeout = 1000; ++// default set subscriber timeout to 300s, maybe could be configured later ++const int64_t subscribe_timeout = 300; + + static void message_queue_subscriber_free(void *key, void *val) + { +diff --git a/src/utils/cutils/blocking_queue.c b/src/utils/cutils/blocking_queue.c +index 7c9c5f50..9bdb2ca3 100644 +--- a/src/utils/cutils/blocking_queue.c ++++ b/src/utils/cutils/blocking_queue.c +@@ -55,12 +55,11 @@ blocking_queue *blocking_queue_create(int64_t timeout, void (*release)(void *)) + queue->release = release; + + if (timeout >= 0) { +- queue->timeout.tv_sec = timeout / (Time_Second / Time_Milli); +- queue->timeout.tv_nsec = (timeout % (Time_Second / Time_Milli) ) * Time_Milli; ++ queue->timeout = timeout; + } else { +- queue->timeout.tv_sec = -1; ++ queue->timeout = -1; + } +- ++ + return isula_transfer_ptr(queue); + } + +@@ -112,8 +111,10 @@ int blocking_queue_pop(blocking_queue *queue, void **data) { + lock = &queue->lock; + + while (queue->head->next == NULL) { +- if (queue->timeout.tv_sec >= 0) { +- int ret = pthread_cond_timedwait(&queue->not_empty, &queue->lock, &queue->timeout); ++ if (queue->timeout >= 0) { ++ struct timespec timeout = { 0 }; ++ timeout.tv_sec = queue->timeout + time(NULL); ++ int ret = pthread_cond_timedwait(&queue->not_empty, &queue->lock, &timeout); + if (ret != 0) { + if (ret != ETIMEDOUT) { + ERROR("Failed to wait cond"); +diff --git a/src/utils/cutils/blocking_queue.h b/src/utils/cutils/blocking_queue.h +index 1c52a9d3..257779c3 100644 +--- a/src/utils/cutils/blocking_queue.h ++++ b/src/utils/cutils/blocking_queue.h +@@ -37,7 +37,7 @@ typedef struct blocking_queue { + blocking_node *head; + blocking_node *tail; + pthread_mutex_t lock; +- struct timespec timeout; ++ int64_t timeout; + pthread_cond_t not_empty; + void (*release)(void *); + } blocking_queue; +-- +2.34.1 + diff --git a/0066-cdi-support-modules-version-spec-spec_dirs-device.patch b/0066-cdi-support-modules-version-spec-spec_dirs-device.patch new file mode 100644 index 0000000..6aff31b --- /dev/null +++ b/0066-cdi-support-modules-version-spec-spec_dirs-device.patch @@ -0,0 +1,1254 @@ +From 684f0aa648061a13e777153e297a7064ba33ea17 Mon Sep 17 00:00:00 2001 +From: liuxu +Date: Thu, 11 Apr 2024 11:00:44 +0800 +Subject: [PATCH 66/69] cdi:support modules version/spec/spec_dirs/device + +--- + .../modules/device/cdi/behavior/cdi_device.c | 100 +++++++- + .../modules/device/cdi/behavior/cdi_device.h | 12 +- + .../modules/device/cdi/behavior/cdi_spec.c | 220 ++++++++++++++++-- + .../modules/device/cdi/behavior/cdi_spec.h | 16 +- + .../device/cdi/behavior/cdi_spec_dirs.c | 80 +++++++ + .../device/cdi/behavior/cdi_spec_dirs.h | 2 +- + .../modules/device/cdi/behavior/cdi_version.c | 173 ++++++++++++-- + .../modules/device/cdi/behavior/cdi_version.h | 1 - + src/daemon/modules/device/cdi/cdi_cache.c | 37 +-- + src/daemon/modules/device/cdi/cdi_cache.h | 1 + + .../network/cni_operator/libcni/libcni_api.c | 98 +------- + src/utils/cutils/utils_version.c | 147 ++++++++++++ + src/utils/cutils/utils_version.h | 36 +++ + 13 files changed, 748 insertions(+), 175 deletions(-) + create mode 100644 src/utils/cutils/utils_version.c + create mode 100644 src/utils/cutils/utils_version.h + +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_device.c b/src/daemon/modules/device/cdi/behavior/cdi_device.c +index 0fef8f42..aec3d7c0 100644 +--- a/src/daemon/modules/device/cdi/behavior/cdi_device.c ++++ b/src/daemon/modules/device/cdi/behavior/cdi_device.c +@@ -14,27 +14,109 @@ + ******************************************************************************/ + #include "cdi_device.h" + ++#include ++#include ++ ++#include "error.h" ++#include "cdi_parser.h" ++#include "cdi_spec.h" ++ ++static int cdi_device_validate(struct cdi_cache_device *d); ++ + void free_cdi_cache_device(struct cdi_cache_device *d) + { +- (void)d; ++ if (d == NULL) { ++ return; ++ } ++ ++ /* ++ * free_cdi_cache_device should not be recursively free raw_device. ++ * Otherwise, the function conflicts with the raw_spec free raw_device ++ * when cdi_cache_spec free raw_spec, triggering double free. ++ */ ++ d->raw_device = NULL; ++ ++ /* ++ * free_cdi_cache_device should not be recursively free cache_spec. ++ * Otherwise, the function conflicts with the cache free specs, ++ * triggering double free. ++ */ ++ d->cache_spec = NULL; ++ ++ free(d); ++} ++ ++struct cdi_cache_device *cdi_device_new_device(struct cdi_cache_spec *spec, cdi_device *d) ++{ ++ struct cdi_cache_device *dev = NULL; ++ ++ if (spec == NULL || d == NULL) { ++ ERROR("Invalid params"); ++ return NULL; ++ } ++ ++ dev = util_common_calloc_s(sizeof(*dev)); ++ if (dev == NULL) { ++ ERROR("Out of memory"); ++ return NULL; ++ } ++ dev->raw_device = d; ++ dev->cache_spec = spec; ++ ++ if (cdi_device_validate(dev) != 0) { ++ free_cdi_cache_device(dev); ++ return NULL; ++ } ++ return dev; + } + +-struct cdi_cache_device *cdi_device_new_device(struct cdi_cache_spec *spec, cdi_device *d, char **error) ++const struct cdi_cache_spec *cdi_device_get_spec(const struct cdi_cache_device *d) + { +- return NULL; ++ if (d == NULL) { ++ ERROR("Invalid params"); ++ return NULL; ++ } ++ return d->cache_spec; + } + +-struct cdi_cache_spec *cdi_device_get_spec(struct cdi_cache_device *d) ++char *cdi_device_get_qualified_name(const struct cdi_cache_device *d) + { +- return NULL; ++ if (d == NULL || d->raw_device == NULL) { ++ ERROR("Invalid params"); ++ return NULL; ++ } ++ return cdi_parser_qualified_name(cdi_spec_get_vendor(d->cache_spec), ++ cdi_spec_get_class(d->cache_spec), d->raw_device->name); + } + +-char *cdi_device_get_qualified_name(struct cdi_cache_device *d) ++cdi_container_edits *cdi_device_get_edits(const struct cdi_cache_device *d) + { +- return NULL; ++ if (d == NULL || d->raw_device == NULL) { ++ ERROR("Invalid params"); ++ return NULL; ++ } ++ return d->raw_device->container_edits; + } + +-cdi_container_edits *cdi_device_get_edits(struct cdi_cache_device *d) ++static int cdi_device_validate(struct cdi_cache_device *d) + { +- return NULL; ++ cdi_container_edits *edits = NULL; ++ ++ if (cdi_parser_validate_device_name(d->raw_device->name) != 0) { ++ ERROR("Failed to validate device name"); ++ return -1; ++ } ++ ++ // ignore validate annotations ++ ++ edits = cdi_device_get_edits(d); ++ if (cdi_container_edits_is_empty(edits)) { ++ ERROR("Invalid device, empty device edits"); ++ return -1; ++ } ++ if (cdi_container_edits_validate(edits) != 0) { ++ ERROR("Invalid device %s", d->raw_device->name); ++ return -1; ++ } ++ return 0; + } +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_device.h b/src/daemon/modules/device/cdi/behavior/cdi_device.h +index 5d63a576..9b0a5eab 100644 +--- a/src/daemon/modules/device/cdi/behavior/cdi_device.h ++++ b/src/daemon/modules/device/cdi/behavior/cdi_device.h +@@ -28,16 +28,16 @@ extern "C" { + struct cdi_cache_spec; + + struct cdi_cache_device { +- cdi_device *raw_device; +- struct cdi_cache_spec *cache_spec; ++ const cdi_device *raw_device; ++ const struct cdi_cache_spec *cache_spec; + }; + + void free_cdi_cache_device(struct cdi_cache_device *d); + +-struct cdi_cache_device *cdi_device_new_device(struct cdi_cache_spec *spec, cdi_device *d, char **error); +-struct cdi_cache_spec *cdi_device_get_spec(struct cdi_cache_device *d); +-char *cdi_device_get_qualified_name(struct cdi_cache_device *d); +-cdi_container_edits *cdi_device_get_edits(struct cdi_cache_device *d); ++struct cdi_cache_device *cdi_device_new_device(struct cdi_cache_spec *spec, cdi_device *d); ++const struct cdi_cache_spec *cdi_device_get_spec(const struct cdi_cache_device *d); ++char *cdi_device_get_qualified_name(const struct cdi_cache_device *d); ++cdi_container_edits *cdi_device_get_edits(const struct cdi_cache_device *d); + + #ifdef __cplusplus + } +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_spec.c b/src/daemon/modules/device/cdi/behavior/cdi_spec.c +index f79b5a44..235b1863 100644 +--- a/src/daemon/modules/device/cdi/behavior/cdi_spec.c ++++ b/src/daemon/modules/device/cdi/behavior/cdi_spec.c +@@ -14,47 +14,235 @@ + ******************************************************************************/ + #include "cdi_spec.h" + ++#include ++#include ++#include ++ ++#include "utils.h" ++#include "utils_version.h" ++#include "error.h" ++#include "path.h" ++#include "cdi_version.h" ++#include "cdi_parser.h" ++#include "cdi_device.h" ++ ++static int cdi_spec_init(struct cdi_cache_spec *s); ++ + void free_cdi_cache_spec(struct cdi_cache_spec *s) + { +- (void)s; ++ if (s == NULL) { ++ return; ++ } ++ ++ free_cdi_spec(s->raw_spec); ++ s->raw_spec = NULL; ++ free(s->vendor); ++ s->vendor = NULL; ++ free(s->class); ++ s->class = NULL; ++ free(s->path); ++ s->path = NULL; ++ map_free(s->devices); ++ s->devices = NULL; ++ ++ free(s); + } + +-struct cdi_cache_spec *cdi_spec_read_spec(const char *path, int priority, char **error) ++struct cdi_cache_spec *cdi_spec_read_spec(const char *path, int priority) + { +- return NULL; ++ cdi_spec *raw_spec = NULL; ++ __isula_auto_free parser_error err = NULL; ++ char cleanpath[PATH_MAX] = { 0 }; ++ ++ if (util_clean_path(path, cleanpath, sizeof(cleanpath)) == NULL) { ++ ERROR("Failed to get clean path %s", path); ++ return NULL; ++ } ++ ++ raw_spec = cdi_spec_parse_file(cleanpath, NULL, &err); ++ if (raw_spec == NULL) { ++ ERROR("Failed to read CDI Spec %s: %s", cleanpath, err); ++ return NULL; ++ } ++ DEBUG("Read cdi spec %s", cleanpath); ++ ++ return cdi_spec_new_spec(raw_spec, cleanpath, priority); + } + +-struct cdi_cache_spec *cdi_spec_new_spec(cdi_spec *raw, const char *path, int priority, char **error) ++struct cdi_cache_spec *cdi_spec_new_spec(cdi_spec *raw, const char *path, int priority) + { ++ struct cdi_cache_spec *spec = NULL; ++ __isula_auto_free char *checked_path = NULL; ++ ++ if (raw == NULL) { ++ ERROR("Invalid param"); ++ return NULL; ++ } ++ ++ if (!util_has_suffix(path, ".json")) { ++ checked_path = util_string_append(path, CDI_DEFAULT_SPEC_EXT); ++ if (checked_path == NULL) { ++ ERROR("Failed to append %s to path %s", CDI_DEFAULT_SPEC_EXT, path); ++ return NULL; ++ } ++ } else { ++ checked_path = util_strdup_s(path); ++ } ++ spec = util_common_calloc_s(sizeof(*spec)); ++ if (spec == NULL) { ++ ERROR("Out of memory"); ++ return NULL; ++ } ++ spec->raw_spec = raw; ++ spec->path = checked_path; ++ checked_path = NULL; ++ spec->priority = priority; ++ ++ if (cdi_parser_parse_qualifier(raw->kind, &spec->vendor, &spec->class) != 0) { ++ ERROR("Failed to parse kind %s", raw->kind); ++ goto error_out; ++ } ++ if (cdi_spec_init(spec) != 0) { ++ ERROR("Invalid CDI Spec"); ++ goto error_out; ++ } ++ ++ return spec; ++ ++error_out: ++ free_cdi_cache_spec(spec); + return NULL; + } + +-const char *cdi_spec_get_vendor(struct cdi_cache_spec *s) ++const char *cdi_spec_get_vendor(const struct cdi_cache_spec *s) + { +- return NULL; ++ if (s == NULL) { ++ ERROR("Invalid params"); ++ return NULL; ++ } ++ return s->vendor; + } + +-const char *cdi_spec_get_class(struct cdi_cache_spec *s) ++const char *cdi_spec_get_class(const struct cdi_cache_spec *s) + { +- return NULL; ++ if (s == NULL) { ++ ERROR("Invalid params"); ++ return NULL; ++ } ++ return s->class; + } + +-struct cdi_cache_device *cdi_spec_get_cache_device(struct cdi_cache_spec *s, const char *name) ++struct cdi_cache_device *cdi_spec_get_cache_device(const struct cdi_cache_spec *s, const char *name) + { +- return NULL; ++ if (s == NULL) { ++ ERROR("Invalid params"); ++ return NULL; ++ } ++ return map_search(s->devices, (void *)name);; + } + +-const char *cdi_spec_get_path(struct cdi_cache_spec *s) ++const char *cdi_spec_get_path(const struct cdi_cache_spec *s) + { +- return NULL; ++ if (s == NULL) { ++ ERROR("Invalid params"); ++ return NULL; ++ } ++ return s->path; + } + +-int cdi_spec_get_priority(struct cdi_cache_spec *s) ++int cdi_spec_get_priority(const struct cdi_cache_spec *s) + { +- return 0; ++ if (s == NULL) { ++ ERROR("Invalid params"); ++ return -1; ++ } ++ return s->priority; + } + +-cdi_container_edits *cdi_spec_get_edits(struct cdi_cache_spec *s) ++cdi_container_edits *cdi_spec_get_edits(const struct cdi_cache_spec *s) + { +- return NULL; ++ if (s == NULL || s->raw_spec == NULL) { ++ ERROR("Invalid params"); ++ return NULL; ++ } ++ return s->raw_spec->container_edits; ++} ++ ++static void map_cdi_cache_device_kvfree(void *key, void *value) ++{ ++ free(key); ++ free_cdi_cache_device((struct cdi_cache_device *)value); ++} ++ ++static int cdi_spec_init(struct cdi_cache_spec *s) ++{ ++ const char *min_version = NULL; ++ __isula_auto_free char *spec_version = NULL; ++ cdi_container_edits *edits = NULL; ++ struct cdi_cache_device *dev = NULL; ++ cdi_device *d = NULL; ++ size_t i; ++ bool version_result = true; ++ ++ if (!cdi_is_valid_version(s->raw_spec->cdi_version)) { ++ ERROR("Failed to validate cdi spec version: %s", s->raw_spec->cdi_version); ++ return -1; ++ } ++ ++ min_version = cdi_minimum_required_version(s->raw_spec); ++ if (min_version == NULL) { ++ ERROR("Could not determine minimum required version"); ++ return -1; ++ } ++ if (util_version_greater_than(min_version, s->raw_spec->cdi_version, &version_result) != 0) { ++ ERROR("Failed to compare version %s and %s", min_version, s->raw_spec->cdi_version); ++ return -1; ++ } ++ if (version_result) { ++ ERROR("The spec version must be at least v%s", min_version); ++ return -1; ++ } ++ ++ if (cdi_parser_validate_vendor_name(s->vendor) != 0) { ++ return -1; ++ } ++ if (cdi_parser_validate_class_name(s->class) != 0) { ++ return -1; ++ } ++ ++ // ignore validate annotations ++ ++ edits = cdi_spec_get_edits(s); ++ if (cdi_container_edits_validate(edits) != 0) { ++ return -1; ++ } ++ ++ s->devices = map_new(MAP_STR_PTR, MAP_DEFAULT_CMP_FUNC, map_cdi_cache_device_kvfree); ++ if (s->devices == NULL) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ for (i = 0; i < s->raw_spec->devices_len; i++) { ++ d = s->raw_spec->devices[i]; ++ dev = cdi_device_new_device(s, d); ++ if (dev == NULL) { ++ ERROR("Could not determine minimum required version"); ++ goto error_out; ++ } ++ if (map_search(s->devices, (void *)d->name) != NULL) { ++ ERROR("Invalid spec, multiple device %s", d->name); ++ goto error_out; ++ } ++ if (!map_insert(s->devices, (void *)d->name, dev)) { ++ ERROR("Failed to insert device %s", d->name); ++ goto error_out; ++ } ++ } ++ ++ return 0; ++ ++error_out: ++ map_free(s->devices); ++ s->devices = NULL; ++ return -1; + } +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_spec.h b/src/daemon/modules/device/cdi/behavior/cdi_spec.h +index 87248041..ca7b2cfa 100644 +--- a/src/daemon/modules/device/cdi/behavior/cdi_spec.h ++++ b/src/daemon/modules/device/cdi/behavior/cdi_spec.h +@@ -40,14 +40,14 @@ struct cdi_cache_spec { + + void free_cdi_cache_spec(struct cdi_cache_spec *s); + +-struct cdi_cache_spec *cdi_spec_read_spec(const char *path, int priority, char **error); +-struct cdi_cache_spec *cdi_spec_new_spec(cdi_spec *raw, const char *path, int priority, char **error); +-const char *cdi_spec_get_vendor(struct cdi_cache_spec *s); +-const char *cdi_spec_get_class(struct cdi_cache_spec *s); +-struct cdi_cache_device *cdi_spec_get_cache_device(struct cdi_cache_spec *s, const char *name); +-const char *cdi_spec_get_path(struct cdi_cache_spec *s); +-int cdi_spec_get_priority(struct cdi_cache_spec *s); +-cdi_container_edits *cdi_spec_get_edits(struct cdi_cache_spec *s); ++struct cdi_cache_spec *cdi_spec_read_spec(const char *path, int priority); ++struct cdi_cache_spec *cdi_spec_new_spec(cdi_spec *raw, const char *path, int priority); ++const char *cdi_spec_get_vendor(const struct cdi_cache_spec *s); ++const char *cdi_spec_get_class(const struct cdi_cache_spec *s); ++struct cdi_cache_device *cdi_spec_get_cache_device(const struct cdi_cache_spec *s, const char *name); ++const char *cdi_spec_get_path(const struct cdi_cache_spec *s); ++int cdi_spec_get_priority(const struct cdi_cache_spec *s); ++cdi_container_edits *cdi_spec_get_edits(const struct cdi_cache_spec *s); + + #ifdef __cplusplus + } +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_spec_dirs.c b/src/daemon/modules/device/cdi/behavior/cdi_spec_dirs.c +index e340abc0..cafb52b8 100644 +--- a/src/daemon/modules/device/cdi/behavior/cdi_spec_dirs.c ++++ b/src/daemon/modules/device/cdi/behavior/cdi_spec_dirs.c +@@ -14,6 +14,17 @@ + ******************************************************************************/ + #include "cdi_spec_dirs.h" + ++#include ++#include ++#include ++ ++#include "utils.h" ++#include "path.h" ++#include "error.h" ++#include "utils_file.h" ++#include "utils_array.h" ++#include "cdi_spec.h" ++ + #define DEFAULT_SPEC_DIRS_LEN 2 + static char *default_spec_dirs_items[DEFAULT_SPEC_DIRS_LEN] = {CDI_DEFAULT_STATIC_DIR, CDI_DEFAULT_DYNAMIC_DIR}; + +@@ -23,7 +34,76 @@ string_array g_default_spec_dirs = { + .cap = DEFAULT_SPEC_DIRS_LEN, + }; + ++struct scan_spec_dir_cb_args { ++ struct cdi_scan_fn_maps *scan_fn_maps; ++ cdi_scan_spec_func scan_fn; ++ int priority; ++}; ++ ++static bool scan_spec_dir_cb(const char *dir, const struct dirent *pdirent, void *context) ++{ ++ struct scan_spec_dir_cb_args *args = (struct scan_spec_dir_cb_args *)context; ++ struct cdi_scan_fn_maps *scan_fn_maps = args->scan_fn_maps; ++ cdi_scan_spec_func scan_fn = args->scan_fn; ++ int priority = args->priority; ++ struct stat st = { 0 }; ++ __isula_auto_free char *file_path = NULL; ++ struct cdi_cache_spec *cache_spec = NULL; ++ ++ file_path = util_path_join(dir, pdirent->d_name); ++ if (file_path == NULL) { ++ ERROR("Failed to get path %s/%s", dir, pdirent->d_name); ++ goto error_out; ++ } ++ ++ if (lstat(file_path, &st) != 0) { ++ ERROR("Failed to lstat %s", file_path); ++ goto error_out; ++ } ++ if (S_ISDIR(st.st_mode)) { ++ DEBUG("Skip dir %s", file_path); ++ return true; ++ } ++ ++ if (!util_has_suffix(file_path, ".json")) { ++ DEBUG("Skip file %s", file_path); ++ return true; ++ } ++ ++ cache_spec = cdi_spec_read_spec(file_path, priority); ++ if (cache_spec == NULL) { ++ ERROR("Failed to read spec %s", file_path); ++ goto error_out; ++ } ++ scan_fn(scan_fn_maps, file_path, priority, cache_spec); ++ return true; ++ ++error_out: ++ *(scan_fn_maps->refresh_error_flag) = true; ++ return true; ++} ++ + int cdi_scan_spec_dirs(string_array *dirs, struct cdi_scan_fn_maps *scan_fn_maps, cdi_scan_spec_func scan_fn) + { ++ size_t i; ++ int nret = 0; ++ ++ for (i = 0; i < dirs->len; i++) { ++ struct scan_spec_dir_cb_args args = { ++ .scan_fn_maps = scan_fn_maps, ++ .scan_fn = scan_fn, ++ .priority = i, ++ }; ++ if (!util_dir_exists(dirs->items[i])) { ++ WARN("Cdi dir %s not exists", dirs->items[i]); ++ continue; ++ } ++ nret = util_scan_subdirs(dirs->items[i], scan_spec_dir_cb, &args); ++ if (nret != 0) { ++ ERROR("Failed to scan dir %s", dirs->items[i]); ++ return -1; ++ } ++ } ++ + return 0; + } +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_spec_dirs.h b/src/daemon/modules/device/cdi/behavior/cdi_spec_dirs.h +index eedcabad..b17a0cd8 100644 +--- a/src/daemon/modules/device/cdi/behavior/cdi_spec_dirs.h ++++ b/src/daemon/modules/device/cdi/behavior/cdi_spec_dirs.h +@@ -35,7 +35,7 @@ struct cdi_scan_fn_maps { + bool *refresh_error_flag; + }; + typedef void(*cdi_scan_spec_func)(struct cdi_scan_fn_maps *scan_fn_maps, const char *path, int priority, +- struct cdi_cache_spec *spec, char *error); ++ struct cdi_cache_spec *spec); + + int cdi_scan_spec_dirs(string_array *dirs, struct cdi_scan_fn_maps *scan_fn_maps, cdi_scan_spec_func scan_fn); + +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_version.c b/src/daemon/modules/device/cdi/behavior/cdi_version.c +index 3e87c111..882a965e 100644 +--- a/src/daemon/modules/device/cdi/behavior/cdi_version.c ++++ b/src/daemon/modules/device/cdi/behavior/cdi_version.c +@@ -14,27 +14,174 @@ + ******************************************************************************/ + #include "cdi_version.h" + +-#define CDI_V_CURRENT_VERSION "v"##CDI_CURRENT_VERSION +- +-#define CDI_V010 "v0.1.0" +-#define CDI_V020 "v0.2.0" +-#define CDI_V030 "v0.3.0" +-#define CDI_V040 "v0.4.0" +-#define CDI_V050 "v0.5.0" +-#define CDI_V060 "v0.6.0" ++#include ++#include ++#include ++ ++#include "error.h" ++#include "utils_version.h" ++#include "utils_string.h" ++#include "cdi_container_edits.h" ++#include "cdi_parser.h" ++ ++#define CDI_V010 "0.1.0" ++#define CDI_V020 "0.2.0" ++#define CDI_V030 "0.3.0" ++#define CDI_V040 "0.4.0" ++#define CDI_V050 "0.5.0" ++#define CDI_V060 "0.6.0" + #define CDI_V_EARLIEST CDI_V030 + +-const char *cdi_minimum_required_version(cdi_spec *spec) ++typedef bool (*required_version_cb)(cdi_spec *spec); ++ ++struct required_version_map { ++ char *version; ++ required_version_cb cb; ++}; ++ ++static bool requires_v060(cdi_spec *spec) ++{ ++ size_t i; ++ int ret = 0; ++ __isula_auto_free char *vendor = NULL; ++ __isula_auto_free char *class = NULL; ++ ++ // The 0.6.0 spec allows annotations to be specified at a spec level ++ if (spec->annotations != NULL) { ++ return true; ++ } ++ ++ // The 0.6.0 spec allows annotations to be specified at a device level ++ if (spec->devices != NULL) { ++ for (i = 0; i < spec->devices_len; i++) { ++ if (spec->devices[i]->annotations != NULL) { ++ return true; ++ } ++ } ++ } ++ ++ // The 0.6.0 spec allows dots "." in Kind name label (class) ++ ret = cdi_parser_parse_qualifier(spec->kind, &vendor, &class); ++ if (ret == 0 && vendor != NULL) { ++ if (util_strings_count(class, '.') > 0) { ++ return true; ++ } ++ } ++ return false; ++} ++ ++static bool check_host_path(cdi_container_edits *e) + { +- return NULL; ++ size_t i; ++ ++ if (e == NULL) { ++ return false; ++ } ++ for (i = 0; i < e->device_nodes_len; i++) { ++ // The HostPath field was added in 0.5.0 ++ if (e->device_nodes[i]->host_path != NULL) { ++ return true; ++ } ++ } ++ return false; + } + +-bool cdi_is_greater_than_version(const char *v, const char *o) ++static bool requires_v050(cdi_spec *spec) + { +- return true; ++ size_t i; ++ ++ for (i = 0; i < spec->devices_len; i++) { ++ // The 0.5.0 spec allowed device names to start with a digit instead of requiring a letter ++ if (spec->devices[i]->name != NULL && strlen(spec->devices[i]->name) > 0 && ++ !isalpha(spec->devices[i]->name[0])) { ++ return true; ++ } ++ if (check_host_path(spec->devices[i]->container_edits)) { ++ return true; ++ } ++ } ++ ++ return check_host_path(spec->container_edits); ++} ++ ++static bool check_mount_type(cdi_container_edits *e) ++{ ++ size_t i; ++ ++ if (e == NULL) { ++ return false; ++ } ++ for (i = 0; i < e->mounts_len; i++) { ++ // The Type field was added in 0.4.0 ++ if (e->mounts[i]->type != NULL) { ++ return true; ++ } ++ } ++ return false; ++} ++ ++static bool requires_v040(cdi_spec *spec) ++{ ++ size_t i; ++ ++ for (i = 0; i < spec->devices_len; i++) { ++ if (check_mount_type(spec->devices[i]->container_edits)) { ++ return true; ++ } ++ } ++ ++ return check_mount_type(spec->container_edits); ++} ++ ++#define VALID_SPEC_VERSIONS_LEN 6 ++static struct required_version_map g_valid_spec_versions[VALID_SPEC_VERSIONS_LEN] = { ++ {CDI_V010, NULL}, ++ {CDI_V020, NULL}, ++ {CDI_V030, NULL}, ++ {CDI_V040, requires_v060}, ++ {CDI_V050, requires_v050}, ++ {CDI_V060, requires_v040} ++}; ++ ++const char *cdi_minimum_required_version(cdi_spec *spec) ++{ ++ const char *min_version = CDI_V_EARLIEST; ++ int i; ++ bool result = true; ++ ++ if (spec == NULL) { ++ return NULL; ++ } ++ ++ for (i = 0; i < VALID_SPEC_VERSIONS_LEN; i++) { ++ if (g_valid_spec_versions[i].cb == NULL) { ++ continue; ++ } ++ if (g_valid_spec_versions[i].cb(spec)) { ++ if (util_version_greater_than(g_valid_spec_versions[i].version, min_version, &result) != 0) { ++ ERROR("Failed to compare version %s and %s", g_valid_spec_versions[i].version, min_version); ++ return NULL; ++ } ++ if (result) { ++ min_version = g_valid_spec_versions[i].version; ++ } ++ } ++ if (strcmp(min_version, CDI_CURRENT_VERSION)) { ++ break; ++ } ++ } ++ ++ return min_version; + } + + bool cdi_is_valid_version(const char *spec_version) + { +- return true; ++ int i; ++ ++ for (i = 0; i < VALID_SPEC_VERSIONS_LEN; i++) { ++ if (strcmp(g_valid_spec_versions[i].version, spec_version) == 0) { ++ return true; ++ } ++ } ++ return false; + } +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_version.h b/src/daemon/modules/device/cdi/behavior/cdi_version.h +index 99b7e692..6bd86340 100644 +--- a/src/daemon/modules/device/cdi/behavior/cdi_version.h ++++ b/src/daemon/modules/device/cdi/behavior/cdi_version.h +@@ -24,7 +24,6 @@ extern "C" { + #define CDI_CURRENT_VERSION "0.6.0" + + const char *cdi_minimum_required_version(cdi_spec *spec); +-bool cdi_is_greater_than_version(const char *v, const char *o); + bool cdi_is_valid_version(const char *spec_version); + + #ifdef __cplusplus +diff --git a/src/daemon/modules/device/cdi/cdi_cache.c b/src/daemon/modules/device/cdi/cdi_cache.c +index 37767855..e637f7cd 100644 +--- a/src/daemon/modules/device/cdi/cdi_cache.c ++++ b/src/daemon/modules/device/cdi/cdi_cache.c +@@ -206,13 +206,12 @@ static void map_cdi_cache_specs_kvfree(void *key, void *value) + static void map_cdi_cache_device_kvfree(void *key, void *value) + { + free(key); +- free_cdi_cache_device((struct cdi_cache_device *)value); +-} +- +-static void set_refresh_error_flag(bool *refresh_error_flag, const char *error, const char *path) +-{ +- *refresh_error_flag = true; +- ERROR("Cdi refresh error: %s, spec %s", error, path); ++ /* ++ * map_cdi_cache_device_kvfree should not be recursively free cdi_cache_device. ++ * Otherwise, the function conflicts with the cdi_cache_specs free devices, ++ * triggering double free. ++ */ ++ (void)value; + } + + static bool resolve_conflict(struct cdi_scan_fn_maps *scan_fn_maps, const char *name, +@@ -220,8 +219,8 @@ static bool resolve_conflict(struct cdi_scan_fn_maps *scan_fn_maps, const char * + { + map_t *conflicts = scan_fn_maps->conflicts; + bool *refresh_error_flag = scan_fn_maps->refresh_error_flag; +- struct cdi_cache_spec *dev_spec = NULL; +- struct cdi_cache_spec *old_spec = NULL; ++ const struct cdi_cache_spec *dev_spec = NULL; ++ const struct cdi_cache_spec *old_spec = NULL; + int dev_prio; + int old_prio; + bool val = true; +@@ -251,7 +250,7 @@ static bool resolve_conflict(struct cdi_scan_fn_maps *scan_fn_maps, const char * + } + + static void refresh_scan_spec_func(struct cdi_scan_fn_maps *scan_fn_maps, const char *path, +- int priority, struct cdi_cache_spec *spec, char *error) ++ int priority, struct cdi_cache_spec *spec) + { + map_t *specs = scan_fn_maps->specs; + map_t *devices = scan_fn_maps->devices; +@@ -267,12 +266,6 @@ static void refresh_scan_spec_func(struct cdi_scan_fn_maps *scan_fn_maps, const + + if (util_clean_path(path, clean_path, sizeof(clean_path)) == NULL) { + ERROR("Failed to get clean path %s", path); +- format_errorf(&tmp_error, "Failed to get clean path %s", path); +- return; +- } +- if (error != NULL) { +- ERROR("Failed to load CDI Spec %s", error); +- format_errorf(&tmp_error, "Failed to load CDI Spec %s", error); + goto error_out; + } + +@@ -282,18 +275,15 @@ static void refresh_scan_spec_func(struct cdi_scan_fn_maps *scan_fn_maps, const + spec_array = util_common_array_new(1, (free_common_array_item_cb)free_cdi_cache_spec, util_clone_ptr); + if (spec_array == NULL) { + ERROR("Out of memory"); +- tmp_error = util_strdup_s("Out of memory"); + goto error_out; + } + if (!map_insert(specs, (void *)vendor, spec_array)) { + ERROR("Failed to insert spec array to specs"); +- tmp_error = util_strdup_s("Failed to insert spec array to specs"); + goto error_out; + } + } + if (util_append_common_array(spec_array, spec) != 0) { + ERROR("Failed to append spec"); +- tmp_error = util_strdup_s("Failed to append spec"); + goto error_out; + } + spec_array = NULL; +@@ -301,7 +291,6 @@ static void refresh_scan_spec_func(struct cdi_scan_fn_maps *scan_fn_maps, const + itor = map_itor_new(spec->devices); + if (itor == NULL) { + ERROR("Out of memory, create new map itor failed"); +- tmp_error = util_strdup_s("Out of memory, create new map itor failed"); + goto error_out; + } + for (; map_itor_valid(itor); map_itor_next(itor)) { +@@ -315,7 +304,6 @@ static void refresh_scan_spec_func(struct cdi_scan_fn_maps *scan_fn_maps, const + } + if (!map_replace(devices, (void *)qualified, dev)) { + ERROR("Failed to insert device to devices by name %s", qualified); +- format_errorf(&tmp_error, "Failed to insert device to devices by name %s", qualified); + goto error_out; + } + free(qualified); +@@ -324,7 +312,7 @@ static void refresh_scan_spec_func(struct cdi_scan_fn_maps *scan_fn_maps, const + goto out; + + error_out: +- set_refresh_error_flag(refresh_error_flag, tmp_error, path); ++ *refresh_error_flag = true; + out: + map_itor_free(itor); + return; +@@ -333,7 +321,6 @@ out: + static int refresh(struct cdi_cache *c) + { + int ret = 0; +- __isula_auto_free char *error = NULL; + map_t *specs = NULL; + map_t *devices = NULL; + map_t *conflicts = NULL; +@@ -559,8 +546,6 @@ error_out: + + static void watch_setup(struct cdi_watch *w, string_array *dirs) + { +- __isula_auto_free char *error = NULL; +- + if (w == NULL || dirs == NULL || dirs->len == 0) { + ERROR("Invalid param"); + return; +@@ -735,7 +720,6 @@ static void update_add_watch_dir(struct cdi_watch *w, const char *dir, bool *upd + { + int wd = -1; + bool tmp_value = true; +- __isula_auto_free char *error = NULL; + + wd = inotify_add_watch(w->watcher_fd, dir, CDI_WATCH_EVENTS); + if (wd < 0) { +@@ -770,7 +754,6 @@ static bool watch_update(struct cdi_watch *w, const char *removed, int wd) + bool *ok = NULL; + bool update = false; + map_itor *itor = NULL; +- __isula_auto_free char *error = NULL; + + itor = map_itor_new(w->tracked); + if (itor == NULL) { +diff --git a/src/daemon/modules/device/cdi/cdi_cache.h b/src/daemon/modules/device/cdi/cdi_cache.h +index da315de2..638e954e 100644 +--- a/src/daemon/modules/device/cdi/cdi_cache.h ++++ b/src/daemon/modules/device/cdi/cdi_cache.h +@@ -52,6 +52,7 @@ struct cdi_cache { + pthread_mutex_t mutex; + string_array *spec_dirs; // cdi-spec-dirs will scan for CDI Spec files + map_t *specs; // MAP_STR_PTR specs[vendor] = common_array of cdi_cache_spec* ++ // This map holding the reference to cdi device, the devices will not released when the map is freed. + map_t *devices; // MAP_STR_PTR devices[cdi_device.name] = cdi_cache_device* + bool refresh_error_flag; + bool auto_refresh; +diff --git a/src/daemon/modules/network/cni_operator/libcni/libcni_api.c b/src/daemon/modules/network/cni_operator/libcni/libcni_api.c +index 068881be..7ba983af 100644 +--- a/src/daemon/modules/network/cni_operator/libcni/libcni_api.c ++++ b/src/daemon/modules/network/cni_operator/libcni/libcni_api.c +@@ -28,6 +28,7 @@ + #include + + #include "utils.h" ++#include "utils_version.h" + #include "utils_network.h" + #include "libcni_cached.h" + #include "libcni_conf.h" +@@ -544,97 +545,6 @@ free_out: + return ret; + } + +-struct parse_version { +- int major; +- int minor; +- int micro; +-}; +- +-static bool do_parse_version(const char **splits, size_t splits_len, struct parse_version *ret) +-{ +- if (util_safe_int(splits[0], &ret->major) != 0) { +- ERROR("failed to convert major version part: %s", splits[0]); +- return false; +- } +- +- if (splits_len >= 2 && util_safe_int(splits[1], &ret->minor) != 0) { +- ERROR("failed to convert minor version part: %s", splits[1]); +- return false; +- } +- +- if (splits_len >= 3 && util_safe_int(splits[2], &ret->micro) != 0) { +- ERROR("failed to convert micro version part: %s", splits[2]); +- return false; +- } +- +- return true; +-} +- +-static bool parse_version_from_str(const char *src_version, struct parse_version *result) +-{ +- char **splits = NULL; +- const size_t max_len = 4; +- size_t tlen = 0; +- bool ret = false; +- +- splits = util_string_split(src_version, '.'); +- if (splits == NULL) { +- ERROR("Split version: \"%s\" failed", src_version); +- return false; +- } +- tlen = util_array_len((const char **)splits); +- if (tlen < 1 || tlen >= max_len) { +- ERROR("Invalid version: \"%s\"", src_version); +- goto out; +- } +- +- ret = do_parse_version((const char **)splits, tlen, result); +- +-out: +- util_free_array(splits); +- return ret; +-} +- +-static bool do_compare_version(const struct parse_version *p_first, const struct parse_version *p_second) +-{ +- bool ret = false; +- +- if (p_first->major > p_second->major) { +- ret = true; +- } else if (p_first->major == p_second->major) { +- if (p_first->minor > p_second->minor) { +- ret = true; +- } else if (p_first->minor == p_second->minor && p_first->micro >= p_second->micro) { +- ret = true; +- } +- } +- +- return ret; +-} +- +-static int version_greater_than_or_equal_to(const char *first, const char *second, bool *result) +-{ +- struct parse_version first_parsed = { 0 }; +- struct parse_version second_parsed = { 0 }; +- +- if (result == NULL) { +- ERROR("Invalid argument"); +- return -1; +- } +- +- if (!parse_version_from_str(first, &first_parsed)) { +- return -1; +- } +- +- if (!parse_version_from_str(second, &second_parsed)) { +- return -1; +- } +- +- *result = do_compare_version(&first_parsed, &second_parsed); +- +- return 0; +-} +- + static inline bool check_add_network_args(const cni_net_conf *net, const struct runtime_conf *rc) + { + return (net == NULL || rc == NULL); +@@ -690,7 +600,7 @@ int cni_add_network_list(const struct cni_network_list_conf *list, const struct + } + + if (*pret != NULL && +- version_greater_than_or_equal_to((*pret)->cniversion, SUPPORT_CACHE_AND_CHECK_VERSION, &greater) != 0) { ++ util_version_greater_than_or_equal_to((*pret)->cniversion, SUPPORT_CACHE_AND_CHECK_VERSION, &greater) != 0) { + return 0; + } + +@@ -741,7 +651,7 @@ int cni_del_network_list(const struct cni_network_list_conf *list, const struct + return -1; + } + +- if (version_greater_than_or_equal_to(list->list->cni_version, SUPPORT_CACHE_AND_CHECK_VERSION, &greater) != 0) { ++ if (util_version_greater_than_or_equal_to(list->list->cni_version, SUPPORT_CACHE_AND_CHECK_VERSION, &greater) != 0) { + return -1; + } + +@@ -807,7 +717,7 @@ int cni_check_network_list(const struct cni_network_list_conf *list, const struc + return -1; + } + +- if (version_greater_than_or_equal_to(list->list->cni_version, SUPPORT_CACHE_AND_CHECK_VERSION, &greater) != 0) { ++ if (util_version_greater_than_or_equal_to(list->list->cni_version, SUPPORT_CACHE_AND_CHECK_VERSION, &greater) != 0) { + return -1; + } + +diff --git a/src/utils/cutils/utils_version.c b/src/utils/cutils/utils_version.c +new file mode 100644 +index 00000000..9dea5b09 +--- /dev/null ++++ b/src/utils/cutils/utils_version.c +@@ -0,0 +1,147 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2018-2022. All rights reserved. ++ * iSulad 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: liuxu ++ * Create: 2024-4-7 ++ * Description: provide version functions ++ ********************************************************************************/ ++ ++#define _GNU_SOURCE ++#include "utils_version.h" ++ ++#include ++ ++#include "utils.h" ++#include "utils_string.h" ++ ++struct parse_version { ++ int major; ++ int minor; ++ int micro; ++}; ++ ++static bool do_parse_version(const char **splits, size_t splits_len, struct parse_version *ret) ++{ ++ if (util_safe_int(splits[0], &ret->major) != 0) { ++ ERROR("Failed to convert major version part: %s", splits[0]); ++ return false; ++ } ++ ++ if (splits_len >= 2 && util_safe_int(splits[1], &ret->minor) != 0) { ++ ERROR("Failed to convert minor version part: %s", splits[1]); ++ return false; ++ } ++ ++ if (splits_len >= 3 && util_safe_int(splits[2], &ret->micro) != 0) { ++ ERROR("Failed to convert micro version part: %s", splits[2]); ++ return false; ++ } ++ ++ return true; ++} ++ ++static bool parse_version_from_str(const char *src_version, struct parse_version *result) ++{ ++ __isula_auto_array_t char **splits = NULL; ++ const size_t max_len = 4; ++ size_t tlen = 0; ++ bool ret = false; ++ ++ splits = util_string_split(src_version, '.'); ++ if (splits == NULL) { ++ ERROR("Split version: \"%s\" failed", src_version); ++ return false; ++ } ++ tlen = util_array_len((const char **)splits); ++ if (tlen < 1 || tlen >= max_len) { ++ ERROR("Invalid version: \"%s\"", src_version); ++ return false; ++ } ++ ++ ret = do_parse_version((const char **)splits, tlen, result); ++ ++ return ret; ++} ++ ++static int do_compare_version(const struct parse_version *p_first, const struct parse_version *p_second) ++{ ++ if (p_first->major != p_second->major) { ++ return p_first->major - p_second->major; ++ } ++ if (p_first->minor != p_second->minor) { ++ return p_first->minor - p_second->minor; ++ } ++ if (p_first->micro != p_second->micro) { ++ return p_first->micro - p_second->micro; ++ } ++ ++ return 0; ++} ++ ++int util_version_compare(const char *first, const char *second, int *diff_value) ++{ ++ struct parse_version first_parsed = { 0 }; ++ struct parse_version second_parsed = { 0 }; ++ ++ if (first == NULL || second == NULL || diff_value == NULL) { ++ ERROR("Invalid argument"); ++ return -1; ++ } ++ ++ if (!parse_version_from_str(first, &first_parsed)) { ++ return -1; ++ } ++ ++ if (!parse_version_from_str(second, &second_parsed)) { ++ return -1; ++ } ++ ++ *diff_value = do_compare_version(&first_parsed, &second_parsed); ++ ++ return 0; ++} ++ ++int util_version_greater_than(const char *first, const char *second, bool *result) ++{ ++ int ret; ++ int diff_value = 0; ++ ++ if (result == NULL) { ++ ERROR("Invalid argument"); ++ return -1; ++ } ++ ++ ret = util_version_compare(first, second, &diff_value); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ *result = (diff_value > 0); ++ return ret; ++} ++ ++int util_version_greater_than_or_equal_to(const char *first, const char *second, bool *result) ++{ ++ int ret; ++ int diff_value = 0; ++ ++ if (result == NULL) { ++ ERROR("Invalid argument"); ++ return -1; ++ } ++ ++ ret = util_version_compare(first, second, &diff_value); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ *result = (diff_value >= 0); ++ return ret; ++} +diff --git a/src/utils/cutils/utils_version.h b/src/utils/cutils/utils_version.h +new file mode 100644 +index 00000000..f9b543b8 +--- /dev/null ++++ b/src/utils/cutils/utils_version.h +@@ -0,0 +1,36 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2018-2022. All rights reserved. ++ * iSulad 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: liuxu ++ * Create: 2024-4-7 ++ * Description: provide version functions ++ ********************************************************************************/ ++ ++#ifndef UTILS_CUTILS_UTILS_VERSION_H ++#define UTILS_CUTILS_UTILS_VERSION_H ++ ++#include ++#include ++#include ++#include ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++int util_version_compare(const char *first, const char *second, int *diff_value); ++int util_version_greater_than(const char *first, const char *second, bool *result); ++int util_version_greater_than_or_equal_to(const char *first, const char *second, bool *result); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif // UTILS_CUTILS_UTILS_VERSION_H +\ No newline at end of file +-- +2.34.1 + diff --git a/0067-cdi-support-modules-container_edits-parser.patch b/0067-cdi-support-modules-container_edits-parser.patch new file mode 100644 index 0000000..901de2b --- /dev/null +++ b/0067-cdi-support-modules-container_edits-parser.patch @@ -0,0 +1,1210 @@ +From d0442316761717849deb248b5da45240f7bb1d38 Mon Sep 17 00:00:00 2001 +From: liuxu +Date: Thu, 11 Apr 2024 11:01:44 +0800 +Subject: [PATCH 67/69] cdi:support modules container_edits/parser + +--- + src/daemon/modules/api/specs_api.h | 13 + + .../device/cdi/behavior/cdi_container_edits.c | 622 +++++++++++++++++- + .../device/cdi/behavior/cdi_container_edits.h | 2 +- + .../device/cdi/behavior/parser/cdi_parser.c | 196 +++++- + .../device/cdi/behavior/parser/cdi_parser.h | 6 +- + src/daemon/modules/spec/specs.c | 230 +++++++ + 6 files changed, 1052 insertions(+), 17 deletions(-) + +diff --git a/src/daemon/modules/api/specs_api.h b/src/daemon/modules/api/specs_api.h +index f54c0d31..0999836b 100644 +--- a/src/daemon/modules/api/specs_api.h ++++ b/src/daemon/modules/api/specs_api.h +@@ -55,6 +55,19 @@ const oci_runtime_spec *get_readonly_default_oci_spec(bool system_container); + + int spec_module_init(void); + ++#ifdef ENABLE_CDI ++int defs_process_add_multiple_env(defs_process *dp, const char **envs, size_t env_len); ++int spec_add_multiple_process_env(oci_runtime_spec *oci_spec, const char **envs, size_t env_len); ++int spec_add_device(oci_runtime_spec *oci_spec, defs_device *device); ++int spec_add_linux_resources_device(oci_runtime_spec *oci_spec, bool allow, const char *dev_type, ++ int64_t major, int64_t minor, const char *access); ++void spec_remove_mount(oci_runtime_spec *oci_spec, const char *dest); ++int spec_add_mount(oci_runtime_spec *oci_spec, defs_mount *mnt); ++int spec_add_prestart_hook(oci_runtime_spec *oci_spec, defs_hook *prestart_hook); ++int spec_add_poststart_hook(oci_runtime_spec *oci_spec, defs_hook *poststart_hook); ++int spec_add_poststop_hook(oci_runtime_spec *oci_spec, defs_hook *poststop_hook); ++#endif /* ENABLE_CDI */ ++ + #ifdef __cplusplus + } + #endif +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_container_edits.c b/src/daemon/modules/device/cdi/behavior/cdi_container_edits.c +index 590118b1..816b9c2d 100644 +--- a/src/daemon/modules/device/cdi/behavior/cdi_container_edits.c ++++ b/src/daemon/modules/device/cdi/behavior/cdi_container_edits.c +@@ -14,36 +14,642 @@ + ******************************************************************************/ + #include "cdi_container_edits.h" + ++#include ++#include ++#include ++#include ++#include ++ ++#include "error.h" ++#include "path.h" ++#include "specs_extend.h" ++#include "utils.h" ++#include "utils_array.h" ++#include "specs_api.h" ++ ++/* ++ * The OCI being used by the iSulad not supportes ++ * createRuntime/createContainer/startContainer currently. ++ */ + // PRESTART_HOOK is the name of the OCI "prestart" hook. + #define PRESTART_HOOK "prestart" +-// CREATE_RUNTIME_HOOK is the name of the OCI "createRuntime" hook. +-#define CREATE_RUNTIME_HOOK "createRuntime" +-// CREATE_CONTAINER_HOOK is the name of the OCI "createContainer" hook. +-#define CREATE_CONTAINER_HOOK "createContainer" +-// START_CONTAINER_HOOK is the name of the OCI "startContainer" hook. +-#define START_CONTAINER_HOOK "startContainer" + // POSTSTART_HOOK is the name of the OCI "poststart" hook. + #define POSTSTART_HOOK "poststart" + // POSTSTOP_HOOK is the name of the OCI "poststop" hook. + #define POSTSTOP_HOOK "poststop" + ++#define VALID_HOOK_NAME_LEN 3 ++static const char* g_valid_hook_names[VALID_HOOK_NAME_LEN] = { ++ PRESTART_HOOK, POSTSTART_HOOK, POSTSTOP_HOOK ++}; ++ ++static int cdi_validate_env(char **envs, size_t envs_len); ++static int cdi_validate_device_node(cdi_device_node *d); ++static int cdi_validate_hook(cdi_hook *h); ++static int cdi_validate_mount(cdi_mount *m); ++ ++#define BLOCK_DEVICE "b" ++#define CHAR_DEVICE "c" ++#define FIFO_DEVICE "p" ++static int device_info_from_path(const char *path, char **dev_type, int64_t *major, int64_t *minor) ++{ ++ struct stat stat = { 0 }; ++ int ret = 0; ++ ++ ret = lstat(path, &stat); ++ if (ret != 0) { ++ ERROR("Failed to stat %s", path); ++ return -1; ++ } ++ ++ if (S_ISBLK(stat.st_mode)) { ++ *dev_type = util_strdup_s(BLOCK_DEVICE); ++ } else if (S_ISCHR(stat.st_mode)) { ++ *dev_type = util_strdup_s(CHAR_DEVICE); ++ } else if (S_ISFIFO(stat.st_mode)) { ++ *dev_type = util_strdup_s(FIFO_DEVICE); ++ } else { ++ *dev_type = NULL; ++ *major = 0; ++ *minor = 0; ++ ERROR("Not a device node"); ++ return -1; ++ } ++ ++ *major = (int64_t)major(stat.st_rdev); ++ *minor = (int64_t)minor(stat.st_rdev); ++ return 0; ++} ++ ++static int fill_device_node_info(cdi_device_node *d) ++{ ++ __isula_auto_free char *dev_type = NULL; ++ int64_t major; ++ int64_t minor; ++ ++ if (d->host_path == NULL) { ++ d->host_path = util_strdup_s(d->path); ++ } ++ ++ if (d->type != NULL && (d->major != 0 || strcmp(d->type, FIFO_DEVICE) == 0)) { ++ return 0; ++ } ++ ++ if (device_info_from_path(d->host_path, &dev_type, &major, &minor) != 0) { ++ ERROR("Failed to stat CDI host device %s", d->host_path); ++ return -1; ++ } ++ ++ if (d->type == NULL) { ++ d->type = dev_type; ++ dev_type = NULL; ++ } else { ++ if (strcmp(d->type, dev_type) != 0) { ++ ERROR("CDI device (%s, %s), host type mismatch (%s, %s)", ++ d->path, d->host_path, d->type, dev_type); ++ return -1; ++ } ++ } ++ if (d->major == 0 && strcmp(d->type, FIFO_DEVICE) != 0) { ++ d->major = major; ++ d->minor = minor; ++ } ++ return 0; ++} ++ ++static cdi_device_node *clone_cdi_device_node(cdi_device_node *d) ++{ ++ cdi_device_node *device_node = NULL; ++ ++ device_node = util_common_calloc_s(sizeof(*device_node)); ++ if (device_node == NULL) { ++ ERROR("Out of memory"); ++ return NULL; ++ } ++ ++ device_node->path = util_strdup_s(d->path); ++ device_node->host_path = util_strdup_s(d->host_path); ++ device_node->type = util_strdup_s(d->type); ++ device_node->major = d->major; ++ device_node->minor = d->minor; ++ device_node->file_mode = d->file_mode; ++ device_node->permissions = util_strdup_s(d->permissions); ++ device_node->uid = d->uid; ++ device_node->gid = d->gid; ++ return device_node; ++} ++ ++static cdi_hook *clone_cdi_hook(cdi_hook *h) ++{ ++ cdi_hook *hook = NULL; ++ ++ hook = util_common_calloc_s(sizeof(*hook)); ++ if (hook == NULL) { ++ ERROR("Out of memory"); ++ return NULL; ++ } ++ ++ hook->hook_name = util_strdup_s(h->hook_name); ++ hook->path = util_strdup_s(h->path); ++ if (h->args_len != 0) { ++ hook->args = util_copy_array_by_len(h->args, h->args_len); ++ if (hook->args == NULL) { ++ ERROR("Failed to copy args"); ++ goto error_out; ++ } ++ hook->args_len = h->args_len; ++ } ++ if (h->env_len != 0) { ++ hook->env = util_copy_array_by_len(h->env, h->env_len); ++ if (hook->env == NULL) { ++ ERROR("Failed to copy env"); ++ goto error_out; ++ } ++ hook->env_len = h->env_len; ++ } ++ hook->timeout = h->timeout; ++ ++ return hook; ++ ++error_out: ++ free_cdi_hook(hook); ++ return NULL; ++} ++ ++static cdi_mount *clone_cdi_mount(cdi_mount *m) ++{ ++ cdi_mount *mount = NULL; ++ ++ mount = util_common_calloc_s(sizeof(*mount)); ++ if (mount == NULL) { ++ ERROR("Out of memory"); ++ return NULL; ++ } ++ ++ mount->host_path = util_strdup_s(m->host_path); ++ mount->container_path = util_strdup_s(m->container_path); ++ if (m->options_len != 0) { ++ mount->options = util_copy_array_by_len(m->options, m->options_len); ++ if (mount->options == NULL) { ++ ERROR("Failed to copy options"); ++ free_cdi_mount(mount); ++ return NULL; ++ } ++ mount->options_len = m->options_len; ++ } ++ mount->type = util_strdup_s(m->type); ++ ++ return mount; ++} ++ ++static defs_hook *cdi_hook_to_oci(cdi_hook *h) ++{ ++ defs_hook *oci_hook = NULL; ++ ++ oci_hook = util_common_calloc_s(sizeof(*oci_hook)); ++ if (oci_hook == NULL) { ++ ERROR("Out of memory"); ++ return NULL; ++ } ++ ++ oci_hook->path = util_strdup_s(h->path); ++ if (h->args_len != 0) { ++ oci_hook->args = util_copy_array_by_len(h->args, h->args_len); ++ if (oci_hook->args == NULL) { ++ ERROR("Failed to copy args"); ++ goto error_out; ++ } ++ oci_hook->args_len = h->args_len; ++ } ++ if (h->env_len != 0) { ++ oci_hook->env = util_copy_array_by_len(h->env, h->env_len); ++ if (oci_hook->env == NULL) { ++ ERROR("Failed to copy env"); ++ goto error_out; ++ } ++ oci_hook->env_len = h->env_len; ++ } ++ oci_hook->timeout = h->timeout; ++ return oci_hook; ++ ++error_out: ++ free_defs_hook(oci_hook); ++ return NULL; ++} ++ ++static defs_mount *cdi_mount_to_oci(cdi_mount *m) ++{ ++ defs_mount *oci_mount = NULL; ++ ++ oci_mount = util_common_calloc_s(sizeof(*oci_mount)); ++ if (oci_mount == NULL) { ++ ERROR("Out of memory"); ++ return NULL; ++ } ++ ++ oci_mount->source = util_strdup_s(m->host_path); ++ oci_mount->destination = util_strdup_s(m->container_path); ++ if (m->options_len != 0) { ++ oci_mount->options = util_copy_array_by_len(m->options, m->options_len); ++ if (oci_mount->options == NULL) { ++ ERROR("Failed to copy options"); ++ free_defs_mount(oci_mount); ++ return NULL; ++ } ++ oci_mount->options_len = m->options_len; ++ } ++ oci_mount->type = util_strdup_s(m->type); ++ ++ return oci_mount; ++} ++ ++static defs_device *cdi_device_node_to_oci(cdi_device_node *d) ++{ ++ defs_device *oci_device = NULL; ++ ++ oci_device = util_common_calloc_s(sizeof(*oci_device)); ++ if (oci_device == NULL) { ++ ERROR("Out of memory"); ++ return NULL; ++ } ++ ++ oci_device->path = util_strdup_s(d->path); ++ oci_device->type = util_strdup_s(d->type); ++ oci_device->major = d->major; ++ oci_device->minor = d->minor; ++ oci_device->file_mode = d->file_mode; ++ oci_device->uid = d->uid; ++ oci_device->gid = d->gid; ++ ++ return oci_device; ++} ++ ++static int apply_cdi_device_nodes(cdi_container_edits *e, oci_runtime_spec *spec) ++{ ++ size_t i; ++ defs_device *dev = NULL; ++ cdi_device_node *dn = NULL; ++ const char *access = NULL; ++ ++ for (i = 0; i < e->device_nodes_len; i++) { ++ dn = clone_cdi_device_node(e->device_nodes[i]); ++ if (dn == NULL) { ++ ERROR("Failed to copy device node"); ++ goto error_out; ++ } ++ ++ if (fill_device_node_info(dn) != 0) { ++ goto error_out; ++ } ++ dev = cdi_device_node_to_oci(dn); ++ if (dev == NULL) { ++ ERROR("Failed to generate oci device"); ++ goto error_out; ++ } ++ /* Currently, for uid and gid, isulad cannot distinguish ++ * 0 and unspecified. Here, 0 is processed as unspecified. ++ */ ++ if (dev->uid == 0 && spec->process != NULL) { ++ if (spec->process->user->uid > 0) { ++ dev->uid = spec->process->user->uid; ++ } ++ } ++ if (dev->gid == 0 && spec->process != NULL) { ++ if (spec->process->user->gid > 0) { ++ dev->gid = spec->process->user->gid; ++ } ++ } ++ ++ if (spec_add_device(spec, dev) != 0) { ++ goto error_out; ++ } ++ ++ if (strcmp(dev->type, BLOCK_DEVICE) == 0 || strcmp(dev->type, CHAR_DEVICE) == 0) { ++ if (e->device_nodes[i]->permissions != NULL) { ++ access = e->device_nodes[i]->permissions; ++ } else { ++ access = "rwm"; ++ } ++ if (spec_add_linux_resources_device(spec, true, dev->type, ++ dev->major, dev->minor, access)) { ++ dev = NULL; ++ goto error_out; ++ } ++ } ++ free_cdi_device_node(dn); ++ dn = NULL; ++ dev = NULL; ++ } ++ ++ return 0; ++ ++error_out: ++ free_cdi_device_node(dn); ++ free_defs_device(dev); ++ return -1; ++} ++ ++static int defs_mount_parts(defs_mount *m) ++{ ++ char cleanpath[PATH_MAX] = { 0 }; ++ if (util_clean_path(m->destination, cleanpath, sizeof(cleanpath)) == NULL) { ++ return -1; ++ } ++ ++ return util_strings_count(cleanpath, '/'); ++} ++ ++static inline int defs_mount_cmp(defs_mount **first, defs_mount **second) ++{ ++ int first_part = defs_mount_parts(*first); ++ int second_part = defs_mount_parts(*second); ++ ++ if (first_part < second_part) { ++ return -1; ++ } ++ if (first_part > second_part) { ++ return 1; ++ } ++ ++ return strcmp((*first)->destination, (*second)->destination); ++} ++ ++static int apply_cdi_mounts(cdi_container_edits *e, oci_runtime_spec *spec) ++{ ++ size_t i; ++ defs_mount *mnt = NULL; ++ ++ if (e->mounts_len == 0) { ++ return 0; ++ } ++ ++ for (i = 0; i < e->mounts_len; i++) { ++ spec_remove_mount(spec, e->mounts[i]->container_path); ++ mnt = cdi_mount_to_oci(e->mounts[i]); ++ if (spec_add_mount(spec, mnt) != 0) { ++ free_defs_mount(mnt); ++ return -1; ++ } ++ } ++ ++ qsort(spec->mounts, spec->mounts_len, ++ sizeof(defs_mount *), (int (*)(const void *, const void *))defs_mount_cmp); ++ return 0; ++} ++ ++static int apply_cdi_hooks(cdi_container_edits *e, oci_runtime_spec *spec) ++{ ++ size_t i; ++ int ret = 0; ++ ++ for (i = 0; i < e->hooks_len; i++) { ++ defs_hook *oci_hook = cdi_hook_to_oci(e->hooks[i]); ++ if (strcmp(e->hooks[i]->hook_name, PRESTART_HOOK)) { ++ ret = spec_add_prestart_hook(spec, oci_hook); ++ } else if (strcmp(e->hooks[i]->hook_name, POSTSTART_HOOK)) { ++ ret = spec_add_poststart_hook(spec, oci_hook); ++ } else if (strcmp(e->hooks[i]->hook_name, POSTSTOP_HOOK)) { ++ ret = spec_add_poststop_hook(spec, oci_hook); ++ } else { ++ /* ++ * The OCI being used by the iSulad not supportes ++ * createRuntime/createContainer/startContainer currently. ++ */ ++ ERROR("Unknown hook name %s", e->hooks[i]->hook_name); ++ free_defs_hook(oci_hook); ++ return -1; ++ } ++ if (ret != 0) { ++ ERROR("Failed add hook %s", e->hooks[i]->hook_name); ++ free_defs_hook(oci_hook); ++ return -1; ++ } ++ } ++ return ret; ++} ++ + int cdi_container_edits_apply(cdi_container_edits *e, oci_runtime_spec *spec) + { ++ if (spec == NULL) { ++ ERROR("Can't edit nil OCI Spec"); ++ return -1; ++ } ++ if (e == NULL) { ++ WARN("Cdi container edits is nil"); ++ return 0; ++ } ++ ++ if (e->env_len > 0) { ++ if (spec_add_multiple_process_env(spec, (const char **)e->env, e->env_len) != 0) { ++ ERROR("Failed to merge envs"); ++ return -1; ++ } ++ } ++ ++ if (apply_cdi_device_nodes(e, spec) != 0) { ++ ERROR("Failed to apply device nodes"); ++ return -1; ++ } ++ ++ if (apply_cdi_mounts(e, spec) != 0) { ++ ERROR("Failed to apply mounts"); ++ return -1; ++ } ++ ++ if (apply_cdi_hooks(e, spec) != 0) { ++ ERROR("Failed to apply hooks"); ++ return -1; ++ } ++ + return 0; + } + +-int cdi_container_edits_validate(cdi_container_edits *e, char **error) ++int cdi_container_edits_validate(cdi_container_edits *e) + { ++ size_t i; ++ ++ if (e == NULL) { ++ WARN("Cdi container edits is nil"); ++ return 0; ++ } ++ ++ if (cdi_validate_env(e->env, e->env_len) != 0) { ++ ERROR("Invalid container edits"); ++ return -1; ++ } ++ for (i = 0; i < e->device_nodes_len; i++) { ++ if (cdi_validate_device_node(e->device_nodes[i]) != 0) { ++ ERROR("Invalid container device node"); ++ return -1; ++ } ++ } ++ for (i = 0; i < e->hooks_len; i++) { ++ if (cdi_validate_hook(e->hooks[i]) != 0) { ++ ERROR("Invalid container hook"); ++ return -1; ++ } ++ } ++ for (i = 0; i < e->mounts_len; i++) { ++ if (cdi_validate_mount(e->mounts[i]) != 0) { ++ ERROR("Invalid container mount"); ++ return -1; ++ } ++ } ++ + return 0; + } + ++#define EDITS_APPEND_ITEM_DEF(item) \ ++ static int append_##item(cdi_container_edits *e, cdi_container_edits *o, clone_common_array_item_cb cb) \ ++ { \ ++ common_array e_array = { \ ++ .items = (void **)e->item, \ ++ .len = e->item##_len, \ ++ .cap = e->item##_len, \ ++ .free_item_cb = NULL, \ ++ .clone_item_cb = cb \ ++ }; \ ++ common_array o_array = { \ ++ .items = (void **)o->item, \ ++ .len = o->item##_len, \ ++ .cap = o->item##_len, \ ++ .free_item_cb = NULL, \ ++ .clone_item_cb = cb \ ++ }; \ ++ if (util_merge_common_array(&e_array, &o_array) != 0) { \ ++ ERROR("Out of memory"); \ ++ return -1; \ ++ } \ ++ e->item = (void *)e_array.items; \ ++ e->item##_len += o->item##_len; \ ++ return 0; \ ++ } ++ ++EDITS_APPEND_ITEM_DEF(env) ++EDITS_APPEND_ITEM_DEF(device_nodes) ++EDITS_APPEND_ITEM_DEF(hooks) ++EDITS_APPEND_ITEM_DEF(mounts) ++ + int cdi_container_edits_append(cdi_container_edits *e, cdi_container_edits *o) + { ++ if (o == NULL) { ++ return 0; ++ } ++ if (e == NULL) { ++ ERROR("Invalid params"); ++ return -1; ++ } ++ ++ if (append_env(e, o, (clone_common_array_item_cb)util_strdup_s) != 0) { ++ return -1; ++ } ++ if (append_device_nodes(e, o, (clone_common_array_item_cb)clone_cdi_device_node) != 0) { ++ return -1; ++ } ++ if (append_hooks(e, o, (clone_common_array_item_cb)clone_cdi_hook) != 0) { ++ return -1; ++ } ++ if (append_mounts(e, o, (clone_common_array_item_cb)clone_cdi_mount) != 0) { ++ return -1; ++ } ++ + return 0; + } + + bool cdi_container_edits_is_empty(cdi_container_edits *e) + { +- return true; ++ if (e == NULL) { ++ return false; ++ } ++ return e->env_len + e->device_nodes_len + e->hooks_len + e->mounts_len == 0; + } + ++static int cdi_validate_env(char **envs, size_t envs_len) ++{ ++ size_t i; ++ char *ptr = NULL; ++ ++ for (i = 0; i < envs_len; i++) { ++ ptr = strchr(envs[i], '='); ++ if (ptr == NULL || ptr == envs[i]) { ++ ERROR("Invalid environment variable %s", envs[i]); ++ return -1; ++ } ++ } ++ return 0; ++} ++ ++static int cdi_validate_device_node(cdi_device_node *d) ++{ ++ char *p = NULL; ++ ++ if (d == NULL) { ++ ERROR("Device node is nil"); ++ return -1; ++ } ++ ++ if (d->path == NULL) { ++ ERROR("Invalid (empty) device path"); ++ return -1; ++ } ++ if (d->type != NULL && strcmp(d->type, BLOCK_DEVICE) != 0 && ++ strcmp(d->type, CHAR_DEVICE) != 0 && strcmp(d->type, FIFO_DEVICE) != 0) { ++ ERROR("Device %s: invalid type %s", d->path, d->type); ++ return -1; ++ } ++ for (p = d->permissions; p != NULL && *p != '\0'; p++) { ++ if (*p != 'r' && *p != 'w' && *p != 'm') { ++ ERROR("Device %s: invalid permissions %s", d->path, d->permissions); ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ ++static int cdi_validate_hook(cdi_hook *h) ++{ ++ size_t i; ++ ++ if (h == NULL) { ++ ERROR("Hook is nil"); ++ return -1; ++ } ++ ++ for (i = 0; i < VALID_HOOK_NAME_LEN; i++) { ++ if (strcmp(h->hook_name, g_valid_hook_names[i]) == 0) { ++ break; ++ } ++ } ++ if (i == VALID_HOOK_NAME_LEN) { ++ ERROR("Invalid hook name %s", h->hook_name); ++ return -1; ++ } ++ if (h->path == NULL) { ++ ERROR("Invalid hook %s with empty path", h->hook_name); ++ return -1; ++ } ++ if (cdi_validate_env(h->env, h->env_len) != 0) { ++ ERROR("Invalid hook %s", h->hook_name); ++ return -1; ++ } ++ return 0; ++} ++ ++static int cdi_validate_mount(cdi_mount *m) ++{ ++ if (m == NULL) { ++ ERROR("Mount is nil"); ++ return -1; ++ } ++ ++ if (m->host_path == NULL) { ++ ERROR("Invalid mount, empty host path"); ++ return -1; ++ } ++ if (m->container_path == NULL) { ++ ERROR("Invalid mount, empty container path"); ++ return -1; ++ } ++ return 0; ++} +diff --git a/src/daemon/modules/device/cdi/behavior/cdi_container_edits.h b/src/daemon/modules/device/cdi/behavior/cdi_container_edits.h +index ea921e37..ddceec25 100644 +--- a/src/daemon/modules/device/cdi/behavior/cdi_container_edits.h ++++ b/src/daemon/modules/device/cdi/behavior/cdi_container_edits.h +@@ -28,7 +28,7 @@ extern "C" { + #endif + + int cdi_container_edits_apply(cdi_container_edits *e, oci_runtime_spec *spec); +-int cdi_container_edits_validate(cdi_container_edits *e, char **error); ++int cdi_container_edits_validate(cdi_container_edits *e); + int cdi_container_edits_append(cdi_container_edits *e, cdi_container_edits *o); + bool cdi_container_edits_is_empty(cdi_container_edits *e); + +diff --git a/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.c b/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.c +index 14293c72..8824d29c 100644 +--- a/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.c ++++ b/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.c +@@ -14,42 +14,228 @@ + ******************************************************************************/ + #include "cdi_parser.h" + ++#include ++#include ++#include ++#include ++#include ++ ++#include "error.h" ++#include "utils_string.h" ++ ++/* cdi_parser_qualified_name returns the qualified name for a device. ++ * The syntax for a qualified device names is ++ * ++ * "/=". ++ * ++ * A valid vendor and class name may contain the following runes: ++ * ++ * 'A'-'Z', 'a'-'z', '0'-'9', '.', '-', '_'. ++ * ++ * A valid device name may contain the following runes: ++ * ++ * 'A'-'Z', 'a'-'z', '0'-'9', '-', '_', '.', ':' ++ */ + char *cdi_parser_qualified_name(const char *vendor, const char *class, const char *name) + { +- return NULL; ++ char device_name[PATH_MAX] = { 0 }; ++ int nret; ++ ++ if (vendor == NULL || class == NULL || name == NULL) { ++ ERROR("Invalid argument"); ++ return NULL; ++ } ++ ++ nret = snprintf(device_name, sizeof(device_name), "%s/%s=%s", ++ vendor, class, name); ++ if (nret < 0 || (size_t)nret >= sizeof(device_name)) { ++ ERROR("Device name is too long"); ++ return NULL; ++ } ++ return util_strdup_s(device_name); + } + ++// cdi_parser_is_qualified_name tests if a device name is qualified. + bool cdi_parser_is_qualified_name(const char *device) + { +- return true; ++ __isula_auto_free char *vendor = NULL; ++ __isula_auto_free char *class = NULL; ++ __isula_auto_free char *name = NULL; ++ ++ return cdi_parser_parse_qualified_name(device, &vendor, &class, &name) == 0; + } + ++// cdi_parser_parse_qualified_name splits a qualified name into device vendor, class, and name. + int cdi_parser_parse_qualified_name(const char *device, char **vendor, char **class, char **name) + { ++ int ret = 0; ++ ++ ret = cdi_parser_parse_device(device, vendor, class, name); ++ if (ret != 0) { ++ if (*vendor == NULL) { ++ ERROR("Unqualified device %s, missing vendor", device); ++ return -1; ++ } ++ if (*class == NULL) { ++ ERROR("Unqualified device %s, missing class", device); ++ return -1; ++ } ++ if (*name == NULL) { ++ ERROR("Unqualified device %s, missing name", device); ++ return -1; ++ } ++ ERROR("Unqualified device %s", device); ++ return -1; ++ } ++ ++ if (cdi_parser_validate_vendor_name(*vendor) != 0) { ++ ERROR("Invalid device %s", device); ++ goto err_out; ++ } ++ if (cdi_parser_validate_class_name(*class) != 0) { ++ ERROR("Invalid device %s", device); ++ goto err_out; ++ } ++ if (cdi_parser_validate_device_name(*name) != 0) { ++ ERROR("Invalid device %s", device); ++ goto err_out; ++ } ++ + return 0; ++ ++err_out: ++ free(*vendor); ++ *vendor = NULL; ++ free(*class); ++ *class = NULL; ++ free(*name); ++ *name = NULL; ++ return -1; + } + ++// cdi_parser_parse_device tries to split a device name into vendor, class, and name. + int cdi_parser_parse_device(const char *device, char **vendor, char **class, char **name) + { ++ __isula_auto_array_t char **parts = NULL; ++ ++ if (vendor == NULL || class == NULL || name == NULL || ++ device == NULL || device[0] == '/') { ++ ERROR("Invalid argument"); ++ return -1; ++ } ++ ++ parts = util_string_split_n(device, '=', 2); ++ if (parts == NULL || util_array_len((const char **)parts) != 2 || parts[0] == NULL || parts[1] == NULL) { ++ return -1; ++ } ++ ++ *name = parts[1]; ++ parts[1] = NULL; ++ (void)cdi_parser_parse_qualifier(parts[0], vendor, class); ++ if (*vendor == NULL) { ++ ERROR("Failed to parse device qualifier: %s", parts[0]); ++ return -1; ++ } ++ + return 0; + } + ++/* cdi_parser_parse_qualifier splits a device qualifier into vendor and class. ++ * The syntax for a device qualifier is ++ * ++ * "/" ++ */ + int cdi_parser_parse_qualifier(const char *kind, char **vendor, char **class) + { ++ __isula_auto_array_t char **parts = NULL; ++ ++ if (kind == NULL || vendor == NULL || class == NULL) { ++ ERROR("Invalid argument"); ++ return -1; ++ } ++ ++ parts = util_string_split_n(kind, '/', 2); ++ if (parts == NULL || util_array_len((const char **)parts) != 2 || parts[0] == NULL || parts[1] == NULL) { ++ return -1; ++ } ++ *vendor = parts[0]; ++ parts[0] = NULL; ++ *class = parts[1]; ++ parts[1] = NULL; ++ ++ return 0; ++} ++ ++static int validate_vendor_or_class_name(const char *name) ++{ ++ int i = 0; ++ ++ if (name == NULL) { ++ ERROR("Empty name"); ++ return -1; ++ } ++ ++ if (!isalpha(name[0])) { ++ ERROR("%s, should start with letter", name); ++ return -1; ++ } ++ for (i = 1; name[i] != '\0'; i++) { ++ if (!(isalnum(name[i]) || name[i] == '_' || name[i] == '-' || name[i] == '.')) { ++ ERROR("Invalid character '%c' in name %s", name[i], name); ++ return -1; ++ } ++ } ++ if (!isalnum(name[i - 1])) { ++ ERROR("%s, should end with a letter or digit", name); ++ return -1; ++ } ++ + return 0; + } + +-int cdi_parser_validate_vendor_name(const char *vendor, char **error) ++int cdi_parser_validate_vendor_name(const char *vendor) + { ++ if (validate_vendor_or_class_name(vendor) != 0) { ++ ERROR("Invalid vendor"); ++ return -1; ++ } + return 0; + } + +-int cdi_parser_validate_class_name(const char *class, char **error) ++int cdi_parser_validate_class_name(const char *class) + { ++ if (validate_vendor_or_class_name(class) != 0) { ++ ERROR("Invalid class."); ++ return -1; ++ } + return 0; + } + +-int cdi_parser_validate_device_name(const char *name, char **error) ++int cdi_parser_validate_device_name(const char *name) + { ++ size_t i; ++ ++ if (name == NULL) { ++ ERROR("Invalid (empty) device name"); ++ return -1; ++ } ++ if (!isalnum(name[0])) { ++ ERROR("Invalid class %s, should start with a letter or digit", name); ++ return -1; ++ } ++ if (strlen(name) == 1) { ++ return 0; ++ } ++ for (i = 1; name[i] != '\0'; i++) { ++ if (!(isalnum(name[i]) || name[i] == '_' || name[i] == '-' || name[i] == '.' || name[i] == ':')) { ++ ERROR("Invalid character '%c' in device name %s", name[i], name); ++ return -1; ++ } ++ } ++ if (!isalnum(name[i - 1])) { ++ ERROR("Invalid name %s, should end with a letter or digit", name); ++ return -1; ++ } ++ + return 0; + } +diff --git a/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.h b/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.h +index 467641a1..3658e29b 100644 +--- a/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.h ++++ b/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.h +@@ -27,9 +27,9 @@ bool cdi_parser_is_qualified_name(const char *device); + int cdi_parser_parse_qualified_name(const char *device, char **vendor, char **class, char **name); + int cdi_parser_parse_device(const char *device, char **vendor, char **class, char **name); + int cdi_parser_parse_qualifier(const char *kind, char **vendor, char **class); +-int cdi_parser_validate_vendor_name(const char *vendor, char **error); +-int cdi_parser_validate_class_name(const char *class, char **error); +-int cdi_parser_validate_device_name(const char *name, char **error); ++int cdi_parser_validate_vendor_name(const char *vendor); ++int cdi_parser_validate_class_name(const char *class); ++int cdi_parser_validate_device_name(const char *name); + + #ifdef __cplusplus + } +diff --git a/src/daemon/modules/spec/specs.c b/src/daemon/modules/spec/specs.c +index b4d2b0f6..77ca70f9 100644 +--- a/src/daemon/modules/spec/specs.c ++++ b/src/daemon/modules/spec/specs.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + + #include "specs_api.h" + #include "utils.h" +@@ -2595,3 +2596,232 @@ int spec_module_init(void) + return 0; + } + ++#ifdef ENABLE_CDI ++static int add_env(defs_process *dp, const char *env, const char *key) ++{ ++ size_t i; ++ char *oci_key = NULL; ++ char *oci_value = NULL; ++ char *saveptr = NULL; ++ __isula_auto_free char *tmp_env = NULL; ++ ++ for (i = 0; i < dp->env_len; i++) { ++ tmp_env = util_strdup_s(dp->env[i]); ++ oci_key = strtok_r(tmp_env, "=", &saveptr); ++ oci_value = strtok_r(NULL, "=", &saveptr); ++ if (oci_key == NULL || oci_value == NULL) { ++ ERROR("Bad env format"); ++ return -1; ++ } ++ if (strcmp(key, oci_key) == 0) { ++ free(dp->env[i]); ++ dp->env[i] = util_strdup_s(env); ++ return 0; ++ } ++ free(tmp_env); ++ tmp_env = NULL; ++ } ++ if (util_mem_realloc((void **)&dp->env, (dp->env_len + 1) * sizeof(char *), ++ (void *)dp->env, dp->env_len * sizeof(char *)) != 0) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ dp->env[dp->env_len] = util_strdup_s(env); ++ dp->env_len++; ++ return 0; ++} ++ ++int defs_process_add_multiple_env(defs_process *dp, const char **envs, size_t env_len) ++{ ++ size_t i; ++ char *key = NULL; ++ char *value = NULL; ++ char *saveptr = NULL; ++ __isula_auto_free char *tmp_env = NULL; ++ ++ if (envs == NULL || env_len == 0) { ++ DEBUG("empty envs"); ++ return 0; ++ } ++ if (dp == NULL) { ++ ERROR("Invalid params"); ++ return -1; ++ } ++ ++ for (i = 0; i < env_len; i++) { ++ tmp_env = util_strdup_s(envs[i]); ++ key = strtok_r(tmp_env, "=", &saveptr); ++ value = strtok_r(NULL, "=", &saveptr); ++ if (key == NULL || value == NULL) { ++ ERROR("Bad env format: %s", tmp_env); ++ return -1; ++ } ++ if (add_env(dp, envs[i], key) != 0) { ++ return -1; ++ } ++ free(tmp_env); ++ tmp_env = NULL; ++ } ++ ++ return 0; ++} ++ ++int spec_add_multiple_process_env(oci_runtime_spec *oci_spec, const char **envs, size_t env_len) ++{ ++ int ret = 0; ++ ++ if (envs == NULL || env_len == 0) { ++ DEBUG("empty envs"); ++ return 0; ++ } ++ if (oci_spec == NULL) { ++ ERROR("Invalid params"); ++ return -1; ++ } ++ ++ ret = make_sure_oci_spec_process(oci_spec); ++ if (ret < 0) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ ++ ret = defs_process_add_multiple_env(oci_spec->process, envs, env_len); ++ if (ret < 0) { ++ ERROR("Failed to add envs"); ++ } ++ ++ return ret; ++} ++ ++int spec_add_device(oci_runtime_spec *oci_spec, defs_device *device) ++{ ++ int ret = 0; ++ size_t i; ++ ++ if (device == NULL) { ++ return -1; ++ } ++ ret = make_sure_oci_spec_linux(oci_spec); ++ if (ret < 0) { ++ return -1; ++ } ++ ++ for (i = 0; i < oci_spec->linux->devices_len; i++) { ++ if (strcmp(oci_spec->linux->devices[i]->path, device->path) == 0) { ++ free_defs_device(oci_spec->linux->devices[i]); ++ oci_spec->linux->devices[i] = device; ++ return 0; ++ } ++ } ++ ++ if (util_mem_realloc((void **)&oci_spec->linux->devices, (oci_spec->linux->devices_len + 1) * sizeof(char *), ++ (void *)oci_spec->linux->devices, oci_spec->linux->devices_len * sizeof(char *)) != 0) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ oci_spec->linux->devices[oci_spec->linux->devices_len] = device; ++ oci_spec->linux->devices_len++; ++ ++ return 0; ++} ++ ++int spec_add_linux_resources_device(oci_runtime_spec *oci_spec, bool allow, const char *dev_type, ++ int64_t major, int64_t minor, const char *access) ++{ ++ int ret = 0; ++ defs_device_cgroup *device = NULL; ++ ++ ret = make_sure_oci_spec_linux_resources(oci_spec); ++ if (ret < 0) { ++ return -1; ++ } ++ ++ device = util_common_calloc_s(sizeof(*device)); ++ if (device == NULL) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ device->allow = allow; ++ device->type = util_strdup_s(dev_type); ++ device->access = util_strdup_s(access); ++ device->major = major; ++ device->minor = minor; ++ ++ if (util_mem_realloc((void **)&oci_spec->linux->resources->devices, (oci_spec->linux->resources->devices_len + 1) * sizeof(char *), ++ (void *)oci_spec->linux->resources->devices, oci_spec->linux->resources->devices_len * sizeof(char *)) != 0) { ++ ERROR("Out of memory"); ++ free_defs_device_cgroup(device); ++ return -1; ++ } ++ oci_spec->linux->resources->devices[oci_spec->linux->resources->devices_len] = device; ++ oci_spec->linux->resources->devices_len++; ++ ++ return 0; ++} ++ ++void spec_remove_mount(oci_runtime_spec *oci_spec, const char *dest) ++{ ++ size_t i; ++ ++ if (oci_spec == NULL || oci_spec->mounts == NULL || dest == NULL) { ++ return; ++ } ++ ++ for (i = 0; i < oci_spec->mounts_len; i++) { ++ if (strcmp(oci_spec->mounts[i]->destination, dest) == 0) { ++ free_defs_mount(oci_spec->mounts[i]); ++ (void)memcpy((void **)&oci_spec->mounts[i], (void **)&oci_spec->mounts[i + 1], ++ (oci_spec->mounts_len - i - 1) * sizeof(void *)); ++ oci_spec->mounts_len--; ++ return; ++ } ++ } ++} ++ ++int spec_add_mount(oci_runtime_spec *oci_spec, defs_mount *mnt) ++{ ++ if (oci_spec == NULL || mnt == NULL) { ++ return -1; ++ } ++ ++ if (util_mem_realloc((void **)&oci_spec->mounts, (oci_spec->mounts_len + 1) * sizeof(char *), ++ (void *)oci_spec->mounts, oci_spec->mounts_len * sizeof(char *)) != 0) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ oci_spec->mounts[oci_spec->mounts_len] = mnt; ++ oci_spec->mounts_len++; ++ ++ return 0; ++} ++ ++#define SPEC_ADD_HOOKS_ITEM_DEF(hooktype) \ ++ int spec_add_##hooktype##_hook(oci_runtime_spec *oci_spec, defs_hook *hooktype##_hook) \ ++ { \ ++ int ret = 0; \ ++ if (oci_spec == NULL || hooktype##_hook == NULL) { \ ++ return -1; \ ++ } \ ++ ret = make_sure_oci_spec_hooks(oci_spec); \ ++ if (ret < 0) { \ ++ return -1; \ ++ } \ ++ if (util_mem_realloc((void **)&oci_spec->hooks->hooktype, (oci_spec->hooks->hooktype##_len + 1) * sizeof(char *), \ ++ (void *)oci_spec->hooks->hooktype, oci_spec->hooks->hooktype##_len * sizeof(char *)) != 0) { \ ++ ERROR("Out of memory"); \ ++ return -1; \ ++ } \ ++ oci_spec->hooks->hooktype[oci_spec->hooks->hooktype##_len] = hooktype##_hook; \ ++ oci_spec->hooks->hooktype##_len++; \ ++ return 0; \ ++ } ++ ++/* ++* The OCI being used by the iSulad not supportes ++* createRuntime/createContainer/startContainer currently. ++*/ ++SPEC_ADD_HOOKS_ITEM_DEF(prestart) ++SPEC_ADD_HOOKS_ITEM_DEF(poststart) ++SPEC_ADD_HOOKS_ITEM_DEF(poststop) ++ ++#endif /* ENABLE_CDI */ +\ No newline at end of file +-- +2.34.1 + diff --git a/0068-cdi-invoke-cdi-operate-when-init-isulad-and-create-c.patch b/0068-cdi-invoke-cdi-operate-when-init-isulad-and-create-c.patch new file mode 100644 index 0000000..3633616 --- /dev/null +++ b/0068-cdi-invoke-cdi-operate-when-init-isulad-and-create-c.patch @@ -0,0 +1,371 @@ +From 0674bfac4dd1ab812432334c779ab718dc54bc8b Mon Sep 17 00:00:00 2001 +From: liuxu +Date: Thu, 11 Apr 2024 11:02:19 +0800 +Subject: [PATCH 68/69] cdi:invoke cdi operate when init isulad and create + container + +--- + src/cmd/isulad/main.c | 11 +++ + src/daemon/common/cri/v1/v1_cri_helpers.cc | 79 +++++++++++++++++++ + src/daemon/common/cri/v1/v1_cri_helpers.h | 3 + + src/daemon/config/daemon_arguments.c | 4 + + src/daemon/config/isulad_config.c | 8 ++ + .../v1/v1_cri_container_manager_service.cc | 8 ++ + .../executor/container_cb/execution_create.c | 9 +++ + .../modules/service/service_container.c | 10 +++ + src/daemon/modules/spec/specs_mount.c | 43 +++++++++- + src/daemon/modules/spec/specs_mount.h | 4 + + src/daemon/modules/spec/verify.c | 2 +- + 11 files changed, 179 insertions(+), 2 deletions(-) + +diff --git a/src/cmd/isulad/main.c b/src/cmd/isulad/main.c +index 9fa87bdb..3e2249d7 100644 +--- a/src/cmd/isulad/main.c ++++ b/src/cmd/isulad/main.c +@@ -83,6 +83,9 @@ + #endif + #include "id_name_manager.h" + #include "cgroup.h" ++#ifdef ENABLE_CDI ++#include "cdi_operate_api.h" ++#endif /* ENABLE_CDI */ + + sem_t g_daemon_shutdown_sem; + sem_t g_daemon_wait_shutdown_sem; +@@ -1400,6 +1403,14 @@ static int isulad_server_init_common() + } + #endif + ++#ifdef ENABLE_CDI ++ if (args->json_confs->enable_cdi && ++ cdi_operate_registry_init(args->json_confs->cdi_spec_dirs, args->json_confs->cdi_spec_dirs_len) != 0) { ++ ERROR("Failed to init CDI module"); ++ goto out; ++ } ++#endif /* ENABLE_CDI */ ++ + if (spec_module_init() != 0) { + ERROR("Failed to init spec module"); + goto out; +diff --git a/src/daemon/common/cri/v1/v1_cri_helpers.cc b/src/daemon/common/cri/v1/v1_cri_helpers.cc +index ea5c8bb5..520d23d4 100644 +--- a/src/daemon/common/cri/v1/v1_cri_helpers.cc ++++ b/src/daemon/common/cri/v1/v1_cri_helpers.cc +@@ -22,6 +22,7 @@ + + #include + #include ++#include + + #include "v1_cri_security_context.h" + #include "cri_helpers.h" +@@ -33,6 +34,9 @@ + #include "isulad_config.h" + #include "sha256.h" + #include "v1_naming.h" ++#ifdef ENABLE_CDI ++#include "cdi_operate_api.h" ++#endif /* ENABLE_CDI */ + + namespace CRIHelpersV1 { + +@@ -666,4 +670,79 @@ std::unique_ptr GetContainerStatus(service_executo + return contStatus; + } + ++#ifdef ENABLE_CDI ++static int InsertCDIDevices(std::unordered_set &fromCRI, const std::string &devName, ++ string_array *requested, Errors &err) ++{ ++ if (fromCRI.find(devName) == fromCRI.end()) { ++ fromCRI.insert(devName); ++ if (util_append_string_array(requested, devName.c_str()) != 0) { ++ ERROR("Out of memory"); ++ err.Errorf("Out of memory"); ++ return -1; ++ } ++ DEBUG("Appended device: %s", devName.c_str()); ++ } else { ++ INFO("Skipping duplicate CDI device %s", devName.c_str()); ++ } ++ return 0; ++} ++ ++void GenerateCDIRequestedDevices(const runtime::v1::ContainerConfig &config, host_config *hostconfig, Errors &err) ++{ ++ std::unordered_set fromCRI; ++ __isula_auto_string_array_t string_array *requested = nullptr; ++ __isula_auto_string_array_t string_array *keys = nullptr; ++ __isula_auto_string_array_t string_array *devices = nullptr; ++ json_map_string_string *annotations = nullptr; ++ __isula_auto_free char *error = nullptr; ++ ++ if (hostconfig == nullptr) { ++ ERROR("Invalid input arguments"); ++ err.Errorf("Invalid input arguments"); ++ return; ++ } ++ ++ if (config.cdi_devices().empty() && config.annotations().empty()) { ++ return; ++ } ++ requested = (string_array *)util_common_calloc_s(sizeof(*requested)); ++ if (requested == nullptr) { ++ ERROR("Out of memory"); ++ err.Errorf("Out of memory"); ++ return; ++ } ++ if (!config.cdi_devices().empty()) { ++ for (int i = 0; i < config.cdi_devices().size(); i++) { ++ if (InsertCDIDevices(fromCRI, config.cdi_devices(i).name(), requested, err) != 0) { ++ goto free_out; ++ } ++ } ++ } ++ if (!config.annotations().empty()) { ++ annotations = CRIHelpers::MakeAnnotations(config.annotations(), err); ++ if (err.NotEmpty()) { ++ goto free_out; ++ } ++ if (cdi_operate_parse_annotations(annotations, &keys, &devices, &error) != 0) { ++ ERROR("Failed to parse CDI annotations: %s", error); ++ err.Errorf("Failed to parse CDI annotations: %s", error); ++ goto free_out; ++ } ++ for (size_t i = 0; i < devices->len; i++) { ++ if (InsertCDIDevices(fromCRI, std::string(devices->items[i]), requested, err) != 0) { ++ goto free_out; ++ } ++ } ++ } ++ hostconfig->cdi_requested_devices = requested->items; ++ requested->items = nullptr; ++ hostconfig->cdi_requested_devices_len = requested->len; ++ requested->len = 0; ++ ++free_out: ++ free_json_map_string_string(annotations); ++} ++#endif /* ENABLE_CDI */ ++ + } // v1 namespace CRIHelpers +diff --git a/src/daemon/common/cri/v1/v1_cri_helpers.h b/src/daemon/common/cri/v1/v1_cri_helpers.h +index 1578c428..22cffd0d 100644 +--- a/src/daemon/common/cri/v1/v1_cri_helpers.h ++++ b/src/daemon/common/cri/v1/v1_cri_helpers.h +@@ -79,6 +79,9 @@ std::string CRISandboxerConvert(const std::string &runtime); + + void ApplySandboxSecurityContextToHostConfig(const runtime::v1::LinuxSandboxSecurityContext &context, host_config *hc, + Errors &error); ++#ifdef ENABLE_CDI ++void GenerateCDIRequestedDevices(const runtime::v1::ContainerConfig &config, host_config *hostconfig, Errors &err); ++#endif /* ENABLE_CDI */ + + auto GetContainerStatus(service_executor_t *m_cb, const std::string &containerID, Errors &error) + -> std::unique_ptr; +diff --git a/src/daemon/config/daemon_arguments.c b/src/daemon/config/daemon_arguments.c +index 0ae6268a..ef15934a 100644 +--- a/src/daemon/config/daemon_arguments.c ++++ b/src/daemon/config/daemon_arguments.c +@@ -173,6 +173,10 @@ int service_arguments_init(struct service_arguments *args) + goto free_out; + } + ++#ifdef ENABLE_CDI ++ args->json_confs->enable_cdi = false; ++#endif /* ENABLE_CDI */ ++ + ret = 0; + + free_out: +diff --git a/src/daemon/config/isulad_config.c b/src/daemon/config/isulad_config.c +index 778ff921..695a0d95 100644 +--- a/src/daemon/config/isulad_config.c ++++ b/src/daemon/config/isulad_config.c +@@ -1830,6 +1830,14 @@ int merge_json_confs_into_global(struct service_arguments *args) + args->json_confs->metrics_port = tmp_json_confs->metrics_port; + #endif + ++#ifdef ENABLE_CDI ++ args->json_confs->enable_cdi = tmp_json_confs->enable_cdi; ++ args->json_confs->cdi_spec_dirs = tmp_json_confs->cdi_spec_dirs; ++ tmp_json_confs->cdi_spec_dirs = NULL; ++ args->json_confs->cdi_spec_dirs_len = tmp_json_confs->cdi_spec_dirs_len; ++ tmp_json_confs->cdi_spec_dirs_len = 0; ++#endif /* ENABLE_CDI */ ++ + out: + free(err); + free_isulad_daemon_configs(tmp_json_confs); +diff --git a/src/daemon/entry/cri/v1/v1_cri_container_manager_service.cc b/src/daemon/entry/cri/v1/v1_cri_container_manager_service.cc +index e86dafae..1097c32c 100644 +--- a/src/daemon/entry/cri/v1/v1_cri_container_manager_service.cc ++++ b/src/daemon/entry/cri/v1/v1_cri_container_manager_service.cc +@@ -199,6 +199,14 @@ auto ContainerManagerService::GenerateCreateContainerHostConfig( + } + } + ++#ifdef ENABLE_CDI ++ CRIHelpersV1::GenerateCDIRequestedDevices(containerConfig, hostconfig, error); ++ if (error.NotEmpty()) { ++ ERROR("Failed to generate CDI requested devices"); ++ goto cleanup; ++ } ++#endif /* ENABLE_CDI */ ++ + return hostconfig; + + cleanup: +diff --git a/src/daemon/executor/container_cb/execution_create.c b/src/daemon/executor/container_cb/execution_create.c +index a9102226..785b4e27 100644 +--- a/src/daemon/executor/container_cb/execution_create.c ++++ b/src/daemon/executor/container_cb/execution_create.c +@@ -63,6 +63,7 @@ + #include "runtime_api.h" + #include "id_name_manager.h" + #include "mailbox.h" ++#include "specs_mount.h" + + #ifdef ENABLE_CRI_API_V1 + static bool validate_sandbox_info(const container_sandbox_info *sandbox) +@@ -512,6 +513,14 @@ static oci_runtime_spec *generate_oci_config(host_config *host_spec, const char + goto error_out; + } + ++#ifdef ENABLE_CDI ++ ret = inject_CDI_devcies_for_oci_spec(oci_spec, host_spec); ++ if (ret != 0) { ++ ERROR("Failed to inject CDI devices"); ++ goto error_out; ++ } ++#endif /* ENABLE_CDI */ ++ + return oci_spec; + + error_out: +diff --git a/src/daemon/modules/service/service_container.c b/src/daemon/modules/service/service_container.c +index eb7ce4f4..b19a134a 100644 +--- a/src/daemon/modules/service/service_container.c ++++ b/src/daemon/modules/service/service_container.c +@@ -2003,6 +2003,16 @@ static defs_process *make_exec_process_spec(const container_config *container_sp + } + + spec->no_new_privileges = oci_spec->process->no_new_privileges; ++ ++#ifdef ENABLE_CDI ++ // extend step: merge env from oci_spec which comes from injected devices ++ ret = defs_process_add_multiple_env(spec, (const char **)oci_spec->process->env, ++ oci_spec->process->env_len); ++ if (ret != 0) { ++ ERROR("Failed to dup oci env for exec process spec"); ++ goto err_out; ++ } ++#endif /* ENABLE_CDI */ + } + + // for oci runtime: +diff --git a/src/daemon/modules/spec/specs_mount.c b/src/daemon/modules/spec/specs_mount.c +index 50ee9a85..12bd261b 100644 +--- a/src/daemon/modules/spec/specs_mount.c ++++ b/src/daemon/modules/spec/specs_mount.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -54,6 +55,9 @@ + #include "volume_api.h" + #include "parse_volume.h" + #include "specs_api.h" ++#ifdef ENABLE_CDI ++#include "cdi_operate_api.h" ++#endif /* ENABLE_CDI */ + + enum update_rw { + update_rw_untouch, +@@ -3582,6 +3586,15 @@ int update_devcies_for_oci_spec(oci_runtime_spec *oci_spec, host_config *hostcon + oci_spec->linux->resources->devices_len += 1; + } + ++ // extend step: inject CDI devcies ++#ifdef ENABLE_CDI ++ ret = inject_CDI_devcies_for_oci_spec(oci_spec, hostconfig); ++ if (ret != 0) { ++ ERROR("Failed to inject CDI devices"); ++ return -1; ++ } ++#endif /* ENABLE_CDI */ ++ + // Step8: do update devices and cgroup device rules at here + if (hostconfig->privileged) { + // Step8.1: for priviledged container, we should merge all devices under /dev +@@ -3592,4 +3605,32 @@ int update_devcies_for_oci_spec(oci_runtime_spec *oci_spec, host_config *hostcon + } + + return ret; +-} +\ No newline at end of file ++} ++ ++#ifdef ENABLE_CDI ++int inject_CDI_devcies_for_oci_spec(oci_runtime_spec *oci_spec, host_config *hostconfig) ++{ ++ int ret = 0; ++ string_array devices_array = { 0 }; ++ __isula_auto_free char *error = NULL; ++ ++ if (oci_spec == NULL || hostconfig == NULL) { ++ ERROR("Invalid params"); ++ return -1; ++ } ++ if (hostconfig->cdi_requested_devices == NULL) { ++ return 0; ++ } ++ devices_array.items = hostconfig->cdi_requested_devices; ++ devices_array.len = hostconfig->cdi_requested_devices_len; ++ devices_array.cap = hostconfig->cdi_requested_devices_len; ++ if (cdi_operate_refresh() != 0) { ++ WARN("CDI registry has errors, please check past logs"); ++ } ++ if (cdi_operate_inject_devices(oci_spec, &devices_array) != 0) { ++ ERROR("Failed to inject CDI devices"); ++ ret = -1; ++ } ++ return ret; ++} ++#endif /* ENABLE_CDI */ +\ No newline at end of file +diff --git a/src/daemon/modules/spec/specs_mount.h b/src/daemon/modules/spec/specs_mount.h +index b742ca35..1406c557 100644 +--- a/src/daemon/modules/spec/specs_mount.h ++++ b/src/daemon/modules/spec/specs_mount.h +@@ -49,6 +49,10 @@ int setup_ipc_dirs(host_config *host_spec, container_config_v2_common_config *v2 + + int update_devcies_for_oci_spec(oci_runtime_spec *oci_spec, host_config *hostconfig); + ++#ifdef ENABLE_CDI ++int inject_CDI_devcies_for_oci_spec(oci_runtime_spec *oci_spec, host_config *hostconfig); ++#endif /* ENABLE_CDI */ ++ + #ifdef __cplusplus + } + #endif +diff --git a/src/daemon/modules/spec/verify.c b/src/daemon/modules/spec/verify.c +index af790d6e..617b7f23 100644 +--- a/src/daemon/modules/spec/verify.c ++++ b/src/daemon/modules/spec/verify.c +@@ -1518,7 +1518,7 @@ static int verify_custom_mount(defs_mount **mounts, size_t len) + + for (i = 0; i < len; ++i) { + iter = *(mounts + i); +- if (iter == NULL || strcmp(iter->type, MOUNT_TYPE_BIND)) { ++ if (iter == NULL || iter->type == NULL || strcmp(iter->type, MOUNT_TYPE_BIND)) { + continue; + } + +-- +2.34.1 + diff --git a/0069-bugfix-fix-cni_operate_ut-ut.patch b/0069-bugfix-fix-cni_operate_ut-ut.patch new file mode 100644 index 0000000..538fcff --- /dev/null +++ b/0069-bugfix-fix-cni_operate_ut-ut.patch @@ -0,0 +1,24 @@ +From a1f75fd089309d0f8620195ce7e517294be2c410 Mon Sep 17 00:00:00 2001 +From: liuxu +Date: Fri, 19 Apr 2024 18:37:05 +0800 +Subject: [PATCH 69/69] bugfix:fix cni_operate_ut ut + +--- + test/network/cni_operate/CMakeLists.txt | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/test/network/cni_operate/CMakeLists.txt b/test/network/cni_operate/CMakeLists.txt +index 5b4d7c7d..752e5199 100644 +--- a/test/network/cni_operate/CMakeLists.txt ++++ b/test/network/cni_operate/CMakeLists.txt +@@ -14,6 +14,7 @@ add_executable(${EXE} + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils_string.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils_array.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils_regex.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils_version.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/namespace.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/sha256/sha256.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/path.c +-- +2.34.1 + diff --git a/iSulad.spec b/iSulad.spec index 5ce391a..9500769 100644 --- a/iSulad.spec +++ b/iSulad.spec @@ -1,5 +1,5 @@ %global _version 2.1.5 -%global _release 4 +%global _release 5 %global is_systemd 1 %global enable_criv1 1 %global enable_shimv2 1 @@ -52,12 +52,38 @@ Patch0034: 0034-bugfix-for-cpurt.sh.patch Patch0035: 0035-monitor-cgroup-oom-killed-event-and-update-to-cri-of.patch Patch0036: 0036-add-ci-cases-for-oomkilled-monitor.patch Patch0037: 0037-add-cgroup-v2-doc.patch -Patch0038: 0038-fix-run-ubuntu-container-bug-in-inspect.sh.patch -Patch0039: 0039-add-support-for-GetContainerEvents.patch -Patch0040: 0040-fix-cpurt-init-bug-for-systemd-cgroup.patch -Patch0041: 0041-fix-message-queue-concurrent-bug.patch -Patch0042: 0042-specify-runtime-as-runc-for-oom-test-CI.patch -Patch0043: 0043-set-oomkilled-in-cri.patch +Patch0038: 0038-add-modify-for-cgroup-v2-ci-test.patch +Patch0039: 0039-fix-run-ubuntu-container-bug-in-inspect.sh.patch +Patch0040: 0040-add-support-for-GetContainerEvents.patch +Patch0041: 0041-fix-cpurt-init-bug-for-systemd-cgroup.patch +Patch0042: 0042-fix-message-queue-concurrent-bug.patch +Patch0043: 0043-specify-runtime-as-runc-for-oom-test-CI.patch +Patch0044: 0044-set-oomkilled-in-cri.patch +Patch0045: 0045-add-cri-1.29-update-design-doc.patch +Patch0046: 0046-oom-monitor-in-manual-cases.patch +Patch0047: 0047-add-usage-restrictions-for-CRI-1.29-update.patch +Patch0048: 0048-CDI-interface-definition.patch +Patch0049: 0049-distinguish-between-runtime-and-runtime_cmd-in-isula.patch +Patch0050: 0050-Use-user-defined-shm-for-CRI-request.patch +Patch0051: 0051-Fix-memory-leak-in-set_connected_container_shm_path.patch +Patch0052: 0052-init-enable_pod_events-as-false.patch +Patch0053: 0053-remove-container-root-path-in-rt_lcr_rm-if-lcr-runti.patch +Patch0054: 0054-ensure-sandbox-can-be-removed-if-sandbox-container-r.patch +Patch0055: 0055-bugfix-for-shim-timeout-exit-error-log-changes.patch +Patch0056: 0056-bugfix-for-the-pre-created-pipe-was-not-closed-when-.patch +Patch0057: 0057-add-debug-msg-info-in-image_load.sh.patch +Patch0058: 0058-empty-pointer-check-in-lcr_rt_ops.patch +Patch0059: 0059-modify-some-grpc-status-codes-of-cri-in-case-of-erro.patch +Patch0060: 0060-cdi-return-int-instead-of-error-string.patch +Patch0061: 0061-cdi-support-modules-operate-registry-annotations.patch +Patch0062: 0062-do-not-umount-shmpath-for-sandbox-container.patch +Patch0063: 0063-remove-default-systemd-cgroup-and-enable-cri-v1-valu.patch +Patch0064: 0064-cdi-support-module-cache.patch +Patch0065: 0065-change-default-subscribe-timeout-to-5min.patch +Patch0066: 0066-cdi-support-modules-version-spec-spec_dirs-device.patch +Patch0067: 0067-cdi-support-modules-container_edits-parser.patch +Patch0068: 0068-cdi-invoke-cdi-operate-when-init-isulad-and-create-c.patch +Patch0069: 0069-bugfix-fix-cni_operate_ut-ut.patch %ifarch x86_64 aarch64 Provides: libhttpclient.so()(64bit) @@ -130,6 +156,7 @@ cd build %if 0%{?enable_criv1} -DENABLE_CRI_API_V1=ON \ -DENABLE_SANDBOXER=ON \ + -DENABLE_CDI=ON \ %endif %if 0%{?enable_shimv2} -DENABLE_SHIM_V2=ON \ @@ -312,6 +339,12 @@ fi %endif %changelog +* Sat Apr 20 2024 liuxu - 2.1.5-5 +- Type: update +- ID: NA +- SUG: NA +- DESC: upgrade from upstream + * Tue Apr 02 2024 jikai - 2.1.5-4 - Type: update - ID: NA -- Gitee